|
|
@@ -712,7 +712,22 @@ int pmd_clear_huge(pmd_t *pmd)
|
|
|
*/
|
|
|
int pud_free_pmd_page(pud_t *pud)
|
|
|
{
|
|
|
- return pud_none(*pud);
|
|
|
+ pmd_t *pmd;
|
|
|
+ int i;
|
|
|
+
|
|
|
+ if (pud_none(*pud))
|
|
|
+ return 1;
|
|
|
+
|
|
|
+ pmd = (pmd_t *)pud_page_vaddr(*pud);
|
|
|
+
|
|
|
+ for (i = 0; i < PTRS_PER_PMD; i++)
|
|
|
+ if (!pmd_free_pte_page(&pmd[i]))
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ pud_clear(pud);
|
|
|
+ free_page((unsigned long)pmd);
|
|
|
+
|
|
|
+ return 1;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -724,6 +739,15 @@ int pud_free_pmd_page(pud_t *pud)
|
|
|
*/
|
|
|
int pmd_free_pte_page(pmd_t *pmd)
|
|
|
{
|
|
|
- return pmd_none(*pmd);
|
|
|
+ pte_t *pte;
|
|
|
+
|
|
|
+ if (pmd_none(*pmd))
|
|
|
+ return 1;
|
|
|
+
|
|
|
+ pte = (pte_t *)pmd_page_vaddr(*pmd);
|
|
|
+ pmd_clear(pmd);
|
|
|
+ free_page((unsigned long)pte);
|
|
|
+
|
|
|
+ return 1;
|
|
|
}
|
|
|
#endif /* CONFIG_HAVE_ARCH_HUGE_VMAP */
|