summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/acpi/dock.c25
-rw-r--r--drivers/acpi/internal.h2
-rw-r--r--drivers/acpi/osl.c96
-rw-r--r--drivers/acpi/pci_root.c14
-rw-r--r--drivers/acpi/scan.c43
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c18
-rw-r--r--include/acpi/acpi_bus.h12
-rw-r--r--include/acpi/acpiosxf.h3
8 files changed, 71 insertions, 142 deletions
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index 05ea4be..eab7d11 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -671,39 +671,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(data, event);
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);
}
/**
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
index 80cd1a1..c6db680 100644
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -87,7 +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(struct acpi_device *device, u32 ost_src);
+void acpi_bus_device_eject(void *data, u32 ost_src);
/* --------------------------------------------------------------------------
Power Resource
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index e5f416c..cfc3e26 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -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
@@ -1067,9 +1066,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);
}
@@ -1089,8 +1085,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;
@@ -1117,20 +1113,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 {
@@ -1155,28 +1142,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)
@@ -1825,25 +1843,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);
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index d77f0bf..417876b 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -592,17 +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_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;
- kfree(hp_work); /* allocated in handle_hotplug_event_bridge */
acpi_scan_lock_acquire();
@@ -654,8 +647,7 @@ static void _handle_hotplug_event_root(struct work_struct *work)
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
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 5cd7f8c..276cde7 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -285,8 +285,9 @@ static int acpi_scan_hot_remove(struct acpi_device *device)
return 0;
}
-void acpi_bus_device_eject(struct acpi_device *device, u32 ost_src)
+void acpi_bus_device_eject(void *data, u32 ost_src)
{
+ struct acpi_device *device = data;
acpi_handle handle = device->handle;
struct acpi_scan_handler *handler;
u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
@@ -327,8 +328,9 @@ void acpi_bus_device_eject(struct acpi_device *device, u32 ost_src)
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;
@@ -363,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;
@@ -403,18 +393,8 @@ static void acpi_hotplug_unsupported(acpi_handle handle, u32 type)
acpi_evaluate_hotplug_ost(handle, type, ost_status, NULL);
}
-/**
- * acpi_bus_hot_remove_device: Hot-remove a device and its children.
- * @context: Address of the ACPI device object to hot-remove.
- */
-static void acpi_bus_hot_remove_device(void *context)
-{
- acpi_bus_device_eject(context, ACPI_NOTIFY_EJECT_REQUEST);
-}
-
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;
@@ -425,11 +405,9 @@ 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");
@@ -438,8 +416,7 @@ static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
goto err_out;
get_device(&adev->dev);
- callback = acpi_bus_hot_remove_device;
- status = acpi_os_hotplug_execute(callback, adev);
+ status = acpi_hotplug_execute(acpi_bus_device_eject, adev, type);
if (ACPI_SUCCESS(status))
return;
@@ -449,7 +426,7 @@ static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
/* non-hotplug event; possibly handled by other handler */
return;
}
- status = acpi_os_hotplug_execute(callback, handle);
+ status = acpi_hotplug_execute(acpi_scan_bus_device_check, handle, type);
if (ACPI_SUCCESS(status))
return;
@@ -484,11 +461,6 @@ static ssize_t power_state_show(struct device *dev,
static DEVICE_ATTR(power_state, 0444, power_state_show, NULL);
-static void acpi_eject_store_work(void *context)
-{
- acpi_bus_device_eject(context, ACPI_OST_EC_OSPM_EJECT);
-}
-
static ssize_t
acpi_eject_store(struct device *d, struct device_attribute *attr,
const char *buf, size_t count)
@@ -511,7 +483,8 @@ acpi_eject_store(struct device *d, struct device_attribute *attr,
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_os_hotplug_execute(acpi_eject_store_work, acpi_device);
+ status = acpi_hotplug_execute(acpi_bus_device_eject, acpi_device,
+ ACPI_OST_EC_OSPM_EJECT);
if (ACPI_SUCCESS(status))
return count;
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 0b7d23b..5246ba2 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -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;
}
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index eb37a6f..d64a301 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -339,15 +339,6 @@ struct acpi_bus_event {
u32 data;
};
-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 *);
@@ -393,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
diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h
index 64b8c76..505cb4d 100644
--- a/include/acpi/acpiosxf.h
+++ b/include/acpi/acpiosxf.h
@@ -200,9 +200,6 @@ acpi_status
acpi_os_execute(acpi_execute_type type,
acpi_osd_exec_callback function, void *context);
-acpi_status
-acpi_os_hotplug_execute(acpi_osd_exec_callback function, void *context);
-
void acpi_os_wait_events_complete(void);
void acpi_os_sleep(u64 milliseconds);
OpenPOWER on IntegriCloud