diff options
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/dock.c | 25 | ||||
-rw-r--r-- | drivers/acpi/osl.c | 46 |
2 files changed, 65 insertions, 6 deletions
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 2563bc62987d..4b395b1e61b2 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -748,6 +748,20 @@ static void dock_notify(acpi_handle handle, u32 event, void *data) } } +struct dock_data { + acpi_handle handle; + unsigned long event; + struct dock_station *ds; +}; + +static void acpi_dock_deferred_cb(void *context) +{ + struct dock_data *data = (struct dock_data *)context; + + dock_notify(data->handle, data->event, data->ds); + kfree(data); +} + static int acpi_dock_notifier_call(struct notifier_block *this, unsigned long event, void *data) { @@ -759,7 +773,16 @@ static int acpi_dock_notifier_call(struct notifier_block *this, return 0; list_for_each_entry(dock_station, &dock_stations, sibiling) { if (dock_station->handle == handle) { - dock_notify(handle, event, dock_station); + struct dock_data *dock_data; + + dock_data = kmalloc(sizeof(*dock_data), GFP_KERNEL); + if (!dock_data) + return 0; + dock_data->handle = handle; + dock_data->event = event; + dock_data->ds = dock_station; + acpi_os_hotplug_execute(acpi_dock_deferred_cb, + dock_data); return 0 ; } } diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 235a1386888a..750e0df15604 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -682,6 +682,22 @@ static void acpi_os_execute_deferred(struct work_struct *work) return; } +static void acpi_os_execute_hp_deferred(struct work_struct *work) +{ + struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work); + if (!dpc) { + printk(KERN_ERR PREFIX "Invalid (NULL) context\n"); + return; + } + + acpi_os_wait_events_complete(NULL); + + dpc->function(dpc->context); + kfree(dpc); + + return; +} + /******************************************************************************* * * FUNCTION: acpi_os_execute @@ -697,12 +713,13 @@ static void acpi_os_execute_deferred(struct work_struct *work) * ******************************************************************************/ -acpi_status acpi_os_execute(acpi_execute_type type, - acpi_osd_exec_callback function, void *context) +static acpi_status __acpi_os_execute(acpi_execute_type type, + acpi_osd_exec_callback function, void *context, int hp) { acpi_status status = AE_OK; struct acpi_os_dpc *dpc; struct workqueue_struct *queue; + int ret; ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Scheduling function [%p(%p)] for deferred execution.\n", function, context)); @@ -726,9 +743,17 @@ acpi_status acpi_os_execute(acpi_execute_type type, dpc->function = function; dpc->context = context; - INIT_WORK(&dpc->work, acpi_os_execute_deferred); - queue = (type == OSL_NOTIFY_HANDLER) ? kacpi_notify_wq : kacpid_wq; - if (!queue_work(queue, &dpc->work)) { + if (!hp) { + INIT_WORK(&dpc->work, acpi_os_execute_deferred); + queue = (type == OSL_NOTIFY_HANDLER) ? + kacpi_notify_wq : kacpid_wq; + ret = queue_work(queue, &dpc->work); + } else { + INIT_WORK(&dpc->work, acpi_os_execute_hp_deferred); + ret = schedule_work(&dpc->work); + } + + if (!ret) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Call to queue_work() failed.\n")); status = AE_ERROR; @@ -737,8 +762,19 @@ acpi_status acpi_os_execute(acpi_execute_type type, return_ACPI_STATUS(status); } +acpi_status acpi_os_execute(acpi_execute_type type, + acpi_osd_exec_callback function, void *context) +{ + return __acpi_os_execute(type, function, context, 0); +} EXPORT_SYMBOL(acpi_os_execute); +acpi_status acpi_os_hotplug_execute(acpi_osd_exec_callback function, + void *context) +{ + return __acpi_os_execute(0, function, context, 1); +} + void acpi_os_wait_events_complete(void *context) { flush_workqueue(kacpid_wq); |