Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[linux-drm-fsl-dcu.git] / arch / x86 / mm / pgtable.c
index dfa537a03be1e187fe8772b83a44639600d1cdf4..c96314abd144ca91cfcccaba72352ad0fdc6cf5b 100644 (file)
@@ -25,8 +25,12 @@ pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address)
        struct page *pte;
 
        pte = alloc_pages(__userpte_alloc_gfp, 0);
-       if (pte)
-               pgtable_page_ctor(pte);
+       if (!pte)
+               return NULL;
+       if (!pgtable_page_ctor(pte)) {
+               __free_page(pte);
+               return NULL;
+       }
        return pte;
 }
 
@@ -57,6 +61,7 @@ void ___pte_free_tlb(struct mmu_gather *tlb, struct page *pte)
 #if PAGETABLE_LEVELS > 2
 void ___pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd)
 {
+       struct page *page = virt_to_page(pmd);
        paravirt_release_pmd(__pa(pmd) >> PAGE_SHIFT);
        /*
         * NOTE! For PAE, any changes to the top page-directory-pointer-table
@@ -65,7 +70,8 @@ void ___pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd)
 #ifdef CONFIG_X86_PAE
        tlb->need_flush_all = 1;
 #endif
-       tlb_remove_page(tlb, virt_to_page(pmd));
+       pgtable_pmd_page_dtor(page);
+       tlb_remove_page(tlb, page);
 }
 
 #if PAGETABLE_LEVELS > 3
@@ -189,8 +195,10 @@ static void free_pmds(pmd_t *pmds[])
        int i;
 
        for(i = 0; i < PREALLOCATED_PMDS; i++)
-               if (pmds[i])
+               if (pmds[i]) {
+                       pgtable_pmd_page_dtor(virt_to_page(pmds[i]));
                        free_page((unsigned long)pmds[i]);
+               }
 }
 
 static int preallocate_pmds(pmd_t *pmds[])
@@ -200,8 +208,13 @@ static int preallocate_pmds(pmd_t *pmds[])
 
        for(i = 0; i < PREALLOCATED_PMDS; i++) {
                pmd_t *pmd = (pmd_t *)__get_free_page(PGALLOC_GFP);
-               if (pmd == NULL)
+               if (!pmd)
                        failed = true;
+               if (pmd && !pgtable_pmd_page_ctor(virt_to_page(pmd))) {
+                       free_page((unsigned long)pmd);
+                       pmd = NULL;
+                       failed = true;
+               }
                pmds[i] = pmd;
        }