diff options
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/dock.c | 25 | ||||
-rw-r--r-- | drivers/acpi/osl.c | 46 |
2 files changed, 65 insertions, 6 deletions
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 2563bc62987d..4b395b1e61b2 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c | |||
@@ -748,6 +748,20 @@ static void dock_notify(acpi_handle handle, u32 event, void *data) | |||
748 | } | 748 | } |
749 | } | 749 | } |
750 | 750 | ||
751 | struct dock_data { | ||
752 | acpi_handle handle; | ||
753 | unsigned long event; | ||
754 | struct dock_station *ds; | ||
755 | }; | ||
756 | |||
757 | static void acpi_dock_deferred_cb(void *context) | ||
758 | { | ||
759 | struct dock_data *data = (struct dock_data *)context; | ||
760 | |||
761 | dock_notify(data->handle, data->event, data->ds); | ||
762 | kfree(data); | ||
763 | } | ||
764 | |||
751 | static int acpi_dock_notifier_call(struct notifier_block *this, | 765 | static int acpi_dock_notifier_call(struct notifier_block *this, |
752 | unsigned long event, void *data) | 766 | unsigned long event, void *data) |
753 | { | 767 | { |
@@ -759,7 +773,16 @@ static int acpi_dock_notifier_call(struct notifier_block *this, | |||
759 | return 0; | 773 | return 0; |
760 | list_for_each_entry(dock_station, &dock_stations, sibiling) { | 774 | list_for_each_entry(dock_station, &dock_stations, sibiling) { |
761 | if (dock_station->handle == handle) { | 775 | if (dock_station->handle == handle) { |
762 | dock_notify(handle, event, dock_station); | 776 | struct dock_data *dock_data; |
777 | |||
778 | dock_data = kmalloc(sizeof(*dock_data), GFP_KERNEL); | ||
779 | if (!dock_data) | ||
780 | return 0; | ||
781 | dock_data->handle = handle; | ||
782 | dock_data->event = event; | ||
783 | dock_data->ds = dock_station; | ||
784 | acpi_os_hotplug_execute(acpi_dock_deferred_cb, | ||
785 | dock_data); | ||
763 | return 0 ; | 786 | return 0 ; |
764 | } | 787 | } |
765 | } | 788 | } |
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 235a1386888a..750e0df15604 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c | |||
@@ -682,6 +682,22 @@ static void acpi_os_execute_deferred(struct work_struct *work) | |||
682 | return; | 682 | return; |
683 | } | 683 | } |
684 | 684 | ||
685 | static void acpi_os_execute_hp_deferred(struct work_struct *work) | ||
686 | { | ||
687 | struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work); | ||
688 | if (!dpc) { | ||
689 | printk(KERN_ERR PREFIX "Invalid (NULL) context\n"); | ||
690 | return; | ||
691 | } | ||
692 | |||
693 | acpi_os_wait_events_complete(NULL); | ||
694 | |||
695 | dpc->function(dpc->context); | ||
696 | kfree(dpc); | ||
697 | |||
698 | return; | ||
699 | } | ||
700 | |||
685 | /******************************************************************************* | 701 | /******************************************************************************* |
686 | * | 702 | * |
687 | * FUNCTION: acpi_os_execute | 703 | * FUNCTION: acpi_os_execute |
@@ -697,12 +713,13 @@ static void acpi_os_execute_deferred(struct work_struct *work) | |||
697 | * | 713 | * |
698 | ******************************************************************************/ | 714 | ******************************************************************************/ |
699 | 715 | ||
700 | acpi_status acpi_os_execute(acpi_execute_type type, | 716 | static acpi_status __acpi_os_execute(acpi_execute_type type, |
701 | acpi_osd_exec_callback function, void *context) | 717 | acpi_osd_exec_callback function, void *context, int hp) |
702 | { | 718 | { |
703 | acpi_status status = AE_OK; | 719 | acpi_status status = AE_OK; |
704 | struct acpi_os_dpc *dpc; | 720 | struct acpi_os_dpc *dpc; |
705 | struct workqueue_struct *queue; | 721 | struct workqueue_struct *queue; |
722 | int ret; | ||
706 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | 723 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, |
707 | "Scheduling function [%p(%p)] for deferred execution.\n", | 724 | "Scheduling function [%p(%p)] for deferred execution.\n", |
708 | function, context)); | 725 | function, context)); |
@@ -726,9 +743,17 @@ acpi_status acpi_os_execute(acpi_execute_type type, | |||
726 | dpc->function = function; | 743 | dpc->function = function; |
727 | dpc->context = context; | 744 | dpc->context = context; |
728 | 745 | ||
729 | INIT_WORK(&dpc->work, acpi_os_execute_deferred); | 746 | if (!hp) { |
730 | queue = (type == OSL_NOTIFY_HANDLER) ? kacpi_notify_wq : kacpid_wq; | 747 | INIT_WORK(&dpc->work, acpi_os_execute_deferred); |
731 | if (!queue_work(queue, &dpc->work)) { | 748 | queue = (type == OSL_NOTIFY_HANDLER) ? |
749 | kacpi_notify_wq : kacpid_wq; | ||
750 | ret = queue_work(queue, &dpc->work); | ||
751 | } else { | ||
752 | INIT_WORK(&dpc->work, acpi_os_execute_hp_deferred); | ||
753 | ret = schedule_work(&dpc->work); | ||
754 | } | ||
755 | |||
756 | if (!ret) { | ||
732 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | 757 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, |
733 | "Call to queue_work() failed.\n")); | 758 | "Call to queue_work() failed.\n")); |
734 | status = AE_ERROR; | 759 | status = AE_ERROR; |
@@ -737,8 +762,19 @@ acpi_status acpi_os_execute(acpi_execute_type type, | |||
737 | return_ACPI_STATUS(status); | 762 | return_ACPI_STATUS(status); |
738 | } | 763 | } |
739 | 764 | ||
765 | acpi_status acpi_os_execute(acpi_execute_type type, | ||
766 | acpi_osd_exec_callback function, void *context) | ||
767 | { | ||
768 | return __acpi_os_execute(type, function, context, 0); | ||
769 | } | ||
740 | EXPORT_SYMBOL(acpi_os_execute); | 770 | EXPORT_SYMBOL(acpi_os_execute); |
741 | 771 | ||
772 | acpi_status acpi_os_hotplug_execute(acpi_osd_exec_callback function, | ||
773 | void *context) | ||
774 | { | ||
775 | return __acpi_os_execute(0, function, context, 1); | ||
776 | } | ||
777 | |||
742 | void acpi_os_wait_events_complete(void *context) | 778 | void acpi_os_wait_events_complete(void *context) |
743 | { | 779 | { |
744 | flush_workqueue(kacpid_wq); | 780 | flush_workqueue(kacpid_wq); |