diff options
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/ec.c | 5 | ||||
-rw-r--r-- | drivers/acpi/osl.c | 80 | ||||
-rw-r--r-- | drivers/acpi/thermal.c | 3 |
3 files changed, 56 insertions, 32 deletions
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 79b09d76c180..1e3222762bf3 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c | |||
@@ -763,8 +763,7 @@ static u32 acpi_ec_gpe_poll_handler(void *data) | |||
763 | 763 | ||
764 | acpi_disable_gpe(NULL, ec->common.gpe_bit, ACPI_ISR); | 764 | acpi_disable_gpe(NULL, ec->common.gpe_bit, ACPI_ISR); |
765 | 765 | ||
766 | status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE, | 766 | status = acpi_os_execute(OSL_EC_POLL_HANDLER, acpi_ec_gpe_query, ec); |
767 | acpi_ec_gpe_query, ec); | ||
768 | 767 | ||
769 | if (status == AE_OK) | 768 | if (status == AE_OK) |
770 | return ACPI_INTERRUPT_HANDLED; | 769 | return ACPI_INTERRUPT_HANDLED; |
@@ -799,7 +798,7 @@ static u32 acpi_ec_gpe_intr_handler(void *data) | |||
799 | 798 | ||
800 | if (value & ACPI_EC_FLAG_SCI) { | 799 | if (value & ACPI_EC_FLAG_SCI) { |
801 | atomic_add(1, &ec->intr.pending_gpe); | 800 | atomic_add(1, &ec->intr.pending_gpe); |
802 | status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE, | 801 | status = acpi_os_execute(OSL_EC_BURST_HANDLER, |
803 | acpi_ec_gpe_query, ec); | 802 | acpi_ec_gpe_query, ec); |
804 | return status == AE_OK ? | 803 | return status == AE_OK ? |
805 | ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED; | 804 | ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED; |
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 109c3f8ae7df..e80ca4730a44 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/delay.h> | 37 | #include <linux/delay.h> |
38 | #include <linux/workqueue.h> | 38 | #include <linux/workqueue.h> |
39 | #include <linux/nmi.h> | 39 | #include <linux/nmi.h> |
40 | #include <linux/kthread.h> | ||
40 | #include <acpi/acpi.h> | 41 | #include <acpi/acpi.h> |
41 | #include <asm/io.h> | 42 | #include <asm/io.h> |
42 | #include <acpi/acpi_bus.h> | 43 | #include <acpi/acpi_bus.h> |
@@ -600,23 +601,41 @@ static void acpi_os_execute_deferred(void *context) | |||
600 | return_VOID; | 601 | return_VOID; |
601 | } | 602 | } |
602 | 603 | ||
603 | acpi_status | 604 | static int acpi_os_execute_thread(void *context) |
604 | acpi_os_queue_for_execution(u32 priority, | 605 | { |
606 | struct acpi_os_dpc *dpc = (struct acpi_os_dpc *)context; | ||
607 | if (dpc) { | ||
608 | dpc->function(dpc->context); | ||
609 | kfree(dpc); | ||
610 | } | ||
611 | do_exit(0); | ||
612 | } | ||
613 | |||
614 | /******************************************************************************* | ||
615 | * | ||
616 | * FUNCTION: acpi_os_execute | ||
617 | * | ||
618 | * PARAMETERS: Type - Type of the callback | ||
619 | * Function - Function to be executed | ||
620 | * Context - Function parameters | ||
621 | * | ||
622 | * RETURN: Status | ||
623 | * | ||
624 | * DESCRIPTION: Depending on type, either queues function for deferred execution or | ||
625 | * immediately executes function on a separate thread. | ||
626 | * | ||
627 | ******************************************************************************/ | ||
628 | |||
629 | acpi_status acpi_os_execute(acpi_execute_type type, | ||
605 | acpi_osd_exec_callback function, void *context) | 630 | acpi_osd_exec_callback function, void *context) |
606 | { | 631 | { |
607 | acpi_status status = AE_OK; | 632 | acpi_status status = AE_OK; |
608 | struct acpi_os_dpc *dpc; | 633 | struct acpi_os_dpc *dpc; |
609 | struct work_struct *task; | 634 | struct work_struct *task; |
610 | 635 | struct task_struct *p; | |
611 | ACPI_FUNCTION_TRACE("os_queue_for_execution"); | ||
612 | |||
613 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | ||
614 | "Scheduling function [%p(%p)] for deferred execution.\n", | ||
615 | function, context)); | ||
616 | 636 | ||
617 | if (!function) | 637 | if (!function) |
618 | return_ACPI_STATUS(AE_BAD_PARAMETER); | 638 | return AE_BAD_PARAMETER; |
619 | |||
620 | /* | 639 | /* |
621 | * Allocate/initialize DPC structure. Note that this memory will be | 640 | * Allocate/initialize DPC structure. Note that this memory will be |
622 | * freed by the callee. The kernel handles the tq_struct list in a | 641 | * freed by the callee. The kernel handles the tq_struct list in a |
@@ -627,30 +646,37 @@ acpi_os_queue_for_execution(u32 priority, | |||
627 | * We can save time and code by allocating the DPC and tq_structs | 646 | * We can save time and code by allocating the DPC and tq_structs |
628 | * from the same memory. | 647 | * from the same memory. |
629 | */ | 648 | */ |
630 | 649 | if (type == OSL_NOTIFY_HANDLER) { | |
631 | dpc = | 650 | dpc = kmalloc(sizeof(struct acpi_os_dpc), GFP_KERNEL); |
632 | kmalloc(sizeof(struct acpi_os_dpc) + sizeof(struct work_struct), | 651 | } else { |
633 | GFP_ATOMIC); | 652 | dpc = kmalloc(sizeof(struct acpi_os_dpc) + |
653 | sizeof(struct work_struct), GFP_ATOMIC); | ||
654 | } | ||
634 | if (!dpc) | 655 | if (!dpc) |
635 | return_ACPI_STATUS(AE_NO_MEMORY); | 656 | return AE_NO_MEMORY; |
636 | |||
637 | dpc->function = function; | 657 | dpc->function = function; |
638 | dpc->context = context; | 658 | dpc->context = context; |
639 | 659 | ||
640 | task = (void *)(dpc + 1); | 660 | if (type == OSL_NOTIFY_HANDLER) { |
641 | INIT_WORK(task, acpi_os_execute_deferred, (void *)dpc); | 661 | p = kthread_create(acpi_os_execute_thread, dpc, "kacpid_notify"); |
642 | 662 | if (!IS_ERR(p)) { | |
643 | if (!queue_work(kacpid_wq, task)) { | 663 | wake_up_process(p); |
644 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | 664 | } else { |
645 | "Call to queue_work() failed.\n")); | 665 | status = AE_NO_MEMORY; |
646 | kfree(dpc); | 666 | kfree(dpc); |
647 | status = AE_ERROR; | 667 | } |
668 | } else { | ||
669 | task = (void *)(dpc + 1); | ||
670 | INIT_WORK(task, acpi_os_execute_deferred, (void *)dpc); | ||
671 | if (!queue_work(kacpid_wq, task)) { | ||
672 | status = AE_ERROR; | ||
673 | kfree(dpc); | ||
674 | } | ||
648 | } | 675 | } |
649 | 676 | return status; | |
650 | return_ACPI_STATUS(status); | ||
651 | } | 677 | } |
652 | 678 | ||
653 | EXPORT_SYMBOL(acpi_os_queue_for_execution); | 679 | EXPORT_SYMBOL(acpi_os_execute); |
654 | 680 | ||
655 | void acpi_os_wait_events_complete(void *context) | 681 | void acpi_os_wait_events_complete(void *context) |
656 | { | 682 | { |
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 19f3ea48475e..fba9c230a84d 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c | |||
@@ -684,8 +684,7 @@ static void acpi_thermal_run(unsigned long data) | |||
684 | { | 684 | { |
685 | struct acpi_thermal *tz = (struct acpi_thermal *)data; | 685 | struct acpi_thermal *tz = (struct acpi_thermal *)data; |
686 | if (!tz->zombie) | 686 | if (!tz->zombie) |
687 | acpi_os_queue_for_execution(OSD_PRIORITY_GPE, | 687 | acpi_os_execute(OSL_GPE_HANDLER, acpi_thermal_check, (void *)data); |
688 | acpi_thermal_check, (void *)data); | ||
689 | } | 688 | } |
690 | 689 | ||
691 | static void acpi_thermal_check(void *data) | 690 | static void acpi_thermal_check(void *data) |