[PATCH] x86_64: Support memory hotadd without sparsemem
authorAndi Kleen <ak@suse.de>
Fri, 7 Apr 2006 17:49:15 +0000 (19:49 +0200)
committerLinus Torvalds <torvalds@g5.osdl.org>
Sun, 9 Apr 2006 18:53:16 +0000 (11:53 -0700)
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>
arch/i386/mm/init.c
arch/x86_64/kernel/e820.c
arch/x86_64/mm/init.c
drivers/acpi/Kconfig
include/linux/init.h
include/linux/memory_hotplug.h

index 9f66ac5..ae6534a 100644 (file)
@@ -651,6 +651,7 @@ void __init mem_init(void)
  * Specifically, in the case of x86, we will always add
  * memory to the highmem for now.
  */
+#ifdef CONFIG_HOTPLUG_MEMORY
 #ifndef CONFIG_NEED_MULTIPLE_NODES
 int add_memory(u64 start, u64 size)
 {
@@ -667,6 +668,7 @@ int remove_memory(u64 start, u64 size)
        return -EINVAL;
 }
 #endif
+#endif
 
 kmem_cache_t *pgd_cache;
 kmem_cache_t *pmd_cache;
index 293cd71..db57d3f 100644 (file)
@@ -80,7 +80,7 @@ static inline int bad_addr(unsigned long *addrp, unsigned long size)
        return 0;
 } 
 
-int __init e820_mapped(unsigned long start, unsigned long end, unsigned type) 
+int __meminit e820_mapped(unsigned long start, unsigned long end, unsigned type)
 { 
        int i;
        for (i = 0; i < e820.nr_map; i++) { 
index e5f7f1c..4921611 100644 (file)
@@ -507,9 +507,8 @@ void __init clear_kernel_mapping(unsigned long address, unsigned long size)
 
 /*
  * Memory hotplug specific functions
- * These are only for non-NUMA machines right now.
  */
-#ifdef CONFIG_MEMORY_HOTPLUG
+#if defined(CONFIG_ACPI_HOTPLUG_MEMORY) || defined(CONFIG_ACPI_HOTPLUG_MEMORY_MODULE)
 
 void online_page(struct page *page)
 {
@@ -520,6 +519,39 @@ void online_page(struct page *page)
        num_physpages++;
 }
 
+#ifndef 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++) {
+               unsigned long addr = pfn << PAGE_SHIFT;
+               if (pfn_valid(pfn) && e820_mapped(addr, addr+1, E820_RAM)) {
+                       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
+
+/*
+ * Memory is added always to NORMAL zone. This means you will never get
+ * additional DMA/DMA32 memory.
+ */
 int add_memory(u64 start, u64 size)
 {
        struct pglist_data *pgdat = NODE_DATA(0);
index 5cb9630..c24652d 100644 (file)
@@ -329,7 +329,7 @@ config ACPI_CONTAINER
 config ACPI_HOTPLUG_MEMORY
        tristate "Memory Hotplug"
        depends on ACPI
-       depends on MEMORY_HOTPLUG
+       depends on MEMORY_HOTPLUG || X86_64
        default n
        help
          This driver adds supports for ACPI Memory Hotplug.  This driver
index ed0ac7c..93dcbe1 100644 (file)
@@ -245,7 +245,8 @@ void __init parse_early_param(void);
 #define __cpuexitdata  __exitdata
 #endif
 
-#ifdef CONFIG_MEMORY_HOTPLUG
+#if defined(CONFIG_MEMORY_HOTPLUG) || defined(CONFIG_ACPI_HOTPLUG_MEMORY) \
+       || defined(CONFIG_ACPI_HOTPLUG_MEMORY_MODULE)
 #define __meminit
 #define __meminitdata
 #define __memexit
index 968b1aa..4ca3e6a 100644 (file)
@@ -58,8 +58,6 @@ extern int add_one_highpage(struct page *page, int pfn, int bad_ppro);
 /* need some defines for these for archs that don't support it */
 extern void online_page(struct page *page);
 /* VM interface that may be used by firmware interface */
-extern int add_memory(u64 start, u64 size);
-extern int remove_memory(u64 start, u64 size);
 extern int online_pages(unsigned long, unsigned long);
 
 /* reasonably generic interface to expand the physical pages in a zone  */
@@ -92,11 +90,6 @@ static inline int mhp_notimplemented(const char *func)
        return -ENOSYS;
 }
 
-static inline int __add_pages(struct zone *zone, unsigned long start_pfn,
-       unsigned long nr_pages)
-{
-       return mhp_notimplemented(__FUNCTION__);
-}
 #endif /* ! CONFIG_MEMORY_HOTPLUG */
 static inline int __remove_pages(struct zone *zone, unsigned long start_pfn,
        unsigned long nr_pages)
@@ -105,4 +98,11 @@ static inline int __remove_pages(struct zone *zone, unsigned long start_pfn,
        dump_stack();
        return -ENOSYS;
 }
+
+#if defined(CONFIG_MEMORY_HOTPLUG) || defined(CONFIG_ACPI_HOTPLUG_MEMORY) \
+       || defined(CONFIG_ACPI_HOTPLUG_MEMORY_MODULE)
+extern int add_memory(u64 start, u64 size);
+extern int remove_memory(u64 start, u64 size);
+#endif
+
 #endif /* __LINUX_MEMORY_HOTPLUG_H */