aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@evo.osdl.org>2006-11-17 22:31:09 -0500
committerLinus Torvalds <torvalds@evo.osdl.org>2006-11-17 22:31:09 -0500
commitb976fe19acc565e5137e6f12af7b6633a23e6b7c (patch)
treef5bd7eecbee3c165ff97ab8c642cae4f421a3cec
parent808dbbb6bb61173bf52946a28f99089d2efa4c55 (diff)
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>
-rw-r--r--drivers/acpi/osl.c34
1 files changed, 21 insertions, 13 deletions
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index c84286cbbe25..068fe4f100b0 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -73,7 +73,6 @@ static unsigned int acpi_irq_irq;
73static acpi_osd_handler acpi_irq_handler; 73static acpi_osd_handler acpi_irq_handler;
74static void *acpi_irq_context; 74static void *acpi_irq_context;
75static struct workqueue_struct *kacpid_wq; 75static struct workqueue_struct *kacpid_wq;
76static struct workqueue_struct *kacpi_notify_wq;
77 76
78acpi_status acpi_os_initialize(void) 77acpi_status acpi_os_initialize(void)
79{ 78{
@@ -92,9 +91,8 @@ acpi_status acpi_os_initialize1(void)
92 return AE_NULL_ENTRY; 91 return AE_NULL_ENTRY;
93 } 92 }
94 kacpid_wq = create_singlethread_workqueue("kacpid"); 93 kacpid_wq = create_singlethread_workqueue("kacpid");
95 kacpi_notify_wq = create_singlethread_workqueue("kacpi_notify");
96 BUG_ON(!kacpid_wq); 94 BUG_ON(!kacpid_wq);
97 BUG_ON(!kacpi_notify_wq); 95
98 return AE_OK; 96 return AE_OK;
99} 97}
100 98
@@ -106,7 +104,6 @@ acpi_status acpi_os_terminate(void)
106 } 104 }
107 105
108 destroy_workqueue(kacpid_wq); 106 destroy_workqueue(kacpid_wq);
109 destroy_workqueue(kacpi_notify_wq);
110 107
111 return AE_OK; 108 return AE_OK;
112} 109}
@@ -569,7 +566,10 @@ void acpi_os_derive_pci_id(acpi_handle rhandle, /* upper bound */
569 566
570static void acpi_os_execute_deferred(void *context) 567static void acpi_os_execute_deferred(void *context)
571{ 568{
572 struct acpi_os_dpc *dpc = (struct acpi_os_dpc *)context; 569 struct acpi_os_dpc *dpc = NULL;
570
571
572 dpc = (struct acpi_os_dpc *)context;
573 if (!dpc) { 573 if (!dpc) {
574 printk(KERN_ERR PREFIX "Invalid (NULL) context\n"); 574 printk(KERN_ERR PREFIX "Invalid (NULL) context\n");
575 return; 575 return;
@@ -604,12 +604,14 @@ acpi_status acpi_os_execute(acpi_execute_type type,
604 struct acpi_os_dpc *dpc; 604 struct acpi_os_dpc *dpc;
605 struct work_struct *task; 605 struct work_struct *task;
606 606
607 ACPI_FUNCTION_TRACE("os_queue_for_execution");
608
607 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 609 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
608 "Scheduling function [%p(%p)] for deferred execution.\n", 610 "Scheduling function [%p(%p)] for deferred execution.\n",
609 function, context)); 611 function, context));
610 612
611 if (!function) 613 if (!function)
612 return AE_BAD_PARAMETER; 614 return_ACPI_STATUS(AE_BAD_PARAMETER);
613 615
614 /* 616 /*
615 * Allocate/initialize DPC structure. Note that this memory will be 617 * Allocate/initialize DPC structure. Note that this memory will be
@@ -622,20 +624,26 @@ acpi_status acpi_os_execute(acpi_execute_type type,
622 * from the same memory. 624 * from the same memory.
623 */ 625 */
624 626
625 dpc = kmalloc(sizeof(struct acpi_os_dpc) + 627 dpc =
626 sizeof(struct work_struct), GFP_ATOMIC); 628 kmalloc(sizeof(struct acpi_os_dpc) + sizeof(struct work_struct),
629 GFP_ATOMIC);
627 if (!dpc) 630 if (!dpc)
628 return AE_NO_MEMORY; 631 return_ACPI_STATUS(AE_NO_MEMORY);
632
629 dpc->function = function; 633 dpc->function = function;
630 dpc->context = context; 634 dpc->context = context;
635
631 task = (void *)(dpc + 1); 636 task = (void *)(dpc + 1);
632 INIT_WORK(task, acpi_os_execute_deferred, (void *)dpc); 637 INIT_WORK(task, acpi_os_execute_deferred, (void *)dpc);
633 if (!queue_work((type == OSL_NOTIFY_HANDLER)? 638
634 kacpi_notify_wq : kacpid_wq, task)) { 639 if (!queue_work(kacpid_wq, task)) {
635 status = AE_ERROR; 640 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
641 "Call to queue_work() failed.\n"));
636 kfree(dpc); 642 kfree(dpc);
643 status = AE_ERROR;
637 } 644 }
638 return status; 645
646 return_ACPI_STATUS(status);
639} 647}
640 648
641EXPORT_SYMBOL(acpi_os_execute); 649EXPORT_SYMBOL(acpi_os_execute);