X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=drivers%2Fbase%2Fmemory.c;h=989429cfed88a7395f38a4d1dd44d8d8ff8745ac;hb=401097ea4b89846d66ac78f7f108d49c2e922d9c;hp=4d4e0e7b6e925e656c8346d63671f0179bca880e;hpb=4a0b2b4dbe1335b8b9886ba3dc85a145d5d938ed;p=safe%2Fjmp%2Flinux-2.6 diff --git a/drivers/base/memory.c b/drivers/base/memory.c index 4d4e0e7..989429c 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c @@ -21,6 +21,8 @@ #include #include #include +#include + #include #include @@ -101,6 +103,22 @@ static ssize_t show_mem_phys_index(struct sys_device *dev, } /* + * Show whether the section of memory is likely to be hot-removable + */ +static ssize_t show_mem_removable(struct sys_device *dev, + struct sysdev_attribute *attr, char *buf) +{ + unsigned long start_pfn; + int ret; + struct memory_block *mem = + container_of(dev, struct memory_block, sysdev); + + start_pfn = section_nr_to_pfn(mem->phys_index); + ret = is_mem_section_removable(start_pfn, PAGES_PER_SECTION); + return sprintf(buf, "%d\n", ret); +} + +/* * online, offline, going offline, etc. */ static ssize_t show_mem_state(struct sys_device *dev, @@ -189,9 +207,8 @@ memory_block_action(struct memory_block *mem, unsigned long action) } break; default: - printk(KERN_WARNING "%s(%p, %ld) unknown action: %ld\n", + WARN(1, KERN_WARNING "%s(%p, %ld) unknown action: %ld\n", __func__, mem, action, action); - WARN_ON(1); ret = -EINVAL; } @@ -262,6 +279,7 @@ static ssize_t show_phys_device(struct sys_device *dev, static SYSDEV_ATTR(phys_index, 0444, show_mem_phys_index, NULL); static SYSDEV_ATTR(state, 0644, show_mem_state, store_mem_state); static SYSDEV_ATTR(phys_device, 0444, show_phys_device, NULL); +static SYSDEV_ATTR(removable, 0444, show_mem_removable, NULL); #define mem_create_simple_file(mem, attr_name) \ sysdev_create_file(&mem->sysdev, &attr_##attr_name) @@ -309,7 +327,7 @@ memory_probe_store(struct class *class, const char *buf, size_t count) return count; } -static CLASS_ATTR(probe, 0700, NULL, memory_probe_store); +static CLASS_ATTR(probe, S_IWUSR, NULL, memory_probe_store); static int memory_probe_init(void) { @@ -329,8 +347,9 @@ static inline int memory_probe_init(void) * section belongs to... */ -static int add_memory_block(unsigned long node_id, struct mem_section *section, - unsigned long state, int phys_device) +static int add_memory_block(int nid, struct mem_section *section, + unsigned long state, int phys_device, + enum mem_add_context context) { struct memory_block *mem = kzalloc(sizeof(*mem), GFP_KERNEL); int ret = 0; @@ -350,6 +369,12 @@ static int add_memory_block(unsigned long node_id, struct mem_section *section, ret = mem_create_simple_file(mem, state); if (!ret) ret = mem_create_simple_file(mem, phys_device); + if (!ret) + ret = mem_create_simple_file(mem, removable); + if (!ret) { + if (context == HOTPLUG) + ret = register_mem_sect_under_node(mem, nid); + } return ret; } @@ -362,7 +387,7 @@ static int add_memory_block(unsigned long node_id, struct mem_section *section, * * This could be made generic for all sysdev classes. */ -static struct memory_block *find_memory_block(struct mem_section *section) +struct memory_block *find_memory_block(struct mem_section *section) { struct kobject *kobj; struct sys_device *sysdev; @@ -391,9 +416,11 @@ int remove_memory_block(unsigned long node_id, struct mem_section *section, struct memory_block *mem; mem = find_memory_block(section); + unregister_mem_sect_under_nodes(mem); mem_remove_simple_file(mem, phys_index); mem_remove_simple_file(mem, state); mem_remove_simple_file(mem, phys_device); + mem_remove_simple_file(mem, removable); unregister_memory(mem, section); return 0; @@ -403,9 +430,9 @@ int remove_memory_block(unsigned long node_id, struct mem_section *section, * need an interface for the VM to add new memory regions, * but without onlining it. */ -int register_new_memory(struct mem_section *section) +int register_new_memory(int nid, struct mem_section *section) { - return add_memory_block(0, section, MEM_OFFLINE, 0); + return add_memory_block(nid, section, MEM_OFFLINE, 0, HOTPLUG); } int unregister_memory_section(struct mem_section *section) @@ -437,7 +464,8 @@ int __init memory_dev_init(void) for (i = 0; i < NR_MEM_SECTIONS; i++) { if (!present_section_nr(i)) continue; - err = add_memory_block(0, __nr_to_section(i), MEM_ONLINE, 0); + err = add_memory_block(0, __nr_to_section(i), MEM_ONLINE, + 0, BOOT); if (!ret) ret = err; }