]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge branch 'master' into x86/memblock
authorTejun Heo <tj@kernel.org>
Mon, 28 Nov 2011 17:46:22 +0000 (09:46 -0800)
committerTejun Heo <tj@kernel.org>
Mon, 28 Nov 2011 17:46:22 +0000 (09:46 -0800)
Conflicts & resolutions:

* arch/x86/xen/setup.c

dc91c728fd "xen: allow extra memory to be in multiple regions"
24aa07882b "memblock, x86: Replace memblock_x86_reserve/free..."

conflicted on xen_add_extra_mem() updates.  The resolution is
trivial as the latter just want to replace
memblock_x86_reserve_range() with memblock_reserve().

* drivers/pci/intel-iommu.c

166e9278a3f "x86/ia64: intel-iommu: move to drivers/iommu/"
5dfe8660a3d "bootmem: Replace work_with_active_regions() with..."

conflicted as the former moved the file under drivers/iommu/.
Resolved by applying the chnages from the latter on the moved
file.

* mm/Kconfig

6661672053a "memblock: add NO_BOOTMEM config symbol"
c378ddd53f9 "memblock, x86: Make ARCH_DISCARD_MEMBLOCK a config option"

conflicted trivially.  Both added config options.  Just
letting both add their own options resolves the conflict.

* mm/memblock.c

d1f0ece6cdc "mm/memblock.c: small function definition fixes"
ed7b56a799c "memblock: Remove memblock_memory_can_coalesce()"

confliected.  The former updates function removed by the
latter.  Resolution is trivial.

Signed-off-by: Tejun Heo <tj@kernel.org>
36 files changed:
arch/powerpc/mm/numa.c
arch/sparc/mm/init_64.c
arch/x86/Kconfig
arch/x86/include/asm/e820.h
arch/x86/include/asm/memblock.h [deleted file]
arch/x86/kernel/aperture_64.c
arch/x86/kernel/check.c
arch/x86/kernel/e820.c
arch/x86/kernel/head.c
arch/x86/kernel/head32.c
arch/x86/kernel/head64.c
arch/x86/kernel/mpparse.c
arch/x86/kernel/setup.c
arch/x86/kernel/trampoline.c
arch/x86/mm/Makefile
arch/x86/mm/init.c
arch/x86/mm/init_32.c
arch/x86/mm/init_64.c
arch/x86/mm/memblock.c [deleted file]
arch/x86/mm/memtest.c
arch/x86/mm/numa.c
arch/x86/mm/numa_32.c
arch/x86/mm/numa_64.c
arch/x86/mm/numa_emulation.c
arch/x86/platform/efi/efi.c
arch/x86/xen/mmu.c
arch/x86/xen/setup.c
drivers/iommu/intel-iommu.c
include/linux/bootmem.h
include/linux/memblock.h
include/linux/mm.h
kernel/printk.c
mm/Kconfig
mm/memblock.c
mm/nobootmem.c
mm/page_alloc.c

index b22a83a91cb852b92d023529e3f1b3bf011dce38..261adbd3b55a58734eec39966cc74ca40b335c33 100644 (file)
@@ -127,45 +127,25 @@ static int __cpuinit fake_numa_create_new_node(unsigned long end_pfn,
 }
 
 /*
- * get_active_region_work_fn - A helper function for get_node_active_region
- *     Returns datax set to the start_pfn and end_pfn if they contain
- *     the initial value of datax->start_pfn between them
- * @start_pfn: start page(inclusive) of region to check
- * @end_pfn: end page(exclusive) of region to check
- * @datax: comes in with ->start_pfn set to value to search for and
- *     goes out with active range if it contains it
- * Returns 1 if search value is in range else 0
- */
-static int __init get_active_region_work_fn(unsigned long start_pfn,
-                                       unsigned long end_pfn, void *datax)
-{
-       struct node_active_region *data;
-       data = (struct node_active_region *)datax;
-
-       if (start_pfn <= data->start_pfn && end_pfn > data->start_pfn) {
-               data->start_pfn = start_pfn;
-               data->end_pfn = end_pfn;
-               return 1;
-       }
-       return 0;
-
-}
-
-/*
- * get_node_active_region - Return active region containing start_pfn
+ * get_node_active_region - Return active region containing pfn
  * Active range returned is empty if none found.
- * @start_pfn: The page to return the region for.
- * @node_ar: Returned set to the active region containing start_pfn
+ * @pfn: The page to return the region for
+ * @node_ar: Returned set to the active region containing @pfn
  */
-static void __init get_node_active_region(unsigned long start_pfn,
-                      struct node_active_region *node_ar)
+static void __init get_node_active_region(unsigned long pfn,
+                                         struct node_active_region *node_ar)
 {
-       int nid = early_pfn_to_nid(start_pfn);
+       unsigned long start_pfn, end_pfn;
+       int i, nid;
 
-       node_ar->nid = nid;
-       node_ar->start_pfn = start_pfn;
-       node_ar->end_pfn = start_pfn;
-       work_with_active_regions(nid, get_active_region_work_fn, node_ar);
+       for_each_mem_pfn_range(i, MAX_NUMNODES, &start_pfn, &end_pfn, &nid) {
+               if (pfn >= start_pfn && pfn < end_pfn) {
+                       node_ar->nid = nid;
+                       node_ar->start_pfn = start_pfn;
+                       node_ar->end_pfn = end_pfn;
+                       break;
+               }
+       }
 }
 
 static void map_cpu_to_node(int cpu, int node)
index 8e073d802139705aa9d6fc280c8e20f8d8f8e0f0..8584a25a9f0df742675fa8318746ee911a38aa91 100644 (file)
@@ -790,7 +790,7 @@ static int find_node(unsigned long addr)
        return -1;
 }
 
-u64 memblock_nid_range(u64 start, u64 end, int *nid)
+static u64 memblock_nid_range(u64 start, u64 end, int *nid)
 {
        *nid = find_node(start);
        start += PAGE_SIZE;
@@ -808,7 +808,7 @@ u64 memblock_nid_range(u64 start, u64 end, int *nid)
        return start;
 }
 #else
-u64 memblock_nid_range(u64 start, u64 end, int *nid)
+static u64 memblock_nid_range(u64 start, u64 end, int *nid)
 {
        *nid = 0;
        return end;
index cb9a1044a771be75563305f8909097a67cd21778..5d1514c263f84a26c591f4951ae3989c861d2eae 100644 (file)
@@ -26,6 +26,8 @@ config X86
        select HAVE_IOREMAP_PROT
        select HAVE_KPROBES
        select HAVE_MEMBLOCK
+       select HAVE_MEMBLOCK_NODE_MAP
+       select ARCH_DISCARD_MEMBLOCK
        select ARCH_WANT_OPTIONAL_GPIOLIB
        select ARCH_WANT_FRAME_POINTERS
        select HAVE_DMA_ATTRS
index 908b96957d88adf11694f6e83652b47d06d3b8f0..37782566af241dca3d6e0c8264935dc3e0a16258 100644 (file)
@@ -117,7 +117,7 @@ static inline void early_memtest(unsigned long start, unsigned long end)
 
 extern unsigned long e820_end_of_ram_pfn(void);
 extern unsigned long e820_end_of_low_ram_pfn(void);
-extern u64 early_reserve_e820(u64 startt, u64 sizet, u64 align);
+extern u64 early_reserve_e820(u64 sizet, u64 align);
 
 void memblock_x86_fill(void);
 void memblock_find_dma_reserve(void);
diff --git a/arch/x86/include/asm/memblock.h b/arch/x86/include/asm/memblock.h
deleted file mode 100644 (file)
index 0cd3800..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef _X86_MEMBLOCK_H
-#define _X86_MEMBLOCK_H
-
-#define ARCH_DISCARD_MEMBLOCK
-
-u64 memblock_x86_find_in_range_size(u64 start, u64 *sizep, u64 align);
-
-void memblock_x86_reserve_range(u64 start, u64 end, char *name);
-void memblock_x86_free_range(u64 start, u64 end);
-struct range;
-int __get_free_all_memory_range(struct range **range, int nodeid,
-                        unsigned long start_pfn, unsigned long end_pfn);
-int get_free_all_memory_range(struct range **rangep, int nodeid);
-
-void memblock_x86_register_active_regions(int nid, unsigned long start_pfn,
-                                        unsigned long last_pfn);
-u64 memblock_x86_hole_size(u64 start, u64 end);
-u64 memblock_x86_find_in_range_node(int nid, u64 start, u64 end, u64 size, u64 align);
-u64 memblock_x86_free_memory_in_range(u64 addr, u64 limit);
-u64 memblock_x86_memory_in_range(u64 addr, u64 limit);
-bool memblock_x86_check_reserved_size(u64 *addrp, u64 *sizep, u64 align);
-
-#endif
index 3d2661ca6542f3527fc24b3841e04de8d8437522..6e76c191a83572c07bf86c9bbc7c129c4bbc912c 100644 (file)
@@ -88,13 +88,13 @@ static u32 __init allocate_aperture(void)
         */
        addr = memblock_find_in_range(GART_MIN_ADDR, GART_MAX_ADDR,
                                      aper_size, aper_size);
-       if (addr == MEMBLOCK_ERROR || addr + aper_size > GART_MAX_ADDR) {
+       if (!addr || addr + aper_size > GART_MAX_ADDR) {
                printk(KERN_ERR
                        "Cannot allocate aperture memory hole (%lx,%uK)\n",
                                addr, aper_size>>10);
                return 0;
        }
-       memblock_x86_reserve_range(addr, addr + aper_size, "aperture64");
+       memblock_reserve(addr, aper_size);
        /*
         * Kmemleak should not scan this block as it may not be mapped via the
         * kernel direct mapping.
index 452932d3473077cabf505d00f96073319c93b983..5da1269e8ddcbcb55ff840d90dd912502fd582d5 100644 (file)
@@ -62,7 +62,8 @@ early_param("memory_corruption_check_size", set_corruption_check_size);
 
 void __init setup_bios_corruption_check(void)
 {
-       u64 addr = PAGE_SIZE;   /* assume first page is reserved anyway */
+       phys_addr_t start, end;
+       u64 i;
 
        if (memory_corruption_check == -1) {
                memory_corruption_check =
@@ -82,28 +83,23 @@ void __init setup_bios_corruption_check(void)
 
        corruption_check_size = round_up(corruption_check_size, PAGE_SIZE);
 
-       while (addr < corruption_check_size && num_scan_areas < MAX_SCAN_AREAS) {
-               u64 size;
-               addr = memblock_x86_find_in_range_size(addr, &size, PAGE_SIZE);
+       for_each_free_mem_range(i, MAX_NUMNODES, &start, &end, NULL) {
+               start = clamp_t(phys_addr_t, round_up(start, PAGE_SIZE),
+                               PAGE_SIZE, corruption_check_size);
+               end = clamp_t(phys_addr_t, round_down(end, PAGE_SIZE),
+                             PAGE_SIZE, corruption_check_size);
+               if (start >= end)
+                       continue;
 
-               if (addr == MEMBLOCK_ERROR)
-                       break;
-
-               if (addr >= corruption_check_size)
-                       break;
-
-               if ((addr + size) > corruption_check_size)
-                       size = corruption_check_size - addr;
-
-               memblock_x86_reserve_range(addr, addr + size, "SCAN RAM");
-               scan_areas[num_scan_areas].addr = addr;
-               scan_areas[num_scan_areas].size = size;
-               num_scan_areas++;
+               memblock_reserve(start, end - start);
+               scan_areas[num_scan_areas].addr = start;
+               scan_areas[num_scan_areas].size = end - start;
 
                /* Assume we've already mapped this early memory */
-               memset(__va(addr), 0, size);
+               memset(__va(start), 0, end - start);
 
-               addr += size;
+               if (++num_scan_areas >= MAX_SCAN_AREAS)
+                       break;
        }
 
        if (num_scan_areas)
index 303a0e48f076feb3feb522d4052ac4b958995d42..056e65d5012bc9edbbdc57fb3ced81b5148d79e2 100644 (file)
@@ -738,35 +738,17 @@ core_initcall(e820_mark_nvs_memory);
 /*
  * pre allocated 4k and reserved it in memblock and e820_saved
  */
-u64 __init early_reserve_e820(u64 startt, u64 sizet, u64 align)
+u64 __init early_reserve_e820(u64 size, u64 align)
 {
-       u64 size = 0;
        u64 addr;
-       u64 start;
 
-       for (start = startt; ; start += size) {
-               start = memblock_x86_find_in_range_size(start, &size, align);
-               if (start == MEMBLOCK_ERROR)
-                       return 0;
-               if (size >= sizet)
-                       break;
+       addr = __memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ACCESSIBLE);
+       if (addr) {
+               e820_update_range_saved(addr, size, E820_RAM, E820_RESERVED);
+               printk(KERN_INFO "update e820_saved for early_reserve_e820\n");
+               update_e820_saved();
        }
 
-#ifdef CONFIG_X86_32
-       if (start >= MAXMEM)
-               return 0;
-       if (start + size > MAXMEM)
-               size = MAXMEM - start;
-#endif
-
-       addr = round_down(start + size - sizet, align);
-       if (addr < start)
-               return 0;
-       memblock_x86_reserve_range(addr, addr + sizet, "new next");
-       e820_update_range_saved(addr, sizet, E820_RAM, E820_RESERVED);
-       printk(KERN_INFO "update e820_saved for early_reserve_e820\n");
-       update_e820_saved();
-
        return addr;
 }
 
@@ -1112,15 +1094,30 @@ void __init memblock_x86_fill(void)
 void __init memblock_find_dma_reserve(void)
 {
 #ifdef CONFIG_X86_64
-       u64 free_size_pfn;
-       u64 mem_size_pfn;
+       u64 nr_pages = 0, nr_free_pages = 0;
+       unsigned long start_pfn, end_pfn;
+       phys_addr_t start, end;
+       int i;
+       u64 u;
+
        /*
         * need to find out used area below MAX_DMA_PFN
         * need to use memblock to get free size in [0, MAX_DMA_PFN]
         * at first, and assume boot_mem will not take below MAX_DMA_PFN
         */
-       mem_size_pfn = memblock_x86_memory_in_range(0, MAX_DMA_PFN << PAGE_SHIFT) >> PAGE_SHIFT;
-       free_size_pfn = memblock_x86_free_memory_in_range(0, MAX_DMA_PFN << PAGE_SHIFT) >> PAGE_SHIFT;
-       set_dma_reserve(mem_size_pfn - free_size_pfn);
+       for_each_mem_pfn_range(i, MAX_NUMNODES, &start_pfn, &end_pfn, NULL) {
+               start_pfn = min_t(unsigned long, start_pfn, MAX_DMA_PFN);
+               end_pfn = min_t(unsigned long, end_pfn, MAX_DMA_PFN);
+               nr_pages += end_pfn - start_pfn;
+       }
+
+       for_each_free_mem_range(u, MAX_NUMNODES, &start, &end, NULL) {
+               start_pfn = min_t(unsigned long, PFN_UP(start), MAX_DMA_PFN);
+               end_pfn = min_t(unsigned long, PFN_DOWN(end), MAX_DMA_PFN);
+               if (start_pfn < end_pfn)
+                       nr_free_pages += end_pfn - start_pfn;
+       }
+
+       set_dma_reserve(nr_pages - nr_free_pages);
 #endif
 }
index af0699ba48cfb7efebb03bc5bc57af750b73f9ef..48d9d4ea1020fadf3732f7cac6cc8c78f6310918 100644 (file)
@@ -52,5 +52,5 @@ void __init reserve_ebda_region(void)
                lowmem = 0x9f000;
 
        /* reserve all memory between lowmem and the 1MB mark */
-       memblock_x86_reserve_range(lowmem, 0x100000, "* BIOS reserved");
+       memblock_reserve(lowmem, 0x100000 - lowmem);
 }
index 3bb08509a7a151725182e5cf64d7dd636958e239..be9282bcda72ae257e64202edac6cafba4bcb308 100644 (file)
@@ -33,7 +33,8 @@ void __init i386_start_kernel(void)
 {
        memblock_init();
 
-       memblock_x86_reserve_range(__pa_symbol(&_text), __pa_symbol(&__bss_stop), "TEXT DATA BSS");
+       memblock_reserve(__pa_symbol(&_text),
+                        __pa_symbol(&__bss_stop) - __pa_symbol(&_text));
 
 #ifdef CONFIG_BLK_DEV_INITRD
        /* Reserve INITRD */
@@ -42,7 +43,7 @@ void __init i386_start_kernel(void)
                u64 ramdisk_image = boot_params.hdr.ramdisk_image;
                u64 ramdisk_size  = boot_params.hdr.ramdisk_size;
                u64 ramdisk_end   = PAGE_ALIGN(ramdisk_image + ramdisk_size);
-               memblock_x86_reserve_range(ramdisk_image, ramdisk_end, "RAMDISK");
+               memblock_reserve(ramdisk_image, ramdisk_end - ramdisk_image);
        }
 #endif
 
index 5655c2272adb86244f1927127a40c705c5a4d447..fd25b11549b896fefc9d1e3b2cd149056bf9fe3a 100644 (file)
@@ -100,7 +100,8 @@ void __init x86_64_start_reservations(char *real_mode_data)
 
        memblock_init();
 
-       memblock_x86_reserve_range(__pa_symbol(&_text), __pa_symbol(&__bss_stop), "TEXT DATA BSS");
+       memblock_reserve(__pa_symbol(&_text),
+                        __pa_symbol(&__bss_stop) - __pa_symbol(&_text));
 
 #ifdef CONFIG_BLK_DEV_INITRD
        /* Reserve INITRD */
@@ -109,7 +110,7 @@ void __init x86_64_start_reservations(char *real_mode_data)
                unsigned long ramdisk_image = boot_params.hdr.ramdisk_image;
                unsigned long ramdisk_size  = boot_params.hdr.ramdisk_size;
                unsigned long ramdisk_end   = PAGE_ALIGN(ramdisk_image + ramdisk_size);
-               memblock_x86_reserve_range(ramdisk_image, ramdisk_end, "RAMDISK");
+               memblock_reserve(ramdisk_image, ramdisk_end - ramdisk_image);
        }
 #endif
 
index 9103b89c145a534215824a9b2a7d80aa9e112527..a6b79c16ec78cfaef1bd48c77ac701b37ee88523 100644 (file)
@@ -564,9 +564,7 @@ void __init default_get_smp_config(unsigned int early)
 
 static void __init smp_reserve_memory(struct mpf_intel *mpf)
 {
-       unsigned long size = get_mpc_size(mpf->physptr);
-
-       memblock_x86_reserve_range(mpf->physptr, mpf->physptr+size, "* MP-table mpc");
+       memblock_reserve(mpf->physptr, get_mpc_size(mpf->physptr));
 }
 
 static int __init smp_scan_config(unsigned long base, unsigned long length)
@@ -595,7 +593,7 @@ static int __init smp_scan_config(unsigned long base, unsigned long length)
                               mpf, (u64)virt_to_phys(mpf));
 
                        mem = virt_to_phys(mpf);
-                       memblock_x86_reserve_range(mem, mem + sizeof(*mpf), "* MP-table mpf");
+                       memblock_reserve(mem, sizeof(*mpf));
                        if (mpf->physptr)
                                smp_reserve_memory(mpf);
 
@@ -836,10 +834,8 @@ early_param("alloc_mptable", parse_alloc_mptable_opt);
 
 void __init early_reserve_e820_mpc_new(void)
 {
-       if (enable_update_mptable && alloc_mptable) {
-               u64 startt = 0;
-               mpc_new_phys = early_reserve_e820(startt, mpc_new_length, 4);
-       }
+       if (enable_update_mptable && alloc_mptable)
+               mpc_new_phys = early_reserve_e820(mpc_new_length, 4);
 }
 
 static int __init update_mp_table(void)
index cf0ef986cb6dff51348c17c691491f6f48c61a60..d05444ac2aea59378d1aac95e53c44f0a7a19a4e 100644 (file)
@@ -306,7 +306,8 @@ static void __init cleanup_highmap(void)
 static void __init reserve_brk(void)
 {
        if (_brk_end > _brk_start)
-               memblock_x86_reserve_range(__pa(_brk_start), __pa(_brk_end), "BRK");
+               memblock_reserve(__pa(_brk_start),
+                                __pa(_brk_end) - __pa(_brk_start));
 
        /* Mark brk area as locked down and no longer taking any
           new allocations */
@@ -331,13 +332,13 @@ static void __init relocate_initrd(void)
        ramdisk_here = memblock_find_in_range(0, end_of_lowmem, area_size,
                                         PAGE_SIZE);
 
-       if (ramdisk_here == MEMBLOCK_ERROR)
+       if (!ramdisk_here)
                panic("Cannot find place for new RAMDISK of size %lld\n",
                         ramdisk_size);
 
        /* Note: this includes all the lowmem currently occupied by
           the initrd, we rely on that fact to keep the data intact. */
-       memblock_x86_reserve_range(ramdisk_here, ramdisk_here + area_size, "NEW RAMDISK");
+       memblock_reserve(ramdisk_here, area_size);
        initrd_start = ramdisk_here + PAGE_OFFSET;
        initrd_end   = initrd_start + ramdisk_size;
        printk(KERN_INFO "Allocated new RAMDISK: %08llx - %08llx\n",
@@ -393,7 +394,7 @@ static void __init reserve_initrd(void)
        initrd_start = 0;
 
        if (ramdisk_size >= (end_of_lowmem>>1)) {
-               memblock_x86_free_range(ramdisk_image, ramdisk_end);
+               memblock_free(ramdisk_image, ramdisk_end - ramdisk_image);
                printk(KERN_ERR "initrd too large to handle, "
                       "disabling initrd\n");
                return;
@@ -416,7 +417,7 @@ static void __init reserve_initrd(void)
 
        relocate_initrd();
 
-       memblock_x86_free_range(ramdisk_image, ramdisk_end);
+       memblock_free(ramdisk_image, ramdisk_end - ramdisk_image);
 }
 #else
 static void __init reserve_initrd(void)
@@ -490,15 +491,13 @@ static void __init memblock_x86_reserve_range_setup_data(void)
 {
        struct setup_data *data;
        u64 pa_data;
-       char buf[32];
 
        if (boot_params.hdr.version < 0x0209)
                return;
        pa_data = boot_params.hdr.setup_data;
        while (pa_data) {
                data = early_memremap(pa_data, sizeof(*data));
-               sprintf(buf, "setup data %x", data->type);
-               memblock_x86_reserve_range(pa_data, pa_data+sizeof(*data)+data->len, buf);
+               memblock_reserve(pa_data, sizeof(*data) + data->len);
                pa_data = data->next;
                early_iounmap(data, sizeof(*data));
        }
@@ -554,7 +553,7 @@ static void __init reserve_crashkernel(void)
                crash_base = memblock_find_in_range(alignment,
                               CRASH_KERNEL_ADDR_MAX, crash_size, alignment);
 
-               if (crash_base == MEMBLOCK_ERROR) {
+               if (!crash_base) {
                        pr_info("crashkernel reservation failed - No suitable area found.\n");
                        return;
                }
@@ -568,7 +567,7 @@ static void __init reserve_crashkernel(void)
                        return;
                }
        }
-       memblock_x86_reserve_range(crash_base, crash_base + crash_size, "CRASH KERNEL");
+       memblock_reserve(crash_base, crash_size);
 
        printk(KERN_INFO "Reserving %ldMB of memory at %ldMB "
                        "for crashkernel (System RAM: %ldMB)\n",
@@ -626,7 +625,7 @@ static __init void reserve_ibft_region(void)
        addr = find_ibft_region(&size);
 
        if (size)
-               memblock_x86_reserve_range(addr, addr + size, "* ibft");
+               memblock_reserve(addr, size);
 }
 
 static unsigned reserve_low = CONFIG_X86_RESERVE_LOW << 10;
index a91ae7709b49ea17628aff1fc253899b4c9e4efa..a73b61055ad6358adf8e93c107680d66b5f6b2e3 100644 (file)
@@ -14,11 +14,11 @@ void __init setup_trampolines(void)
 
        /* Has to be in very low memory so we can execute real-mode AP code. */
        mem = memblock_find_in_range(0, 1<<20, size, PAGE_SIZE);
-       if (mem == MEMBLOCK_ERROR)
+       if (!mem)
                panic("Cannot allocate trampoline\n");
 
        x86_trampoline_base = __va(mem);
-       memblock_x86_reserve_range(mem, mem + size, "TRAMPOLINE");
+       memblock_reserve(mem, size);
 
        printk(KERN_DEBUG "Base memory trampoline at [%p] %llx size %zu\n",
               x86_trampoline_base, (unsigned long long)mem, size);
index 3d11327c9ab4630cd0aa687dcf7118bc3efb4d25..23d8e5fecf76ba654c3cc2fd8f9b3d3efdfa193d 100644 (file)
@@ -27,6 +27,4 @@ obj-$(CONFIG_AMD_NUMA)                += amdtopology.o
 obj-$(CONFIG_ACPI_NUMA)                += srat.o
 obj-$(CONFIG_NUMA_EMU)         += numa_emulation.o
 
-obj-$(CONFIG_HAVE_MEMBLOCK)            += memblock.o
-
 obj-$(CONFIG_MEMTEST)          += memtest.o
index 87488b93a65ce19695947bc6ca7f58f948e0f24b..a298914058f9c98ebeaba6a84725f7310a1e6f5d 100644 (file)
@@ -67,7 +67,7 @@ static void __init find_early_table_space(unsigned long end, int use_pse,
        good_end = max_pfn_mapped << PAGE_SHIFT;
 
        base = memblock_find_in_range(start, good_end, tables, PAGE_SIZE);
-       if (base == MEMBLOCK_ERROR)
+       if (!base)
                panic("Cannot find space for the kernel page tables");
 
        pgt_buf_start = base >> PAGE_SHIFT;
@@ -80,7 +80,7 @@ static void __init find_early_table_space(unsigned long end, int use_pse,
 
 void __init native_pagetable_reserve(u64 start, u64 end)
 {
-       memblock_x86_reserve_range(start, end, "PGTABLE");
+       memblock_reserve(start, end - start);
 }
 
 struct map_range {
@@ -279,8 +279,8 @@ unsigned long __init_refok init_memory_mapping(unsigned long start,
         * pgt_buf_end) and free the other ones (pgt_buf_end - pgt_buf_top)
         * so that they can be reused for other purposes.
         *
-        * On native it just means calling memblock_x86_reserve_range, on Xen it
-        * also means marking RW the pagetable pages that we allocated before
+        * On native it just means calling memblock_reserve, on Xen it also
+        * means marking RW the pagetable pages that we allocated before
         * but that haven't been used.
         *
         * In fact on xen we mark RO the whole range pgt_buf_start -
index 29f7c6d981790cea29114c1b20d7cb54904a702e..0c1da394a6347d3b26858f3e16fe54fa785812ad 100644 (file)
@@ -427,23 +427,17 @@ static void __init add_one_highpage_init(struct page *page)
 void __init add_highpages_with_active_regions(int nid,
                         unsigned long start_pfn, unsigned long end_pfn)
 {
-       struct range *range;
-       int nr_range;
-       int i;
-
-       nr_range = __get_free_all_memory_range(&range, nid, start_pfn, end_pfn);
-
-       for (i = 0; i < nr_range; i++) {
-               struct page *page;
-               int node_pfn;
-
-               for (node_pfn = range[i].start; node_pfn < range[i].end;
-                    node_pfn++) {
-                       if (!pfn_valid(node_pfn))
-                               continue;
-                       page = pfn_to_page(node_pfn);
-                       add_one_highpage_init(page);
-               }
+       phys_addr_t start, end;
+       u64 i;
+
+       for_each_free_mem_range(i, nid, &start, &end, NULL) {
+               unsigned long pfn = clamp_t(unsigned long, PFN_UP(start),
+                                           start_pfn, end_pfn);
+               unsigned long e_pfn = clamp_t(unsigned long, PFN_DOWN(end),
+                                             start_pfn, end_pfn);
+               for ( ; pfn < e_pfn; pfn++)
+                       if (pfn_valid(pfn))
+                               add_one_highpage_init(pfn_to_page(pfn));
        }
 }
 #else
@@ -650,18 +644,18 @@ void __init initmem_init(void)
        highstart_pfn = highend_pfn = max_pfn;
        if (max_pfn > max_low_pfn)
                highstart_pfn = max_low_pfn;
-       memblock_x86_register_active_regions(0, 0, highend_pfn);
-       sparse_memory_present_with_active_regions(0);
        printk(KERN_NOTICE "%ldMB HIGHMEM available.\n",
                pages_to_mb(highend_pfn - highstart_pfn));
        num_physpages = highend_pfn;
        high_memory = (void *) __va(highstart_pfn * PAGE_SIZE - 1) + 1;
 #else
-       memblock_x86_register_active_regions(0, 0, max_low_pfn);
-       sparse_memory_present_with_active_regions(0);
        num_physpages = max_low_pfn;
        high_memory = (void *) __va(max_low_pfn * PAGE_SIZE - 1) + 1;
 #endif
+
+       memblock_set_node(0, (phys_addr_t)ULLONG_MAX, 0);
+       sparse_memory_present_with_active_regions(0);
+
 #ifdef CONFIG_FLATMEM
        max_mapnr = num_physpages;
 #endif
index bbaaa005bf0e865a9c3fc84a7ff1ed9854b80888..a8a56ce3a962ad7c1c46285830dd8cb994695231 100644 (file)
@@ -608,7 +608,7 @@ kernel_physical_mapping_init(unsigned long start,
 #ifndef CONFIG_NUMA
 void __init initmem_init(void)
 {
-       memblock_x86_register_active_regions(0, 0, max_pfn);
+       memblock_set_node(0, (phys_addr_t)ULLONG_MAX, 0);
 }
 #endif
 
diff --git a/arch/x86/mm/memblock.c b/arch/x86/mm/memblock.c
deleted file mode 100644 (file)
index 992da5e..0000000
+++ /dev/null
@@ -1,348 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/bitops.h>
-#include <linux/memblock.h>
-#include <linux/bootmem.h>
-#include <linux/mm.h>
-#include <linux/range.h>
-
-/* Check for already reserved areas */
-bool __init memblock_x86_check_reserved_size(u64 *addrp, u64 *sizep, u64 align)
-{
-       struct memblock_region *r;
-       u64 addr = *addrp, last;
-       u64 size = *sizep;
-       bool changed = false;
-
-again:
-       last = addr + size;
-       for_each_memblock(reserved, r) {
-               if (last > r->base && addr < r->base) {
-                       size = r->base - addr;
-                       changed = true;
-                       goto again;
-               }
-               if (last > (r->base + r->size) && addr < (r->base + r->size)) {
-                       addr = round_up(r->base + r->size, align);
-                       size = last - addr;
-                       changed = true;
-                       goto again;
-               }
-               if (last <= (r->base + r->size) && addr >= r->base) {
-                       *sizep = 0;
-                       return false;
-               }
-       }
-       if (changed) {
-               *addrp = addr;
-               *sizep = size;
-       }
-       return changed;
-}
-
-/*
- * Find next free range after start, and size is returned in *sizep
- */
-u64 __init memblock_x86_find_in_range_size(u64 start, u64 *sizep, u64 align)
-{
-       struct memblock_region *r;
-
-       for_each_memblock(memory, r) {
-               u64 ei_start = r->base;
-               u64 ei_last = ei_start + r->size;
-               u64 addr;
-
-               addr = round_up(ei_start, align);
-               if (addr < start)
-                       addr = round_up(start, align);
-               if (addr >= ei_last)
-                       continue;
-               *sizep = ei_last - addr;
-               while (memblock_x86_check_reserved_size(&addr, sizep, align))
-                       ;
-
-               if (*sizep)
-                       return addr;
-       }
-
-       return MEMBLOCK_ERROR;
-}
-
-static __init struct range *find_range_array(int count)
-{
-       u64 end, size, mem;
-       struct range *range;
-
-       size = sizeof(struct range) * count;
-       end = memblock.current_limit;
-
-       mem = memblock_find_in_range(0, end, size, sizeof(struct range));
-       if (mem == MEMBLOCK_ERROR)
-               panic("can not find more space for range array");
-
-       /*
-        * This range is tempoaray, so don't reserve it, it will not be
-        * overlapped because We will not alloccate new buffer before
-        * We discard this one
-        */
-       range = __va(mem);
-       memset(range, 0, size);
-
-       return range;
-}
-
-static void __init memblock_x86_subtract_reserved(struct range *range, int az)
-{
-       u64 final_start, final_end;
-       struct memblock_region *r;
-
-       /* Take out region array itself at first*/
-       memblock_free_reserved_regions();
-
-       memblock_dbg("Subtract (%ld early reservations)\n", memblock.reserved.cnt);
-
-       for_each_memblock(reserved, r) {
-               memblock_dbg("  [%010llx-%010llx]\n", (u64)r->base, (u64)r->base + r->size - 1);
-               final_start = PFN_DOWN(r->base);
-               final_end = PFN_UP(r->base + r->size);
-               if (final_start >= final_end)
-                       continue;
-               subtract_range(range, az, final_start, final_end);
-       }
-
-       /* Put region array back ? */
-       memblock_reserve_reserved_regions();
-}
-
-struct count_data {
-       int nr;
-};
-
-static int __init count_work_fn(unsigned long start_pfn,
-                               unsigned long end_pfn, void *datax)
-{
-       struct count_data *data = datax;
-
-       data->nr++;
-
-       return 0;
-}
-
-static int __init count_early_node_map(int nodeid)
-{
-       struct count_data data;
-
-       data.nr = 0;
-       work_with_active_regions(nodeid, count_work_fn, &data);
-
-       return data.nr;
-}
-
-int __init __get_free_all_memory_range(struct range **rangep, int nodeid,
-                        unsigned long start_pfn, unsigned long end_pfn)
-{
-       int count;
-       struct range *range;
-       int nr_range;
-
-       count = (memblock.reserved.cnt + count_early_node_map(nodeid)) * 2;
-
-       range = find_range_array(count);
-       nr_range = 0;
-
-       /*
-        * Use early_node_map[] and memblock.reserved.region to get range array
-        * at first
-        */
-       nr_range = add_from_early_node_map(range, count, nr_range, nodeid);
-       subtract_range(range, count, 0, start_pfn);
-       subtract_range(range, count, end_pfn, -1ULL);
-
-       memblock_x86_subtract_reserved(range, count);
-       nr_range = clean_sort_range(range, count);
-
-       *rangep = range;
-       return nr_range;
-}
-
-int __init get_free_all_memory_range(struct range **rangep, int nodeid)
-{
-       unsigned long end_pfn = -1UL;
-
-#ifdef CONFIG_X86_32
-       end_pfn = max_low_pfn;
-#endif
-       return __get_free_all_memory_range(rangep, nodeid, 0, end_pfn);
-}
-
-static u64 __init __memblock_x86_memory_in_range(u64 addr, u64 limit, bool get_free)
-{
-       int i, count;
-       struct range *range;
-       int nr_range;
-       u64 final_start, final_end;
-       u64 free_size;
-       struct memblock_region *r;
-
-       count = (memblock.reserved.cnt + memblock.memory.cnt) * 2;
-
-       range = find_range_array(count);
-       nr_range = 0;
-
-       addr = PFN_UP(addr);
-       limit = PFN_DOWN(limit);
-
-       for_each_memblock(memory, r) {
-               final_start = PFN_UP(r->base);
-               final_end = PFN_DOWN(r->base + r->size);
-               if (final_start >= final_end)
-                       continue;
-               if (final_start >= limit || final_end <= addr)
-                       continue;
-
-               nr_range = add_range(range, count, nr_range, final_start, final_end);
-       }
-       subtract_range(range, count, 0, addr);
-       subtract_range(range, count, limit, -1ULL);
-
-       /* Subtract memblock.reserved.region in range ? */
-       if (!get_free)
-               goto sort_and_count_them;
-       for_each_memblock(reserved, r) {
-               final_start = PFN_DOWN(r->base);
-               final_end = PFN_UP(r->base + r->size);
-               if (final_start >= final_end)
-                       continue;
-               if (final_start >= limit || final_end <= addr)
-                       continue;
-
-               subtract_range(range, count, final_start, final_end);
-       }
-
-sort_and_count_them:
-       nr_range = clean_sort_range(range, count);
-
-       free_size = 0;
-       for (i = 0; i < nr_range; i++)
-               free_size += range[i].end - range[i].start;
-
-       return free_size << PAGE_SHIFT;
-}
-
-u64 __init memblock_x86_free_memory_in_range(u64 addr, u64 limit)
-{
-       return __memblock_x86_memory_in_range(addr, limit, true);
-}
-
-u64 __init memblock_x86_memory_in_range(u64 addr, u64 limit)
-{
-       return __memblock_x86_memory_in_range(addr, limit, false);
-}
-
-void __init memblock_x86_reserve_range(u64 start, u64 end, char *name)
-{
-       if (start == end)
-               return;
-
-       if (WARN_ONCE(start > end, "memblock_x86_reserve_range: wrong range [%#llx, %#llx)\n", start, end))
-               return;
-
-       memblock_dbg("    memblock_x86_reserve_range: [%#010llx-%#010llx] %16s\n", start, end - 1, name);
-
-       memblock_reserve(start, end - start);
-}
-
-void __init memblock_x86_free_range(u64 start, u64 end)
-{
-       if (start == end)
-               return;
-
-       if (WARN_ONCE(start > end, "memblock_x86_free_range: wrong range [%#llx, %#llx)\n", start, end))
-               return;
-
-       memblock_dbg("       memblock_x86_free_range: [%#010llx-%#010llx]\n", start, end - 1);
-
-       memblock_free(start, end - start);
-}
-
-/*
- * Need to call this function after memblock_x86_register_active_regions,
- * so early_node_map[] is filled already.
- */
-u64 __init memblock_x86_find_in_range_node(int nid, u64 start, u64 end, u64 size, u64 align)
-{
-       u64 addr;
-       addr = find_memory_core_early(nid, size, align, start, end);
-       if (addr != MEMBLOCK_ERROR)
-               return addr;
-
-       /* Fallback, should already have start end within node range */
-       return memblock_find_in_range(start, end, size, align);
-}
-
-/*
- * Finds an active region in the address range from start_pfn to last_pfn and
- * returns its range in ei_startpfn and ei_endpfn for the memblock entry.
- */
-static int __init memblock_x86_find_active_region(const struct memblock_region *ei,
-                                 unsigned long start_pfn,
-                                 unsigned long last_pfn,
-                                 unsigned long *ei_startpfn,
-                                 unsigned long *ei_endpfn)
-{
-       u64 align = PAGE_SIZE;
-
-       *ei_startpfn = round_up(ei->base, align) >> PAGE_SHIFT;
-       *ei_endpfn = round_down(ei->base + ei->size, align) >> PAGE_SHIFT;
-
-       /* Skip map entries smaller than a page */
-       if (*ei_startpfn >= *ei_endpfn)
-               return 0;
-
-       /* Skip if map is outside the node */
-       if (*ei_endpfn <= start_pfn || *ei_startpfn >= last_pfn)
-               return 0;
-
-       /* Check for overlaps */
-       if (*ei_startpfn < start_pfn)
-               *ei_startpfn = start_pfn;
-       if (*ei_endpfn > last_pfn)
-               *ei_endpfn = last_pfn;
-
-       return 1;
-}
-
-/* Walk the memblock.memory map and register active regions within a node */
-void __init memblock_x86_register_active_regions(int nid, unsigned long start_pfn,
-                                        unsigned long last_pfn)
-{
-       unsigned long ei_startpfn;
-       unsigned long ei_endpfn;
-       struct memblock_region *r;
-
-       for_each_memblock(memory, r)
-               if (memblock_x86_find_active_region(r, start_pfn, last_pfn,
-                                          &ei_startpfn, &ei_endpfn))
-                       add_active_range(nid, ei_startpfn, ei_endpfn);
-}
-
-/*
- * Find the hole size (in bytes) in the memory range.
- * @start: starting address of the memory range to scan
- * @end: ending address of the memory range to scan
- */
-u64 __init memblock_x86_hole_size(u64 start, u64 end)
-{
-       unsigned long start_pfn = start >> PAGE_SHIFT;
-       unsigned long last_pfn = end >> PAGE_SHIFT;
-       unsigned long ei_startpfn, ei_endpfn, ram = 0;
-       struct memblock_region *r;
-
-       for_each_memblock(memory, r)
-               if (memblock_x86_find_active_region(r, start_pfn, last_pfn,
-                                          &ei_startpfn, &ei_endpfn))
-                       ram += ei_endpfn - ei_startpfn;
-
-       return end - start - ((u64)ram << PAGE_SHIFT);
-}
index 92faf3a1c53e29fbf82767356fdca0508f9b693c..c80b9fb95734fd07430fde185794e4182ec7a6e8 100644 (file)
@@ -34,7 +34,7 @@ static void __init reserve_bad_mem(u64 pattern, u64 start_bad, u64 end_bad)
               (unsigned long long) pattern,
               (unsigned long long) start_bad,
               (unsigned long long) end_bad);
-       memblock_x86_reserve_range(start_bad, end_bad, "BAD RAM");
+       memblock_reserve(start_bad, end_bad - start_bad);
 }
 
 static void __init memtest(u64 pattern, u64 start_phys, u64 size)
@@ -70,24 +70,19 @@ static void __init memtest(u64 pattern, u64 start_phys, u64 size)
 
 static void __init do_one_pass(u64 pattern, u64 start, u64 end)
 {
-       u64 size = 0;
-
-       while (start < end) {
-               start = memblock_x86_find_in_range_size(start, &size, 1);
-
-               /* done ? */
-               if (start >= end)
-                       break;
-               if (start + size > end)
-                       size = end - start;
-
-               printk(KERN_INFO "  %010llx - %010llx pattern %016llx\n",
-                      (unsigned long long) start,
-                      (unsigned long long) start + size,
-                      (unsigned long long) cpu_to_be64(pattern));
-               memtest(pattern, start, size);
-
-               start += size;
+       u64 i;
+       phys_addr_t this_start, this_end;
+
+       for_each_free_mem_range(i, MAX_NUMNODES, &this_start, &this_end, NULL) {
+               this_start = clamp_t(phys_addr_t, this_start, start, end);
+               this_end = clamp_t(phys_addr_t, this_end, start, end);
+               if (this_start < this_end) {
+                       printk(KERN_INFO "  %010llx - %010llx pattern %016llx\n",
+                              (unsigned long long)this_start,
+                              (unsigned long long)this_end,
+                              (unsigned long long)cpu_to_be64(pattern));
+                       memtest(pattern, this_start, this_end - this_start);
+               }
        }
 }
 
index fbeaaf416610d29ef824db47bd6a3f19756de188..496f494593bf6cfa7f7069c58af5c153f6af1965 100644 (file)
@@ -192,8 +192,6 @@ int __init numa_add_memblk(int nid, u64 start, u64 end)
 /* Initialize NODE_DATA for a node on the local memory */
 static void __init setup_node_data(int nid, u64 start, u64 end)
 {
-       const u64 nd_low = PFN_PHYS(MAX_DMA_PFN);
-       const u64 nd_high = PFN_PHYS(max_pfn_mapped);
        const size_t nd_size = roundup(sizeof(pg_data_t), PAGE_SIZE);
        bool remapped = false;
        u64 nd_pa;
@@ -224,17 +222,12 @@ static void __init setup_node_data(int nid, u64 start, u64 end)
                nd_pa = __pa(nd);
                remapped = true;
        } else {
-               nd_pa = memblock_x86_find_in_range_node(nid, nd_low, nd_high,
-                                               nd_size, SMP_CACHE_BYTES);
-               if (nd_pa == MEMBLOCK_ERROR)
-                       nd_pa = memblock_find_in_range(nd_low, nd_high,
-                                               nd_size, SMP_CACHE_BYTES);
-               if (nd_pa == MEMBLOCK_ERROR) {
+               nd_pa = memblock_alloc_nid(nd_size, SMP_CACHE_BYTES, nid);
+               if (!nd_pa) {
                        pr_err("Cannot find %zu bytes in node %d\n",
                               nd_size, nid);
                        return;
                }
-               memblock_x86_reserve_range(nd_pa, nd_pa + nd_size, "NODE_DATA");
                nd = __va(nd_pa);
        }
 
@@ -371,8 +364,7 @@ void __init numa_reset_distance(void)
 
        /* numa_distance could be 1LU marking allocation failure, test cnt */
        if (numa_distance_cnt)
-               memblock_x86_free_range(__pa(numa_distance),
-                                       __pa(numa_distance) + size);
+               memblock_free(__pa(numa_distance), size);
        numa_distance_cnt = 0;
        numa_distance = NULL;   /* enable table creation */
 }
@@ -395,13 +387,13 @@ static int __init numa_alloc_distance(void)
 
        phys = memblock_find_in_range(0, PFN_PHYS(max_pfn_mapped),
                                      size, PAGE_SIZE);
-       if (phys == MEMBLOCK_ERROR) {
+       if (!phys) {
                pr_warning("NUMA: Warning: can't allocate distance table!\n");
                /* don't retry until explicitly reset */
                numa_distance = (void *)1LU;
                return -ENOMEM;
        }
-       memblock_x86_reserve_range(phys, phys + size, "NUMA DIST");
+       memblock_reserve(phys, size);
 
        numa_distance = __va(phys);
        numa_distance_cnt = cnt;
@@ -482,8 +474,8 @@ static bool __init numa_meminfo_cover_memory(const struct numa_meminfo *mi)
                        numaram = 0;
        }
 
-       e820ram = max_pfn - (memblock_x86_hole_size(0,
-                                       PFN_PHYS(max_pfn)) >> PAGE_SHIFT);
+       e820ram = max_pfn - absent_pages_in_range(0, max_pfn);
+
        /* We seem to lose 3 pages somewhere. Allow 1M of slack. */
        if ((s64)(e820ram - numaram) >= (1 << (20 - PAGE_SHIFT))) {
                printk(KERN_ERR "NUMA: nodes only cover %LuMB of your %LuMB e820 RAM. Not used.\n",
@@ -505,13 +497,10 @@ static int __init numa_register_memblks(struct numa_meminfo *mi)
        if (WARN_ON(nodes_empty(node_possible_map)))
                return -EINVAL;
 
-       for (i = 0; i < mi->nr_blks; i++)
-               memblock_x86_register_active_regions(mi->blk[i].nid,
-                                       mi->blk[i].start >> PAGE_SHIFT,
-                                       mi->blk[i].end >> PAGE_SHIFT);
-
-       /* for out of order entries */
-       sort_node_map();
+       for (i = 0; i < mi->nr_blks; i++) {
+               struct numa_memblk *mb = &mi->blk[i];
+               memblock_set_node(mb->start, mb->end - mb->start, mb->nid);
+       }
 
        /*
         * If sections array is gonna be used for pfn -> nid mapping, check
@@ -545,6 +534,8 @@ static int __init numa_register_memblks(struct numa_meminfo *mi)
                        setup_node_data(nid, start, end);
        }
 
+       /* Dump memblock with node info and return. */
+       memblock_dump_all();
        return 0;
 }
 
@@ -582,7 +573,7 @@ static int __init numa_init(int (*init_func)(void))
        nodes_clear(node_possible_map);
        nodes_clear(node_online_map);
        memset(&numa_meminfo, 0, sizeof(numa_meminfo));
-       remove_all_active_ranges();
+       WARN_ON(memblock_set_node(0, ULLONG_MAX, MAX_NUMNODES));
        numa_reset_distance();
 
        ret = init_func();
index 3adebe7e536ace0a7c729c87fa04e8617e3f8a72..534255a36b6ba28fa358f01540dd180e47ae0b30 100644 (file)
@@ -199,23 +199,23 @@ void __init init_alloc_remap(int nid, u64 start, u64 end)
 
        /* allocate node memory and the lowmem remap area */
        node_pa = memblock_find_in_range(start, end, size, LARGE_PAGE_BYTES);
-       if (node_pa == MEMBLOCK_ERROR) {
+       if (!node_pa) {
                pr_warning("remap_alloc: failed to allocate %lu bytes for node %d\n",
                           size, nid);
                return;
        }
-       memblock_x86_reserve_range(node_pa, node_pa + size, "KVA RAM");
+       memblock_reserve(node_pa, size);
 
        remap_pa = memblock_find_in_range(min_low_pfn << PAGE_SHIFT,
                                          max_low_pfn << PAGE_SHIFT,
                                          size, LARGE_PAGE_BYTES);
-       if (remap_pa == MEMBLOCK_ERROR) {
+       if (!remap_pa) {
                pr_warning("remap_alloc: failed to allocate %lu bytes remap area for node %d\n",
                           size, nid);
-               memblock_x86_free_range(node_pa, node_pa + size);
+               memblock_free(node_pa, size);
                return;
        }
-       memblock_x86_reserve_range(remap_pa, remap_pa + size, "KVA PG");
+       memblock_reserve(remap_pa, size);
        remap_va = phys_to_virt(remap_pa);
 
        /* perform actual remap */
index dd27f401f0a03a3c62268c2097f363178767d795..92e27119ee1a0b5db2559ff8787a3ce83c150a59 100644 (file)
@@ -19,7 +19,7 @@ unsigned long __init numa_free_all_bootmem(void)
        for_each_online_node(i)
                pages += free_all_bootmem_node(NODE_DATA(i));
 
-       pages += free_all_memory_core_early(MAX_NUMNODES);
+       pages += free_low_memory_core_early(MAX_NUMNODES);
 
        return pages;
 }
index d0ed086b6247d35fb986d98dfe35a1711d901876..46db56845f180bcc890195e52052daa686680518 100644 (file)
@@ -28,6 +28,16 @@ static int __init emu_find_memblk_by_nid(int nid, const struct numa_meminfo *mi)
        return -ENOENT;
 }
 
+static u64 mem_hole_size(u64 start, u64 end)
+{
+       unsigned long start_pfn = PFN_UP(start);
+       unsigned long end_pfn = PFN_DOWN(end);
+
+       if (start_pfn < end_pfn)
+               return PFN_PHYS(absent_pages_in_range(start_pfn, end_pfn));
+       return 0;
+}
+
 /*
  * Sets up nid to range from @start to @end.  The return value is -errno if
  * something went wrong, 0 otherwise.
@@ -89,7 +99,7 @@ static int __init split_nodes_interleave(struct numa_meminfo *ei,
         * Calculate target node size.  x86_32 freaks on __udivdi3() so do
         * the division in ulong number of pages and convert back.
         */
-       size = max_addr - addr - memblock_x86_hole_size(addr, max_addr);
+       size = max_addr - addr - mem_hole_size(addr, max_addr);
        size = PFN_PHYS((unsigned long)(size >> PAGE_SHIFT) / nr_nodes);
 
        /*
@@ -135,8 +145,7 @@ static int __init split_nodes_interleave(struct numa_meminfo *ei,
                         * Continue to add memory to this fake node if its
                         * non-reserved memory is less than the per-node size.
                         */
-                       while (end - start -
-                              memblock_x86_hole_size(start, end) < size) {
+                       while (end - start - mem_hole_size(start, end) < size) {
                                end += FAKE_NODE_MIN_SIZE;
                                if (end > limit) {
                                        end = limit;
@@ -150,7 +159,7 @@ static int __init split_nodes_interleave(struct numa_meminfo *ei,
                         * this one must extend to the boundary.
                         */
                        if (end < dma32_end && dma32_end - end -
-                           memblock_x86_hole_size(end, dma32_end) < FAKE_NODE_MIN_SIZE)
+                           mem_hole_size(end, dma32_end) < FAKE_NODE_MIN_SIZE)
                                end = dma32_end;
 
                        /*
@@ -158,8 +167,7 @@ static int __init split_nodes_interleave(struct numa_meminfo *ei,
                         * next node, this one must extend to the end of the
                         * physical node.
                         */
-                       if (limit - end -
-                           memblock_x86_hole_size(end, limit) < size)
+                       if (limit - end - mem_hole_size(end, limit) < size)
                                end = limit;
 
                        ret = emu_setup_memblk(ei, pi, nid++ % nr_nodes,
@@ -180,7 +188,7 @@ static u64 __init find_end_of_node(u64 start, u64 max_addr, u64 size)
 {
        u64 end = start + size;
 
-       while (end - start - memblock_x86_hole_size(start, end) < size) {
+       while (end - start - mem_hole_size(start, end) < size) {
                end += FAKE_NODE_MIN_SIZE;
                if (end > max_addr) {
                        end = max_addr;
@@ -211,8 +219,7 @@ static int __init split_nodes_size_interleave(struct numa_meminfo *ei,
         * creates a uniform distribution of node sizes across the entire
         * machine (but not necessarily over physical nodes).
         */
-       min_size = (max_addr - addr - memblock_x86_hole_size(addr, max_addr)) /
-                                               MAX_NUMNODES;
+       min_size = (max_addr - addr - mem_hole_size(addr, max_addr)) / MAX_NUMNODES;
        min_size = max(min_size, FAKE_NODE_MIN_SIZE);
        if ((min_size & FAKE_NODE_MIN_HASH_MASK) < min_size)
                min_size = (min_size + FAKE_NODE_MIN_SIZE) &
@@ -252,7 +259,7 @@ static int __init split_nodes_size_interleave(struct numa_meminfo *ei,
                         * this one must extend to the boundary.
                         */
                        if (end < dma32_end && dma32_end - end -
-                           memblock_x86_hole_size(end, dma32_end) < FAKE_NODE_MIN_SIZE)
+                           mem_hole_size(end, dma32_end) < FAKE_NODE_MIN_SIZE)
                                end = dma32_end;
 
                        /*
@@ -260,8 +267,7 @@ static int __init split_nodes_size_interleave(struct numa_meminfo *ei,
                         * next node, this one must extend to the end of the
                         * physical node.
                         */
-                       if (limit - end -
-                           memblock_x86_hole_size(end, limit) < size)
+                       if (limit - end - mem_hole_size(end, limit) < size)
                                end = limit;
 
                        ret = emu_setup_memblk(ei, pi, nid++ % MAX_NUMNODES,
@@ -351,11 +357,11 @@ void __init numa_emulation(struct numa_meminfo *numa_meminfo, int numa_dist_cnt)
 
                phys = memblock_find_in_range(0, PFN_PHYS(max_pfn_mapped),
                                              phys_size, PAGE_SIZE);
-               if (phys == MEMBLOCK_ERROR) {
+               if (!phys) {
                        pr_warning("NUMA: Warning: can't allocate copy of distance table, disabling emulation\n");
                        goto no_emu;
                }
-               memblock_x86_reserve_range(phys, phys + phys_size, "TMP NUMA DIST");
+               memblock_reserve(phys, phys_size);
                phys_dist = __va(phys);
 
                for (i = 0; i < numa_dist_cnt; i++)
@@ -424,7 +430,7 @@ void __init numa_emulation(struct numa_meminfo *numa_meminfo, int numa_dist_cnt)
 
        /* free the copied physical distance table */
        if (phys_dist)
-               memblock_x86_free_range(__pa(phys_dist), __pa(phys_dist) + phys_size);
+               memblock_free(__pa(phys_dist), phys_size);
        return;
 
 no_emu:
index 37718f0f053d53346566c80958885f159b61dcde..4a01967f02e76c5d0156e35b94ef303162d661e6 100644 (file)
@@ -352,8 +352,7 @@ void __init efi_memblock_x86_reserve_range(void)
                boot_params.efi_info.efi_memdesc_size;
        memmap.desc_version = boot_params.efi_info.efi_memdesc_version;
        memmap.desc_size = boot_params.efi_info.efi_memdesc_size;
-       memblock_x86_reserve_range(pmap, pmap + memmap.nr_map * memmap.desc_size,
-                     "EFI memmap");
+       memblock_reserve(pmap, memmap.nr_map * memmap.desc_size);
 }
 
 #if EFI_DEBUG
@@ -397,16 +396,14 @@ void __init efi_reserve_boot_services(void)
                if ((start+size >= virt_to_phys(_text)
                                && start <= virt_to_phys(_end)) ||
                        !e820_all_mapped(start, start+size, E820_RAM) ||
-                       memblock_x86_check_reserved_size(&start, &size,
-                                                       1<<EFI_PAGE_SHIFT)) {
+                       memblock_is_region_reserved(start, size)) {
                        /* Could not reserve, skip it */
                        md->num_pages = 0;
                        memblock_dbg(PFX "Could not reserve boot range "
                                        "[0x%010llx-0x%010llx]\n",
                                                start, start+size-1);
                } else
-                       memblock_x86_reserve_range(start, start+size,
-                                                       "EFI Boot");
+                       memblock_reserve(start, size);
        }
 }
 
index 87f6673b1207d6e1f5fc2861a0b1797489b0e862..f4bf8aa574f432aed85bea73fed2c0620c040e5b 100644 (file)
@@ -1774,10 +1774,8 @@ pgd_t * __init xen_setup_kernel_pagetable(pgd_t *pgd,
        __xen_write_cr3(true, __pa(pgd));
        xen_mc_issue(PARAVIRT_LAZY_CPU);
 
-       memblock_x86_reserve_range(__pa(xen_start_info->pt_base),
-                     __pa(xen_start_info->pt_base +
-                          xen_start_info->nr_pt_frames * PAGE_SIZE),
-                     "XEN PAGETABLES");
+       memblock_reserve(__pa(xen_start_info->pt_base),
+                        xen_start_info->nr_pt_frames * PAGE_SIZE);
 
        return pgd;
 }
@@ -1853,10 +1851,8 @@ pgd_t * __init xen_setup_kernel_pagetable(pgd_t *pgd,
                          PFN_DOWN(__pa(initial_page_table)));
        xen_write_cr3(__pa(initial_page_table));
 
-       memblock_x86_reserve_range(__pa(xen_start_info->pt_base),
-                     __pa(xen_start_info->pt_base +
-                          xen_start_info->nr_pt_frames * PAGE_SIZE),
-                     "XEN PAGETABLES");
+       memblock_reserve(__pa(xen_start_info->pt_base),
+                        xen_start_info->nr_pt_frames * PAGE_SIZE));
 
        return initial_page_table;
 }
index 38d0af4fefec19f52d5e724c8f08102d391dc2e6..f5e1362550e76130eb4b770e926825ec76cb56f1 100644 (file)
@@ -75,7 +75,7 @@ static void __init xen_add_extra_mem(u64 start, u64 size)
        if (i == XEN_EXTRA_MEM_MAX_REGIONS)
                printk(KERN_WARNING "Warning: not enough extra memory regions\n");
 
-       memblock_x86_reserve_range(start, start + size, "XEN EXTRA");
+       memblock_reserve(start, size);
 
        xen_max_p2m_pfn = PFN_DOWN(start + size);
 
@@ -299,9 +299,8 @@ char * __init xen_memory_setup(void)
         *  - xen_start_info
         * See comment above "struct start_info" in <xen/interface/xen.h>
         */
-       memblock_x86_reserve_range(__pa(xen_start_info->mfn_list),
-                     __pa(xen_start_info->pt_base),
-                       "XEN START INFO");
+       memblock_reserve(__pa(xen_start_info->mfn_list),
+                        xen_start_info->pt_base - xen_start_info->mfn_list);
 
        sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
 
index c0c7820d4c46b406465e0d2d8e059a80ce819476..bcbd693b351ae8f250496388ff5f0921a90b0be6 100644 (file)
@@ -2185,18 +2185,6 @@ static inline void iommu_prepare_isa(void)
 
 static int md_domain_init(struct dmar_domain *domain, int guest_width);
 
-static int __init si_domain_work_fn(unsigned long start_pfn,
-                                   unsigned long end_pfn, void *datax)
-{
-       int *ret = datax;
-
-       *ret = iommu_domain_identity_map(si_domain,
-                                        (uint64_t)start_pfn << PAGE_SHIFT,
-                                        (uint64_t)end_pfn << PAGE_SHIFT);
-       return *ret;
-
-}
-
 static int __init si_domain_init(int hw)
 {
        struct dmar_drhd_unit *drhd;
@@ -2228,9 +2216,15 @@ static int __init si_domain_init(int hw)
                return 0;
 
        for_each_online_node(nid) {
-               work_with_active_regions(nid, si_domain_work_fn, &ret);
-               if (ret)
-                       return ret;
+               unsigned long start_pfn, end_pfn;
+               int i;
+
+               for_each_mem_pfn_range(i, nid, &start_pfn, &end_pfn, NULL) {
+                       ret = iommu_domain_identity_map(si_domain,
+                                       PFN_PHYS(start_pfn), PFN_PHYS(end_pfn));
+                       if (ret)
+                               return ret;
+               }
        }
 
        return 0;
index ab344a52110571b6600c8bbb37871960fa8d67f0..66d3e954eb6c023de382ab71c7425de622a62663 100644 (file)
@@ -44,7 +44,7 @@ extern unsigned long init_bootmem_node(pg_data_t *pgdat,
                                       unsigned long endpfn);
 extern unsigned long init_bootmem(unsigned long addr, unsigned long memend);
 
-unsigned long free_all_memory_core_early(int nodeid);
+extern unsigned long free_low_memory_core_early(int nodeid);
 extern unsigned long free_all_bootmem_node(pg_data_t *pgdat);
 extern unsigned long free_all_bootmem(void);
 
index e6b843e16e81d592131e74a47974182cadb301d9..ab89b417655c47e1f766dced9c14401080791bcf 100644 (file)
@@ -2,8 +2,6 @@
 #define _LINUX_MEMBLOCK_H
 #ifdef __KERNEL__
 
-#define MEMBLOCK_ERROR 0
-
 #ifdef CONFIG_HAVE_MEMBLOCK
 /*
  * Logical memory blocks.
 #include <linux/init.h>
 #include <linux/mm.h>
 
-#include <asm/memblock.h>
-
 #define INIT_MEMBLOCK_REGIONS  128
 
 struct memblock_region {
        phys_addr_t base;
        phys_addr_t size;
+#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
+       int nid;
+#endif
 };
 
 struct memblock_type {
@@ -48,7 +47,8 @@ extern int memblock_can_resize;
 #define memblock_dbg(fmt, ...) \
        if (memblock_debug) printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)
 
-u64 memblock_find_in_range(u64 start, u64 end, u64 size, u64 align);
+phys_addr_t memblock_find_in_range(phys_addr_t start, phys_addr_t end,
+                                  phys_addr_t size, phys_addr_t align);
 int memblock_free_reserved_regions(void);
 int memblock_reserve_reserved_regions(void);
 
@@ -59,9 +59,56 @@ extern long memblock_remove(phys_addr_t base, phys_addr_t size);
 extern long memblock_free(phys_addr_t base, phys_addr_t size);
 extern long memblock_reserve(phys_addr_t base, phys_addr_t size);
 
+extern void __next_free_mem_range(u64 *idx, int nid, phys_addr_t *out_start,
+                                 phys_addr_t *out_end, int *out_nid);
+
+/**
+ * for_each_free_mem_range - iterate through free memblock areas
+ * @i: u64 used as loop variable
+ * @nid: node selector, %MAX_NUMNODES for all nodes
+ * @p_start: ptr to phys_addr_t for start address of the range, can be %NULL
+ * @p_end: ptr to phys_addr_t for end address of the range, can be %NULL
+ * @p_nid: ptr to int for nid of the range, can be %NULL
+ *
+ * Walks over free (memory && !reserved) areas of memblock.  Available as
+ * soon as memblock is initialized.
+ */
+#define for_each_free_mem_range(i, nid, p_start, p_end, p_nid)         \
+       for (i = 0,                                                     \
+            __next_free_mem_range(&i, nid, p_start, p_end, p_nid);     \
+            i != (u64)ULLONG_MAX;                                      \
+            __next_free_mem_range(&i, nid, p_start, p_end, p_nid))
+
+#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
+extern int memblock_set_node(phys_addr_t base, phys_addr_t size, int nid);
+
+static inline void memblock_set_region_node(struct memblock_region *r, int nid)
+{
+       r->nid = nid;
+}
+
+static inline int memblock_get_region_node(const struct memblock_region *r)
+{
+       return r->nid;
+}
+#else
+static inline void memblock_set_region_node(struct memblock_region *r, int nid)
+{
+}
+
+static inline int memblock_get_region_node(const struct memblock_region *r)
+{
+       return 0;
+}
+#endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */
+
 /* The numa aware allocator is only available if
  * CONFIG_ARCH_POPULATES_NODE_MAP is set
  */
+extern phys_addr_t memblock_find_in_range_node(phys_addr_t start,
+                                              phys_addr_t end,
+                                              phys_addr_t size,
+                                              phys_addr_t align, int nid);
 extern phys_addr_t memblock_alloc_nid(phys_addr_t size, phys_addr_t align,
                                        int nid);
 extern phys_addr_t memblock_alloc_try_nid(phys_addr_t size, phys_addr_t align,
@@ -90,11 +137,6 @@ extern int memblock_is_region_reserved(phys_addr_t base, phys_addr_t size);
 
 extern void memblock_dump_all(void);
 
-/* Provided by the architecture */
-extern phys_addr_t memblock_nid_range(phys_addr_t start, phys_addr_t end, int *nid);
-extern int memblock_memory_can_coalesce(phys_addr_t addr1, phys_addr_t size1,
-                                  phys_addr_t addr2, phys_addr_t size2);
-
 /**
  * memblock_set_current_limit - Set the current allocation limit to allow
  *                         limiting allocations to what is currently
@@ -154,9 +196,9 @@ static inline unsigned long memblock_region_reserved_end_pfn(const struct memblo
             region++)
 
 
-#ifdef ARCH_DISCARD_MEMBLOCK
-#define __init_memblock __init
-#define __initdata_memblock __initdata
+#ifdef CONFIG_ARCH_DISCARD_MEMBLOCK
+#define __init_memblock __meminit
+#define __initdata_memblock __meminitdata
 #else
 #define __init_memblock
 #define __initdata_memblock
@@ -165,7 +207,7 @@ static inline unsigned long memblock_region_reserved_end_pfn(const struct memblo
 #else
 static inline phys_addr_t memblock_alloc(phys_addr_t size, phys_addr_t align)
 {
-       return MEMBLOCK_ERROR;
+       return 0;
 }
 
 #endif /* CONFIG_HAVE_MEMBLOCK */
index 3dc3a8c2c4858a1d3400aa2d5fd029d36a1177c6..6b365aee83960447ee48182ae2e9e01478cc0c46 100644 (file)
@@ -1281,12 +1281,14 @@ extern void free_area_init_node(int nid, unsigned long * zones_size,
  * CONFIG_ARCH_POPULATES_NODE_MAP
  */
 extern void free_area_init_nodes(unsigned long *max_zone_pfn);
+#ifndef CONFIG_HAVE_MEMBLOCK_NODE_MAP
 extern void add_active_range(unsigned int nid, unsigned long start_pfn,
                                        unsigned long end_pfn);
 extern void remove_active_range(unsigned int nid, unsigned long start_pfn,
                                        unsigned long end_pfn);
 extern void remove_all_active_ranges(void);
 void sort_node_map(void);
+#endif
 unsigned long node_map_pfn_alignment(void);
 unsigned long __absent_pages_in_range(int nid, unsigned long start_pfn,
                                                unsigned long end_pfn);
@@ -1299,11 +1301,27 @@ extern void free_bootmem_with_active_regions(int nid,
                                                unsigned long max_low_pfn);
 int add_from_early_node_map(struct range *range, int az,
                                   int nr_range, int nid);
-u64 __init find_memory_core_early(int nid, u64 size, u64 align,
-                                       u64 goal, u64 limit);
-typedef int (*work_fn_t)(unsigned long, unsigned long, void *);
-extern void work_with_active_regions(int nid, work_fn_t work_fn, void *data);
 extern void sparse_memory_present_with_active_regions(int nid);
+
+extern void __next_mem_pfn_range(int *idx, int nid,
+                                unsigned long *out_start_pfn,
+                                unsigned long *out_end_pfn, int *out_nid);
+
+/**
+ * for_each_mem_pfn_range - early memory pfn range iterator
+ * @i: an integer used as loop variable
+ * @nid: node selector, %MAX_NUMNODES for all nodes
+ * @p_start: ptr to ulong for start pfn of the range, can be %NULL
+ * @p_end: ptr to ulong for end pfn of the range, can be %NULL
+ * @p_nid: ptr to int for nid of the range, can be %NULL
+ *
+ * Walks over configured memory ranges.  Available after early_node_map is
+ * populated.
+ */
+#define for_each_mem_pfn_range(i, nid, p_start, p_end, p_nid)          \
+       for (i = -1, __next_mem_pfn_range(&i, nid, p_start, p_end, p_nid); \
+            i >= 0; __next_mem_pfn_range(&i, nid, p_start, p_end, p_nid))
+
 #endif /* CONFIG_ARCH_POPULATES_NODE_MAP */
 
 #if !defined(CONFIG_ARCH_POPULATES_NODE_MAP) && \
index 1455a0d4eedd4b386c759d689f939ba5d7a9007a..baf2aebd6970af85547a865276785557b4066e27 100644 (file)
@@ -199,7 +199,7 @@ void __init setup_log_buf(int early)
                unsigned long mem;
 
                mem = memblock_alloc(new_log_buf_len, PAGE_SIZE);
-               if (mem == MEMBLOCK_ERROR)
+               if (!mem)
                        return;
                new_log_buf = __va(mem);
        } else {
index 011b110365c8681d7b1c546223bdb8a2daccc59d..e338407f1225f0873a8eb20761c86fd82db1dfc0 100644 (file)
@@ -131,6 +131,12 @@ config SPARSEMEM_VMEMMAP
 config HAVE_MEMBLOCK
        boolean
 
+config HAVE_MEMBLOCK_NODE_MAP
+       boolean
+
+config ARCH_DISCARD_MEMBLOCK
+       boolean
+
 config NO_BOOTMEM
        boolean
 
index 84bec4969ed5d3a27d9c6035da6e39ebf1dfdd18..a57092f63a862ec5ec490d50f43a08eb9021f29a 100644 (file)
@@ -41,17 +41,6 @@ static inline const char *memblock_type_name(struct memblock_type *type)
 /*
  * Address comparison utilities
  */
-
-static phys_addr_t __init_memblock memblock_align_down(phys_addr_t addr, phys_addr_t size)
-{
-       return addr & ~(size - 1);
-}
-
-static phys_addr_t __init_memblock memblock_align_up(phys_addr_t addr, phys_addr_t size)
-{
-       return (addr + (size - 1)) & ~(size - 1);
-}
-
 static unsigned long __init_memblock memblock_addrs_overlap(phys_addr_t base1, phys_addr_t size1,
                                       phys_addr_t base2, phys_addr_t size2)
 {
@@ -86,9 +75,9 @@ static phys_addr_t __init_memblock memblock_find_region(phys_addr_t start, phys_
 
        /* In case, huge size is requested */
        if (end < size)
-               return MEMBLOCK_ERROR;
+               return 0;
 
-       base = memblock_align_down((end - size), align);
+       base = round_down(end - size, align);
 
        /* Prevent allocations returning 0 as it's also used to
         * indicate an allocation failure
@@ -103,14 +92,17 @@ static phys_addr_t __init_memblock memblock_find_region(phys_addr_t start, phys_
                res_base = memblock.reserved.regions[j].base;
                if (res_base < size)
                        break;
-               base = memblock_align_down(res_base - size, align);
+               base = round_down(res_base - size, align);
        }
 
-       return MEMBLOCK_ERROR;
+       return 0;
 }
 
-static phys_addr_t __init_memblock memblock_find_base(phys_addr_t size,
-                       phys_addr_t align, phys_addr_t start, phys_addr_t end)
+/*
+ * Find a free area with specified alignment in a specific range.
+ */
+phys_addr_t __init_memblock memblock_find_in_range(phys_addr_t start, phys_addr_t end,
+                                       phys_addr_t size, phys_addr_t align)
 {
        long i;
 
@@ -138,18 +130,10 @@ static phys_addr_t __init_memblock memblock_find_base(phys_addr_t size,
                if (bottom >= top)
                        continue;
                found = memblock_find_region(bottom, top, size, align);
-               if (found != MEMBLOCK_ERROR)
+               if (found)
                        return found;
        }
-       return MEMBLOCK_ERROR;
-}
-
-/*
- * Find a free area with specified alignment in a specific range.
- */
-u64 __init_memblock memblock_find_in_range(u64 start, u64 end, u64 size, u64 align)
-{
-       return memblock_find_base(size, align, start, end);
+       return 0;
 }
 
 /*
@@ -178,12 +162,8 @@ int __init_memblock memblock_reserve_reserved_regions(void)
 
 static void __init_memblock memblock_remove_region(struct memblock_type *type, unsigned long r)
 {
-       unsigned long i;
-
-       for (i = r; i < type->cnt - 1; i++) {
-               type->regions[i].base = type->regions[i + 1].base;
-               type->regions[i].size = type->regions[i + 1].size;
-       }
+       memmove(&type->regions[r], &type->regions[r + 1],
+               (type->cnt - (r + 1)) * sizeof(type->regions[r]));
        type->cnt--;
 
        /* Special case for empty arrays */
@@ -191,6 +171,7 @@ static void __init_memblock memblock_remove_region(struct memblock_type *type, u
                type->cnt = 1;
                type->regions[0].base = 0;
                type->regions[0].size = 0;
+               memblock_set_region_node(&type->regions[0], MAX_NUMNODES);
        }
 }
 
@@ -226,10 +207,10 @@ static int __init_memblock memblock_double_array(struct memblock_type *type)
         */
        if (use_slab) {
                new_array = kmalloc(new_size, GFP_KERNEL);
-               addr = new_array == NULL ? MEMBLOCK_ERROR : __pa(new_array);
+               addr = new_array ? __pa(new_array) : 0;
        } else
-               addr = memblock_find_base(new_size, sizeof(phys_addr_t), 0, MEMBLOCK_ALLOC_ACCESSIBLE);
-       if (addr == MEMBLOCK_ERROR) {
+               addr = memblock_find_in_range(0, MEMBLOCK_ALLOC_ACCESSIBLE, new_size, sizeof(phys_addr_t));
+       if (!addr) {
                pr_err("memblock: Failed to double %s array from %ld to %ld entries !\n",
                       memblock_type_name(type), type->max, type->max * 2);
                return -1;
@@ -268,146 +249,147 @@ static int __init_memblock memblock_double_array(struct memblock_type *type)
        return 0;
 }
 
-int __init_memblock __weak memblock_memory_can_coalesce(phys_addr_t addr1, phys_addr_t size1,
-                                         phys_addr_t addr2, phys_addr_t size2)
+/**
+ * memblock_merge_regions - merge neighboring compatible regions
+ * @type: memblock type to scan
+ *
+ * Scan @type and merge neighboring compatible regions.
+ */
+static void __init_memblock memblock_merge_regions(struct memblock_type *type)
 {
-       return 1;
+       int i = 0;
+
+       /* cnt never goes below 1 */
+       while (i < type->cnt - 1) {
+               struct memblock_region *this = &type->regions[i];
+               struct memblock_region *next = &type->regions[i + 1];
+
+               if (this->base + this->size != next->base ||
+                   memblock_get_region_node(this) !=
+                   memblock_get_region_node(next)) {
+                       BUG_ON(this->base + this->size > next->base);
+                       i++;
+                       continue;
+               }
+
+               this->size += next->size;
+               memmove(next, next + 1, (type->cnt - (i + 1)) * sizeof(*next));
+               type->cnt--;
+       }
 }
 
-static long __init_memblock memblock_add_region(struct memblock_type *type,
-                                               phys_addr_t base, phys_addr_t size)
+/**
+ * memblock_insert_region - insert new memblock region
+ * @type: memblock type to insert into
+ * @idx: index for the insertion point
+ * @base: base address of the new region
+ * @size: size of the new region
+ *
+ * Insert new memblock region [@base,@base+@size) into @type at @idx.
+ * @type must already have extra room to accomodate the new region.
+ */
+static void __init_memblock memblock_insert_region(struct memblock_type *type,
+                                                  int idx, phys_addr_t base,
+                                                  phys_addr_t size, int nid)
 {
-       phys_addr_t end = base + size;
-       int i, slot = -1;
-
-       /* First try and coalesce this MEMBLOCK with others */
-       for (i = 0; i < type->cnt; i++) {
-               struct memblock_region *rgn = &type->regions[i];
-               phys_addr_t rend = rgn->base + rgn->size;
-
-               /* Exit if there's no possible hits */
-               if (rgn->base > end || rgn->size == 0)
-                       break;
-
-               /* Check if we are fully enclosed within an existing
-                * block
-                */
-               if (rgn->base <= base && rend >= end)
-                       return 0;
-
-               /* Check if we overlap or are adjacent with the bottom
-                * of a block.
-                */
-               if (base < rgn->base && end >= rgn->base) {
-                       /* If we can't coalesce, create a new block */
-                       if (!memblock_memory_can_coalesce(base, size,
-                                                         rgn->base,
-                                                         rgn->size)) {
-                               /* Overlap & can't coalesce are mutually
-                                * exclusive, if you do that, be prepared
-                                * for trouble
-                                */
-                               WARN_ON(end != rgn->base);
-                               goto new_block;
-                       }
-                       /* We extend the bottom of the block down to our
-                        * base
-                        */
-                       rgn->base = base;
-                       rgn->size = rend - base;
-
-                       /* Return if we have nothing else to allocate
-                        * (fully coalesced)
-                        */
-                       if (rend >= end)
-                               return 0;
+       struct memblock_region *rgn = &type->regions[idx];
 
-                       /* We continue processing from the end of the
-                        * coalesced block.
-                        */
-                       base = rend;
-                       size = end - base;
-               }
+       BUG_ON(type->cnt >= type->max);
+       memmove(rgn + 1, rgn, (type->cnt - idx) * sizeof(*rgn));
+       rgn->base = base;
+       rgn->size = size;
+       memblock_set_region_node(rgn, nid);
+       type->cnt++;
+}
 
-               /* Now check if we overlap or are adjacent with the
-                * top of a block
-                */
-               if (base <= rend && end >= rend) {
-                       /* If we can't coalesce, create a new block */
-                       if (!memblock_memory_can_coalesce(rgn->base,
-                                                         rgn->size,
-                                                         base, size)) {
-                               /* Overlap & can't coalesce are mutually
-                                * exclusive, if you do that, be prepared
-                                * for trouble
-                                */
-                               WARN_ON(rend != base);
-                               goto new_block;
-                       }
-                       /* We adjust our base down to enclose the
-                        * original block and destroy it. It will be
-                        * part of our new allocation. Since we've
-                        * freed an entry, we know we won't fail
-                        * to allocate one later, so we won't risk
-                        * losing the original block allocation.
-                        */
-                       size += (base - rgn->base);
-                       base = rgn->base;
-                       memblock_remove_region(type, i--);
-               }
-       }
+/**
+ * memblock_add_region - add new memblock region
+ * @type: memblock type to add new region into
+ * @base: base address of the new region
+ * @size: size of the new region
+ *
+ * Add new memblock region [@base,@base+@size) into @type.  The new region
+ * is allowed to overlap with existing ones - overlaps don't affect already
+ * existing regions.  @type is guaranteed to be minimal (all neighbouring
+ * compatible regions are merged) after the addition.
+ *
+ * RETURNS:
+ * 0 on success, -errno on failure.
+ */
+static long __init_memblock memblock_add_region(struct memblock_type *type,
+                                               phys_addr_t base, phys_addr_t size)
+{
+       bool insert = false;
+       phys_addr_t obase = base, end = base + size;
+       int i, nr_new;
 
-       /* If the array is empty, special case, replace the fake
-        * filler region and return
-        */
-       if ((type->cnt == 1) && (type->regions[0].size == 0)) {
+       /* special case for empty array */
+       if (type->regions[0].size == 0) {
+               WARN_ON(type->cnt != 1);
                type->regions[0].base = base;
                type->regions[0].size = size;
+               memblock_set_region_node(&type->regions[0], MAX_NUMNODES);
                return 0;
        }
-
- new_block:
-       /* If we are out of space, we fail. It's too late to resize the array
-        * but then this shouldn't have happened in the first place.
+repeat:
+       /*
+        * The following is executed twice.  Once with %false @insert and
+        * then with %true.  The first counts the number of regions needed
+        * to accomodate the new area.  The second actually inserts them.
         */
-       if (WARN_ON(type->cnt >= type->max))
-               return -1;
+       base = obase;
+       nr_new = 0;
 
-       /* Couldn't coalesce the MEMBLOCK, so add it to the sorted table. */
-       for (i = type->cnt - 1; i >= 0; i--) {
-               if (base < type->regions[i].base) {
-                       type->regions[i+1].base = type->regions[i].base;
-                       type->regions[i+1].size = type->regions[i].size;
-               } else {
-                       type->regions[i+1].base = base;
-                       type->regions[i+1].size = size;
-                       slot = i + 1;
+       for (i = 0; i < type->cnt; i++) {
+               struct memblock_region *rgn = &type->regions[i];
+               phys_addr_t rbase = rgn->base;
+               phys_addr_t rend = rbase + rgn->size;
+
+               if (rbase >= end)
                        break;
+               if (rend <= base)
+                       continue;
+               /*
+                * @rgn overlaps.  If it separates the lower part of new
+                * area, insert that portion.
+                */
+               if (rbase > base) {
+                       nr_new++;
+                       if (insert)
+                               memblock_insert_region(type, i++, base,
+                                               rbase - base, MAX_NUMNODES);
                }
+               /* area below @rend is dealt with, forget about it */
+               base = min(rend, end);
        }
-       if (base < type->regions[0].base) {
-               type->regions[0].base = base;
-               type->regions[0].size = size;
-               slot = 0;
+
+       /* insert the remaining portion */
+       if (base < end) {
+               nr_new++;
+               if (insert)
+                       memblock_insert_region(type, i, base, end - base,
+                                              MAX_NUMNODES);
        }
-       type->cnt++;
 
-       /* The array is full ? Try to resize it. If that fails, we undo
-        * our allocation and return an error
+       /*
+        * If this was the first round, resize array and repeat for actual
+        * insertions; otherwise, merge and return.
         */
-       if (type->cnt == type->max && memblock_double_array(type)) {
-               BUG_ON(slot < 0);
-               memblock_remove_region(type, slot);
-               return -1;
+       if (!insert) {
+               while (type->cnt + nr_new > type->max)
+                       if (memblock_double_array(type) < 0)
+                               return -ENOMEM;
+               insert = true;
+               goto repeat;
+       } else {
+               memblock_merge_regions(type);
+               return 0;
        }
-
-       return 0;
 }
 
 long __init_memblock memblock_add(phys_addr_t base, phys_addr_t size)
 {
        return memblock_add_region(&memblock.memory, base, size);
-
 }
 
 static long __init_memblock __memblock_remove(struct memblock_type *type,
@@ -468,6 +450,11 @@ long __init_memblock memblock_remove(phys_addr_t base, phys_addr_t size)
 
 long __init_memblock memblock_free(phys_addr_t base, phys_addr_t size)
 {
+       memblock_dbg("   memblock_free: [%#016llx-%#016llx] %pF\n",
+                    (unsigned long long)base,
+                    (unsigned long long)base + size,
+                    (void *)_RET_IP_);
+
        return __memblock_remove(&memblock.reserved, base, size);
 }
 
@@ -475,11 +462,186 @@ long __init_memblock memblock_reserve(phys_addr_t base, phys_addr_t size)
 {
        struct memblock_type *_rgn = &memblock.reserved;
 
+       memblock_dbg("memblock_reserve: [%#016llx-%#016llx] %pF\n",
+                    (unsigned long long)base,
+                    (unsigned long long)base + size,
+                    (void *)_RET_IP_);
        BUG_ON(0 == size);
 
        return memblock_add_region(_rgn, base, size);
 }
 
+/**
+ * __next_free_mem_range - next function for for_each_free_mem_range()
+ * @idx: pointer to u64 loop variable
+ * @nid: nid: node selector, %MAX_NUMNODES for all nodes
+ * @p_start: ptr to phys_addr_t for start address of the range, can be %NULL
+ * @p_end: ptr to phys_addr_t for end address of the range, can be %NULL
+ * @p_nid: ptr to int for nid of the range, can be %NULL
+ *
+ * Find the first free area from *@idx which matches @nid, fill the out
+ * parameters, and update *@idx for the next iteration.  The lower 32bit of
+ * *@idx contains index into memory region and the upper 32bit indexes the
+ * areas before each reserved region.  For example, if reserved regions
+ * look like the following,
+ *
+ *     0:[0-16), 1:[32-48), 2:[128-130)
+ *
+ * The upper 32bit indexes the following regions.
+ *
+ *     0:[0-0), 1:[16-32), 2:[48-128), 3:[130-MAX)
+ *
+ * As both region arrays are sorted, the function advances the two indices
+ * in lockstep and returns each intersection.
+ */
+void __init_memblock __next_free_mem_range(u64 *idx, int nid,
+                                          phys_addr_t *out_start,
+                                          phys_addr_t *out_end, int *out_nid)
+{
+       struct memblock_type *mem = &memblock.memory;
+       struct memblock_type *rsv = &memblock.reserved;
+       int mi = *idx & 0xffffffff;
+       int ri = *idx >> 32;
+
+       for ( ; mi < mem->cnt; mi++) {
+               struct memblock_region *m = &mem->regions[mi];
+               phys_addr_t m_start = m->base;
+               phys_addr_t m_end = m->base + m->size;
+
+               /* only memory regions are associated with nodes, check it */
+               if (nid != MAX_NUMNODES && nid != memblock_get_region_node(m))
+                       continue;
+
+               /* scan areas before each reservation for intersection */
+               for ( ; ri < rsv->cnt + 1; ri++) {
+                       struct memblock_region *r = &rsv->regions[ri];
+                       phys_addr_t r_start = ri ? r[-1].base + r[-1].size : 0;
+                       phys_addr_t r_end = ri < rsv->cnt ? r->base : ULLONG_MAX;
+
+                       /* if ri advanced past mi, break out to advance mi */
+                       if (r_start >= m_end)
+                               break;
+                       /* if the two regions intersect, we're done */
+                       if (m_start < r_end) {
+                               if (out_start)
+                                       *out_start = max(m_start, r_start);
+                               if (out_end)
+                                       *out_end = min(m_end, r_end);
+                               if (out_nid)
+                                       *out_nid = memblock_get_region_node(m);
+                               /*
+                                * The region which ends first is advanced
+                                * for the next iteration.
+                                */
+                               if (m_end <= r_end)
+                                       mi++;
+                               else
+                                       ri++;
+                               *idx = (u32)mi | (u64)ri << 32;
+                               return;
+                       }
+               }
+       }
+
+       /* signal end of iteration */
+       *idx = ULLONG_MAX;
+}
+
+#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
+/*
+ * Common iterator interface used to define for_each_mem_range().
+ */
+void __init_memblock __next_mem_pfn_range(int *idx, int nid,
+                               unsigned long *out_start_pfn,
+                               unsigned long *out_end_pfn, int *out_nid)
+{
+       struct memblock_type *type = &memblock.memory;
+       struct memblock_region *r;
+
+       while (++*idx < type->cnt) {
+               r = &type->regions[*idx];
+
+               if (PFN_UP(r->base) >= PFN_DOWN(r->base + r->size))
+                       continue;
+               if (nid == MAX_NUMNODES || nid == r->nid)
+                       break;
+       }
+       if (*idx >= type->cnt) {
+               *idx = -1;
+               return;
+       }
+
+       if (out_start_pfn)
+               *out_start_pfn = PFN_UP(r->base);
+       if (out_end_pfn)
+               *out_end_pfn = PFN_DOWN(r->base + r->size);
+       if (out_nid)
+               *out_nid = r->nid;
+}
+
+/**
+ * memblock_set_node - set node ID on memblock regions
+ * @base: base of area to set node ID for
+ * @size: size of area to set node ID for
+ * @nid: node ID to set
+ *
+ * Set the nid of memblock memory regions in [@base,@base+@size) to @nid.
+ * Regions which cross the area boundaries are split as necessary.
+ *
+ * RETURNS:
+ * 0 on success, -errno on failure.
+ */
+int __init_memblock memblock_set_node(phys_addr_t base, phys_addr_t size,
+                                     int nid)
+{
+       struct memblock_type *type = &memblock.memory;
+       phys_addr_t end = base + size;
+       int i;
+
+       /* we'll create at most two more regions */
+       while (type->cnt + 2 > type->max)
+               if (memblock_double_array(type) < 0)
+                       return -ENOMEM;
+
+       for (i = 0; i < type->cnt; i++) {
+               struct memblock_region *rgn = &type->regions[i];
+               phys_addr_t rbase = rgn->base;
+               phys_addr_t rend = rbase + rgn->size;
+
+               if (rbase >= end)
+                       break;
+               if (rend <= base)
+                       continue;
+
+               if (rbase < base) {
+                       /*
+                        * @rgn intersects from below.  Split and continue
+                        * to process the next region - the new top half.
+                        */
+                       rgn->base = base;
+                       rgn->size = rend - rgn->base;
+                       memblock_insert_region(type, i, rbase, base - rbase,
+                                              rgn->nid);
+               } else if (rend > end) {
+                       /*
+                        * @rgn intersects from above.  Split and redo the
+                        * current region - the new bottom half.
+                        */
+                       rgn->base = end;
+                       rgn->size = rend - rgn->base;
+                       memblock_insert_region(type, i--, rbase, end - rbase,
+                                              rgn->nid);
+               } else {
+                       /* @rgn is fully contained, set ->nid */
+                       rgn->nid = nid;
+               }
+       }
+
+       memblock_merge_regions(type);
+       return 0;
+}
+#endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */
+
 phys_addr_t __init __memblock_alloc_base(phys_addr_t size, phys_addr_t align, phys_addr_t max_addr)
 {
        phys_addr_t found;
@@ -487,11 +649,10 @@ phys_addr_t __init __memblock_alloc_base(phys_addr_t size, phys_addr_t align, ph
        /* We align the size to limit fragmentation. Without this, a lot of
         * small allocs quickly eat up the whole reserve array on sparc
         */
-       size = memblock_align_up(size, align);
+       size = round_up(size, align);
 
-       found = memblock_find_base(size, align, 0, max_addr);
-       if (found != MEMBLOCK_ERROR &&
-           !memblock_add_region(&memblock.reserved, found, size))
+       found = memblock_find_in_range(0, max_addr, size, align);
+       if (found && !memblock_add_region(&memblock.reserved, found, size))
                return found;
 
        return 0;
@@ -517,92 +678,78 @@ phys_addr_t __init memblock_alloc(phys_addr_t size, phys_addr_t align)
 
 
 /*
- * Additional node-local allocators. Search for node memory is bottom up
- * and walks memblock regions within that node bottom-up as well, but allocation
- * within an memblock region is top-down. XXX I plan to fix that at some stage
+ * Additional node-local top-down allocators.
  *
  * WARNING: Only available after early_node_map[] has been populated,
  * on some architectures, that is after all the calls to add_active_range()
  * have been done to populate it.
  */
 
-phys_addr_t __weak __init memblock_nid_range(phys_addr_t start, phys_addr_t end, int *nid)
+static phys_addr_t __init memblock_nid_range_rev(phys_addr_t start,
+                                                phys_addr_t end, int *nid)
 {
 #ifdef CONFIG_ARCH_POPULATES_NODE_MAP
-       /*
-        * This code originates from sparc which really wants use to walk by addresses
-        * and returns the nid. This is not very convenient for early_pfn_map[] users
-        * as the map isn't sorted yet, and it really wants to be walked by nid.
-        *
-        * For now, I implement the inefficient method below which walks the early
-        * map multiple times. Eventually we may want to use an ARCH config option
-        * to implement a completely different method for both case.
-        */
        unsigned long start_pfn, end_pfn;
        int i;
 
-       for (i = 0; i < MAX_NUMNODES; i++) {
-               get_pfn_range_for_nid(i, &start_pfn, &end_pfn);
-               if (start < PFN_PHYS(start_pfn) || start >= PFN_PHYS(end_pfn))
-                       continue;
-               *nid = i;
-               return min(end, PFN_PHYS(end_pfn));
-       }
+       for_each_mem_pfn_range(i, MAX_NUMNODES, &start_pfn, &end_pfn, nid)
+               if (end > PFN_PHYS(start_pfn) && end <= PFN_PHYS(end_pfn))
+                       return max(start, PFN_PHYS(start_pfn));
 #endif
        *nid = 0;
-
-       return end;
+       return start;
 }
 
-static phys_addr_t __init memblock_alloc_nid_region(struct memblock_region *mp,
+phys_addr_t __init memblock_find_in_range_node(phys_addr_t start,
+                                              phys_addr_t end,
                                               phys_addr_t size,
                                               phys_addr_t align, int nid)
 {
-       phys_addr_t start, end;
+       struct memblock_type *mem = &memblock.memory;
+       int i;
+
+       BUG_ON(0 == size);
+
+       /* Pump up max_addr */
+       if (end == MEMBLOCK_ALLOC_ACCESSIBLE)
+               end = memblock.current_limit;
 
-       start = mp->base;
-       end = start + mp->size;
+       for (i = mem->cnt - 1; i >= 0; i--) {
+               struct memblock_region *r = &mem->regions[i];
+               phys_addr_t base = max(start, r->base);
+               phys_addr_t top = min(end, r->base + r->size);
 
-       start = memblock_align_up(start, align);
-       while (start < end) {
-               phys_addr_t this_end;
-               int this_nid;
+               while (base < top) {
+                       phys_addr_t tbase, ret;
+                       int tnid;
 
-               this_end = memblock_nid_range(start, end, &this_nid);
-               if (this_nid == nid) {
-                       phys_addr_t ret = memblock_find_region(start, this_end, size, align);
-                       if (ret != MEMBLOCK_ERROR &&
-                           !memblock_add_region(&memblock.reserved, ret, size))
-                               return ret;
+                       tbase = memblock_nid_range_rev(base, top, &tnid);
+                       if (nid == MAX_NUMNODES || tnid == nid) {
+                               ret = memblock_find_region(tbase, top, size, align);
+                               if (ret)
+                                       return ret;
+                       }
+                       top = tbase;
                }
-               start = this_end;
        }
 
-       return MEMBLOCK_ERROR;
+       return 0;
 }
 
 phys_addr_t __init memblock_alloc_nid(phys_addr_t size, phys_addr_t align, int nid)
 {
-       struct memblock_type *mem = &memblock.memory;
-       int i;
-
-       BUG_ON(0 == size);
+       phys_addr_t found;
 
-       /* We align the size to limit fragmentation. Without this, a lot of
+       /*
+        * We align the size to limit fragmentation. Without this, a lot of
         * small allocs quickly eat up the whole reserve array on sparc
         */
-       size = memblock_align_up(size, align);
+       size = round_up(size, align);
 
-       /* We do a bottom-up search for a region with the right
-        * nid since that's easier considering how memblock_nid_range()
-        * works
-        */
-       for (i = 0; i < mem->cnt; i++) {
-               phys_addr_t ret = memblock_alloc_nid_region(&mem->regions[i],
-                                              size, align, nid);
-               if (ret != MEMBLOCK_ERROR)
-                       return ret;
-       }
+       found = memblock_find_in_range_node(0, MEMBLOCK_ALLOC_ACCESSIBLE,
+                                           size, align, nid);
+       if (found && !memblock_add_region(&memblock.reserved, found, size))
+               return found;
 
        return 0;
 }
@@ -613,7 +760,7 @@ phys_addr_t __init memblock_alloc_try_nid(phys_addr_t size, phys_addr_t align, i
 
        if (res)
                return res;
-       return memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ANYWHERE);
+       return memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ACCESSIBLE);
 }
 
 
@@ -731,19 +878,26 @@ void __init_memblock memblock_set_current_limit(phys_addr_t limit)
        memblock.current_limit = limit;
 }
 
-static void __init_memblock memblock_dump(struct memblock_type *region, char *name)
+static void __init_memblock memblock_dump(struct memblock_type *type, char *name)
 {
        unsigned long long base, size;
        int i;
 
-       pr_info(" %s.cnt  = 0x%lx\n", name, region->cnt);
-
-       for (i = 0; i < region->cnt; i++) {
-               base = region->regions[i].base;
-               size = region->regions[i].size;
+       pr_info(" %s.cnt  = 0x%lx\n", name, type->cnt);
 
-               pr_info(" %s[%#x]\t[%#016llx-%#016llx], %#llx bytes\n",
-                   name, i, base, base + size - 1, size);
+       for (i = 0; i < type->cnt; i++) {
+               struct memblock_region *rgn = &type->regions[i];
+               char nid_buf[32] = "";
+
+               base = rgn->base;
+               size = rgn->size;
+#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
+               if (memblock_get_region_node(rgn) != MAX_NUMNODES)
+                       snprintf(nid_buf, sizeof(nid_buf), " on node %d",
+                                memblock_get_region_node(rgn));
+#endif
+               pr_info(" %s[%#x]\t[%#016llx-%#016llx], %#llx bytes%s\n",
+                       name, i, base, base + size - 1, size, nid_buf);
        }
 }
 
@@ -801,11 +955,13 @@ void __init memblock_init(void)
         */
        memblock.memory.regions[0].base = 0;
        memblock.memory.regions[0].size = 0;
+       memblock_set_region_node(&memblock.memory.regions[0], MAX_NUMNODES);
        memblock.memory.cnt = 1;
 
        /* Ditto. */
        memblock.reserved.regions[0].base = 0;
        memblock.reserved.regions[0].size = 0;
+       memblock_set_region_node(&memblock.reserved.regions[0], MAX_NUMNODES);
        memblock.reserved.cnt = 1;
 
        memblock.current_limit = MEMBLOCK_ALLOC_ANYWHERE;
@@ -819,7 +975,7 @@ static int __init early_memblock(char *p)
 }
 early_param("memblock", early_memblock);
 
-#if defined(CONFIG_DEBUG_FS) && !defined(ARCH_DISCARD_MEMBLOCK)
+#if defined(CONFIG_DEBUG_FS) && !defined(CONFIG_ARCH_DISCARD_MEMBLOCK)
 
 static int memblock_debug_show(struct seq_file *m, void *private)
 {
index 7fa41b4a07bf2c129d57d2df5be92b434252ca7e..24f0fc1a56d60ebbbacf1950ac0ebec7067dbf41 100644 (file)
@@ -41,14 +41,13 @@ static void * __init __alloc_memory_core_early(int nid, u64 size, u64 align,
        if (limit > memblock.current_limit)
                limit = memblock.current_limit;
 
-       addr = find_memory_core_early(nid, size, align, goal, limit);
-
-       if (addr == MEMBLOCK_ERROR)
+       addr = memblock_find_in_range_node(goal, limit, size, align, nid);
+       if (!addr)
                return NULL;
 
        ptr = phys_to_virt(addr);
        memset(ptr, 0, size);
-       memblock_x86_reserve_range(addr, addr + size, "BOOTMEM");
+       memblock_reserve(addr, size);
        /*
         * The min_count is set to 0 so that bootmem allocated blocks
         * are never reported as leaks.
@@ -107,23 +106,27 @@ static void __init __free_pages_memory(unsigned long start, unsigned long end)
                __free_pages_bootmem(pfn_to_page(i), 0);
 }
 
-unsigned long __init free_all_memory_core_early(int nodeid)
+unsigned long __init free_low_memory_core_early(int nodeid)
 {
-       int i;
-       u64 start, end;
        unsigned long count = 0;
-       struct range *range = NULL;
-       int nr_range;
-
-       nr_range = get_free_all_memory_range(&range, nodeid);
-
-       for (i = 0; i < nr_range; i++) {
-               start = range[i].start;
-               end = range[i].end;
-               count += end - start;
-               __free_pages_memory(start, end);
+       phys_addr_t start, end;
+       u64 i;
+
+       /* free reserved array temporarily so that it's treated as free area */
+       memblock_free_reserved_regions();
+
+       for_each_free_mem_range(i, MAX_NUMNODES, &start, &end, NULL) {
+               unsigned long start_pfn = PFN_UP(start);
+               unsigned long end_pfn = min_t(unsigned long,
+                                             PFN_DOWN(end), max_low_pfn);
+               if (start_pfn < end_pfn) {
+                       __free_pages_memory(start_pfn, end_pfn);
+                       count += end_pfn - start_pfn;
+               }
        }
 
+       /* put region array back? */
+       memblock_reserve_reserved_regions();
        return count;
 }
 
@@ -137,7 +140,7 @@ unsigned long __init free_all_bootmem_node(pg_data_t *pgdat)
 {
        register_page_bootmem_info_node(pgdat);
 
-       /* free_all_memory_core_early(MAX_NUMNODES) will be called later */
+       /* free_low_memory_core_early(MAX_NUMNODES) will be called later */
        return 0;
 }
 
@@ -155,7 +158,7 @@ unsigned long __init free_all_bootmem(void)
         * Use MAX_NUMNODES will make sure all ranges in early_node_map[]
         *  will be used instead of only Node0 related
         */
-       return free_all_memory_core_early(MAX_NUMNODES);
+       return free_low_memory_core_early(MAX_NUMNODES);
 }
 
 /**
@@ -172,7 +175,7 @@ void __init free_bootmem_node(pg_data_t *pgdat, unsigned long physaddr,
                              unsigned long size)
 {
        kmemleak_free_part(__va(physaddr), size);
-       memblock_x86_free_range(physaddr, physaddr + size);
+       memblock_free(physaddr, size);
 }
 
 /**
@@ -187,7 +190,7 @@ void __init free_bootmem_node(pg_data_t *pgdat, unsigned long physaddr,
 void __init free_bootmem(unsigned long addr, unsigned long size)
 {
        kmemleak_free_part(__va(addr), size);
-       memblock_x86_free_range(addr, addr + size);
+       memblock_free(addr, size);
 }
 
 static void * __init ___alloc_bootmem_nopanic(unsigned long size,
index 9dd443d89d8be665813bbeb4e17e54fafde46428..6ce27331834c94ee944a68fed300abc57dd1d850 100644 (file)
@@ -182,28 +182,31 @@ static unsigned long __meminitdata nr_all_pages;
 static unsigned long __meminitdata dma_reserve;
 
 #ifdef CONFIG_ARCH_POPULATES_NODE_MAP
-  /*
-   * MAX_ACTIVE_REGIONS determines the maximum number of distinct
-   * ranges of memory (RAM) that may be registered with add_active_range().
-   * Ranges passed to add_active_range() will be merged if possible
-   * so the number of times add_active_range() can be called is
-   * related to the number of nodes and the number of holes
-   */
-  #ifdef CONFIG_MAX_ACTIVE_REGIONS
-    /* Allow an architecture to set MAX_ACTIVE_REGIONS to save memory */
-    #define MAX_ACTIVE_REGIONS CONFIG_MAX_ACTIVE_REGIONS
-  #else
-    #if MAX_NUMNODES >= 32
-      /* If there can be many nodes, allow up to 50 holes per node */
-      #define MAX_ACTIVE_REGIONS (MAX_NUMNODES*50)
+  #ifndef CONFIG_HAVE_MEMBLOCK_NODE_MAP
+    /*
+     * MAX_ACTIVE_REGIONS determines the maximum number of distinct ranges
+     * of memory (RAM) that may be registered with add_active_range().
+     * Ranges passed to add_active_range() will be merged if possible so
+     * the number of times add_active_range() can be called is related to
+     * the number of nodes and the number of holes
+     */
+    #ifdef CONFIG_MAX_ACTIVE_REGIONS
+      /* Allow an architecture to set MAX_ACTIVE_REGIONS to save memory */
+      #define MAX_ACTIVE_REGIONS CONFIG_MAX_ACTIVE_REGIONS
     #else
-      /* By default, allow up to 256 distinct regions */
-      #define MAX_ACTIVE_REGIONS 256
+      #if MAX_NUMNODES >= 32
+        /* If there can be many nodes, allow up to 50 holes per node */
+        #define MAX_ACTIVE_REGIONS (MAX_NUMNODES*50)
+      #else
+        /* By default, allow up to 256 distinct regions */
+        #define MAX_ACTIVE_REGIONS 256
+      #endif
     #endif
-  #endif
 
-  static struct node_active_region __meminitdata early_node_map[MAX_ACTIVE_REGIONS];
-  static int __meminitdata nr_nodemap_entries;
+    static struct node_active_region __meminitdata early_node_map[MAX_ACTIVE_REGIONS];
+    static int __meminitdata nr_nodemap_entries;
+#endif /* !CONFIG_HAVE_MEMBLOCK_NODE_MAP */
+
   static unsigned long __meminitdata arch_zone_lowest_possible_pfn[MAX_NR_ZONES];
   static unsigned long __meminitdata arch_zone_highest_possible_pfn[MAX_NR_ZONES];
   static unsigned long __initdata required_kernelcore;
@@ -706,10 +709,10 @@ void __meminit __free_pages_bootmem(struct page *page, unsigned int order)
                int loop;
 
                prefetchw(page);
-               for (loop = 0; loop < BITS_PER_LONG; loop++) {
+               for (loop = 0; loop < (1 << order); loop++) {
                        struct page *p = &page[loop];
 
-                       if (loop + 1 < BITS_PER_LONG)
+                       if (loop + 1 < (1 << order))
                                prefetchw(p + 1);
                        __ClearPageReserved(p);
                        set_page_count(p, 0);
@@ -3732,34 +3735,6 @@ __meminit int init_currently_empty_zone(struct zone *zone,
 }
 
 #ifdef CONFIG_ARCH_POPULATES_NODE_MAP
-/*
- * Basic iterator support. Return the first range of PFNs for a node
- * Note: nid == MAX_NUMNODES returns first region regardless of node
- */
-static int __meminit first_active_region_index_in_nid(int nid)
-{
-       int i;
-
-       for (i = 0; i < nr_nodemap_entries; i++)
-               if (nid == MAX_NUMNODES || early_node_map[i].nid == nid)
-                       return i;
-
-       return -1;
-}
-
-/*
- * Basic iterator support. Return the next active range of PFNs for a node
- * Note: nid == MAX_NUMNODES returns next region regardless of node
- */
-static int __meminit next_active_region_index_in_nid(int index, int nid)
-{
-       for (index = index + 1; index < nr_nodemap_entries; index++)
-               if (nid == MAX_NUMNODES || early_node_map[index].nid == nid)
-                       return index;
-
-       return -1;
-}
-
 #ifndef CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID
 /*
  * Required by SPARSEMEM. Given a PFN, return what node the PFN is on.
@@ -3769,15 +3744,12 @@ static int __meminit next_active_region_index_in_nid(int index, int nid)
  */
 int __meminit __early_pfn_to_nid(unsigned long pfn)
 {
-       int i;
-
-       for (i = 0; i < nr_nodemap_entries; i++) {
-               unsigned long start_pfn = early_node_map[i].start_pfn;
-               unsigned long end_pfn = early_node_map[i].end_pfn;
+       unsigned long start_pfn, end_pfn;
+       int i, nid;
 
+       for_each_mem_pfn_range(i, MAX_NUMNODES, &start_pfn, &end_pfn, &nid)
                if (start_pfn <= pfn && pfn < end_pfn)
-                       return early_node_map[i].nid;
-       }
+                       return nid;
        /* This is a memory hole */
        return -1;
 }
@@ -3806,11 +3778,6 @@ bool __meminit early_pfn_in_nid(unsigned long pfn, int node)
 }
 #endif
 
-/* Basic iterator support to walk early_node_map[] */
-#define for_each_active_range_index_in_nid(i, nid) \
-       for (i = first_active_region_index_in_nid(nid); i != -1; \
-                               i = next_active_region_index_in_nid(i, nid))
-
 /**
  * free_bootmem_with_active_regions - Call free_bootmem_node for each active range
  * @nid: The node to free memory on. If MAX_NUMNODES, all nodes are freed.
@@ -3820,122 +3787,34 @@ bool __meminit early_pfn_in_nid(unsigned long pfn, int node)
  * add_active_ranges() contain no holes and may be freed, this
  * this function may be used instead of calling free_bootmem() manually.
  */
-void __init free_bootmem_with_active_regions(int nid,
-                                               unsigned long max_low_pfn)
+void __init free_bootmem_with_active_regions(int nid, unsigned long max_low_pfn)
 {
-       int i;
-
-       for_each_active_range_index_in_nid(i, nid) {
-               unsigned long size_pages = 0;
-               unsigned long end_pfn = early_node_map[i].end_pfn;
-
-               if (early_node_map[i].start_pfn >= max_low_pfn)
-                       continue;
+       unsigned long start_pfn, end_pfn;
+       int i, this_nid;
 
-               if (end_pfn > max_low_pfn)
-                       end_pfn = max_low_pfn;
+       for_each_mem_pfn_range(i, nid, &start_pfn, &end_pfn, &this_nid) {
+               start_pfn = min(start_pfn, max_low_pfn);
+               end_pfn = min(end_pfn, max_low_pfn);
 
-               size_pages = end_pfn - early_node_map[i].start_pfn;
-               free_bootmem_node(NODE_DATA(early_node_map[i].nid),
-                               PFN_PHYS(early_node_map[i].start_pfn),
-                               size_pages << PAGE_SHIFT);
+               if (start_pfn < end_pfn)
+                       free_bootmem_node(NODE_DATA(this_nid),
+                                         PFN_PHYS(start_pfn),
+                                         (end_pfn - start_pfn) << PAGE_SHIFT);
        }
 }
 
-#ifdef CONFIG_HAVE_MEMBLOCK
-/*
- * Basic iterator support. Return the last range of PFNs for a node
- * Note: nid == MAX_NUMNODES returns last region regardless of node
- */
-static int __meminit last_active_region_index_in_nid(int nid)
-{
-       int i;
-
-       for (i = nr_nodemap_entries - 1; i >= 0; i--)
-               if (nid == MAX_NUMNODES || early_node_map[i].nid == nid)
-                       return i;
-
-       return -1;
-}
-
-/*
- * Basic iterator support. Return the previous active range of PFNs for a node
- * Note: nid == MAX_NUMNODES returns next region regardless of node
- */
-static int __meminit previous_active_region_index_in_nid(int index, int nid)
-{
-       for (index = index - 1; index >= 0; index--)
-               if (nid == MAX_NUMNODES || early_node_map[index].nid == nid)
-                       return index;
-
-       return -1;
-}
-
-#define for_each_active_range_index_in_nid_reverse(i, nid) \
-       for (i = last_active_region_index_in_nid(nid); i != -1; \
-                               i = previous_active_region_index_in_nid(i, nid))
-
-u64 __init find_memory_core_early(int nid, u64 size, u64 align,
-                                       u64 goal, u64 limit)
-{
-       int i;
-
-       /* Need to go over early_node_map to find out good range for node */
-       for_each_active_range_index_in_nid_reverse(i, nid) {
-               u64 addr;
-               u64 ei_start, ei_last;
-               u64 final_start, final_end;
-
-               ei_last = early_node_map[i].end_pfn;
-               ei_last <<= PAGE_SHIFT;
-               ei_start = early_node_map[i].start_pfn;
-               ei_start <<= PAGE_SHIFT;
-
-               final_start = max(ei_start, goal);
-               final_end = min(ei_last, limit);
-
-               if (final_start >= final_end)
-                       continue;
-
-               addr = memblock_find_in_range(final_start, final_end, size, align);
-
-               if (addr == MEMBLOCK_ERROR)
-                       continue;
-
-               return addr;
-       }
-
-       return MEMBLOCK_ERROR;
-}
-#endif
-
 int __init add_from_early_node_map(struct range *range, int az,
                                   int nr_range, int nid)
 {
+       unsigned long start_pfn, end_pfn;
        int i;
-       u64 start, end;
 
        /* need to go over early_node_map to find out good range for node */
-       for_each_active_range_index_in_nid(i, nid) {
-               start = early_node_map[i].start_pfn;
-               end = early_node_map[i].end_pfn;
-               nr_range = add_range(range, az, nr_range, start, end);
-       }
+       for_each_mem_pfn_range(i, nid, &start_pfn, &end_pfn, NULL)
+               nr_range = add_range(range, az, nr_range, start_pfn, end_pfn);
        return nr_range;
 }
 
-void __init work_with_active_regions(int nid, work_fn_t work_fn, void *data)
-{
-       int i;
-       int ret;
-
-       for_each_active_range_index_in_nid(i, nid) {
-               ret = work_fn(early_node_map[i].start_pfn,
-                             early_node_map[i].end_pfn, data);
-               if (ret)
-                       break;
-       }
-}
 /**
  * sparse_memory_present_with_active_regions - Call memory_present for each active range
  * @nid: The node to call memory_present for. If MAX_NUMNODES, all nodes will be used.
@@ -3946,12 +3825,11 @@ void __init work_with_active_regions(int nid, work_fn_t work_fn, void *data)
  */
 void __init sparse_memory_present_with_active_regions(int nid)
 {
-       int i;
+       unsigned long start_pfn, end_pfn;
+       int i, this_nid;
 
-       for_each_active_range_index_in_nid(i, nid)
-               memory_present(early_node_map[i].nid,
-                               early_node_map[i].start_pfn,
-                               early_node_map[i].end_pfn);
+       for_each_mem_pfn_range(i, nid, &start_pfn, &end_pfn, &this_nid)
+               memory_present(this_nid, start_pfn, end_pfn);
 }
 
 /**
@@ -3968,13 +3846,15 @@ void __init sparse_memory_present_with_active_regions(int nid)
 void __meminit get_pfn_range_for_nid(unsigned int nid,
                        unsigned long *start_pfn, unsigned long *end_pfn)
 {
+       unsigned long this_start_pfn, this_end_pfn;
        int i;
+
        *start_pfn = -1UL;
        *end_pfn = 0;
 
-       for_each_active_range_index_in_nid(i, nid) {
-               *start_pfn = min(*start_pfn, early_node_map[i].start_pfn);
-               *end_pfn = max(*end_pfn, early_node_map[i].end_pfn);
+       for_each_mem_pfn_range(i, nid, &this_start_pfn, &this_end_pfn, NULL) {
+               *start_pfn = min(*start_pfn, this_start_pfn);
+               *end_pfn = max(*end_pfn, this_end_pfn);
        }
 
        if (*start_pfn == -1UL)
@@ -4077,46 +3957,16 @@ unsigned long __meminit __absent_pages_in_range(int nid,
                                unsigned long range_start_pfn,
                                unsigned long range_end_pfn)
 {
-       int i = 0;
-       unsigned long prev_end_pfn = 0, hole_pages = 0;
-       unsigned long start_pfn;
-
-       /* Find the end_pfn of the first active range of pfns in the node */
-       i = first_active_region_index_in_nid(nid);
-       if (i == -1)
-               return 0;
-
-       prev_end_pfn = min(early_node_map[i].start_pfn, range_end_pfn);
-
-       /* Account for ranges before physical memory on this node */
-       if (early_node_map[i].start_pfn > range_start_pfn)
-               hole_pages = prev_end_pfn - range_start_pfn;
-
-       /* Find all holes for the zone within the node */
-       for (; i != -1; i = next_active_region_index_in_nid(i, nid)) {
-
-               /* No need to continue if prev_end_pfn is outside the zone */
-               if (prev_end_pfn >= range_end_pfn)
-                       break;
-
-               /* Make sure the end of the zone is not within the hole */
-               start_pfn = min(early_node_map[i].start_pfn, range_end_pfn);
-               prev_end_pfn = max(prev_end_pfn, range_start_pfn);
+       unsigned long nr_absent = range_end_pfn - range_start_pfn;
+       unsigned long start_pfn, end_pfn;
+       int i;
 
-               /* Update the hole size cound and move on */
-               if (start_pfn > range_start_pfn) {
-                       BUG_ON(prev_end_pfn > start_pfn);
-                       hole_pages += start_pfn - prev_end_pfn;
-               }
-               prev_end_pfn = early_node_map[i].end_pfn;
+       for_each_mem_pfn_range(i, nid, &start_pfn, &end_pfn, NULL) {
+               start_pfn = clamp(start_pfn, range_start_pfn, range_end_pfn);
+               end_pfn = clamp(end_pfn, range_start_pfn, range_end_pfn);
+               nr_absent -= end_pfn - start_pfn;
        }
-
-       /* Account for ranges past physical memory on this node */
-       if (range_end_pfn > prev_end_pfn)
-               hole_pages += range_end_pfn -
-                               max(range_start_pfn, prev_end_pfn);
-
-       return hole_pages;
+       return nr_absent;
 }
 
 /**
@@ -4137,14 +3987,14 @@ static unsigned long __meminit zone_absent_pages_in_node(int nid,
                                        unsigned long zone_type,
                                        unsigned long *ignored)
 {
+       unsigned long zone_low = arch_zone_lowest_possible_pfn[zone_type];
+       unsigned long zone_high = arch_zone_highest_possible_pfn[zone_type];
        unsigned long node_start_pfn, node_end_pfn;
        unsigned long zone_start_pfn, zone_end_pfn;
 
        get_pfn_range_for_nid(nid, &node_start_pfn, &node_end_pfn);
-       zone_start_pfn = max(arch_zone_lowest_possible_pfn[zone_type],
-                                                       node_start_pfn);
-       zone_end_pfn = min(arch_zone_highest_possible_pfn[zone_type],
-                                                       node_end_pfn);
+       zone_start_pfn = clamp(node_start_pfn, zone_low, zone_high);
+       zone_end_pfn = clamp(node_end_pfn, zone_low, zone_high);
 
        adjust_zone_range_for_zone_movable(nid, zone_type,
                        node_start_pfn, node_end_pfn,
@@ -4442,6 +4292,35 @@ static inline void setup_nr_node_ids(void)
 }
 #endif
 
+#ifndef CONFIG_HAVE_MEMBLOCK_NODE_MAP
+/*
+ * Common iterator interface used to define for_each_mem_pfn_range().
+ */
+void __meminit __next_mem_pfn_range(int *idx, int nid,
+                                   unsigned long *out_start_pfn,
+                                   unsigned long *out_end_pfn, int *out_nid)
+{
+       struct node_active_region *r = NULL;
+
+       while (++*idx < nr_nodemap_entries) {
+               if (nid == MAX_NUMNODES || nid == early_node_map[*idx].nid) {
+                       r = &early_node_map[*idx];
+                       break;
+               }
+       }
+       if (!r) {
+               *idx = -1;
+               return;
+       }
+
+       if (out_start_pfn)
+               *out_start_pfn = r->start_pfn;
+       if (out_end_pfn)
+               *out_end_pfn = r->end_pfn;
+       if (out_nid)
+               *out_nid = r->nid;
+}
+
 /**
  * add_active_range - Register a range of PFNs backed by physical memory
  * @nid: The node ID the range resides on
@@ -4519,6 +4398,7 @@ void __init add_active_range(unsigned int nid, unsigned long start_pfn,
 void __init remove_active_range(unsigned int nid, unsigned long start_pfn,
                                unsigned long end_pfn)
 {
+       unsigned long this_start_pfn, this_end_pfn;
        int i, j;
        int removed = 0;
 
@@ -4526,26 +4406,22 @@ void __init remove_active_range(unsigned int nid, unsigned long start_pfn,
                          nid, start_pfn, end_pfn);
 
        /* Find the old active region end and shrink */
-       for_each_active_range_index_in_nid(i, nid) {
-               if (early_node_map[i].start_pfn >= start_pfn &&
-                   early_node_map[i].end_pfn <= end_pfn) {
+       for_each_mem_pfn_range(i, nid, &this_start_pfn, &this_end_pfn, NULL) {
+               if (this_start_pfn >= start_pfn && this_end_pfn <= end_pfn) {
                        /* clear it */
                        early_node_map[i].start_pfn = 0;
                        early_node_map[i].end_pfn = 0;
                        removed = 1;
                        continue;
                }
-               if (early_node_map[i].start_pfn < start_pfn &&
-                   early_node_map[i].end_pfn > start_pfn) {
-                       unsigned long temp_end_pfn = early_node_map[i].end_pfn;
+               if (this_start_pfn < start_pfn && this_end_pfn > start_pfn) {
                        early_node_map[i].end_pfn = start_pfn;
-                       if (temp_end_pfn > end_pfn)
-                               add_active_range(nid, end_pfn, temp_end_pfn);
+                       if (this_end_pfn > end_pfn)
+                               add_active_range(nid, end_pfn, this_end_pfn);
                        continue;
                }
-               if (early_node_map[i].start_pfn >= start_pfn &&
-                   early_node_map[i].end_pfn > end_pfn &&
-                   early_node_map[i].start_pfn < end_pfn) {
+               if (this_start_pfn >= start_pfn && this_end_pfn > end_pfn &&
+                   this_start_pfn < end_pfn) {
                        early_node_map[i].start_pfn = end_pfn;
                        continue;
                }
@@ -4605,6 +4481,11 @@ void __init sort_node_map(void)
                        sizeof(struct node_active_region),
                        cmp_node_active_region, NULL);
 }
+#else /* !CONFIG_HAVE_MEMBLOCK_NODE_MAP */
+static inline void sort_node_map(void)
+{
+}
+#endif
 
 /**
  * node_map_pfn_alignment - determine the maximum internode alignment
@@ -4628,15 +4509,11 @@ void __init sort_node_map(void)
 unsigned long __init node_map_pfn_alignment(void)
 {
        unsigned long accl_mask = 0, last_end = 0;
+       unsigned long start, end, mask;
        int last_nid = -1;
-       int i;
-
-       for_each_active_range_index_in_nid(i, MAX_NUMNODES) {
-               int nid = early_node_map[i].nid;
-               unsigned long start = early_node_map[i].start_pfn;
-               unsigned long end = early_node_map[i].end_pfn;
-               unsigned long mask;
+       int i, nid;
 
+       for_each_mem_pfn_range(i, MAX_NUMNODES, &start, &end, &nid) {
                if (!start || last_nid < 0 || last_nid == nid) {
                        last_nid = nid;
                        last_end = end;
@@ -4663,12 +4540,12 @@ unsigned long __init node_map_pfn_alignment(void)
 /* Find the lowest pfn for a node */
 static unsigned long __init find_min_pfn_for_node(int nid)
 {
-       int i;
        unsigned long min_pfn = ULONG_MAX;
+       unsigned long start_pfn;
+       int i;
 
-       /* Assuming a sorted map, the first range found has the starting pfn */
-       for_each_active_range_index_in_nid(i, nid)
-               min_pfn = min(min_pfn, early_node_map[i].start_pfn);
+       for_each_mem_pfn_range(i, nid, &start_pfn, NULL, NULL)
+               min_pfn = min(min_pfn, start_pfn);
 
        if (min_pfn == ULONG_MAX) {
                printk(KERN_WARNING
@@ -4697,15 +4574,16 @@ unsigned long __init find_min_pfn_with_active_regions(void)
  */
 static unsigned long __init early_calculate_totalpages(void)
 {
-       int i;
        unsigned long totalpages = 0;
+       unsigned long start_pfn, end_pfn;
+       int i, nid;
+
+       for_each_mem_pfn_range(i, MAX_NUMNODES, &start_pfn, &end_pfn, &nid) {
+               unsigned long pages = end_pfn - start_pfn;
 
-       for (i = 0; i < nr_nodemap_entries; i++) {
-               unsigned long pages = early_node_map[i].end_pfn -
-                                               early_node_map[i].start_pfn;
                totalpages += pages;
                if (pages)
-                       node_set_state(early_node_map[i].nid, N_HIGH_MEMORY);
+                       node_set_state(nid, N_HIGH_MEMORY);
        }
        return totalpages;
 }
@@ -4760,6 +4638,8 @@ restart:
        /* Spread kernelcore memory as evenly as possible throughout nodes */
        kernelcore_node = required_kernelcore / usable_nodes;
        for_each_node_state(nid, N_HIGH_MEMORY) {
+               unsigned long start_pfn, end_pfn;
+
                /*
                 * Recalculate kernelcore_node if the division per node
                 * now exceeds what is necessary to satisfy the requested
@@ -4776,13 +4656,10 @@ restart:
                kernelcore_remaining = kernelcore_node;
 
                /* Go through each range of PFNs within this node */
-               for_each_active_range_index_in_nid(i, nid) {
-                       unsigned long start_pfn, end_pfn;
+               for_each_mem_pfn_range(i, nid, &start_pfn, &end_pfn, NULL) {
                        unsigned long size_pages;
 
-                       start_pfn = max(early_node_map[i].start_pfn,
-                                               zone_movable_pfn[nid]);
-                       end_pfn = early_node_map[i].end_pfn;
+                       start_pfn = max(start_pfn, zone_movable_pfn[nid]);
                        if (start_pfn >= end_pfn)
                                continue;
 
@@ -4884,8 +4761,8 @@ static void check_for_regular_memory(pg_data_t *pgdat)
  */
 void __init free_area_init_nodes(unsigned long *max_zone_pfn)
 {
-       unsigned long nid;
-       int i;
+       unsigned long start_pfn, end_pfn;
+       int i, nid;
 
        /* Sort early_node_map as initialisation assumes it is sorted */
        sort_node_map();
@@ -4935,11 +4812,9 @@ void __init free_area_init_nodes(unsigned long *max_zone_pfn)
        }
 
        /* Print out the early_node_map[] */
-       printk("early_node_map[%d] active PFN ranges\n", nr_nodemap_entries);
-       for (i = 0; i < nr_nodemap_entries; i++)
-               printk("  %3d: %0#10lx -> %0#10lx\n", early_node_map[i].nid,
-                                               early_node_map[i].start_pfn,
-                                               early_node_map[i].end_pfn);
+       printk("Early memory PFN ranges\n");
+       for_each_mem_pfn_range(i, MAX_NUMNODES, &start_pfn, &end_pfn, &nid)
+               printk("  %3d: %0#10lx -> %0#10lx\n", nid, start_pfn, end_pfn);
 
        /* Initialise every node */
        mminit_verify_pageflags_layout();