aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-08-30 08:14:25 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-08-30 08:14:25 -0400
commit7bc583d102d6f89c3dc4b502caec6ba03c9d318f (patch)
tree550e6333f2205f006849984b52408ed796bcd0c5 /drivers
parentda48afb26b40ebb5d6b0e84793e0662859c7ea20 (diff)
parentf943db40c29f3c82a56956e9ca36f21d6d855db9 (diff)
Merge branch 'acpi-hotplug'
* acpi-hotplug: ACPI / hotplug: Remove containers synchronously driver core / ACPI: Avoid device hot remove locking issues
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/scan.c49
-rw-r--r--drivers/base/core.c43
-rw-r--r--drivers/base/memory.c4
3 files changed, 46 insertions, 50 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index e76365136ba3..61d090b6ce25 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -287,6 +287,7 @@ static void acpi_bus_device_eject(void *context)
287 struct acpi_device *device = NULL; 287 struct acpi_device *device = NULL;
288 struct acpi_scan_handler *handler; 288 struct acpi_scan_handler *handler;
289 u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; 289 u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
290 int error;
290 291
291 mutex_lock(&acpi_scan_lock); 292 mutex_lock(&acpi_scan_lock);
292 293
@@ -301,17 +302,13 @@ static void acpi_bus_device_eject(void *context)
301 } 302 }
302 acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST, 303 acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST,
303 ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); 304 ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
304 if (handler->hotplug.mode == AHM_CONTAINER) { 305 if (handler->hotplug.mode == AHM_CONTAINER)
305 device->flags.eject_pending = true;
306 kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); 306 kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE);
307 } else {
308 int error;
309 307
310 get_device(&device->dev); 308 get_device(&device->dev);
311 error = acpi_scan_hot_remove(device); 309 error = acpi_scan_hot_remove(device);
312 if (error) 310 if (error)
313 goto err_out; 311 goto err_out;
314 }
315 312
316 out: 313 out:
317 mutex_unlock(&acpi_scan_lock); 314 mutex_unlock(&acpi_scan_lock);
@@ -496,7 +493,6 @@ acpi_eject_store(struct device *d, struct device_attribute *attr,
496 struct acpi_eject_event *ej_event; 493 struct acpi_eject_event *ej_event;
497 acpi_object_type not_used; 494 acpi_object_type not_used;
498 acpi_status status; 495 acpi_status status;
499 u32 ost_source;
500 int ret; 496 int ret;
501 497
502 if (!count || buf[0] != '1') 498 if (!count || buf[0] != '1')
@@ -510,43 +506,28 @@ acpi_eject_store(struct device *d, struct device_attribute *attr,
510 if (ACPI_FAILURE(status) || !acpi_device->flags.ejectable) 506 if (ACPI_FAILURE(status) || !acpi_device->flags.ejectable)
511 return -ENODEV; 507 return -ENODEV;
512 508
513 mutex_lock(&acpi_scan_lock);
514
515 if (acpi_device->flags.eject_pending) {
516 /* ACPI eject notification event. */
517 ost_source = ACPI_NOTIFY_EJECT_REQUEST;
518 acpi_device->flags.eject_pending = 0;
519 } else {
520 /* Eject initiated by user space. */
521 ost_source = ACPI_OST_EC_OSPM_EJECT;
522 }
523 ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL); 509 ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL);
524 if (!ej_event) { 510 if (!ej_event) {
525 ret = -ENOMEM; 511 ret = -ENOMEM;
526 goto err_out; 512 goto err_out;
527 } 513 }
528 acpi_evaluate_hotplug_ost(acpi_device->handle, ost_source, 514 acpi_evaluate_hotplug_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT,
529 ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); 515 ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
530 ej_event->device = acpi_device; 516 ej_event->device = acpi_device;
531 ej_event->event = ost_source; 517 ej_event->event = ACPI_OST_EC_OSPM_EJECT;
532 get_device(&acpi_device->dev); 518 get_device(&acpi_device->dev);
533 status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device, ej_event); 519 status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device, ej_event);
534 if (ACPI_FAILURE(status)) { 520 if (ACPI_SUCCESS(status))
535 put_device(&acpi_device->dev); 521 return count;
536 kfree(ej_event);
537 ret = status == AE_NO_MEMORY ? -ENOMEM : -EAGAIN;
538 goto err_out;
539 }
540 ret = count;
541 522
542 out: 523 put_device(&acpi_device->dev);
543 mutex_unlock(&acpi_scan_lock); 524 kfree(ej_event);
544 return ret; 525 ret = status == AE_NO_MEMORY ? -ENOMEM : -EAGAIN;
545 526
546 err_out: 527 err_out:
547 acpi_evaluate_hotplug_ost(acpi_device->handle, ost_source, 528 acpi_evaluate_hotplug_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT,
548 ACPI_OST_SC_NON_SPECIFIC_FAILURE, NULL); 529 ACPI_OST_SC_NON_SPECIFIC_FAILURE, NULL);
549 goto out; 530 return ret;
550} 531}
551 532
552static DEVICE_ATTR(eject, 0200, NULL, acpi_eject_store); 533static DEVICE_ATTR(eject, 0200, NULL, acpi_eject_store);
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 8856d74545d9..ac419a15fcd4 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -49,6 +49,28 @@ static struct kobject *dev_kobj;
49struct kobject *sysfs_dev_char_kobj; 49struct kobject *sysfs_dev_char_kobj;
50struct kobject *sysfs_dev_block_kobj; 50struct kobject *sysfs_dev_block_kobj;
51 51
52static DEFINE_MUTEX(device_hotplug_lock);
53
54void lock_device_hotplug(void)
55{
56 mutex_lock(&device_hotplug_lock);
57}
58
59void unlock_device_hotplug(void)
60{
61 mutex_unlock(&device_hotplug_lock);
62}
63
64int lock_device_hotplug_sysfs(void)
65{
66 if (mutex_trylock(&device_hotplug_lock))
67 return 0;
68
69 /* Avoid busy looping (5 ms of sleep should do). */
70 msleep(5);
71 return restart_syscall();
72}
73
52#ifdef CONFIG_BLOCK 74#ifdef CONFIG_BLOCK
53static inline int device_is_not_partition(struct device *dev) 75static inline int device_is_not_partition(struct device *dev)
54{ 76{
@@ -408,9 +430,9 @@ static ssize_t show_online(struct device *dev, struct device_attribute *attr,
408{ 430{
409 bool val; 431 bool val;
410 432
411 lock_device_hotplug(); 433 device_lock(dev);
412 val = !dev->offline; 434 val = !dev->offline;
413 unlock_device_hotplug(); 435 device_unlock(dev);
414 return sprintf(buf, "%u\n", val); 436 return sprintf(buf, "%u\n", val);
415} 437}
416 438
@@ -424,7 +446,10 @@ static ssize_t store_online(struct device *dev, struct device_attribute *attr,
424 if (ret < 0) 446 if (ret < 0)
425 return ret; 447 return ret;
426 448
427 lock_device_hotplug(); 449 ret = lock_device_hotplug_sysfs();
450 if (ret)
451 return ret;
452
428 ret = val ? device_online(dev) : device_offline(dev); 453 ret = val ? device_online(dev) : device_offline(dev);
429 unlock_device_hotplug(); 454 unlock_device_hotplug();
430 return ret < 0 ? ret : count; 455 return ret < 0 ? ret : count;
@@ -1479,18 +1504,6 @@ EXPORT_SYMBOL_GPL(put_device);
1479EXPORT_SYMBOL_GPL(device_create_file); 1504EXPORT_SYMBOL_GPL(device_create_file);
1480EXPORT_SYMBOL_GPL(device_remove_file); 1505EXPORT_SYMBOL_GPL(device_remove_file);
1481 1506
1482static DEFINE_MUTEX(device_hotplug_lock);
1483
1484void lock_device_hotplug(void)
1485{
1486 mutex_lock(&device_hotplug_lock);
1487}
1488
1489void unlock_device_hotplug(void)
1490{
1491 mutex_unlock(&device_hotplug_lock);
1492}
1493
1494static int device_check_offline(struct device *dev, void *not_used) 1507static int device_check_offline(struct device *dev, void *not_used)
1495{ 1508{
1496 int ret; 1509 int ret;
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index 2b7813ec6d02..6f4c99ff1ce7 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -351,7 +351,9 @@ store_mem_state(struct device *dev,
351 351
352 mem = container_of(dev, struct memory_block, dev); 352 mem = container_of(dev, struct memory_block, dev);
353 353
354 lock_device_hotplug(); 354 ret = lock_device_hotplug_sysfs();
355 if (ret)
356 return ret;
355 357
356 if (!strncmp(buf, "online_kernel", min_t(int, count, 13))) { 358 if (!strncmp(buf, "online_kernel", min_t(int, count, 13))) {
357 offline = false; 359 offline = false;