diff options
Diffstat (limited to 'drivers/base/memory.c')
-rw-r--r-- | drivers/base/memory.c | 42 |
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 | } |
71 | EXPORT_SYMBOL(unregister_memory_isolate_notifier); | 71 | EXPORT_SYMBOL(unregister_memory_isolate_notifier); |
72 | 72 | ||
73 | static 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 | */ |
248 | static int | 256 | static int |
249 | memory_block_action(unsigned long phys_index, unsigned long action) | 257 | memory_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 | ||
278 | static int __memory_block_change_state(struct memory_block *mem, | 286 | static 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 | ||
313 | static int memory_block_change_state(struct memory_block *mem, | 322 | static 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; |