diff options
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/osl.c | 45 |
1 files changed, 35 insertions, 10 deletions
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index c2bed56915e1..b998340e23d4 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c | |||
@@ -71,6 +71,7 @@ static unsigned int acpi_irq_irq; | |||
71 | static acpi_osd_handler acpi_irq_handler; | 71 | static acpi_osd_handler acpi_irq_handler; |
72 | static void *acpi_irq_context; | 72 | static void *acpi_irq_context; |
73 | static struct workqueue_struct *kacpid_wq; | 73 | static struct workqueue_struct *kacpid_wq; |
74 | static struct workqueue_struct *kacpi_notify_wq; | ||
74 | 75 | ||
75 | static void __init acpi_request_region (struct acpi_generic_address *addr, | 76 | static void __init acpi_request_region (struct acpi_generic_address *addr, |
76 | unsigned int length, char *desc) | 77 | unsigned int length, char *desc) |
@@ -137,8 +138,9 @@ acpi_status acpi_os_initialize1(void) | |||
137 | return AE_NULL_ENTRY; | 138 | return AE_NULL_ENTRY; |
138 | } | 139 | } |
139 | kacpid_wq = create_singlethread_workqueue("kacpid"); | 140 | kacpid_wq = create_singlethread_workqueue("kacpid"); |
141 | kacpi_notify_wq = create_singlethread_workqueue("kacpi_notify"); | ||
140 | BUG_ON(!kacpid_wq); | 142 | BUG_ON(!kacpid_wq); |
141 | 143 | BUG_ON(!kacpi_notify_wq); | |
142 | return AE_OK; | 144 | return AE_OK; |
143 | } | 145 | } |
144 | 146 | ||
@@ -150,6 +152,7 @@ acpi_status acpi_os_terminate(void) | |||
150 | } | 152 | } |
151 | 153 | ||
152 | destroy_workqueue(kacpid_wq); | 154 | destroy_workqueue(kacpid_wq); |
155 | destroy_workqueue(kacpi_notify_wq); | ||
153 | 156 | ||
154 | return AE_OK; | 157 | return AE_OK; |
155 | } | 158 | } |
@@ -603,6 +606,23 @@ void acpi_os_derive_pci_id(acpi_handle rhandle, /* upper bound */ | |||
603 | static void acpi_os_execute_deferred(struct work_struct *work) | 606 | static void acpi_os_execute_deferred(struct work_struct *work) |
604 | { | 607 | { |
605 | struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work); | 608 | struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work); |
609 | if (!dpc) { | ||
610 | printk(KERN_ERR PREFIX "Invalid (NULL) context\n"); | ||
611 | return; | ||
612 | } | ||
613 | |||
614 | dpc->function(dpc->context); | ||
615 | kfree(dpc); | ||
616 | |||
617 | /* Yield cpu to notify thread */ | ||
618 | cond_resched(); | ||
619 | |||
620 | return; | ||
621 | } | ||
622 | |||
623 | static void acpi_os_execute_notify(struct work_struct *work) | ||
624 | { | ||
625 | struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work); | ||
606 | 626 | ||
607 | if (!dpc) { | 627 | if (!dpc) { |
608 | printk(KERN_ERR PREFIX "Invalid (NULL) context\n"); | 628 | printk(KERN_ERR PREFIX "Invalid (NULL) context\n"); |
@@ -637,14 +657,12 @@ acpi_status acpi_os_execute(acpi_execute_type type, | |||
637 | acpi_status status = AE_OK; | 657 | acpi_status status = AE_OK; |
638 | struct acpi_os_dpc *dpc; | 658 | struct acpi_os_dpc *dpc; |
639 | 659 | ||
640 | ACPI_FUNCTION_TRACE("os_queue_for_execution"); | ||
641 | |||
642 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | 660 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, |
643 | "Scheduling function [%p(%p)] for deferred execution.\n", | 661 | "Scheduling function [%p(%p)] for deferred execution.\n", |
644 | function, context)); | 662 | function, context)); |
645 | 663 | ||
646 | if (!function) | 664 | if (!function) |
647 | return_ACPI_STATUS(AE_BAD_PARAMETER); | 665 | return AE_BAD_PARAMETER; |
648 | 666 | ||
649 | /* | 667 | /* |
650 | * Allocate/initialize DPC structure. Note that this memory will be | 668 | * Allocate/initialize DPC structure. Note that this memory will be |
@@ -662,14 +680,21 @@ acpi_status acpi_os_execute(acpi_execute_type type, | |||
662 | dpc->function = function; | 680 | dpc->function = function; |
663 | dpc->context = context; | 681 | dpc->context = context; |
664 | 682 | ||
665 | INIT_WORK(&dpc->work, acpi_os_execute_deferred); | 683 | if (type == OSL_NOTIFY_HANDLER) { |
666 | if (!queue_work(kacpid_wq, &dpc->work)) { | 684 | INIT_WORK(&dpc->work, acpi_os_execute_notify); |
667 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | 685 | if (!queue_work(kacpi_notify_wq, &dpc->work)) { |
686 | status = AE_ERROR; | ||
687 | kfree(dpc); | ||
688 | } | ||
689 | } else { | ||
690 | INIT_WORK(&dpc->work, acpi_os_execute_deferred); | ||
691 | if (!queue_work(kacpid_wq, &dpc->work)) { | ||
692 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | ||
668 | "Call to queue_work() failed.\n")); | 693 | "Call to queue_work() failed.\n")); |
669 | kfree(dpc); | 694 | status = AE_ERROR; |
670 | status = AE_ERROR; | 695 | kfree(dpc); |
696 | } | ||
671 | } | 697 | } |
672 | |||
673 | return_ACPI_STATUS(status); | 698 | return_ACPI_STATUS(status); |
674 | } | 699 | } |
675 | 700 | ||