Commit 9d99aaa31f5994d1923c3713ce9144c4c42332e1
Committed by
Linus Torvalds
1 parent
805e8c03c9
Exists in
master
and in
7 other branches
[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
arch/i386/mm/init.c
... | ... | @@ -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
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
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 */ |