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); ...@@ -106,7 +106,7 @@ EXPORT_SYMBOL(acpi_os_signal_semaphore);
EXPORT_SYMBOL(acpi_os_create_semaphore); EXPORT_SYMBOL(acpi_os_create_semaphore);
EXPORT_SYMBOL(acpi_os_delete_semaphore); EXPORT_SYMBOL(acpi_os_delete_semaphore);
EXPORT_SYMBOL(acpi_os_wait_semaphore); EXPORT_SYMBOL(acpi_os_wait_semaphore);
EXPORT_SYMBOL(acpi_os_wait_events_complete);
EXPORT_SYMBOL(acpi_os_read_pci_configuration); EXPORT_SYMBOL(acpi_os_read_pci_configuration);
/* ACPI Utilities (acpi_utils.c) */ /* ACPI Utilities (acpi_utils.c) */
......
...@@ -406,6 +406,15 @@ acpi_remove_notify_handler ( ...@@ -406,6 +406,15 @@ acpi_remove_notify_handler (
goto unlock_and_exit; 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) { if (handler_type == ACPI_SYSTEM_NOTIFY) {
acpi_gbl_system_notify.node = NULL; acpi_gbl_system_notify.node = NULL;
acpi_gbl_system_notify.handler = NULL; acpi_gbl_system_notify.handler = NULL;
...@@ -452,6 +461,15 @@ acpi_remove_notify_handler ( ...@@ -452,6 +461,15 @@ acpi_remove_notify_handler (
goto unlock_and_exit; 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 */ /* Remove the handler */
if (handler_type == ACPI_SYSTEM_NOTIFY) { if (handler_type == ACPI_SYSTEM_NOTIFY) {
...@@ -614,6 +632,15 @@ acpi_remove_gpe_handler ( ...@@ -614,6 +632,15 @@ acpi_remove_gpe_handler (
goto unlock_and_exit; 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 */ /* Remove the handler */
acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR); acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
......
...@@ -66,6 +66,7 @@ extern char line_buf[80]; ...@@ -66,6 +66,7 @@ extern char line_buf[80];
static unsigned int acpi_irq_irq; static unsigned int acpi_irq_irq;
static OSD_HANDLER acpi_irq_handler; static OSD_HANDLER acpi_irq_handler;
static void *acpi_irq_context; static void *acpi_irq_context;
static struct workqueue_struct *kacpid_wq;
acpi_status acpi_status
acpi_os_initialize(void) acpi_os_initialize(void)
...@@ -80,6 +81,8 @@ acpi_os_initialize(void) ...@@ -80,6 +81,8 @@ acpi_os_initialize(void)
return AE_NULL_ENTRY; return AE_NULL_ENTRY;
} }
#endif #endif
kacpid_wq = create_singlethread_workqueue("kacpid");
BUG_ON(!kacpid_wq);
return AE_OK; return AE_OK;
} }
...@@ -92,6 +95,8 @@ acpi_os_terminate(void) ...@@ -92,6 +95,8 @@ acpi_os_terminate(void)
acpi_irq_handler); acpi_irq_handler);
} }
destroy_workqueue(kacpid_wq);
return AE_OK; return AE_OK;
} }
...@@ -654,8 +659,8 @@ acpi_os_queue_for_execution( ...@@ -654,8 +659,8 @@ acpi_os_queue_for_execution(
task = (void *)(dpc+1); task = (void *)(dpc+1);
INIT_WORK(task, acpi_os_execute_deferred, (void*)dpc); INIT_WORK(task, acpi_os_execute_deferred, (void*)dpc);
if (!schedule_work(task)) { if (!queue_work(kacpid_wq, task)) {
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Call to schedule_work() failed.\n")); ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Call to queue_work() failed.\n"));
kfree(dpc); kfree(dpc);
status = AE_ERROR; status = AE_ERROR;
} }
...@@ -663,6 +668,13 @@ acpi_os_queue_for_execution( ...@@ -663,6 +668,13 @@ acpi_os_queue_for_execution(
return_ACPI_STATUS (status); 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. * Allocate the memory for a spinlock and initialize it.
*/ */
......
...@@ -318,8 +318,10 @@ static int acpi_driver_detach(struct acpi_driver * drv) ...@@ -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); struct acpi_device * dev = container_of(node,struct acpi_device,g_list);
if (dev->driver == drv) { if (dev->driver == drv) {
spin_unlock(&acpi_device_lock);
if (drv->ops.remove) if (drv->ops.remove)
drv->ops.remove(dev,ACPI_BUS_REMOVAL_NORMAL); drv->ops.remove(dev,ACPI_BUS_REMOVAL_NORMAL);
spin_lock(&acpi_device_lock);
dev->driver = NULL; dev->driver = NULL;
dev->driver_data = NULL; dev->driver_data = NULL;
atomic_dec(&drv->references); atomic_dec(&drv->references);
......
...@@ -212,6 +212,10 @@ acpi_os_queue_for_execution ( ...@@ -212,6 +212,10 @@ acpi_os_queue_for_execution (
OSD_EXECUTION_CALLBACK function, OSD_EXECUTION_CALLBACK function,
void *context); void *context);
void
acpi_os_wait_events_complete(
void * context);
void void
acpi_os_sleep ( acpi_os_sleep (
u32 seconds, 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