aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/acpi_memhotplug.c
diff options
context:
space:
mode:
authorWen Congyang <wency@cn.fujitsu.com>2012-11-15 20:10:37 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2012-11-15 20:10:37 -0500
commit65479472571fbf91502b7854be45ec0026b5229e (patch)
tree1f9e40f833838971398dae6c61471fdcc0adb654 /drivers/acpi/acpi_memhotplug.c
parente0b7b24dd9559fcda0f8bfd6acbcad81682c4fdd (diff)
ACPI / memhotplug: don't allow to eject the memory device if it is being used
We eject the memory device even if it is in use. It is very dangerous, and it will cause the kernel to be panicked. Signed-off-by: Wen Congyang <wency@cn.fujitsu.com> Reviewed-by: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com> Acked-by: David Rientjes <rientjes@google.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/acpi/acpi_memhotplug.c')
-rw-r--r--drivers/acpi/acpi_memhotplug.c42
1 files changed, 33 insertions, 9 deletions
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c
index e52ad5d3792d..f7e300769966 100644
--- a/drivers/acpi/acpi_memhotplug.c
+++ b/drivers/acpi/acpi_memhotplug.c
@@ -78,6 +78,7 @@ struct acpi_memory_info {
78 unsigned short caching; /* memory cache attribute */ 78 unsigned short caching; /* memory cache attribute */
79 unsigned short write_protect; /* memory read/write attribute */ 79 unsigned short write_protect; /* memory read/write attribute */
80 unsigned int enabled:1; 80 unsigned int enabled:1;
81 unsigned int failed:1;
81}; 82};
82 83
83struct acpi_memory_device { 84struct acpi_memory_device {
@@ -257,9 +258,23 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device)
257 node = memory_add_physaddr_to_nid(info->start_addr); 258 node = memory_add_physaddr_to_nid(info->start_addr);
258 259
259 result = add_memory(node, info->start_addr, info->length); 260 result = add_memory(node, info->start_addr, info->length);
260 if (result) 261
262 /*
263 * If the memory block has been used by the kernel, add_memory()
264 * returns -EEXIST. If add_memory() returns the other error, it
265 * means that this memory block is not used by the kernel.
266 */
267 if (result && result != -EEXIST) {
268 info->failed = 1;
261 continue; 269 continue;
262 info->enabled = 1; 270 }
271
272 if (!result)
273 info->enabled = 1;
274 /*
275 * Add num_enable even if add_memory() returns -EEXIST, so the
276 * device is bound to this driver.
277 */
263 num_enabled++; 278 num_enabled++;
264 } 279 }
265 if (!num_enabled) { 280 if (!num_enabled) {
@@ -280,21 +295,30 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device)
280 295
281static int acpi_memory_remove_memory(struct acpi_memory_device *mem_device) 296static int acpi_memory_remove_memory(struct acpi_memory_device *mem_device)
282{ 297{
283 int result; 298 int result = 0;
284 struct acpi_memory_info *info, *n; 299 struct acpi_memory_info *info, *n;
285 300
286 list_for_each_entry_safe(info, n, &mem_device->res_list, list) { 301 list_for_each_entry_safe(info, n, &mem_device->res_list, list) {
287 if (info->enabled) { 302 if (info->failed)
288 result = remove_memory(info->start_addr, info->length); 303 /* The kernel does not use this memory block */
289 if (result) 304 continue;
290 return result; 305
291 } 306 if (!info->enabled)
307 /*
308 * The kernel uses this memory block, but it may be not
309 * managed by us.
310 */
311 return -EBUSY;
312
313 result = remove_memory(info->start_addr, info->length);
314 if (result)
315 return result;
292 316
293 list_del(&info->list); 317 list_del(&info->list);
294 kfree(info); 318 kfree(info);
295 } 319 }
296 320
297 return 0; 321 return result;
298} 322}
299 323
300static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data) 324static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data)