aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorWen Congyang <wency@cn.fujitsu.com>2012-10-08 19:34:01 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-09 03:23:02 -0400
commite90bdb7f52f94204c78fb40b0804645defdebd71 (patch)
tree4acb09ecd1f98fd98408f18e816d075601585d2a /drivers
parenta16cee10c7ab994546ed98d9abfd4de74050124a (diff)
memory-hotplug: update memory block's state and notify userspace
remove_memory() will be called when hot removing a memory device. But even if offlining memory, we cannot notice it. So the patch updates the memory block's state and sends notification to userspace. Additionally, the memory device may contain more than one memory block. If the memory block has been offlined, __offline_pages() will fail. So we should try to offline one memory block at a time. Thus remove_memory() also check each memory block's state. So there is no need to check the memory block's state before calling remove_memory(). Signed-off-by: Wen Congyang <wency@cn.fujitsu.com> Signed-off-by: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com> Cc: David Rientjes <rientjes@google.com> Cc: Jiang Liu <liuj97@gmail.com> Cc: Len Brown <len.brown@intel.com> Cc: Christoph Lameter <cl@linux.com> Cc: Minchan Kim <minchan.kim@gmail.com> Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/base/memory.c31
1 files changed, 27 insertions, 4 deletions
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index 44e7de6ce694..86c88216a503 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -275,13 +275,11 @@ memory_block_action(unsigned long phys_index, unsigned long action)
275 return ret; 275 return ret;
276} 276}
277 277
278static int memory_block_change_state(struct memory_block *mem, 278static int __memory_block_change_state(struct memory_block *mem,
279 unsigned long to_state, unsigned long from_state_req) 279 unsigned long to_state, unsigned long from_state_req)
280{ 280{
281 int ret = 0; 281 int ret = 0;
282 282
283 mutex_lock(&mem->state_mutex);
284
285 if (mem->state != from_state_req) { 283 if (mem->state != from_state_req) {
286 ret = -EINVAL; 284 ret = -EINVAL;
287 goto out; 285 goto out;
@@ -309,10 +307,20 @@ static int memory_block_change_state(struct memory_block *mem,
309 break; 307 break;
310 } 308 }
311out: 309out:
312 mutex_unlock(&mem->state_mutex);
313 return ret; 310 return ret;
314} 311}
315 312
313static int memory_block_change_state(struct memory_block *mem,
314 unsigned long to_state, unsigned long from_state_req)
315{
316 int ret;
317
318 mutex_lock(&mem->state_mutex);
319 ret = __memory_block_change_state(mem, to_state, from_state_req);
320 mutex_unlock(&mem->state_mutex);
321
322 return ret;
323}
316static ssize_t 324static ssize_t
317store_mem_state(struct device *dev, 325store_mem_state(struct device *dev,
318 struct device_attribute *attr, const char *buf, size_t count) 326 struct device_attribute *attr, const char *buf, size_t count)
@@ -653,6 +661,21 @@ int unregister_memory_section(struct mem_section *section)
653} 661}
654 662
655/* 663/*
664 * offline one memory block. If the memory block has been offlined, do nothing.
665 */
666int offline_memory_block(struct memory_block *mem)
667{
668 int ret = 0;
669
670 mutex_lock(&mem->state_mutex);
671 if (mem->state != MEM_OFFLINE)
672 ret = __memory_block_change_state(mem, MEM_OFFLINE, MEM_ONLINE);
673 mutex_unlock(&mem->state_mutex);
674
675 return ret;
676}
677
678/*
656 * Initialize the sysfs support for memory devices... 679 * Initialize the sysfs support for memory devices...
657 */ 680 */
658int __init memory_dev_init(void) 681int __init memory_dev_init(void)