Commit 9d99aaa31f5994d1923c3713ce9144c4c42332e1

Authored by Andi Kleen
Committed by Linus Torvalds
1 parent 805e8c03c9

[PATCH] x86_64: Support memory hotadd without sparsemem

Memory hotadd doesn't need SPARSEMEM, but can be handled by just preallocating
mem_maps. This only needs some untangling of ifdefs to enable the necessary
code even without SPARSEMEM.

Originally from Keith Mannthey, hacked by AK.

Signed-off-by: Andi Kleen <ak@suse.de>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

Showing 6 changed files with 47 additions and 12 deletions Side-by-side Diff

... ... @@ -651,6 +651,7 @@
651 651 * Specifically, in the case of x86, we will always add
652 652 * memory to the highmem for now.
653 653 */
  654 +#ifdef CONFIG_HOTPLUG_MEMORY
654 655 #ifndef CONFIG_NEED_MULTIPLE_NODES
655 656 int add_memory(u64 start, u64 size)
656 657 {
... ... @@ -666,6 +667,7 @@
666 667 {
667 668 return -EINVAL;
668 669 }
  670 +#endif
669 671 #endif
670 672  
671 673 kmem_cache_t *pgd_cache;
arch/x86_64/kernel/e820.c
... ... @@ -80,7 +80,7 @@
80 80 return 0;
81 81 }
82 82  
83   -int __init e820_mapped(unsigned long start, unsigned long end, unsigned type)
  83 +int __meminit e820_mapped(unsigned long start, unsigned long end, unsigned type)
84 84 {
85 85 int i;
86 86 for (i = 0; i < e820.nr_map; i++) {
arch/x86_64/mm/init.c
... ... @@ -507,9 +507,8 @@
507 507  
508 508 /*
509 509 * Memory hotplug specific functions
510   - * These are only for non-NUMA machines right now.
511 510 */
512   -#ifdef CONFIG_MEMORY_HOTPLUG
  511 +#if defined(CONFIG_ACPI_HOTPLUG_MEMORY) || defined(CONFIG_ACPI_HOTPLUG_MEMORY_MODULE)
513 512  
514 513 void online_page(struct page *page)
515 514 {
... ... @@ -520,6 +519,39 @@
520 519 num_physpages++;
521 520 }
522 521  
  522 +#ifndef CONFIG_MEMORY_HOTPLUG
  523 +/*
  524 + * Memory Hotadd without sparsemem. The mem_maps have been allocated in advance,
  525 + * just online the pages.
  526 + */
  527 +int __add_pages(struct zone *z, unsigned long start_pfn, unsigned long nr_pages)
  528 +{
  529 + int err = -EIO;
  530 + unsigned long pfn;
  531 + unsigned long total = 0, mem = 0;
  532 + for (pfn = start_pfn; pfn < start_pfn + nr_pages; pfn++) {
  533 + unsigned long addr = pfn << PAGE_SHIFT;
  534 + if (pfn_valid(pfn) && e820_mapped(addr, addr+1, E820_RAM)) {
  535 + online_page(pfn_to_page(pfn));
  536 + err = 0;
  537 + mem++;
  538 + }
  539 + total++;
  540 + }
  541 + if (!err) {
  542 + z->spanned_pages += total;
  543 + z->present_pages += mem;
  544 + z->zone_pgdat->node_spanned_pages += total;
  545 + z->zone_pgdat->node_present_pages += mem;
  546 + }
  547 + return err;
  548 +}
  549 +#endif
  550 +
  551 +/*
  552 + * Memory is added always to NORMAL zone. This means you will never get
  553 + * additional DMA/DMA32 memory.
  554 + */
523 555 int add_memory(u64 start, u64 size)
524 556 {
525 557 struct pglist_data *pgdat = NODE_DATA(0);
drivers/acpi/Kconfig
... ... @@ -329,7 +329,7 @@
329 329 config ACPI_HOTPLUG_MEMORY
330 330 tristate "Memory Hotplug"
331 331 depends on ACPI
332   - depends on MEMORY_HOTPLUG
  332 + depends on MEMORY_HOTPLUG || X86_64
333 333 default n
334 334 help
335 335 This driver adds supports for ACPI Memory Hotplug. This driver
include/linux/init.h
... ... @@ -245,7 +245,8 @@
245 245 #define __cpuexitdata __exitdata
246 246 #endif
247 247  
248   -#ifdef CONFIG_MEMORY_HOTPLUG
  248 +#if defined(CONFIG_MEMORY_HOTPLUG) || defined(CONFIG_ACPI_HOTPLUG_MEMORY) \
  249 + || defined(CONFIG_ACPI_HOTPLUG_MEMORY_MODULE)
249 250 #define __meminit
250 251 #define __meminitdata
251 252 #define __memexit
include/linux/memory_hotplug.h
... ... @@ -58,8 +58,6 @@
58 58 /* need some defines for these for archs that don't support it */
59 59 extern void online_page(struct page *page);
60 60 /* VM interface that may be used by firmware interface */
61   -extern int add_memory(u64 start, u64 size);
62   -extern int remove_memory(u64 start, u64 size);
63 61 extern int online_pages(unsigned long, unsigned long);
64 62  
65 63 /* reasonably generic interface to expand the physical pages in a zone */
... ... @@ -92,11 +90,6 @@
92 90 return -ENOSYS;
93 91 }
94 92  
95   -static inline int __add_pages(struct zone *zone, unsigned long start_pfn,
96   - unsigned long nr_pages)
97   -{
98   - return mhp_notimplemented(__FUNCTION__);
99   -}
100 93 #endif /* ! CONFIG_MEMORY_HOTPLUG */
101 94 static inline int __remove_pages(struct zone *zone, unsigned long start_pfn,
102 95 unsigned long nr_pages)
... ... @@ -105,5 +98,12 @@
105 98 dump_stack();
106 99 return -ENOSYS;
107 100 }
  101 +
  102 +#if defined(CONFIG_MEMORY_HOTPLUG) || defined(CONFIG_ACPI_HOTPLUG_MEMORY) \
  103 + || defined(CONFIG_ACPI_HOTPLUG_MEMORY_MODULE)
  104 +extern int add_memory(u64 start, u64 size);
  105 +extern int remove_memory(u64 start, u64 size);
  106 +#endif
  107 +
108 108 #endif /* __LINUX_MEMORY_HOTPLUG_H */