aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/memory.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/base/memory.c')
-rw-r--r--drivers/base/memory.c42
1 files changed, 30 insertions, 12 deletions
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index 86c88216a503..987604d56c83 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -70,6 +70,13 @@ void unregister_memory_isolate_notifier(struct notifier_block *nb)
70} 70}
71EXPORT_SYMBOL(unregister_memory_isolate_notifier); 71EXPORT_SYMBOL(unregister_memory_isolate_notifier);
72 72
73static void memory_block_release(struct device *dev)
74{
75 struct memory_block *mem = container_of(dev, struct memory_block, dev);
76
77 kfree(mem);
78}
79
73/* 80/*
74 * register_memory - Setup a sysfs device for a memory block 81 * register_memory - Setup a sysfs device for a memory block
75 */ 82 */
@@ -80,6 +87,7 @@ int register_memory(struct memory_block *memory)
80 87
81 memory->dev.bus = &memory_subsys; 88 memory->dev.bus = &memory_subsys;
82 memory->dev.id = memory->start_section_nr / sections_per_block; 89 memory->dev.id = memory->start_section_nr / sections_per_block;
90 memory->dev.release = memory_block_release;
83 91
84 error = device_register(&memory->dev); 92 error = device_register(&memory->dev);
85 return error; 93 return error;
@@ -246,7 +254,7 @@ static bool pages_correctly_reserved(unsigned long start_pfn,
246 * OK to have direct references to sparsemem variables in here. 254 * OK to have direct references to sparsemem variables in here.
247 */ 255 */
248static int 256static int
249memory_block_action(unsigned long phys_index, unsigned long action) 257memory_block_action(unsigned long phys_index, unsigned long action, int online_type)
250{ 258{
251 unsigned long start_pfn; 259 unsigned long start_pfn;
252 unsigned long nr_pages = PAGES_PER_SECTION * sections_per_block; 260 unsigned long nr_pages = PAGES_PER_SECTION * sections_per_block;
@@ -261,7 +269,7 @@ memory_block_action(unsigned long phys_index, unsigned long action)
261 if (!pages_correctly_reserved(start_pfn, nr_pages)) 269 if (!pages_correctly_reserved(start_pfn, nr_pages))
262 return -EBUSY; 270 return -EBUSY;
263 271
264 ret = online_pages(start_pfn, nr_pages); 272 ret = online_pages(start_pfn, nr_pages, online_type);
265 break; 273 break;
266 case MEM_OFFLINE: 274 case MEM_OFFLINE:
267 ret = offline_pages(start_pfn, nr_pages); 275 ret = offline_pages(start_pfn, nr_pages);
@@ -276,7 +284,8 @@ memory_block_action(unsigned long phys_index, unsigned long action)
276} 284}
277 285
278static int __memory_block_change_state(struct memory_block *mem, 286static int __memory_block_change_state(struct memory_block *mem,
279 unsigned long to_state, unsigned long from_state_req) 287 unsigned long to_state, unsigned long from_state_req,
288 int online_type)
280{ 289{
281 int ret = 0; 290 int ret = 0;
282 291
@@ -288,7 +297,7 @@ static int __memory_block_change_state(struct memory_block *mem,
288 if (to_state == MEM_OFFLINE) 297 if (to_state == MEM_OFFLINE)
289 mem->state = MEM_GOING_OFFLINE; 298 mem->state = MEM_GOING_OFFLINE;
290 299
291 ret = memory_block_action(mem->start_section_nr, to_state); 300 ret = memory_block_action(mem->start_section_nr, to_state, online_type);
292 301
293 if (ret) { 302 if (ret) {
294 mem->state = from_state_req; 303 mem->state = from_state_req;
@@ -311,12 +320,14 @@ out:
311} 320}
312 321
313static int memory_block_change_state(struct memory_block *mem, 322static int memory_block_change_state(struct memory_block *mem,
314 unsigned long to_state, unsigned long from_state_req) 323 unsigned long to_state, unsigned long from_state_req,
324 int online_type)
315{ 325{
316 int ret; 326 int ret;
317 327
318 mutex_lock(&mem->state_mutex); 328 mutex_lock(&mem->state_mutex);
319 ret = __memory_block_change_state(mem, to_state, from_state_req); 329 ret = __memory_block_change_state(mem, to_state, from_state_req,
330 online_type);
320 mutex_unlock(&mem->state_mutex); 331 mutex_unlock(&mem->state_mutex);
321 332
322 return ret; 333 return ret;
@@ -330,10 +341,18 @@ store_mem_state(struct device *dev,
330 341
331 mem = container_of(dev, struct memory_block, dev); 342 mem = container_of(dev, struct memory_block, dev);
332 343
333 if (!strncmp(buf, "online", min((int)count, 6))) 344 if (!strncmp(buf, "online_kernel", min_t(int, count, 13)))
334 ret = memory_block_change_state(mem, MEM_ONLINE, MEM_OFFLINE); 345 ret = memory_block_change_state(mem, MEM_ONLINE,
335 else if(!strncmp(buf, "offline", min((int)count, 7))) 346 MEM_OFFLINE, ONLINE_KERNEL);
336 ret = memory_block_change_state(mem, MEM_OFFLINE, MEM_ONLINE); 347 else if (!strncmp(buf, "online_movable", min_t(int, count, 14)))
348 ret = memory_block_change_state(mem, MEM_ONLINE,
349 MEM_OFFLINE, ONLINE_MOVABLE);
350 else if (!strncmp(buf, "online", min_t(int, count, 6)))
351 ret = memory_block_change_state(mem, MEM_ONLINE,
352 MEM_OFFLINE, ONLINE_KEEP);
353 else if(!strncmp(buf, "offline", min_t(int, count, 7)))
354 ret = memory_block_change_state(mem, MEM_OFFLINE,
355 MEM_ONLINE, -1);
337 356
338 if (ret) 357 if (ret)
339 return ret; 358 return ret;
@@ -635,7 +654,6 @@ int remove_memory_block(unsigned long node_id, struct mem_section *section,
635 mem_remove_simple_file(mem, phys_device); 654 mem_remove_simple_file(mem, phys_device);
636 mem_remove_simple_file(mem, removable); 655 mem_remove_simple_file(mem, removable);
637 unregister_memory(mem); 656 unregister_memory(mem);
638 kfree(mem);
639 } else 657 } else
640 kobject_put(&mem->dev.kobj); 658 kobject_put(&mem->dev.kobj);
641 659
@@ -669,7 +687,7 @@ int offline_memory_block(struct memory_block *mem)
669 687
670 mutex_lock(&mem->state_mutex); 688 mutex_lock(&mem->state_mutex);
671 if (mem->state != MEM_OFFLINE) 689 if (mem->state != MEM_OFFLINE)
672 ret = __memory_block_change_state(mem, MEM_OFFLINE, MEM_ONLINE); 690 ret = __memory_block_change_state(mem, MEM_OFFLINE, MEM_ONLINE, -1);
673 mutex_unlock(&mem->state_mutex); 691 mutex_unlock(&mem->state_mutex);
674 692
675 return ret; 693 return ret;