return (nr_pages);
 }
 
+/*
+ * This function is meant to pre-load the iterator for the zone init.
+ * Specifically it walks through the ranges until we are caught up to the
+ * first_init_pfn value and exits there. If we never encounter the value we
+ * return false indicating there are no valid ranges left.
+ */
+static bool __init
+deferred_init_mem_pfn_range_in_zone(u64 *i, struct zone *zone,
+                                   unsigned long *spfn, unsigned long *epfn,
+                                   unsigned long first_init_pfn)
+{
+       u64 j;
+
+       /*
+        * Start out by walking through the ranges in this zone that have
+        * already been initialized. We don't need to do anything with them
+        * so we just need to flush them out of the system.
+        */
+       for_each_free_mem_pfn_range_in_zone(j, zone, spfn, epfn) {
+               if (*epfn <= first_init_pfn)
+                       continue;
+               if (*spfn < first_init_pfn)
+                       *spfn = first_init_pfn;
+               *i = j;
+               return true;
+       }
+
+       return false;
+}
+
+/*
+ * Initialize and free pages. We do it in two loops: first we initialize
+ * struct page, then free to buddy allocator, because while we are
+ * freeing pages we can access pages that are ahead (computing buddy
+ * page in __free_one_page()).
+ *
+ * In order to try and keep some memory in the cache we have the loop
+ * broken along max page order boundaries. This way we will not cause
+ * any issues with the buddy page computation.
+ */
+static unsigned long __init
+deferred_init_maxorder(u64 *i, struct zone *zone, unsigned long *start_pfn,
+                      unsigned long *end_pfn)
+{
+       unsigned long mo_pfn = ALIGN(*start_pfn + 1, MAX_ORDER_NR_PAGES);
+       unsigned long spfn = *start_pfn, epfn = *end_pfn;
+       unsigned long nr_pages = 0;
+       u64 j = *i;
+
+       /* First we loop through and initialize the page values */
+       for_each_free_mem_pfn_range_in_zone_from(j, zone, start_pfn, end_pfn) {
+               unsigned long t;
+
+               if (mo_pfn <= *start_pfn)
+                       break;
+
+               t = min(mo_pfn, *end_pfn);
+               nr_pages += deferred_init_pages(zone, *start_pfn, t);
+
+               if (mo_pfn < *end_pfn) {
+                       *start_pfn = mo_pfn;
+                       break;
+               }
+       }
+
+       /* Reset values and now loop through freeing pages as needed */
+       swap(j, *i);
+
+       for_each_free_mem_pfn_range_in_zone_from(j, zone, &spfn, &epfn) {
+               unsigned long t;
+
+               if (mo_pfn <= spfn)
+                       break;
+
+               t = min(mo_pfn, epfn);
+               deferred_free_pages(spfn, t);
+
+               if (mo_pfn <= epfn)
+                       break;
+       }
+
+       return nr_pages;
+}
+
 /* Initialise remaining memory on a node */
 static int __init deferred_init_memmap(void *data)
 {
        pg_data_t *pgdat = data;
+       const struct cpumask *cpumask = cpumask_of_node(pgdat->node_id);
+       unsigned long spfn = 0, epfn = 0, nr_pages = 0;
+       unsigned long first_init_pfn, flags;
        unsigned long start = jiffies;
-       unsigned long nr_pages = 0;
-       unsigned long spfn, epfn, first_init_pfn, flags;
-       int zid;
        struct zone *zone;
-       const struct cpumask *cpumask = cpumask_of_node(pgdat->node_id);
+       int zid;
        u64 i;
 
        /* Bind memory initialisation thread to a local node if possible */
                if (first_init_pfn < zone_end_pfn(zone))
                        break;
        }
-       first_init_pfn = max(zone->zone_start_pfn, first_init_pfn);
+
+       /* If the zone is empty somebody else may have cleared out the zone */
+       if (!deferred_init_mem_pfn_range_in_zone(&i, zone, &spfn, &epfn,
+                                                first_init_pfn))
+               goto zone_empty;
 
        /*
-        * Initialize and free pages. We do it in two loops: first we initialize
-        * struct page, than free to buddy allocator, because while we are
-        * freeing pages we can access pages that are ahead (computing buddy
-        * page in __free_one_page()).
+        * Initialize and free pages in MAX_ORDER sized increments so
+        * that we can avoid introducing any issues with the buddy
+        * allocator.
         */
-       for_each_free_mem_pfn_range_in_zone(i, zone, &spfn, &epfn) {
-               spfn = max_t(unsigned long, first_init_pfn, spfn);
-               nr_pages += deferred_init_pages(zone, spfn, epfn);
-       }
-       for_each_free_mem_pfn_range_in_zone(i, zone, &spfn, &epfn) {
-               spfn = max_t(unsigned long, first_init_pfn, spfn);
-               deferred_free_pages(spfn, epfn);
-       }
+       while (spfn < epfn)
+               nr_pages += deferred_init_maxorder(&i, zone, &spfn, &epfn);
+zone_empty:
        pgdat_resize_unlock(pgdat, &flags);
 
        /* Sanity check that the next zone really is unpopulated */
 {
        unsigned long nr_pages_needed = ALIGN(1 << order, PAGES_PER_SECTION);
        pg_data_t *pgdat = zone->zone_pgdat;
-       unsigned long nr_pages = 0;
-       unsigned long first_init_pfn, spfn, epfn, t, flags;
        unsigned long first_deferred_pfn = pgdat->first_deferred_pfn;
+       unsigned long spfn, epfn, flags;
+       unsigned long nr_pages = 0;
        u64 i;
 
        /* Only the last zone may have deferred pages */
                return true;
        }
 
-       first_init_pfn = max(zone->zone_start_pfn, first_deferred_pfn);
-
-       if (first_init_pfn >= pgdat_end_pfn(pgdat)) {
+       /* If the zone is empty somebody else may have cleared out the zone */
+       if (!deferred_init_mem_pfn_range_in_zone(&i, zone, &spfn, &epfn,
+                                                first_deferred_pfn)) {
+               pgdat->first_deferred_pfn = ULONG_MAX;
                pgdat_resize_unlock(pgdat, &flags);
-               return false;
+               return true;
        }
 
-       for_each_free_mem_pfn_range_in_zone(i, zone, &spfn, &epfn) {
-               spfn = max_t(unsigned long, first_init_pfn, spfn);
+       /*
+        * Initialize and free pages in MAX_ORDER sized increments so
+        * that we can avoid introducing any issues with the buddy
+        * allocator.
+        */
+       while (spfn < epfn) {
+               /* update our first deferred PFN for this section */
+               first_deferred_pfn = spfn;
+
+               nr_pages += deferred_init_maxorder(&i, zone, &spfn, &epfn);
 
-               while (spfn < epfn && nr_pages < nr_pages_needed) {
-                       t = ALIGN(spfn + PAGES_PER_SECTION, PAGES_PER_SECTION);
-                       first_deferred_pfn = min(t, epfn);
-                       nr_pages += deferred_init_pages(zone, spfn,
-                                                       first_deferred_pfn);
-                       spfn = first_deferred_pfn;
-               }
+               /* We should only stop along section boundaries */
+               if ((first_deferred_pfn ^ spfn) < PAGES_PER_SECTION)
+                       continue;
 
+               /* If our quota has been met we can stop here */
                if (nr_pages >= nr_pages_needed)
                        break;
        }
 
-       for_each_free_mem_pfn_range_in_zone(i, zone, &spfn, &epfn) {
-               spfn = max_t(unsigned long, first_init_pfn, spfn);
-               epfn = min_t(unsigned long, first_deferred_pfn, epfn);
-               deferred_free_pages(spfn, epfn);
-
-               if (first_deferred_pfn == epfn)
-                       break;
-       }
-       pgdat->first_deferred_pfn = first_deferred_pfn;
+       pgdat->first_deferred_pfn = spfn;
        pgdat_resize_unlock(pgdat, &flags);
 
        return nr_pages > 0;