Merge tag 'powerpc-5.3-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc...
[sfrench/cifs-2.6.git] / arch / powerpc / mm / pgtable_64.c
index 12d5e083942d4a83107de851c387dfea57d0f834..9ad59b733984759d15f8edeff4ec445635b6acf2 100644 (file)
@@ -103,14 +103,30 @@ unsigned long ioremap_bot;
 unsigned long ioremap_bot = IOREMAP_BASE;
 #endif
 
+int __weak ioremap_range(unsigned long ea, phys_addr_t pa, unsigned long size, pgprot_t prot, int nid)
+{
+       unsigned long i;
+
+       for (i = 0; i < size; i += PAGE_SIZE) {
+               int err = map_kernel_page(ea + i, pa + i, prot);
+               if (err) {
+                       if (slab_is_available())
+                               unmap_kernel_range(ea, size);
+                       else
+                               WARN_ON_ONCE(1); /* Should clean up */
+                       return err;
+               }
+       }
+
+       return 0;
+}
+
 /**
  * __ioremap_at - Low level function to establish the page tables
  *                for an IO mapping
  */
 void __iomem *__ioremap_at(phys_addr_t pa, void *ea, unsigned long size, pgprot_t prot)
 {
-       unsigned long i;
-
        /* We don't support the 4K PFN hack with ioremap */
        if (pgprot_val(prot) & H_PAGE_4K_PFN)
                return NULL;
@@ -124,9 +140,8 @@ void __iomem *__ioremap_at(phys_addr_t pa, void *ea, unsigned long size, pgprot_
        WARN_ON(((unsigned long)ea) & ~PAGE_MASK);
        WARN_ON(size & ~PAGE_MASK);
 
-       for (i = 0; i < size; i += PAGE_SIZE)
-               if (map_kernel_page((unsigned long)ea + i, pa + i, prot))
-                       return NULL;
+       if (ioremap_range((unsigned long)ea, pa, size, prot, NUMA_NO_NODE))
+               return NULL;
 
        return (void __iomem *)ea;
 }
@@ -177,8 +192,6 @@ void __iomem * __ioremap_caller(phys_addr_t addr, unsigned long size,
 
                area->phys_addr = paligned;
                ret = __ioremap_at(paligned, area->addr, size, prot);
-               if (!ret)
-                       vunmap(area->addr);
        } else {
                ret = __ioremap_at(paligned, (void *)ioremap_bot, size, prot);
                if (ret)
@@ -291,16 +304,20 @@ EXPORT_SYMBOL(__iounmap_at);
 /* 4 level page table */
 struct page *pgd_page(pgd_t pgd)
 {
-       if (pgd_huge(pgd))
+       if (pgd_is_leaf(pgd)) {
+               VM_WARN_ON(!pgd_huge(pgd));
                return pte_page(pgd_pte(pgd));
+       }
        return virt_to_page(pgd_page_vaddr(pgd));
 }
 #endif
 
 struct page *pud_page(pud_t pud)
 {
-       if (pud_huge(pud))
+       if (pud_is_leaf(pud)) {
+               VM_WARN_ON(!pud_huge(pud));
                return pte_page(pud_pte(pud));
+       }
        return virt_to_page(pud_page_vaddr(pud));
 }
 
@@ -310,8 +327,10 @@ struct page *pud_page(pud_t pud)
  */
 struct page *pmd_page(pmd_t pmd)
 {
-       if (pmd_large(pmd) || pmd_huge(pmd) || pmd_devmap(pmd))
+       if (pmd_is_leaf(pmd)) {
+               VM_WARN_ON(!(pmd_large(pmd) || pmd_huge(pmd)));
                return pte_page(pmd_pte(pmd));
+       }
        return virt_to_page(pmd_page_vaddr(pmd));
 }