Merge tag 'powerpc-5.2-2' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc...
[linux-2.6-microblaze.git] / mm / memblock.c
index a48f520..6bbad46 100644 (file)
@@ -94,7 +94,7 @@
  * :c:func:`mem_init` function frees all the memory to the buddy page
  * allocator.
  *
- * If an architecure enables %CONFIG_ARCH_DISCARD_MEMBLOCK, the
+ * Unless an architecure enables %CONFIG_ARCH_KEEP_MEMBLOCK, the
  * memblock data structures will be discarded after the system
  * initialization compltes.
  */
@@ -375,7 +375,7 @@ static void __init_memblock memblock_remove_region(struct memblock_type *type, u
        }
 }
 
-#ifdef CONFIG_ARCH_DISCARD_MEMBLOCK
+#ifndef CONFIG_ARCH_KEEP_MEMBLOCK
 /**
  * memblock_discard - discard memory and reserved arrays if they were allocated
  */
@@ -1255,6 +1255,70 @@ int __init_memblock memblock_set_node(phys_addr_t base, phys_addr_t size,
        return 0;
 }
 #endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */
+#ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT
+/**
+ * __next_mem_pfn_range_in_zone - iterator for for_each_*_range_in_zone()
+ *
+ * @idx: pointer to u64 loop variable
+ * @zone: zone in which all of the memory blocks reside
+ * @out_spfn: ptr to ulong for start pfn of the range, can be %NULL
+ * @out_epfn: ptr to ulong for end pfn of the range, can be %NULL
+ *
+ * This function is meant to be a zone/pfn specific wrapper for the
+ * for_each_mem_range type iterators. Specifically they are used in the
+ * deferred memory init routines and as such we were duplicating much of
+ * this logic throughout the code. So instead of having it in multiple
+ * locations it seemed like it would make more sense to centralize this to
+ * one new iterator that does everything they need.
+ */
+void __init_memblock
+__next_mem_pfn_range_in_zone(u64 *idx, struct zone *zone,
+                            unsigned long *out_spfn, unsigned long *out_epfn)
+{
+       int zone_nid = zone_to_nid(zone);
+       phys_addr_t spa, epa;
+       int nid;
+
+       __next_mem_range(idx, zone_nid, MEMBLOCK_NONE,
+                        &memblock.memory, &memblock.reserved,
+                        &spa, &epa, &nid);
+
+       while (*idx != U64_MAX) {
+               unsigned long epfn = PFN_DOWN(epa);
+               unsigned long spfn = PFN_UP(spa);
+
+               /*
+                * Verify the end is at least past the start of the zone and
+                * that we have at least one PFN to initialize.
+                */
+               if (zone->zone_start_pfn < epfn && spfn < epfn) {
+                       /* if we went too far just stop searching */
+                       if (zone_end_pfn(zone) <= spfn) {
+                               *idx = U64_MAX;
+                               break;
+                       }
+
+                       if (out_spfn)
+                               *out_spfn = max(zone->zone_start_pfn, spfn);
+                       if (out_epfn)
+                               *out_epfn = min(zone_end_pfn(zone), epfn);
+
+                       return;
+               }
+
+               __next_mem_range(idx, zone_nid, MEMBLOCK_NONE,
+                                &memblock.memory, &memblock.reserved,
+                                &spa, &epa, &nid);
+       }
+
+       /* signal end of iteration */
+       if (out_spfn)
+               *out_spfn = ULONG_MAX;
+       if (out_epfn)
+               *out_epfn = 0;
+}
+
+#endif /* CONFIG_DEFERRED_STRUCT_PAGE_INIT */
 
 /**
  * memblock_alloc_range_nid - allocate boot memory block
@@ -1923,7 +1987,7 @@ unsigned long __init memblock_free_all(void)
        return pages;
 }
 
-#if defined(CONFIG_DEBUG_FS) && !defined(CONFIG_ARCH_DISCARD_MEMBLOCK)
+#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_ARCH_KEEP_MEMBLOCK)
 
 static int memblock_debug_show(struct seq_file *m, void *private)
 {