Commit bd3ad3b9 authored by Len Brown's avatar Len Brown Committed by Len Brown

[ACPI] create kacpid thread to handle ACPI work in process context.

Also will be needed for cpu hot-unplug.
from Anil S Keshavamurthy and David Shaohua Li
http://bugzilla.kernel.org/show_bug.cgi?id=2515
parent 6c3d6ae4
......@@ -106,7 +106,7 @@ EXPORT_SYMBOL(acpi_os_signal_semaphore);
EXPORT_SYMBOL(acpi_os_create_semaphore);
EXPORT_SYMBOL(acpi_os_delete_semaphore);
EXPORT_SYMBOL(acpi_os_wait_semaphore);
EXPORT_SYMBOL(acpi_os_wait_events_complete);
EXPORT_SYMBOL(acpi_os_read_pci_configuration);
/* ACPI Utilities (acpi_utils.c) */
......
......@@ -406,6 +406,15 @@ acpi_remove_notify_handler (
goto unlock_and_exit;
}
/* Make sure all deferred tasks are completed */
(void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
acpi_os_wait_events_complete(NULL);
status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
if (handler_type == ACPI_SYSTEM_NOTIFY) {
acpi_gbl_system_notify.node = NULL;
acpi_gbl_system_notify.handler = NULL;
......@@ -452,6 +461,15 @@ acpi_remove_notify_handler (
goto unlock_and_exit;
}
/* Make sure all deferred tasks are completed */
(void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
acpi_os_wait_events_complete(NULL);
status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
/* Remove the handler */
if (handler_type == ACPI_SYSTEM_NOTIFY) {
......@@ -614,6 +632,15 @@ acpi_remove_gpe_handler (
goto unlock_and_exit;
}
/* Make sure all deferred tasks are completed */
(void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
acpi_os_wait_events_complete(NULL);
status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
/* Remove the handler */
acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
......
......@@ -66,6 +66,7 @@ extern char line_buf[80];
static unsigned int acpi_irq_irq;
static OSD_HANDLER acpi_irq_handler;
static void *acpi_irq_context;
static struct workqueue_struct *kacpid_wq;
acpi_status
acpi_os_initialize(void)
......@@ -80,6 +81,8 @@ acpi_os_initialize(void)
return AE_NULL_ENTRY;
}
#endif
kacpid_wq = create_singlethread_workqueue("kacpid");
BUG_ON(!kacpid_wq);
return AE_OK;
}
......@@ -92,6 +95,8 @@ acpi_os_terminate(void)
acpi_irq_handler);
}
destroy_workqueue(kacpid_wq);
return AE_OK;
}
......@@ -654,8 +659,8 @@ acpi_os_queue_for_execution(
task = (void *)(dpc+1);
INIT_WORK(task, acpi_os_execute_deferred, (void*)dpc);
if (!schedule_work(task)) {
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Call to schedule_work() failed.\n"));
if (!queue_work(kacpid_wq, task)) {
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Call to queue_work() failed.\n"));
kfree(dpc);
status = AE_ERROR;
}
......@@ -663,6 +668,13 @@ acpi_os_queue_for_execution(
return_ACPI_STATUS (status);
}
void
acpi_os_wait_events_complete(
void *context)
{
flush_workqueue(kacpid_wq);
}
/*
* Allocate the memory for a spinlock and initialize it.
*/
......
......@@ -318,8 +318,10 @@ static int acpi_driver_detach(struct acpi_driver * drv)
struct acpi_device * dev = container_of(node,struct acpi_device,g_list);
if (dev->driver == drv) {
spin_unlock(&acpi_device_lock);
if (drv->ops.remove)
drv->ops.remove(dev,ACPI_BUS_REMOVAL_NORMAL);
spin_lock(&acpi_device_lock);
dev->driver = NULL;
dev->driver_data = NULL;
atomic_dec(&drv->references);
......
......@@ -212,6 +212,10 @@ acpi_os_queue_for_execution (
OSD_EXECUTION_CALLBACK function,
void *context);
void
acpi_os_wait_events_complete(
void * context);
void
acpi_os_sleep (
u32 seconds,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment