diff options
Diffstat (limited to 'drivers/acpi/osl.c')
| -rw-r--r-- | drivers/acpi/osl.c | 25 |
1 files changed, 16 insertions, 9 deletions
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index d916bea729f1..71670719d61a 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c | |||
| @@ -79,6 +79,7 @@ static acpi_osd_handler acpi_irq_handler; | |||
| 79 | static void *acpi_irq_context; | 79 | static void *acpi_irq_context; |
| 80 | static struct workqueue_struct *kacpid_wq; | 80 | static struct workqueue_struct *kacpid_wq; |
| 81 | static struct workqueue_struct *kacpi_notify_wq; | 81 | static struct workqueue_struct *kacpi_notify_wq; |
| 82 | static struct workqueue_struct *kacpi_hotplug_wq; | ||
| 82 | 83 | ||
| 83 | struct acpi_res_list { | 84 | struct acpi_res_list { |
| 84 | resource_size_t start; | 85 | resource_size_t start; |
| @@ -192,8 +193,10 @@ acpi_status acpi_os_initialize1(void) | |||
| 192 | { | 193 | { |
| 193 | kacpid_wq = create_singlethread_workqueue("kacpid"); | 194 | kacpid_wq = create_singlethread_workqueue("kacpid"); |
| 194 | kacpi_notify_wq = create_singlethread_workqueue("kacpi_notify"); | 195 | kacpi_notify_wq = create_singlethread_workqueue("kacpi_notify"); |
| 196 | kacpi_hotplug_wq = create_singlethread_workqueue("kacpi_hotplug"); | ||
| 195 | BUG_ON(!kacpid_wq); | 197 | BUG_ON(!kacpid_wq); |
| 196 | BUG_ON(!kacpi_notify_wq); | 198 | BUG_ON(!kacpi_notify_wq); |
| 199 | BUG_ON(!kacpi_hotplug_wq); | ||
| 197 | return AE_OK; | 200 | return AE_OK; |
| 198 | } | 201 | } |
| 199 | 202 | ||
| @@ -206,6 +209,7 @@ acpi_status acpi_os_terminate(void) | |||
| 206 | 209 | ||
| 207 | destroy_workqueue(kacpid_wq); | 210 | destroy_workqueue(kacpid_wq); |
| 208 | destroy_workqueue(kacpi_notify_wq); | 211 | destroy_workqueue(kacpi_notify_wq); |
| 212 | destroy_workqueue(kacpi_hotplug_wq); | ||
| 209 | 213 | ||
| 210 | return AE_OK; | 214 | return AE_OK; |
| 211 | } | 215 | } |
| @@ -716,6 +720,7 @@ static acpi_status __acpi_os_execute(acpi_execute_type type, | |||
| 716 | acpi_status status = AE_OK; | 720 | acpi_status status = AE_OK; |
| 717 | struct acpi_os_dpc *dpc; | 721 | struct acpi_os_dpc *dpc; |
| 718 | struct workqueue_struct *queue; | 722 | struct workqueue_struct *queue; |
| 723 | work_func_t func; | ||
| 719 | int ret; | 724 | int ret; |
| 720 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | 725 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, |
| 721 | "Scheduling function [%p(%p)] for deferred execution.\n", | 726 | "Scheduling function [%p(%p)] for deferred execution.\n", |
| @@ -740,15 +745,17 @@ static acpi_status __acpi_os_execute(acpi_execute_type type, | |||
| 740 | dpc->function = function; | 745 | dpc->function = function; |
| 741 | dpc->context = context; | 746 | dpc->context = context; |
| 742 | 747 | ||
| 743 | if (!hp) { | 748 | /* |
| 744 | INIT_WORK(&dpc->work, acpi_os_execute_deferred); | 749 | * We can't run hotplug code in keventd_wq/kacpid_wq/kacpid_notify_wq |
| 745 | queue = (type == OSL_NOTIFY_HANDLER) ? | 750 | * because the hotplug code may call driver .remove() functions, |
| 746 | kacpi_notify_wq : kacpid_wq; | 751 | * which invoke flush_scheduled_work/acpi_os_wait_events_complete |
| 747 | ret = queue_work(queue, &dpc->work); | 752 | * to flush these workqueues. |
| 748 | } else { | 753 | */ |
| 749 | INIT_WORK(&dpc->work, acpi_os_execute_hp_deferred); | 754 | queue = hp ? kacpi_hotplug_wq : |
| 750 | ret = schedule_work(&dpc->work); | 755 | (type == OSL_NOTIFY_HANDLER ? kacpi_notify_wq : kacpid_wq); |
| 751 | } | 756 | func = hp ? acpi_os_execute_hp_deferred : acpi_os_execute_deferred; |
| 757 | INIT_WORK(&dpc->work, func); | ||
| 758 | ret = queue_work(queue, &dpc->work); | ||
| 752 | 759 | ||
| 753 | if (!ret) { | 760 | if (!ret) { |
| 754 | printk(KERN_ERR PREFIX | 761 | printk(KERN_ERR PREFIX |
