summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaulo Zanoni <paulo.r.zanoni@intel.com>2017-03-27 17:32:51 -0300
committerPaulo Zanoni <paulo.r.zanoni@intel.com>2017-03-27 17:32:51 -0300
commitaefc2f50051461f24221c0f223e0d010fcc4bdb1 (patch)
treed22b2705aced92a405612d3d7fb8e6a48f726349
parent65f12fb82225e027826b0f862c5ca1c6e9798b35 (diff)
parentecf522b9010f38f423f2394df14e170dc7384940 (diff)
Merge remote-tracking branch 'intel/topic/core-for-CI' into drm-tip
-rw-r--r--drivers/net/ethernet/intel/e1000e/netdev.c9
-rw-r--r--mm/vmalloc.c108
2 files changed, 34 insertions, 83 deletions
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index 2175cced402f..5ee1d18c9a01 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -6613,12 +6613,19 @@ static int e1000e_pm_thaw(struct device *dev)
static int e1000e_pm_suspend(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
+ int rc;
e1000e_flush_lpic(pdev);
e1000e_pm_freeze(dev);
- return __e1000_shutdown(pdev, false);
+ rc = __e1000_shutdown(pdev, false);
+ if (rc) {
+ e1000e_pm_thaw(dev);
+ return rc;
+ }
+
+ return 0;
}
static int e1000e_pm_resume(struct device *dev)
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 0b057628a7ba..8cc8a7a40296 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -133,80 +133,27 @@ static void vunmap_page_range(unsigned long addr, unsigned long end)
} while (pgd++, addr = next, addr != end);
}
-static int vmap_pte_range(pmd_t *pmd, unsigned long addr,
- unsigned long end, pgprot_t prot, struct page **pages, int *nr)
-{
- pte_t *pte;
-
- /*
- * nr is a running index into the array which helps higher level
- * callers keep track of where we're up to.
- */
-
- pte = pte_alloc_kernel(pmd, addr);
- if (!pte)
- return -ENOMEM;
- do {
- struct page *page = pages[*nr];
-
- if (WARN_ON(!pte_none(*pte)))
- return -EBUSY;
- if (WARN_ON(!page))
- return -ENOMEM;
- set_pte_at(&init_mm, addr, pte, mk_pte(page, prot));
- (*nr)++;
- } while (pte++, addr += PAGE_SIZE, addr != end);
- return 0;
-}
+struct vmap_page {
+ pgprot_t prot;
+ struct page **pages;
+ unsigned long count;
+};
-static int vmap_pmd_range(pud_t *pud, unsigned long addr,
- unsigned long end, pgprot_t prot, struct page **pages, int *nr)
+static int vmap_page(pte_t *pte, pgtable_t token,
+ unsigned long addr, void *data)
{
- pmd_t *pmd;
- unsigned long next;
-
- pmd = pmd_alloc(&init_mm, pud, addr);
- if (!pmd)
- return -ENOMEM;
- do {
- next = pmd_addr_end(addr, end);
- if (vmap_pte_range(pmd, addr, next, prot, pages, nr))
- return -ENOMEM;
- } while (pmd++, addr = next, addr != end);
- return 0;
-}
+ struct vmap_page *v = data;
+ struct page *page;
-static int vmap_pud_range(p4d_t *p4d, unsigned long addr,
- unsigned long end, pgprot_t prot, struct page **pages, int *nr)
-{
- pud_t *pud;
- unsigned long next;
+ if (WARN_ON(!pte_none(*pte)))
+ return -EBUSY;
- pud = pud_alloc(&init_mm, p4d, addr);
- if (!pud)
+ page = v->pages[v->count];
+ if (WARN_ON(!page))
return -ENOMEM;
- do {
- next = pud_addr_end(addr, end);
- if (vmap_pmd_range(pud, addr, next, prot, pages, nr))
- return -ENOMEM;
- } while (pud++, addr = next, addr != end);
- return 0;
-}
-static int vmap_p4d_range(pgd_t *pgd, unsigned long addr,
- unsigned long end, pgprot_t prot, struct page **pages, int *nr)
-{
- p4d_t *p4d;
- unsigned long next;
-
- p4d = p4d_alloc(&init_mm, pgd, addr);
- if (!p4d)
- return -ENOMEM;
- do {
- next = p4d_addr_end(addr, end);
- if (vmap_pud_range(p4d, addr, next, prot, pages, nr))
- return -ENOMEM;
- } while (p4d++, addr = next, addr != end);
+ set_pte_at(&init_mm, addr, pte, mk_pte(page, v->prot));
+ v->count++;
return 0;
}
@@ -219,22 +166,19 @@ static int vmap_p4d_range(pgd_t *pgd, unsigned long addr,
static int vmap_page_range_noflush(unsigned long start, unsigned long end,
pgprot_t prot, struct page **pages)
{
- pgd_t *pgd;
- unsigned long next;
- unsigned long addr = start;
- int err = 0;
- int nr = 0;
+ struct vmap_page v = { prot, pages };
+ int err;
- BUG_ON(addr >= end);
- pgd = pgd_offset_k(addr);
- do {
- next = pgd_addr_end(addr, end);
- err = vmap_p4d_range(pgd, addr, next, prot, pages, &nr);
- if (err)
- return err;
- } while (pgd++, addr = next, addr != end);
+ if ((end - start) >> PAGE_SHIFT > INT_MAX)
+ return -EINVAL;
+
+ err = apply_to_page_range(&init_mm, start, end - start, vmap_page, &v);
+ if (unlikely(err)) {
+ vunmap_page_range(start, start + (v.count << PAGE_SHIFT));
+ return err;
+ }
- return nr;
+ return v.count;
}
static int vmap_page_range(unsigned long start, unsigned long end,