Merge branch 'acpi-hotplug'
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Thu, 7 Nov 2013 18:31:15 +0000 (19:31 +0100)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Thu, 7 Nov 2013 18:31:15 +0000 (19:31 +0100)
* acpi-hotplug:
  ACPI / hotplug: Consolidate deferred execution of ACPI hotplug routines
  ACPI / hotplug: Do not execute "insert in progress" _OST
  ACPI / hotplug: Carry out PCI root eject directly
  ACPI / hotplug: Merge device hot-removal routines
  ACPI / hotplug: Make acpi_bus_hot_remove_device() internal
  ACPI / hotplug: Simplify device ejection routines
  ACPI / hotplug: Fix handle_root_bridge_removal()
  ACPI / hotplug: Refuse to hot-remove all objects with disabled hotplug
  ACPI / scan: Start matching drivers after trying scan handlers
  ACPI: Remove acpi_pci_slot_init() headers from internal.h

Conflicts:
include/acpi/acpiosxf.h (with the 'acpica' branch)

drivers/acpi/dock.c
drivers/acpi/internal.h
drivers/acpi/osl.c
drivers/acpi/pci_root.c
drivers/acpi/scan.c
drivers/pci/hotplug/acpiphp_glue.c
include/acpi/acpi_bus.h
include/acpi/platform/aclinux.h

index ca86c1ce7c8a1b5d06713e6a5264e25bd05e99e5..dcd73ccb514c601df4efdee7043f2a7cffeb718e 100644 (file)
@@ -669,39 +669,20 @@ static void dock_notify(struct dock_station *ds, u32 event)
        }
 }
 
-struct dock_data {
-       struct dock_station *ds;
-       u32 event;
-};
-
-static void acpi_dock_deferred_cb(void *context)
+static void acpi_dock_deferred_cb(void *data, u32 event)
 {
-       struct dock_data *data = context;
-
        acpi_scan_lock_acquire();
-       dock_notify(data->ds, data->event);
+       dock_notify(dataevent);
        acpi_scan_lock_release();
-       kfree(data);
 }
 
 static void dock_notify_handler(acpi_handle handle, u32 event, void *data)
 {
-       struct dock_data *dd;
-
        if (event != ACPI_NOTIFY_BUS_CHECK && event != ACPI_NOTIFY_DEVICE_CHECK
           && event != ACPI_NOTIFY_EJECT_REQUEST)
                return;
 
-       dd = kmalloc(sizeof(*dd), GFP_KERNEL);
-       if (dd) {
-               acpi_status status;
-
-               dd->ds = data;
-               dd->event = event;
-               status = acpi_os_hotplug_execute(acpi_dock_deferred_cb, dd);
-               if (ACPI_FAILURE(status))
-                       kfree(dd);
-       }
+       acpi_hotplug_execute(acpi_dock_deferred_cb, data, event);
 }
 
 /**
index e9304dc7ebfa0dc40c37dcc3be270cc299b94170..a29739c0ba790af9c967efc29ef6907bf06b63d6 100644 (file)
 acpi_status acpi_os_initialize1(void);
 int init_acpi_device_notify(void);
 int acpi_scan_init(void);
-#ifdef CONFIG_ACPI_PCI_SLOT
-void acpi_pci_slot_init(void);
-#else
-static inline void acpi_pci_slot_init(void) { }
-#endif
 void acpi_pci_root_init(void);
 void acpi_pci_link_init(void);
 void acpi_pci_root_hp_init(void);
@@ -92,6 +87,7 @@ void acpi_device_add_finalize(struct acpi_device *device);
 void acpi_free_pnp_ids(struct acpi_device_pnp *pnp);
 int acpi_bind_one(struct device *dev, acpi_handle handle);
 int acpi_unbind_one(struct device *dev);
+void acpi_bus_device_eject(void *data, u32 ost_src);
 
 /* --------------------------------------------------------------------------
                                   Power Resource
index a0c09adf7e7d2043587dad0384ba1374353989c7..54a20ff4b864d90881cf41be6fbebd33de1c32a9 100644 (file)
@@ -61,7 +61,6 @@ struct acpi_os_dpc {
        acpi_osd_exec_callback function;
        void *context;
        struct work_struct work;
-       int wait;
 };
 
 #ifdef CONFIG_ACPI_CUSTOM_DSDT
@@ -1087,9 +1086,6 @@ static void acpi_os_execute_deferred(struct work_struct *work)
 {
        struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work);
 
-       if (dpc->wait)
-               acpi_os_wait_events_complete();
-
        dpc->function(dpc->context);
        kfree(dpc);
 }
@@ -1109,8 +1105,8 @@ static void acpi_os_execute_deferred(struct work_struct *work)
  *
  ******************************************************************************/
 
-static acpi_status __acpi_os_execute(acpi_execute_type type,
-       acpi_osd_exec_callback function, void *context, int hp)
+acpi_status acpi_os_execute(acpi_execute_type type,
+                           acpi_osd_exec_callback function, void *context)
 {
        acpi_status status = AE_OK;
        struct acpi_os_dpc *dpc;
@@ -1137,20 +1133,11 @@ static acpi_status __acpi_os_execute(acpi_execute_type type,
        dpc->context = context;
 
        /*
-        * We can't run hotplug code in keventd_wq/kacpid_wq/kacpid_notify_wq
-        * because the hotplug code may call driver .remove() functions,
-        * which invoke flush_scheduled_work/acpi_os_wait_events_complete
-        * to flush these workqueues.
-        *
         * To prevent lockdep from complaining unnecessarily, make sure that
         * there is a different static lockdep key for each workqueue by using
         * INIT_WORK() for each of them separately.
         */
-       if (hp) {
-               queue = kacpi_hotplug_wq;
-               dpc->wait = 1;
-               INIT_WORK(&dpc->work, acpi_os_execute_deferred);
-       } else if (type == OSL_NOTIFY_HANDLER) {
+       if (type == OSL_NOTIFY_HANDLER) {
                queue = kacpi_notify_wq;
                INIT_WORK(&dpc->work, acpi_os_execute_deferred);
        } else {
@@ -1175,28 +1162,59 @@ static acpi_status __acpi_os_execute(acpi_execute_type type,
        }
        return status;
 }
+EXPORT_SYMBOL(acpi_os_execute);
 
-acpi_status acpi_os_execute(acpi_execute_type type,
-                           acpi_osd_exec_callback function, void *context)
+void acpi_os_wait_events_complete(void)
 {
-       return __acpi_os_execute(type, function, context, 0);
+       flush_workqueue(kacpid_wq);
+       flush_workqueue(kacpi_notify_wq);
 }
-EXPORT_SYMBOL(acpi_os_execute);
 
-acpi_status acpi_os_hotplug_execute(acpi_osd_exec_callback function,
-       void *context)
+struct acpi_hp_work {
+       struct work_struct work;
+       acpi_hp_callback func;
+       void *data;
+       u32 src;
+};
+
+static void acpi_hotplug_work_fn(struct work_struct *work)
 {
-       return __acpi_os_execute(0, function, context, 1);
+       struct acpi_hp_work *hpw = container_of(work, struct acpi_hp_work, work);
+
+       acpi_os_wait_events_complete();
+       hpw->func(hpw->data, hpw->src);
+       kfree(hpw);
 }
-EXPORT_SYMBOL(acpi_os_hotplug_execute);
 
-void acpi_os_wait_events_complete(void)
+acpi_status acpi_hotplug_execute(acpi_hp_callback func, void *data, u32 src)
 {
-       flush_workqueue(kacpid_wq);
-       flush_workqueue(kacpi_notify_wq);
+       struct acpi_hp_work *hpw;
+
+       ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+                 "Scheduling function [%p(%p, %u)] for deferred execution.\n",
+                 func, data, src));
+
+       hpw = kmalloc(sizeof(*hpw), GFP_KERNEL);
+       if (!hpw)
+               return AE_NO_MEMORY;
+
+       INIT_WORK(&hpw->work, acpi_hotplug_work_fn);
+       hpw->func = func;
+       hpw->data = data;
+       hpw->src = src;
+       /*
+        * We can't run hotplug code in kacpid_wq/kacpid_notify_wq etc., because
+        * the hotplug code may call driver .remove() functions, which may
+        * invoke flush_scheduled_work()/acpi_os_wait_events_complete() to flush
+        * these workqueues.
+        */
+       if (!queue_work(kacpi_hotplug_wq, &hpw->work)) {
+               kfree(hpw);
+               return AE_ERROR;
+       }
+       return AE_OK;
 }
 
-EXPORT_SYMBOL(acpi_os_wait_events_complete);
 
 acpi_status
 acpi_os_create_semaphore(u32 max_units, u32 initial_units, acpi_handle * handle)
@@ -1845,25 +1863,3 @@ void acpi_os_set_prepare_extended_sleep(int (*func)(u8 sleep_state,
 {
        __acpi_os_prepare_extended_sleep = func;
 }
-
-
-void alloc_acpi_hp_work(acpi_handle handle, u32 type, void *context,
-                       void (*func)(struct work_struct *work))
-{
-       struct acpi_hp_work *hp_work;
-       int ret;
-
-       hp_work = kmalloc(sizeof(*hp_work), GFP_KERNEL);
-       if (!hp_work)
-               return;
-
-       hp_work->handle = handle;
-       hp_work->type = type;
-       hp_work->context = context;
-
-       INIT_WORK(&hp_work->work, func);
-       ret = queue_work(kacpi_hotplug_wq, &hp_work->work);
-       if (!ret)
-               kfree(hp_work);
-}
-EXPORT_SYMBOL_GPL(alloc_acpi_hp_work);
index d3874f4256534d06aeb0fdb9f364e5f5851963f3..417876bce8541f578cab2c01d5d1b459256f3195 100644 (file)
@@ -39,6 +39,8 @@
 #include <acpi/acpi_drivers.h>
 #include <acpi/apei.h>
 
+#include "internal.h"
+
 #define PREFIX "ACPI: "
 
 #define _COMPONENT             ACPI_PCI_COMPONENT
@@ -590,39 +592,10 @@ static void handle_root_bridge_insertion(acpi_handle handle)
                acpi_handle_err(handle, "cannot add bridge to acpi list\n");
 }
 
-static void handle_root_bridge_removal(struct acpi_device *device)
-{
-       acpi_status status;
-       struct acpi_eject_event *ej_event;
-
-       ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL);
-       if (!ej_event) {
-               /* Inform firmware the hot-remove operation has error */
-               (void) acpi_evaluate_hotplug_ost(device->handle,
-                                       ACPI_NOTIFY_EJECT_REQUEST,
-                                       ACPI_OST_SC_NON_SPECIFIC_FAILURE,
-                                       NULL);
-               return;
-       }
-
-       ej_event->device = device;
-       ej_event->event = ACPI_NOTIFY_EJECT_REQUEST;
-
-       status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device, ej_event);
-       if (ACPI_FAILURE(status))
-               kfree(ej_event);
-}
-
-static void _handle_hotplug_event_root(struct work_struct *work)
+static void hotplug_event_root(void *data, u32 type)
 {
+       acpi_handle handle = data;
        struct acpi_pci_root *root;
-       struct acpi_hp_work *hp_work;
-       acpi_handle handle;
-       u32 type;
-
-       hp_work = container_of(work, struct acpi_hp_work, work);
-       handle = hp_work->handle;
-       type = hp_work->type;
 
        acpi_scan_lock_acquire();
 
@@ -652,9 +625,15 @@ static void _handle_hotplug_event_root(struct work_struct *work)
                /* request device eject */
                acpi_handle_printk(KERN_DEBUG, handle,
                                   "Device eject notify on %s\n", __func__);
-               if (root)
-                       handle_root_bridge_removal(root->device);
-               break;
+               if (!root)
+                       break;
+
+               get_device(&root->device->dev);
+
+               acpi_scan_lock_release();
+
+               acpi_bus_device_eject(root->device, ACPI_NOTIFY_EJECT_REQUEST);
+               return;
        default:
                acpi_handle_warn(handle,
                                 "notify_handler: unknown event type 0x%x\n",
@@ -663,14 +642,12 @@ static void _handle_hotplug_event_root(struct work_struct *work)
        }
 
        acpi_scan_lock_release();
-       kfree(hp_work); /* allocated in handle_hotplug_event_bridge */
 }
 
 static void handle_hotplug_event_root(acpi_handle handle, u32 type,
                                        void *context)
 {
-       alloc_acpi_hp_work(handle, type, context,
-                               _handle_hotplug_event_root);
+       acpi_hotplug_execute(hotplug_event_root, handle, type);
 }
 
 static acpi_status __init
index fee8a297c7d95310caa64492b75e6c2fae0c280e..55f9dedbbf9fedc5aae2cf21852c7474514cd0d1 100644 (file)
@@ -125,8 +125,8 @@ acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, cha
 }
 static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL);
 
-static acpi_status acpi_bus_offline_companions(acpi_handle handle, u32 lvl,
-                                              void *data, void **ret_p)
+static acpi_status acpi_bus_offline(acpi_handle handle, u32 lvl, void *data,
+                                   void **ret_p)
 {
        struct acpi_device *device = NULL;
        struct acpi_device_physical_node *pn;
@@ -136,6 +136,11 @@ static acpi_status acpi_bus_offline_companions(acpi_handle handle, u32 lvl,
        if (acpi_bus_get_device(handle, &device))
                return AE_OK;
 
+       if (device->handler && !device->handler->hotplug.enabled) {
+               *ret_p = &device->dev;
+               return AE_SUPPORT;
+       }
+
        mutex_lock(&device->physical_node_lock);
 
        list_for_each_entry(pn, &device->physical_node_list, node) {
@@ -168,8 +173,8 @@ static acpi_status acpi_bus_offline_companions(acpi_handle handle, u32 lvl,
        return status;
 }
 
-static acpi_status acpi_bus_online_companions(acpi_handle handle, u32 lvl,
-                                             void *data, void **ret_p)
+static acpi_status acpi_bus_online(acpi_handle handle, u32 lvl, void *data,
+                                  void **ret_p)
 {
        struct acpi_device *device = NULL;
        struct acpi_device_physical_node *pn;
@@ -214,26 +219,32 @@ static int acpi_scan_hot_remove(struct acpi_device *device)
         * If the first pass is successful, the second one isn't needed, though.
         */
        errdev = NULL;
-       acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
-                           NULL, acpi_bus_offline_companions,
-                           (void *)false, (void **)&errdev);
-       acpi_bus_offline_companions(handle, 0, (void *)false, (void **)&errdev);
+       status = acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
+                                    NULL, acpi_bus_offline, (void *)false,
+                                    (void **)&errdev);
+       if (status == AE_SUPPORT) {
+               dev_warn(errdev, "Offline disabled.\n");
+               acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
+                                   acpi_bus_online, NULL, NULL, NULL);
+               put_device(&device->dev);
+               return -EPERM;
+       }
+       acpi_bus_offline(handle, 0, (void *)false, (void **)&errdev);
        if (errdev) {
                errdev = NULL;
                acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
-                                   NULL, acpi_bus_offline_companions,
-                                   (void *)true , (void **)&errdev);
+                                   NULL, acpi_bus_offline, (void *)true,
+                                   (void **)&errdev);
                if (!errdev || acpi_force_hot_remove)
-                       acpi_bus_offline_companions(handle, 0, (void *)true,
-                                                   (void **)&errdev);
+                       acpi_bus_offline(handle, 0, (void *)true,
+                                        (void **)&errdev);
 
                if (errdev && !acpi_force_hot_remove) {
                        dev_warn(errdev, "Offline failed.\n");
-                       acpi_bus_online_companions(handle, 0, NULL, NULL);
+                       acpi_bus_online(handle, 0, NULL, NULL);
                        acpi_walk_namespace(ACPI_TYPE_ANY, handle,
-                                           ACPI_UINT32_MAX,
-                                           acpi_bus_online_companions, NULL,
-                                           NULL, NULL);
+                                           ACPI_UINT32_MAX, acpi_bus_online,
+                                           NULL, NULL, NULL);
                        put_device(&device->dev);
                        return -EBUSY;
                }
@@ -274,10 +285,10 @@ static int acpi_scan_hot_remove(struct acpi_device *device)
        return 0;
 }
 
-static void acpi_bus_device_eject(void *context)
+void acpi_bus_device_eject(void *data, u32 ost_src)
 {
-       acpi_handle handle = context;
-       struct acpi_device *device = NULL;
+       struct acpi_device *device = data;
+       acpi_handle handle = device->handle;
        struct acpi_scan_handler *handler;
        u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
        int error;
@@ -285,38 +296,41 @@ static void acpi_bus_device_eject(void *context)
        lock_device_hotplug();
        mutex_lock(&acpi_scan_lock);
 
-       acpi_bus_get_device(handle, &device);
-       if (!device)
-               goto err_out;
-
        handler = device->handler;
        if (!handler || !handler->hotplug.enabled) {
-               ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
-               goto err_out;
+               put_device(&device->dev);
+               goto err_support;
        }
-       acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST,
-                                 ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
+
+       if (ost_src == ACPI_NOTIFY_EJECT_REQUEST)
+               acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST,
+                                         ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
+
        if (handler->hotplug.mode == AHM_CONTAINER)
                kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE);
 
-       get_device(&device->dev);
        error = acpi_scan_hot_remove(device);
-       if (error)
+       if (error == -EPERM) {
+               goto err_support;
+       } else if (error) {
                goto err_out;
+       }
 
  out:
        mutex_unlock(&acpi_scan_lock);
        unlock_device_hotplug();
        return;
 
+ err_support:
+       ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
  err_out:
-       acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST, ost_code,
-                                 NULL);
+       acpi_evaluate_hotplug_ost(handle, ost_src, ost_code, NULL);
        goto out;
 }
 
-static void acpi_scan_bus_device_check(acpi_handle handle, u32 ost_source)
+static void acpi_scan_bus_device_check(void *data, u32 ost_source)
 {
+       acpi_handle handle = data;
        struct acpi_device *device = NULL;
        u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
        int error;
@@ -331,8 +345,6 @@ static void acpi_scan_bus_device_check(acpi_handle handle, u32 ost_source)
                        goto out;
                }
        }
-       acpi_evaluate_hotplug_ost(handle, ost_source,
-                                 ACPI_OST_SC_INSERT_IN_PROGRESS, NULL);
        error = acpi_bus_scan(handle);
        if (error) {
                acpi_handle_warn(handle, "Namespace scan failure\n");
@@ -353,18 +365,6 @@ static void acpi_scan_bus_device_check(acpi_handle handle, u32 ost_source)
        unlock_device_hotplug();
 }
 
-static void acpi_scan_bus_check(void *context)
-{
-       acpi_scan_bus_device_check((acpi_handle)context,
-                                  ACPI_NOTIFY_BUS_CHECK);
-}
-
-static void acpi_scan_device_check(void *context)
-{
-       acpi_scan_bus_device_check((acpi_handle)context,
-                                  ACPI_NOTIFY_DEVICE_CHECK);
-}
-
 static void acpi_hotplug_unsupported(acpi_handle handle, u32 type)
 {
        u32 ost_status;
@@ -395,8 +395,8 @@ static void acpi_hotplug_unsupported(acpi_handle handle, u32 type)
 
 static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
 {
-       acpi_osd_exec_callback callback;
        struct acpi_scan_handler *handler = data;
+       struct acpi_device *adev;
        acpi_status status;
 
        if (!handler->hotplug.enabled)
@@ -405,56 +405,35 @@ static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
        switch (type) {
        case ACPI_NOTIFY_BUS_CHECK:
                acpi_handle_debug(handle, "ACPI_NOTIFY_BUS_CHECK event\n");
-               callback = acpi_scan_bus_check;
                break;
        case ACPI_NOTIFY_DEVICE_CHECK:
                acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK event\n");
-               callback = acpi_scan_device_check;
                break;
        case ACPI_NOTIFY_EJECT_REQUEST:
                acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n");
-               callback = acpi_bus_device_eject;
-               break;
+               status = acpi_bus_get_device(handle, &adev);
+               if (ACPI_FAILURE(status))
+                       goto err_out;
+
+               get_device(&adev->dev);
+               status = acpi_hotplug_execute(acpi_bus_device_eject, adev, type);
+               if (ACPI_SUCCESS(status))
+                       return;
+
+               put_device(&adev->dev);
+               goto err_out;
        default:
                /* non-hotplug event; possibly handled by other handler */
                return;
        }
-       status = acpi_os_hotplug_execute(callback, handle);
-       if (ACPI_FAILURE(status))
-               acpi_evaluate_hotplug_ost(handle, type,
-                                         ACPI_OST_SC_NON_SPECIFIC_FAILURE,
-                                         NULL);
-}
-
-/**
- * acpi_bus_hot_remove_device: hot-remove a device and its children
- * @context: struct acpi_eject_event pointer (freed in this func)
- *
- * Hot-remove a device and its children. This function frees up the
- * memory space passed by arg context, so that the caller may call
- * this function asynchronously through acpi_os_hotplug_execute().
- */
-void acpi_bus_hot_remove_device(void *context)
-{
-       struct acpi_eject_event *ej_event = context;
-       struct acpi_device *device = ej_event->device;
-       acpi_handle handle = device->handle;
-       int error;
-
-       lock_device_hotplug();
-       mutex_lock(&acpi_scan_lock);
-
-       error = acpi_scan_hot_remove(device);
-       if (error && handle)
-               acpi_evaluate_hotplug_ost(handle, ej_event->event,
-                                         ACPI_OST_SC_NON_SPECIFIC_FAILURE,
-                                         NULL);
+       status = acpi_hotplug_execute(acpi_scan_bus_device_check, handle, type);
+       if (ACPI_SUCCESS(status))
+               return;
 
-       mutex_unlock(&acpi_scan_lock);
-       unlock_device_hotplug();
-       kfree(context);
+ err_out:
+       acpi_evaluate_hotplug_ost(handle, type,
+                                 ACPI_OST_SC_NON_SPECIFIC_FAILURE, NULL);
 }
-EXPORT_SYMBOL(acpi_bus_hot_remove_device);
 
 static ssize_t real_power_state_show(struct device *dev,
                                     struct device_attribute *attr, char *buf)
@@ -487,10 +466,8 @@ acpi_eject_store(struct device *d, struct device_attribute *attr,
                const char *buf, size_t count)
 {
        struct acpi_device *acpi_device = to_acpi_device(d);
-       struct acpi_eject_event *ej_event;
        acpi_object_type not_used;
        acpi_status status;
-       int ret;
 
        if (!count || buf[0] != '1')
                return -EINVAL;
@@ -503,28 +480,18 @@ acpi_eject_store(struct device *d, struct device_attribute *attr,
        if (ACPI_FAILURE(status) || !acpi_device->flags.ejectable)
                return -ENODEV;
 
-       ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL);
-       if (!ej_event) {
-               ret = -ENOMEM;
-               goto err_out;
-       }
        acpi_evaluate_hotplug_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT,
                                  ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
-       ej_event->device = acpi_device;
-       ej_event->event = ACPI_OST_EC_OSPM_EJECT;
        get_device(&acpi_device->dev);
-       status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device, ej_event);
+       status = acpi_hotplug_execute(acpi_bus_device_eject, acpi_device,
+                                     ACPI_OST_EC_OSPM_EJECT);
        if (ACPI_SUCCESS(status))
                return count;
 
        put_device(&acpi_device->dev);
-       kfree(ej_event);
-       ret = status == AE_NO_MEMORY ? -ENOMEM : -EAGAIN;
-
- err_out:
        acpi_evaluate_hotplug_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT,
                                  ACPI_OST_SC_NON_SPECIFIC_FAILURE, NULL);
-       return ret;
+       return status == AE_NO_MEMORY ? -ENOMEM : -EAGAIN;
 }
 
 static DEVICE_ATTR(eject, 0200, NULL, acpi_eject_store);
@@ -1676,7 +1643,6 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
 
 void acpi_device_add_finalize(struct acpi_device *device)
 {
-       device->flags.match_driver = true;
        dev_set_uevent_suppress(&device->dev, false);
        kobject_uevent(&device->dev.kobj, KOBJ_ADD);
 }
@@ -1915,8 +1881,12 @@ static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used,
                return AE_OK;
 
        ret = acpi_scan_attach_handler(device);
-       if (ret)
-               return ret > 0 ? AE_OK : AE_CTRL_DEPTH;
+       if (ret < 0)
+               return AE_CTRL_DEPTH;
+
+       device->flags.match_driver = true;
+       if (ret > 0)
+               return AE_OK;
 
        ret = device_attach(&device->dev);
        return ret >= 0 ? AE_OK : AE_CTRL_DEPTH;
index be12fbfcae1042e90c00d192bffe46c47821b6c4..e98018b43e2aedc528a5a97b63217e72da83eaa8 100644 (file)
@@ -875,21 +875,17 @@ static void hotplug_event(acpi_handle handle, u32 type, void *data)
                put_bridge(bridge);
 }
 
-static void hotplug_event_work(struct work_struct *work)
+static void hotplug_event_work(void *data, u32 type)
 {
-       struct acpiphp_context *context;
-       struct acpi_hp_work *hp_work;
+       struct acpiphp_context *context = data;
+       acpi_handle handle = context->handle;
 
-       hp_work = container_of(work, struct acpi_hp_work, work);
-       context = hp_work->context;
        acpi_scan_lock_acquire();
 
-       hotplug_event(hp_work->handle, hp_work->type, context);
+       hotplug_event(handle, type, context);
 
        acpi_scan_lock_release();
-       acpi_evaluate_hotplug_ost(hp_work->handle, hp_work->type,
-                                 ACPI_OST_SC_SUCCESS, NULL);
-       kfree(hp_work); /* allocated in handle_hotplug_event() */
+       acpi_evaluate_hotplug_ost(handle, type, ACPI_OST_SC_SUCCESS, NULL);
        put_bridge(context->func.parent);
 }
 
@@ -940,10 +936,10 @@ static void handle_hotplug_event(acpi_handle handle, u32 type, void *data)
 
        mutex_lock(&acpiphp_context_lock);
        context = acpiphp_get_context(handle);
-       if (context) {
+       if (context && !WARN_ON(context->handle != handle)) {
                get_bridge(context->func.parent);
                acpiphp_put_context(context);
-               alloc_acpi_hp_work(handle, type, context, hotplug_event_work);
+               acpi_hotplug_execute(hotplug_event_work, context, type);
                mutex_unlock(&acpiphp_context_lock);
                return;
        }
index 15100f625e6550a94bc2afe721ccf3804a2360d5..89c60b0f640819c7ed93b40774d5b9c3f3cbadfb 100644 (file)
@@ -339,20 +339,6 @@ struct acpi_bus_event {
        u32 data;
 };
 
-struct acpi_eject_event {
-       struct acpi_device      *device;
-       u32             event;
-};
-
-struct acpi_hp_work {
-       struct work_struct work;
-       acpi_handle handle;
-       u32 type;
-       void *context;
-};
-void alloc_acpi_hp_work(acpi_handle handle, u32 type, void *context,
-                       void (*func)(struct work_struct *work));
-
 extern struct kobject *acpi_kobj;
 extern int acpi_bus_generate_netlink_event(const char*, const char*, u8, int);
 void acpi_bus_private_data_handler(acpi_handle, void *);
@@ -391,7 +377,6 @@ int acpi_scan_add_handler(struct acpi_scan_handler *handler);
 int acpi_bus_register_driver(struct acpi_driver *driver);
 void acpi_bus_unregister_driver(struct acpi_driver *driver);
 int acpi_bus_scan(acpi_handle handle);
-void acpi_bus_hot_remove_device(void *context);
 void acpi_bus_trim(struct acpi_device *start);
 acpi_status acpi_bus_get_ejd(acpi_handle handle, acpi_handle * ejd);
 int acpi_match_device_ids(struct acpi_device *device,
@@ -399,6 +384,9 @@ int acpi_match_device_ids(struct acpi_device *device,
 int acpi_create_dir(struct acpi_device *);
 void acpi_remove_dir(struct acpi_device *);
 
+typedef void (*acpi_hp_callback)(void *data, u32 src);
+
+acpi_status acpi_hotplug_execute(acpi_hp_callback func, void *data, u32 src);
 
 /**
  * module_acpi_driver(acpi_driver) - Helper macro for registering an ACPI driver
index ab57930794a5843e252c59c2ffadf310af877ff5..28f4f4dba0b667c5ee10001199ee87e02dd887ae 100644 (file)
@@ -243,9 +243,6 @@ void acpi_os_gpe_count(u32 gpe_number);
 
 void acpi_os_fixed_event_count(u32 fixed_event_number);
 
-acpi_status
-acpi_os_hotplug_execute(acpi_osd_exec_callback function, void *context);
-
 #endif                         /* __KERNEL__ */
 
 #endif                         /* __ACLINUX_H__ */