Revert "ACPI: created a dedicated workqueue for notify() execution"
This reverts commit 37605a6900f6b4d886d995751fcfeef88c4e462c.
Again.
This same bug has now been introduced twice: it was done earlier by
commit b8d35192c55fb055792ff0641408eaaec7c88988, only to be reverted
last time in commit 72945b2b90a5554975b8f72673ab7139d232a121.
We must NOT try to queue up notify handlers to another thread than the
normal ACPI execution thread, because the notifications on some systems
seem to just keep on accumulating until we run out of memory and/or
threads.
Keeping events within the one deferred execution thread automatically
throttles the events properly.
At least the Compaq N620c will lock up completely on the first thermal
event without this patch reverted.
Cc: David Brownell <david-b@pacbell.net>
Cc: Len Brown <len.brown@intel.com>
Cc: Alexey Starikovskiy <alexey.y.starikovskiy@linux.intel.com>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index c84286c..068fe4f 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -73,7 +73,6 @@
static acpi_osd_handler acpi_irq_handler;
static void *acpi_irq_context;
static struct workqueue_struct *kacpid_wq;
-static struct workqueue_struct *kacpi_notify_wq;
acpi_status acpi_os_initialize(void)
{
@@ -92,9 +91,8 @@
return AE_NULL_ENTRY;
}
kacpid_wq = create_singlethread_workqueue("kacpid");
- kacpi_notify_wq = create_singlethread_workqueue("kacpi_notify");
BUG_ON(!kacpid_wq);
- BUG_ON(!kacpi_notify_wq);
+
return AE_OK;
}
@@ -106,7 +104,6 @@
}
destroy_workqueue(kacpid_wq);
- destroy_workqueue(kacpi_notify_wq);
return AE_OK;
}
@@ -569,7 +566,10 @@
static void acpi_os_execute_deferred(void *context)
{
- struct acpi_os_dpc *dpc = (struct acpi_os_dpc *)context;
+ struct acpi_os_dpc *dpc = NULL;
+
+
+ dpc = (struct acpi_os_dpc *)context;
if (!dpc) {
printk(KERN_ERR PREFIX "Invalid (NULL) context\n");
return;
@@ -604,12 +604,14 @@
struct acpi_os_dpc *dpc;
struct work_struct *task;
+ ACPI_FUNCTION_TRACE("os_queue_for_execution");
+
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"Scheduling function [%p(%p)] for deferred execution.\n",
function, context));
if (!function)
- return AE_BAD_PARAMETER;
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
/*
* Allocate/initialize DPC structure. Note that this memory will be
@@ -622,20 +624,26 @@
* from the same memory.
*/
- dpc = kmalloc(sizeof(struct acpi_os_dpc) +
- sizeof(struct work_struct), GFP_ATOMIC);
+ dpc =
+ kmalloc(sizeof(struct acpi_os_dpc) + sizeof(struct work_struct),
+ GFP_ATOMIC);
if (!dpc)
- return AE_NO_MEMORY;
+ return_ACPI_STATUS(AE_NO_MEMORY);
+
dpc->function = function;
dpc->context = context;
+
task = (void *)(dpc + 1);
INIT_WORK(task, acpi_os_execute_deferred, (void *)dpc);
- if (!queue_work((type == OSL_NOTIFY_HANDLER)?
- kacpi_notify_wq : kacpid_wq, task)) {
- status = AE_ERROR;
+
+ if (!queue_work(kacpid_wq, task)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Call to queue_work() failed.\n"));
kfree(dpc);
+ status = AE_ERROR;
}
- return status;
+
+ return_ACPI_STATUS(status);
}
EXPORT_SYMBOL(acpi_os_execute);