aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexey Starikovskiy <astarikovskiy@suse.de>2007-11-13 05:05:45 -0500
committerLen Brown <len.brown@intel.com>2007-12-06 21:54:43 -0500
commit17bc54eef91df29f0a22e8a1562a404cf7a68e74 (patch)
tree48f6f26a243789582721e2a3419346ea22a6dcc9
parentf194d132e4971111f85c18c96067acffb13cee6d (diff)
ACPI: Defer enabling of level GPE until all pending notifies done
Level GPE should not be enabled until all work caused by it is done, e.g. all Notify() methods are completed. This can be accomplished by appending enable_gpe function to the end of notify queue. Signed-off-by: Alexey Starikovskiy <astarikovskiy@suse.de> Acked-by: Shaohua Li <shaohua.li@intel.com> Signed-off-by: Len Brown <len.brown@intel.com>
-rw-r--r--drivers/acpi/events/evgpe.c17
-rw-r--r--drivers/acpi/osl.c42
2 files changed, 21 insertions, 38 deletions
diff --git a/drivers/acpi/events/evgpe.c b/drivers/acpi/events/evgpe.c
index e22f4a973c0f..b4509f93ff81 100644
--- a/drivers/acpi/events/evgpe.c
+++ b/drivers/acpi/events/evgpe.c
@@ -501,6 +501,7 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
501 * an interrupt handler. 501 * an interrupt handler.
502 * 502 *
503 ******************************************************************************/ 503 ******************************************************************************/
504static void acpi_ev_asynch_enable_gpe(void *context);
504 505
505static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) 506static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
506{ 507{
@@ -576,22 +577,30 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
576 method_node))); 577 method_node)));
577 } 578 }
578 } 579 }
580 /* Defer enabling of GPE until all notify handlers are done */
581 acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_ev_asynch_enable_gpe,
582 gpe_event_info);
583 return_VOID;
584}
579 585
580 if ((local_gpe_event_info.flags & ACPI_GPE_XRUPT_TYPE_MASK) == 586static void acpi_ev_asynch_enable_gpe(void *context)
587{
588 struct acpi_gpe_event_info *gpe_event_info = context;
589 acpi_status status;
590 if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
581 ACPI_GPE_LEVEL_TRIGGERED) { 591 ACPI_GPE_LEVEL_TRIGGERED) {
582 /* 592 /*
583 * GPE is level-triggered, we clear the GPE status bit after 593 * GPE is level-triggered, we clear the GPE status bit after
584 * handling the event. 594 * handling the event.
585 */ 595 */
586 status = acpi_hw_clear_gpe(&local_gpe_event_info); 596 status = acpi_hw_clear_gpe(gpe_event_info);
587 if (ACPI_FAILURE(status)) { 597 if (ACPI_FAILURE(status)) {
588 return_VOID; 598 return_VOID;
589 } 599 }
590 } 600 }
591 601
592 /* Enable this GPE */ 602 /* Enable this GPE */
593 603 (void)acpi_hw_write_gpe_enable_reg(gpe_event_info);
594 (void)acpi_hw_write_gpe_enable_reg(&local_gpe_event_info);
595 return_VOID; 604 return_VOID;
596} 605}
597 606
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index e3a673a00845..21d34595dbae 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -618,25 +618,6 @@ static void acpi_os_execute_deferred(struct work_struct *work)
618 dpc->function(dpc->context); 618 dpc->function(dpc->context);
619 kfree(dpc); 619 kfree(dpc);
620 620
621 /* Yield cpu to notify thread */
622 cond_resched();
623
624 return;
625}
626
627static void acpi_os_execute_notify(struct work_struct *work)
628{
629 struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work);
630
631 if (!dpc) {
632 printk(KERN_ERR PREFIX "Invalid (NULL) context\n");
633 return;
634 }
635
636 dpc->function(dpc->context);
637
638 kfree(dpc);
639
640 return; 621 return;
641} 622}
642 623
@@ -660,7 +641,7 @@ acpi_status acpi_os_execute(acpi_execute_type type,
660{ 641{
661 acpi_status status = AE_OK; 642 acpi_status status = AE_OK;
662 struct acpi_os_dpc *dpc; 643 struct acpi_os_dpc *dpc;
663 644 struct workqueue_struct *queue;
664 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 645 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
665 "Scheduling function [%p(%p)] for deferred execution.\n", 646 "Scheduling function [%p(%p)] for deferred execution.\n",
666 function, context)); 647 function, context));
@@ -684,20 +665,13 @@ acpi_status acpi_os_execute(acpi_execute_type type,
684 dpc->function = function; 665 dpc->function = function;
685 dpc->context = context; 666 dpc->context = context;
686 667
687 if (type == OSL_NOTIFY_HANDLER) { 668 INIT_WORK(&dpc->work, acpi_os_execute_deferred);
688 INIT_WORK(&dpc->work, acpi_os_execute_notify); 669 queue = (type == OSL_NOTIFY_HANDLER) ? kacpi_notify_wq : kacpid_wq;
689 if (!queue_work(kacpi_notify_wq, &dpc->work)) { 670 if (!queue_work(queue, &dpc->work)) {
690 status = AE_ERROR; 671 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
691 kfree(dpc); 672 "Call to queue_work() failed.\n"));
692 } 673 status = AE_ERROR;
693 } else { 674 kfree(dpc);
694 INIT_WORK(&dpc->work, acpi_os_execute_deferred);
695 if (!queue_work(kacpid_wq, &dpc->work)) {
696 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
697 "Call to queue_work() failed.\n"));
698 status = AE_ERROR;
699 kfree(dpc);
700 }
701 } 675 }
702 return_ACPI_STATUS(status); 676 return_ACPI_STATUS(status);
703} 677}