]> Pileus Git - ~andy/linux/blobdiff - drivers/base/memory.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
[~andy/linux] / drivers / base / memory.c
index a7994409b9a5dc438f58cdd5552a597c099fd54e..cafeaaf0428fc5ef59a622b5671c252e7b77b1a4 100644 (file)
@@ -27,6 +27,8 @@
 #include <asm/atomic.h>
 #include <asm/uaccess.h>
 
+static DEFINE_MUTEX(mem_sysfs_mutex);
+
 #define MEMORY_CLASS_NAME      "memory"
 
 static struct sysdev_class memory_sysdev_class = {
@@ -435,39 +437,6 @@ int __weak arch_get_memory_phys_device(unsigned long start_pfn)
        return 0;
 }
 
-static int add_memory_block(int nid, struct mem_section *section,
-                       unsigned long state, enum mem_add_context context)
-{
-       struct memory_block *mem = kzalloc(sizeof(*mem), GFP_KERNEL);
-       unsigned long start_pfn;
-       int ret = 0;
-
-       if (!mem)
-               return -ENOMEM;
-
-       mem->phys_index = __section_nr(section);
-       mem->state = state;
-       mutex_init(&mem->state_mutex);
-       start_pfn = section_nr_to_pfn(mem->phys_index);
-       mem->phys_device = arch_get_memory_phys_device(start_pfn);
-
-       ret = register_memory(mem, section);
-       if (!ret)
-               ret = mem_create_simple_file(mem, phys_index);
-       if (!ret)
-               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;
-}
-
 struct memory_block *find_memory_block_hinted(struct mem_section *section,
                                              struct memory_block *hint)
 {
@@ -507,19 +476,62 @@ struct memory_block *find_memory_block(struct mem_section *section)
        return find_memory_block_hinted(section, NULL);
 }
 
+static int add_memory_block(int nid, struct mem_section *section,
+                       unsigned long state, enum mem_add_context context)
+{
+       struct memory_block *mem = kzalloc(sizeof(*mem), GFP_KERNEL);
+       unsigned long start_pfn;
+       int ret = 0;
+
+       if (!mem)
+               return -ENOMEM;
+
+       mutex_lock(&mem_sysfs_mutex);
+
+       mem->phys_index = __section_nr(section);
+       mem->state = state;
+       mem->section_count++;
+       mutex_init(&mem->state_mutex);
+       start_pfn = section_nr_to_pfn(mem->phys_index);
+       mem->phys_device = arch_get_memory_phys_device(start_pfn);
+
+       ret = register_memory(mem, section);
+       if (!ret)
+               ret = mem_create_simple_file(mem, phys_index);
+       if (!ret)
+               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);
+       }
+
+       mutex_unlock(&mem_sysfs_mutex);
+       return ret;
+}
+
 int remove_memory_block(unsigned long node_id, struct mem_section *section,
                int phys_device)
 {
        struct memory_block *mem;
 
+       mutex_lock(&mem_sysfs_mutex);
        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);
 
+       mem->section_count--;
+       if (mem->section_count == 0) {
+               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);
+       }
+
+       mutex_unlock(&mem_sysfs_mutex);
        return 0;
 }