aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/i386/mm/init.c2
-rw-r--r--arch/ia64/mm/init.c5
-rw-r--r--arch/powerpc/mm/mem.c11
-rw-r--r--arch/x86_64/mm/init.c66
-rw-r--r--drivers/acpi/Kconfig2
-rw-r--r--drivers/acpi/acpi_memhotplug.c3
-rw-r--r--drivers/base/memory.c4
-rw-r--r--include/linux/memory_hotplug.h13
-rw-r--r--mm/memory_hotplug.c11
9 files changed, 78 insertions, 39 deletions
diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c
index bf19513f0cea..468592531793 100644
--- a/arch/i386/mm/init.c
+++ b/arch/i386/mm/init.c
@@ -654,7 +654,7 @@ void __init mem_init(void)
654 */ 654 */
655#ifdef CONFIG_MEMORY_HOTPLUG 655#ifdef CONFIG_MEMORY_HOTPLUG
656#ifndef CONFIG_NEED_MULTIPLE_NODES 656#ifndef CONFIG_NEED_MULTIPLE_NODES
657int add_memory(u64 start, u64 size) 657int arch_add_memory(int nid, u64 start, u64 size)
658{ 658{
659 struct pglist_data *pgdata = &contig_page_data; 659 struct pglist_data *pgdata = &contig_page_data;
660 struct zone *zone = pgdata->node_zones + MAX_NR_ZONES-1; 660 struct zone *zone = pgdata->node_zones + MAX_NR_ZONES-1;
diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
index 11f08001f8c2..38306e98f04b 100644
--- a/arch/ia64/mm/init.c
+++ b/arch/ia64/mm/init.c
@@ -652,7 +652,7 @@ void online_page(struct page *page)
652 num_physpages++; 652 num_physpages++;
653} 653}
654 654
655int add_memory(u64 start, u64 size) 655int arch_add_memory(int nid, u64 start, u64 size)
656{ 656{
657 pg_data_t *pgdat; 657 pg_data_t *pgdat;
658 struct zone *zone; 658 struct zone *zone;
@@ -660,7 +660,7 @@ int add_memory(u64 start, u64 size)
660 unsigned long nr_pages = size >> PAGE_SHIFT; 660 unsigned long nr_pages = size >> PAGE_SHIFT;
661 int ret; 661 int ret;
662 662
663 pgdat = NODE_DATA(0); 663 pgdat = NODE_DATA(nid);
664 664
665 zone = pgdat->node_zones + ZONE_NORMAL; 665 zone = pgdat->node_zones + ZONE_NORMAL;
666 ret = __add_pages(zone, start_pfn, nr_pages); 666 ret = __add_pages(zone, start_pfn, nr_pages);
@@ -671,7 +671,6 @@ int add_memory(u64 start, u64 size)
671 671
672 return ret; 672 return ret;
673} 673}
674EXPORT_SYMBOL_GPL(add_memory);
675 674
676int remove_memory(u64 start, u64 size) 675int remove_memory(u64 start, u64 size)
677{ 676{
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index 69f3b9a20beb..089d939a0b3e 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -114,15 +114,20 @@ void online_page(struct page *page)
114 num_physpages++; 114 num_physpages++;
115} 115}
116 116
117int __devinit add_memory(u64 start, u64 size) 117#ifdef CONFIG_NUMA
118int memory_add_physaddr_to_nid(u64 start)
119{
120 return hot_add_scn_to_nid(start);
121}
122#endif
123
124int __devinit arch_add_memory(int nid, u64 start, u64 size)
118{ 125{
119 struct pglist_data *pgdata; 126 struct pglist_data *pgdata;
120 struct zone *zone; 127 struct zone *zone;
121 int nid;
122 unsigned long start_pfn = start >> PAGE_SHIFT; 128 unsigned long start_pfn = start >> PAGE_SHIFT;
123 unsigned long nr_pages = size >> PAGE_SHIFT; 129 unsigned long nr_pages = size >> PAGE_SHIFT;
124 130
125 nid = hot_add_scn_to_nid(start);
126 pgdata = NODE_DATA(nid); 131 pgdata = NODE_DATA(nid);
127 132
128 start = (unsigned long)__va(start); 133 start = (unsigned long)__va(start);
diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c
index 02add1d1dfa8..51fbf3eddf13 100644
--- a/arch/x86_64/mm/init.c
+++ b/arch/x86_64/mm/init.c
@@ -506,8 +506,6 @@ void __init clear_kernel_mapping(unsigned long address, unsigned long size)
506/* 506/*
507 * Memory hotplug specific functions 507 * Memory hotplug specific functions
508 */ 508 */
509#if defined(CONFIG_ACPI_HOTPLUG_MEMORY) || defined(CONFIG_ACPI_HOTPLUG_MEMORY_MODULE)
510
511void online_page(struct page *page) 509void online_page(struct page *page)
512{ 510{
513 ClearPageReserved(page); 511 ClearPageReserved(page);
@@ -517,31 +515,17 @@ void online_page(struct page *page)
517 num_physpages++; 515 num_physpages++;
518} 516}
519 517
520#ifndef CONFIG_MEMORY_HOTPLUG 518#ifdef CONFIG_MEMORY_HOTPLUG
521/* 519/*
522 * Memory Hotadd without sparsemem. The mem_maps have been allocated in advance, 520 * XXX: memory_add_physaddr_to_nid() is to find node id from physical address
523 * just online the pages. 521 * via probe interface of sysfs. If acpi notifies hot-add event, then it
522 * can tell node id by searching dsdt. But, probe interface doesn't have
523 * node id. So, return 0 as node id at this time.
524 */ 524 */
525int __add_pages(struct zone *z, unsigned long start_pfn, unsigned long nr_pages) 525#ifdef CONFIG_NUMA
526int memory_add_physaddr_to_nid(u64 start)
526{ 527{
527 int err = -EIO; 528 return 0;
528 unsigned long pfn;
529 unsigned long total = 0, mem = 0;
530 for (pfn = start_pfn; pfn < start_pfn + nr_pages; pfn++) {
531 if (pfn_valid(pfn)) {
532 online_page(pfn_to_page(pfn));
533 err = 0;
534 mem++;
535 }
536 total++;
537 }
538 if (!err) {
539 z->spanned_pages += total;
540 z->present_pages += mem;
541 z->zone_pgdat->node_spanned_pages += total;
542 z->zone_pgdat->node_present_pages += mem;
543 }
544 return err;
545} 529}
546#endif 530#endif
547 531
@@ -549,9 +533,9 @@ int __add_pages(struct zone *z, unsigned long start_pfn, unsigned long nr_pages)
549 * Memory is added always to NORMAL zone. This means you will never get 533 * Memory is added always to NORMAL zone. This means you will never get
550 * additional DMA/DMA32 memory. 534 * additional DMA/DMA32 memory.
551 */ 535 */
552int add_memory(u64 start, u64 size) 536int arch_add_memory(int nid, u64 start, u64 size)
553{ 537{
554 struct pglist_data *pgdat = NODE_DATA(0); 538 struct pglist_data *pgdat = NODE_DATA(nid);
555 struct zone *zone = pgdat->node_zones + MAX_NR_ZONES-2; 539 struct zone *zone = pgdat->node_zones + MAX_NR_ZONES-2;
556 unsigned long start_pfn = start >> PAGE_SHIFT; 540 unsigned long start_pfn = start >> PAGE_SHIFT;
557 unsigned long nr_pages = size >> PAGE_SHIFT; 541 unsigned long nr_pages = size >> PAGE_SHIFT;
@@ -568,7 +552,7 @@ error:
568 printk("%s: Problem encountered in __add_pages!\n", __func__); 552 printk("%s: Problem encountered in __add_pages!\n", __func__);
569 return ret; 553 return ret;
570} 554}
571EXPORT_SYMBOL_GPL(add_memory); 555EXPORT_SYMBOL_GPL(arch_add_memory);
572 556
573int remove_memory(u64 start, u64 size) 557int remove_memory(u64 start, u64 size)
574{ 558{
@@ -576,7 +560,33 @@ int remove_memory(u64 start, u64 size)
576} 560}
577EXPORT_SYMBOL_GPL(remove_memory); 561EXPORT_SYMBOL_GPL(remove_memory);
578 562
579#endif 563#else /* CONFIG_MEMORY_HOTPLUG */
564/*
565 * Memory Hotadd without sparsemem. The mem_maps have been allocated in advance,
566 * just online the pages.
567 */
568int __add_pages(struct zone *z, unsigned long start_pfn, unsigned long nr_pages)
569{
570 int err = -EIO;
571 unsigned long pfn;
572 unsigned long total = 0, mem = 0;
573 for (pfn = start_pfn; pfn < start_pfn + nr_pages; pfn++) {
574 if (pfn_valid(pfn)) {
575 online_page(pfn_to_page(pfn));
576 err = 0;
577 mem++;
578 }
579 total++;
580 }
581 if (!err) {
582 z->spanned_pages += total;
583 z->present_pages += mem;
584 z->zone_pgdat->node_spanned_pages += total;
585 z->zone_pgdat->node_present_pages += mem;
586 }
587 return err;
588}
589#endif /* CONFIG_MEMORY_HOTPLUG */
580 590
581static struct kcore_list kcore_mem, kcore_vmalloc, kcore_kernel, kcore_modules, 591static struct kcore_list kcore_mem, kcore_vmalloc, kcore_kernel, kcore_modules,
582 kcore_vsyscall; 592 kcore_vsyscall;
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 94b8d820c512..610d2cc02cf8 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -328,7 +328,7 @@ config ACPI_CONTAINER
328config ACPI_HOTPLUG_MEMORY 328config ACPI_HOTPLUG_MEMORY
329 tristate "Memory Hotplug" 329 tristate "Memory Hotplug"
330 depends on ACPI 330 depends on ACPI
331 depends on MEMORY_HOTPLUG || X86_64 331 depends on MEMORY_HOTPLUG
332 default n 332 default n
333 help 333 help
334 This driver adds supports for ACPI Memory Hotplug. This driver 334 This driver adds supports for ACPI Memory Hotplug. This driver
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c
index 5652569b3762..0424326eae15 100644
--- a/drivers/acpi/acpi_memhotplug.c
+++ b/drivers/acpi/acpi_memhotplug.c
@@ -215,6 +215,7 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device)
215{ 215{
216 int result, num_enabled = 0; 216 int result, num_enabled = 0;
217 struct acpi_memory_info *info; 217 struct acpi_memory_info *info;
218 int node = 0;
218 219
219 ACPI_FUNCTION_TRACE("acpi_memory_enable_device"); 220 ACPI_FUNCTION_TRACE("acpi_memory_enable_device");
220 221
@@ -245,7 +246,7 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device)
245 continue; 246 continue;
246 } 247 }
247 248
248 result = add_memory(info->start_addr, info->length); 249 result = add_memory(node, info->start_addr, info->length);
249 if (result) 250 if (result)
250 continue; 251 continue;
251 info->enabled = 1; 252 info->enabled = 1;
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index dd547af4681a..c6b7d9c4b651 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -306,11 +306,13 @@ static ssize_t
306memory_probe_store(struct class *class, const char *buf, size_t count) 306memory_probe_store(struct class *class, const char *buf, size_t count)
307{ 307{
308 u64 phys_addr; 308 u64 phys_addr;
309 int nid;
309 int ret; 310 int ret;
310 311
311 phys_addr = simple_strtoull(buf, NULL, 0); 312 phys_addr = simple_strtoull(buf, NULL, 0);
312 313
313 ret = add_memory(phys_addr, PAGES_PER_SECTION << PAGE_SHIFT); 314 nid = memory_add_physaddr_to_nid(phys_addr);
315 ret = add_memory(nid, phys_addr, PAGES_PER_SECTION << PAGE_SHIFT);
314 316
315 if (ret) 317 if (ret)
316 count = ret; 318 count = ret;
diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h
index 911206386171..29c1472efad0 100644
--- a/include/linux/memory_hotplug.h
+++ b/include/linux/memory_hotplug.h
@@ -63,6 +63,16 @@ extern int online_pages(unsigned long, unsigned long);
63/* reasonably generic interface to expand the physical pages in a zone */ 63/* reasonably generic interface to expand the physical pages in a zone */
64extern int __add_pages(struct zone *zone, unsigned long start_pfn, 64extern int __add_pages(struct zone *zone, unsigned long start_pfn,
65 unsigned long nr_pages); 65 unsigned long nr_pages);
66
67#ifdef CONFIG_NUMA
68extern int memory_add_physaddr_to_nid(u64 start);
69#else
70static inline int memory_add_physaddr_to_nid(u64 start)
71{
72 return 0;
73}
74#endif
75
66#else /* ! CONFIG_MEMORY_HOTPLUG */ 76#else /* ! CONFIG_MEMORY_HOTPLUG */
67/* 77/*
68 * Stub functions for when hotplug is off 78 * Stub functions for when hotplug is off
@@ -99,7 +109,8 @@ static inline int __remove_pages(struct zone *zone, unsigned long start_pfn,
99 return -ENOSYS; 109 return -ENOSYS;
100} 110}
101 111
102extern int add_memory(u64 start, u64 size); 112extern int add_memory(int nid, u64 start, u64 size);
113extern int arch_add_memory(int nid, u64 start, u64 size);
103extern int remove_memory(u64 start, u64 size); 114extern int remove_memory(u64 start, u64 size);
104 115
105#endif /* __LINUX_MEMORY_HOTPLUG_H */ 116#endif /* __LINUX_MEMORY_HOTPLUG_H */
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 841a077d5aeb..6cdeabe9f6d4 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -163,3 +163,14 @@ int online_pages(unsigned long pfn, unsigned long nr_pages)
163 vm_total_pages = nr_free_pagecache_pages(); 163 vm_total_pages = nr_free_pagecache_pages();
164 return 0; 164 return 0;
165} 165}
166
167int add_memory(int nid, u64 start, u64 size)
168{
169 int ret;
170
171 /* call arch's memory hotadd */
172 ret = arch_add_memory(nid, start, size);
173
174 return ret;
175}
176EXPORT_SYMBOL_GPL(add_memory);