ACPI / hotplug / PCI: Rework the handling of eject requests
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Mon, 3 Feb 2014 23:44:02 +0000 (00:44 +0100)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Thu, 6 Feb 2014 16:31:51 +0000 (17:31 +0100)
To avoid the need to install a hotplug notify handler for each ACPI
namespace node representing a device and having a matching scan
handler, move the check whether or not the ejection of the given
device is enabled through its scan handler from acpi_hotplug_notify_cb()
to acpi_generic_hotplug_event().  Also, move the execution of
ACPI_OST_SC_EJECT_IN_PROGRESS _OST to acpi_generic_hotplug_event(),
because in acpi_hotplug_notify_cb() or in acpi_eject_store() we really
don't know whether or not the eject is going to be in progress (for
example, acpi_hotplug_execute() may still fail without queuing up the
work item).

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Tested-by: Mika Westerberg <mika.westerberg@linux.intel.com>
drivers/acpi/scan.c

index 984eaff..a3f5d6e 100644 (file)
@@ -459,6 +459,12 @@ static int acpi_generic_hotplug_event(struct acpi_device *adev, u32 type)
                return acpi_scan_device_check(adev);
        case ACPI_NOTIFY_EJECT_REQUEST:
        case ACPI_OST_EC_OSPM_EJECT:
+               if (adev->handler && !adev->handler->hotplug.enabled) {
+                       dev_info(&adev->dev, "Eject disabled\n");
+                       return -EPERM;
+               }
+               acpi_evaluate_hotplug_ost(adev->handle, ACPI_NOTIFY_EJECT_REQUEST,
+                                         ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
                return acpi_scan_hot_remove(adev);
        }
        return -EINVAL;
@@ -483,6 +489,10 @@ static void acpi_device_hotplug(void *data, u32 src)
 
        if (adev->flags.hotplug_notify) {
                error = acpi_generic_hotplug_event(adev, src);
+               if (error == -EPERM) {
+                       ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
+                       goto err_out;
+               }
        } else {
                int (*event)(struct acpi_device *, u32);
 
@@ -512,7 +522,6 @@ static void acpi_device_hotplug(void *data, u32 src)
 
 static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
 {
-       struct acpi_scan_handler *handler = data;
        u32 ost_code = ACPI_OST_SC_SUCCESS;
        struct acpi_device *adev;
        acpi_status status;
@@ -528,13 +537,6 @@ static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
 
        case ACPI_NOTIFY_EJECT_REQUEST:
                acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n");
-               if (handler && !handler->hotplug.enabled) {
-                       acpi_handle_err(handle, "Eject disabled\n");
-                       ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
-                       goto out;
-               }
-               acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST,
-                                         ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
                break;
 
        case ACPI_NOTIFY_DEVICE_WAKE:
@@ -632,8 +634,6 @@ acpi_eject_store(struct device *d, struct device_attribute *attr,
        if (ACPI_FAILURE(status) || !acpi_device->flags.ejectable)
                return -ENODEV;
 
-       acpi_evaluate_hotplug_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT,
-                                 ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
        get_device(&acpi_device->dev);
        status = acpi_hotplug_execute(acpi_device_hotplug, acpi_device,
                                      ACPI_OST_EC_OSPM_EJECT);