@@ -1416,6 +1416,9 @@ and is between 256 and 4096 characters. It is defined in the file
seconds. Use this parameter to check at some
other rate. 0 disables periodic checking.
+ mem_hotadd_auto= [KNL]
+ Disable the auto-onlining of hot-added memory.
+
memtest= [KNL,X86] Enable memtest
Format: <integer>
default : 0 <disable>
@@ -350,6 +350,14 @@ config ACPI_HOTPLUG_MEMORY
To compile this driver as a module, choose M here:
the module will be called acpi_memhotplug.
+config ACPI_HOTPLUG_MEMORY_AUTO_ONLINE
+ bool "Automatically online hotplugged memory"
+ depends on ACPI_HOTPLUG_MEMORY
+ default n
+ help
+ This forces memory that is brought into service by ACPI
+ to be automatically onlined.
+
config ACPI_SBS
tristate "Smart Battery System"
depends on X86
@@ -30,6 +30,7 @@
#include <linux/init.h>
#include <linux/types.h>
#include <linux/memory_hotplug.h>
+#include <linux/memory.h>
#include <acpi/acpi_drivers.h>
#define ACPI_MEMORY_DEVICE_CLASS "memory"
@@ -86,6 +87,17 @@ struct acpi_memory_device {
};
static int acpi_hotmem_initialized;
+#ifdef CONFIG_ACPI_HOTPLUG_MEMORY_AUTO_ONLINE
+static int mem_hotadd_auto = 1;
+static int __init setup_mem_hotadd_auto(char *str)
+{
+ if (!strncmp(str, "off", 3))
+ mem_hotadd_auto = 0;
+
+ return 1;
+}
+__setup("mem_hotadd_auto=", setup_mem_hotadd_auto);
+#endif
static acpi_status
acpi_memory_get_resource(struct acpi_resource *resource, void *context)
@@ -252,6 +264,18 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device)
result = add_memory(node, info->start_addr, info->length);
if (result)
continue;
+#ifdef CONFIG_ACPI_HOTPLUG_MEMORY_AUTO_ONLINE
+ if (mem_hotadd_auto) {
+ result = online_pages(info->start_addr >> PAGE_SHIFT,
+ info->length >> PAGE_SHIFT);
+ if (!result)
+ set_memory_state(info->start_addr >> PAGE_SHIFT,
+ info->length >> PAGE_SHIFT,
+ MEM_ONLINE);
+ else
+ printk("Memory online failed.\n");
+ }
+#endif
info->enabled = 1;
num_enabled++;
}
@@ -515,6 +515,29 @@ int remove_memory_block(unsigned long node_id, struct mem_section *section,
}
/*
+ * need an interface for the VM to mark sections on and offline when
+ * hot-swapping memory.
+ */
+void set_memory_state(unsigned long start_pfn, unsigned long nr_pages,
+ unsigned long state)
+{
+ struct mem_section *section;
+ struct memory_block *mem;
+ unsigned long start_sec, end_sec, i;
+
+ start_sec = pfn_to_section_nr(start_pfn);
+ end_sec = pfn_to_section_nr(start_pfn + nr_pages - 1);
+ for (i = start_sec; i <= end_sec; i++) {
+ if (valid_section_nr(i) && present_section_nr(i)) {
+ section = __nr_to_section(i);
+ mem = find_memory_block(section);
+ mem->state = state;
+ }
+ }
+}
+EXPORT_SYMBOL(set_memory_state);
+
+/*
* need an interface for the VM to add new memory regions,
* but without onlining it.
*/
@@ -114,6 +114,7 @@ extern int remove_memory_block(unsigned long, struct mem_section *, int);
extern int memory_notify(unsigned long val, void *v);
extern int memory_isolate_notify(unsigned long val, void *v);
extern struct memory_block *find_memory_block(struct mem_section *);
+extern void set_memory_state(unsigned long, unsigned long, unsigned long);
#define CONFIG_MEM_BLOCK_SIZE (PAGES_PER_SECTION<<PAGE_SHIFT)
enum mem_add_context { BOOT, HOTPLUG };
#endif /* CONFIG_MEMORY_HOTPLUG_SPARSE */
@@ -450,6 +450,7 @@ int online_pages(unsigned long pfn, unsigned long nr_pages)
return 0;
}
+EXPORT_SYMBOL_GPL(online_pages);
#endif /* CONFIG_MEMORY_HOTPLUG_SPARSE */
/* we are OK calling __meminit stuff here - we have CONFIG_MEMORY_HOTPLUG */