powerpc/8xx: Manage 512k huge pages as standard pages.
[linux-2.6-microblaze.git] / arch / powerpc / mm / hugetlbpage.c
index 521929a..38bad83 100644 (file)
@@ -189,6 +189,9 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr, unsigned long sz
        if (!hpdp)
                return NULL;
 
+       if (IS_ENABLED(CONFIG_PPC_8xx) && sz == SZ_512K)
+               return pte_alloc_map(mm, (pmd_t *)hpdp, addr);
+
        BUG_ON(!hugepd_none(*hpdp) && !hugepd_ok(*hpdp));
 
        if (hugepd_none(*hpdp) && __hugepte_alloc(mm, hpdp, addr,
@@ -331,13 +334,20 @@ static void free_hugepd_range(struct mmu_gather *tlb, hugepd_t *hpdp, int pdshif
 
        if (shift >= pdshift)
                hugepd_free(tlb, hugepte);
-       else if (IS_ENABLED(CONFIG_PPC_8xx))
-               pgtable_free_tlb(tlb, hugepte, 0);
        else
                pgtable_free_tlb(tlb, hugepte,
                                 get_hugepd_cache_index(pdshift - shift));
 }
 
+static void hugetlb_free_pte_range(struct mmu_gather *tlb, pmd_t *pmd, unsigned long addr)
+{
+       pgtable_t token = pmd_pgtable(*pmd);
+
+       pmd_clear(pmd);
+       pte_free_tlb(tlb, token, addr);
+       mm_dec_nr_ptes(tlb->mm);
+}
+
 static void hugetlb_free_pmd_range(struct mmu_gather *tlb, pud_t *pud,
                                   unsigned long addr, unsigned long end,
                                   unsigned long floor, unsigned long ceiling)
@@ -353,11 +363,17 @@ static void hugetlb_free_pmd_range(struct mmu_gather *tlb, pud_t *pud,
                pmd = pmd_offset(pud, addr);
                next = pmd_addr_end(addr, end);
                if (!is_hugepd(__hugepd(pmd_val(*pmd)))) {
+                       if (pmd_none_or_clear_bad(pmd))
+                               continue;
+
                        /*
                         * if it is not hugepd pointer, we should already find
                         * it cleared.
                         */
-                       WARN_ON(!pmd_none_or_clear_bad(pmd));
+                       WARN_ON(!IS_ENABLED(CONFIG_PPC_8xx));
+
+                       hugetlb_free_pte_range(tlb, pmd, addr);
+
                        continue;
                }
                /*