From: Yasunori Goto Change the name of old add_memory() to arch_add_memory. And use node id to get pgdat for the node at NODE_DATA(). Note: Powerpc's old add_memory() is defined as __devinit. However, add_memory() is usually called only after bootup. I suppose it may be redundant. But, I'm not well known about powerpc. So, I keep it. (But, __meminit is better at least.) Signed-off-by: Yasunori Goto Cc: Dave Hansen Cc: "Brown, Len" Signed-off-by: Andrew Morton --- arch/i386/mm/init.c | 2 arch/ia64/mm/init.c | 5 -- arch/powerpc/mm/mem.c | 11 +++-- arch/x86_64/mm/init.c | 66 +++++++++++++++++-------------- drivers/acpi/Kconfig | 2 drivers/acpi/acpi_memhotplug.c | 3 - drivers/base/memory.c | 4 + include/linux/memory_hotplug.h | 13 +++++- mm/memory_hotplug.c | 11 +++++ 9 files changed, 78 insertions(+), 39 deletions(-) diff -puN arch/i386/mm/init.c~pgdat-allocation-for-new-node-add-specify-node-id arch/i386/mm/init.c --- 25/arch/i386/mm/init.c~pgdat-allocation-for-new-node-add-specify-node-id Fri May 26 15:53:46 2006 +++ 25-akpm/arch/i386/mm/init.c Fri May 26 15:53:57 2006 @@ -653,7 +653,7 @@ void __init mem_init(void) */ #ifdef CONFIG_MEMORY_HOTPLUG #ifndef CONFIG_NEED_MULTIPLE_NODES -int add_memory(u64 start, u64 size) +int arch_add_memory(int nid, u64 start, u64 size) { struct pglist_data *pgdata = &contig_page_data; struct zone *zone = pgdata->node_zones + MAX_NR_ZONES-1; diff -puN arch/ia64/mm/init.c~pgdat-allocation-for-new-node-add-specify-node-id arch/ia64/mm/init.c --- 25/arch/ia64/mm/init.c~pgdat-allocation-for-new-node-add-specify-node-id Fri May 26 15:53:46 2006 +++ 25-akpm/arch/ia64/mm/init.c Fri May 26 15:53:58 2006 @@ -652,7 +652,7 @@ void online_page(struct page *page) num_physpages++; } -int add_memory(u64 start, u64 size) +int arch_add_memory(int nid, u64 start, u64 size) { pg_data_t *pgdat; struct zone *zone; @@ -660,7 +660,7 @@ int add_memory(u64 start, u64 size) unsigned long nr_pages = size >> PAGE_SHIFT; int ret; - pgdat = NODE_DATA(0); + pgdat = NODE_DATA(nid); zone = pgdat->node_zones + ZONE_NORMAL; ret = __add_pages(zone, start_pfn, nr_pages); @@ -671,7 +671,6 @@ int add_memory(u64 start, u64 size) return ret; } -EXPORT_SYMBOL_GPL(add_memory); int remove_memory(u64 start, u64 size) { diff -puN arch/powerpc/mm/mem.c~pgdat-allocation-for-new-node-add-specify-node-id arch/powerpc/mm/mem.c --- 25/arch/powerpc/mm/mem.c~pgdat-allocation-for-new-node-add-specify-node-id Fri May 26 15:53:46 2006 +++ 25-akpm/arch/powerpc/mm/mem.c Fri May 26 15:53:58 2006 @@ -114,15 +114,20 @@ void online_page(struct page *page) num_physpages++; } -int __devinit add_memory(u64 start, u64 size) +#ifdef CONFIG_NUMA +int memory_add_physaddr_to_nid(u64 start) +{ + return hot_add_scn_to_nid(start); +} +#endif + +int __devinit arch_add_memory(int nid, u64 start, u64 size) { struct pglist_data *pgdata; struct zone *zone; - int nid; unsigned long start_pfn = start >> PAGE_SHIFT; unsigned long nr_pages = size >> PAGE_SHIFT; - nid = hot_add_scn_to_nid(start); pgdata = NODE_DATA(nid); start = (unsigned long)__va(start); diff -puN arch/x86_64/mm/init.c~pgdat-allocation-for-new-node-add-specify-node-id arch/x86_64/mm/init.c --- 25/arch/x86_64/mm/init.c~pgdat-allocation-for-new-node-add-specify-node-id Fri May 26 15:53:46 2006 +++ 25-akpm/arch/x86_64/mm/init.c Fri May 26 15:53:58 2006 @@ -506,8 +506,6 @@ void __init clear_kernel_mapping(unsigne /* * Memory hotplug specific functions */ -#if defined(CONFIG_ACPI_HOTPLUG_MEMORY) || defined(CONFIG_ACPI_HOTPLUG_MEMORY_MODULE) - void online_page(struct page *page) { ClearPageReserved(page); @@ -517,31 +515,17 @@ void online_page(struct page *page) num_physpages++; } -#ifndef CONFIG_MEMORY_HOTPLUG +#ifdef CONFIG_MEMORY_HOTPLUG /* - * Memory Hotadd without sparsemem. The mem_maps have been allocated in advance, - * just online the pages. + * XXX: memory_add_physaddr_to_nid() is to find node id from physical address + * via probe interface of sysfs. If acpi notifies hot-add event, then it + * can tell node id by searching dsdt. But, probe interface doesn't have + * node id. So, return 0 as node id at this time. */ -int __add_pages(struct zone *z, unsigned long start_pfn, unsigned long nr_pages) +#ifdef CONFIG_NUMA +int memory_add_physaddr_to_nid(u64 start) { - int err = -EIO; - unsigned long pfn; - unsigned long total = 0, mem = 0; - for (pfn = start_pfn; pfn < start_pfn + nr_pages; pfn++) { - if (pfn_valid(pfn)) { - online_page(pfn_to_page(pfn)); - err = 0; - mem++; - } - total++; - } - if (!err) { - z->spanned_pages += total; - z->present_pages += mem; - z->zone_pgdat->node_spanned_pages += total; - z->zone_pgdat->node_present_pages += mem; - } - return err; + return 0; } #endif @@ -549,9 +533,9 @@ int __add_pages(struct zone *z, unsigned * Memory is added always to NORMAL zone. This means you will never get * additional DMA/DMA32 memory. */ -int add_memory(u64 start, u64 size) +int arch_add_memory(int nid, u64 start, u64 size) { - struct pglist_data *pgdat = NODE_DATA(0); + struct pglist_data *pgdat = NODE_DATA(nid); struct zone *zone = pgdat->node_zones + MAX_NR_ZONES-2; unsigned long start_pfn = start >> PAGE_SHIFT; unsigned long nr_pages = size >> PAGE_SHIFT; @@ -568,7 +552,7 @@ error: printk("%s: Problem encountered in __add_pages!\n", __func__); return ret; } -EXPORT_SYMBOL_GPL(add_memory); +EXPORT_SYMBOL_GPL(arch_add_memory); int remove_memory(u64 start, u64 size) { @@ -576,7 +560,33 @@ int remove_memory(u64 start, u64 size) } EXPORT_SYMBOL_GPL(remove_memory); -#endif +#else /* CONFIG_MEMORY_HOTPLUG */ +/* + * Memory Hotadd without sparsemem. The mem_maps have been allocated in advance, + * just online the pages. + */ +int __add_pages(struct zone *z, unsigned long start_pfn, unsigned long nr_pages) +{ + int err = -EIO; + unsigned long pfn; + unsigned long total = 0, mem = 0; + for (pfn = start_pfn; pfn < start_pfn + nr_pages; pfn++) { + if (pfn_valid(pfn)) { + online_page(pfn_to_page(pfn)); + err = 0; + mem++; + } + total++; + } + if (!err) { + z->spanned_pages += total; + z->present_pages += mem; + z->zone_pgdat->node_spanned_pages += total; + z->zone_pgdat->node_present_pages += mem; + } + return err; +} +#endif /* CONFIG_MEMORY_HOTPLUG */ static struct kcore_list kcore_mem, kcore_vmalloc, kcore_kernel, kcore_modules, kcore_vsyscall; diff -puN drivers/acpi/acpi_memhotplug.c~pgdat-allocation-for-new-node-add-specify-node-id drivers/acpi/acpi_memhotplug.c --- 25/drivers/acpi/acpi_memhotplug.c~pgdat-allocation-for-new-node-add-specify-node-id Fri May 26 15:53:46 2006 +++ 25-akpm/drivers/acpi/acpi_memhotplug.c Fri May 26 15:53:46 2006 @@ -209,6 +209,7 @@ static int acpi_memory_enable_device(str { int result, num_enabled = 0; struct acpi_memory_info *info; + int node = 0; /* Get the range from the _CRS */ result = acpi_memory_get_device_resources(mem_device); @@ -236,7 +237,7 @@ static int acpi_memory_enable_device(str continue; } - result = add_memory(info->start_addr, info->length); + result = add_memory(node, info->start_addr, info->length); if (result) continue; info->enabled = 1; diff -puN drivers/base/memory.c~pgdat-allocation-for-new-node-add-specify-node-id drivers/base/memory.c --- 25/drivers/base/memory.c~pgdat-allocation-for-new-node-add-specify-node-id Fri May 26 15:53:46 2006 +++ 25-akpm/drivers/base/memory.c Fri May 26 15:53:46 2006 @@ -306,11 +306,13 @@ static ssize_t memory_probe_store(struct class *class, const char *buf, size_t count) { u64 phys_addr; + int nid; int ret; phys_addr = simple_strtoull(buf, NULL, 0); - ret = add_memory(phys_addr, PAGES_PER_SECTION << PAGE_SHIFT); + nid = memory_add_physaddr_to_nid(phys_addr); + ret = add_memory(nid, phys_addr, PAGES_PER_SECTION << PAGE_SHIFT); if (ret) count = ret; diff -puN include/linux/memory_hotplug.h~pgdat-allocation-for-new-node-add-specify-node-id include/linux/memory_hotplug.h --- 25/include/linux/memory_hotplug.h~pgdat-allocation-for-new-node-add-specify-node-id Fri May 26 15:53:46 2006 +++ 25-akpm/include/linux/memory_hotplug.h Fri May 26 15:53:58 2006 @@ -63,6 +63,16 @@ extern int online_pages(unsigned long, u /* reasonably generic interface to expand the physical pages in a zone */ extern int __add_pages(struct zone *zone, unsigned long start_pfn, unsigned long nr_pages); + +#ifdef CONFIG_NUMA +extern int memory_add_physaddr_to_nid(u64 start); +#else +static inline int memory_add_physaddr_to_nid(u64 start) +{ + return 0; +} +#endif + #else /* ! CONFIG_MEMORY_HOTPLUG */ /* * Stub functions for when hotplug is off @@ -99,7 +109,8 @@ static inline int __remove_pages(struct return -ENOSYS; } -extern int add_memory(u64 start, u64 size); +extern int add_memory(int nid, u64 start, u64 size); +extern int arch_add_memory(int nid, u64 start, u64 size); extern int remove_memory(u64 start, u64 size); #endif /* __LINUX_MEMORY_HOTPLUG_H */ diff -puN mm/memory_hotplug.c~pgdat-allocation-for-new-node-add-specify-node-id mm/memory_hotplug.c --- 25/mm/memory_hotplug.c~pgdat-allocation-for-new-node-add-specify-node-id Fri May 26 15:53:46 2006 +++ 25-akpm/mm/memory_hotplug.c Fri May 26 15:53:58 2006 @@ -163,3 +163,14 @@ int online_pages(unsigned long pfn, unsi return 0; } + +int add_memory(int nid, u64 start, u64 size) +{ + int ret; + + /* call arch's memory hotadd */ + ret = arch_add_memory(nid, start, size); + + return ret; +} +EXPORT_SYMBOL_GPL(add_memory); diff -puN drivers/acpi/Kconfig~pgdat-allocation-for-new-node-add-specify-node-id drivers/acpi/Kconfig --- 25/drivers/acpi/Kconfig~pgdat-allocation-for-new-node-add-specify-node-id Fri May 26 15:53:57 2006 +++ 25-akpm/drivers/acpi/Kconfig Fri May 26 15:53:57 2006 @@ -360,7 +360,7 @@ config ACPI_CONTAINER config ACPI_HOTPLUG_MEMORY tristate "Memory Hotplug" depends on ACPI - depends on MEMORY_HOTPLUG || X86_64 + depends on MEMORY_HOTPLUG default n help This driver adds supports for ACPI Memory Hotplug. This driver _