mm/page_alloc: skip non present sections on zone initialization
[linux-2.6-microblaze.git] / mm / page_alloc.c
index d047bf7..fe8a529 100644 (file)
@@ -5848,6 +5848,30 @@ overlap_memmap_init(unsigned long zone, unsigned long *pfn)
        return false;
 }
 
+#ifdef CONFIG_SPARSEMEM
+/* Skip PFNs that belong to non-present sections */
+static inline __meminit unsigned long next_pfn(unsigned long pfn)
+{
+       unsigned long section_nr;
+
+       section_nr = pfn_to_section_nr(++pfn);
+       if (present_section_nr(section_nr))
+               return pfn;
+
+       while (++section_nr <= __highest_present_section_nr) {
+               if (present_section_nr(section_nr))
+                       return section_nr_to_pfn(section_nr);
+       }
+
+       return -1;
+}
+#else
+static inline __meminit unsigned long next_pfn(unsigned long pfn)
+{
+       return pfn++;
+}
+#endif
+
 /*
  * Initially all pages are reserved - free ones are freed
  * up by memblock_free_all() once the early boot process is
@@ -5887,8 +5911,10 @@ void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone,
                 * function.  They do not exist on hotplugged memory.
                 */
                if (context == MEMMAP_EARLY) {
-                       if (!early_pfn_valid(pfn))
+                       if (!early_pfn_valid(pfn)) {
+                               pfn = next_pfn(pfn) - 1;
                                continue;
+                       }
                        if (!early_pfn_in_nid(pfn, nid))
                                continue;
                        if (overlap_memmap_init(zone, &pfn))