]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - mm/hugetlb.c
hugetlb: call arch_prepare_hugepage() for surplus pages
[linux-2.6-omap-h63xx.git] / mm / hugetlb.c
index 3be79dc18c5c65a0c3b251d4849e3c895eadefd3..92155db888b97f99aac1b29f804544ab0a2cf022 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/mm.h>
 #include <linux/sysctl.h>
 #include <linux/highmem.h>
+#include <linux/mmu_notifier.h>
 #include <linux/nodemask.h>
 #include <linux/pagemap.h>
 #include <linux/mempolicy.h>
@@ -19,6 +20,7 @@
 
 #include <asm/page.h>
 #include <asm/pgtable.h>
+#include <asm/io.h>
 
 #include <linux/hugetlb.h>
 #include "internal.h"
@@ -563,7 +565,7 @@ static struct page *alloc_fresh_huge_page_node(struct hstate *h, int nid)
                huge_page_order(h));
        if (page) {
                if (arch_prepare_hugepage(page)) {
-                       __free_pages(page, HUGETLB_PAGE_ORDER);
+                       __free_pages(page, huge_page_order(h));
                        return NULL;
                }
                prep_new_huge_page(h, page, nid);
@@ -663,6 +665,11 @@ static struct page *alloc_buddy_huge_page(struct hstate *h,
                                        __GFP_REPEAT|__GFP_NOWARN,
                                        huge_page_order(h));
 
+       if (page && arch_prepare_hugepage(page)) {
+               __free_pages(page, huge_page_order(h));
+               return NULL;
+       }
+
        spin_lock(&hugetlb_lock);
        if (page) {
                /*
@@ -1281,7 +1288,12 @@ module_exit(hugetlb_exit);
 
 static int __init hugetlb_init(void)
 {
-       BUILD_BUG_ON(HPAGE_SHIFT == 0);
+       /* Some platform decide whether they support huge pages at boot
+        * time. On these, such as powerpc, HPAGE_SHIFT is set to 0 when
+        * there is no such support
+        */
+       if (HPAGE_SHIFT == 0)
+               return 0;
 
        if (!size_to_hstate(default_hstate_size)) {
                default_hstate_size = HPAGE_SIZE;
@@ -1672,6 +1684,7 @@ void __unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start,
        BUG_ON(start & ~huge_page_mask(h));
        BUG_ON(end & ~huge_page_mask(h));
 
+       mmu_notifier_invalidate_range_start(mm, start, end);
        spin_lock(&mm->page_table_lock);
        for (address = start; address < end; address += sz) {
                ptep = huge_pte_offset(mm, address);
@@ -1713,6 +1726,7 @@ void __unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start,
        }
        spin_unlock(&mm->page_table_lock);
        flush_tlb_range(vma, start, end);
+       mmu_notifier_invalidate_range_end(mm, start, end);
        list_for_each_entry_safe(page, tmp, &page_list, lru) {
                list_del(&page->lru);
                put_page(page);