]> rtime.felk.cvut.cz Git - linux-imx.git/blobdiff - drivers/base/memory.c
memory hotplug: suppress "Device memoryX does not have a release() function" warning
[linux-imx.git] / drivers / base / memory.c
index 7dda4f790f00d58145cc3b58ce4607c42ea829b1..7eb1211ab6881f0117f35f5e46b28f4dde86b2d3 100644 (file)
@@ -70,6 +70,13 @@ void unregister_memory_isolate_notifier(struct notifier_block *nb)
 }
 EXPORT_SYMBOL(unregister_memory_isolate_notifier);
 
+static void memory_block_release(struct device *dev)
+{
+       struct memory_block *mem = container_of(dev, struct memory_block, dev);
+
+       kfree(mem);
+}
+
 /*
  * register_memory - Setup a sysfs device for a memory block
  */
@@ -80,6 +87,7 @@ int register_memory(struct memory_block *memory)
 
        memory->dev.bus = &memory_subsys;
        memory->dev.id = memory->start_section_nr / sections_per_block;
+       memory->dev.release = memory_block_release;
 
        error = device_register(&memory->dev);
        return error;
@@ -248,26 +256,23 @@ static bool pages_correctly_reserved(unsigned long start_pfn,
 static int
 memory_block_action(unsigned long phys_index, unsigned long action)
 {
-       unsigned long start_pfn, start_paddr;
+       unsigned long start_pfn;
        unsigned long nr_pages = PAGES_PER_SECTION * sections_per_block;
        struct page *first_page;
        int ret;
 
        first_page = pfn_to_page(phys_index << PFN_SECTION_SHIFT);
+       start_pfn = page_to_pfn(first_page);
 
        switch (action) {
                case MEM_ONLINE:
-                       start_pfn = page_to_pfn(first_page);
-
                        if (!pages_correctly_reserved(start_pfn, nr_pages))
                                return -EBUSY;
 
                        ret = online_pages(start_pfn, nr_pages);
                        break;
                case MEM_OFFLINE:
-                       start_paddr = page_to_pfn(first_page) << PAGE_SHIFT;
-                       ret = remove_memory(start_paddr,
-                                           nr_pages << PAGE_SHIFT);
+                       ret = offline_pages(start_pfn, nr_pages);
                        break;
                default:
                        WARN(1, KERN_WARNING "%s(%ld, %ld) unknown action: "
@@ -278,13 +283,11 @@ memory_block_action(unsigned long phys_index, unsigned long action)
        return ret;
 }
 
-static int memory_block_change_state(struct memory_block *mem,
+static int __memory_block_change_state(struct memory_block *mem,
                unsigned long to_state, unsigned long from_state_req)
 {
        int ret = 0;
 
-       mutex_lock(&mem->state_mutex);
-
        if (mem->state != from_state_req) {
                ret = -EINVAL;
                goto out;
@@ -312,10 +315,20 @@ static int memory_block_change_state(struct memory_block *mem,
                break;
        }
 out:
-       mutex_unlock(&mem->state_mutex);
        return ret;
 }
 
+static int memory_block_change_state(struct memory_block *mem,
+               unsigned long to_state, unsigned long from_state_req)
+{
+       int ret;
+
+       mutex_lock(&mem->state_mutex);
+       ret = __memory_block_change_state(mem, to_state, from_state_req);
+       mutex_unlock(&mem->state_mutex);
+
+       return ret;
+}
 static ssize_t
 store_mem_state(struct device *dev,
                struct device_attribute *attr, const char *buf, size_t count)
@@ -630,7 +643,6 @@ int remove_memory_block(unsigned long node_id, struct mem_section *section,
                mem_remove_simple_file(mem, phys_device);
                mem_remove_simple_file(mem, removable);
                unregister_memory(mem);
-               kfree(mem);
        } else
                kobject_put(&mem->dev.kobj);
 
@@ -655,6 +667,21 @@ int unregister_memory_section(struct mem_section *section)
        return remove_memory_block(0, section, 0);
 }
 
+/*
+ * offline one memory block. If the memory block has been offlined, do nothing.
+ */
+int offline_memory_block(struct memory_block *mem)
+{
+       int ret = 0;
+
+       mutex_lock(&mem->state_mutex);
+       if (mem->state != MEM_OFFLINE)
+               ret = __memory_block_change_state(mem, MEM_OFFLINE, MEM_ONLINE);
+       mutex_unlock(&mem->state_mutex);
+
+       return ret;
+}
+
 /*
  * Initialize the sysfs support for memory devices...
  */