diff options
author | Lin Ming <ming.m.lin@intel.com> | 2010-12-13 00:39:17 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2011-01-12 04:27:00 -0500 |
commit | bba63a296ffab20e08d9e8252d2f0d99050ac859 (patch) | |
tree | 53d4abf7dc5fcf8b563a6cce554312d800c760e0 /drivers/acpi/acpica/evgpe.c | |
parent | 5a284cd75d635e3c5db0210dc9a9a44c6839f460 (diff) |
ACPICA: Implicit notify support
This feature provides an automatic device notification for wake devices
when a wakeup GPE occurs and there is no corresponding GPE method or
handler. Rather than ignoring such a GPE, an implicit AML Notify
operation is performed on the parent device object.
This feature is not part of the ACPI specification and is provided for
Windows compatibility only.
Signed-off-by: Lin Ming <ming.m.lin@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/acpica/evgpe.c')
-rw-r--r-- | drivers/acpi/acpica/evgpe.c | 172 |
1 files changed, 100 insertions, 72 deletions
diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c index c25999546c8c..2dbca95979ce 100644 --- a/drivers/acpi/acpica/evgpe.c +++ b/drivers/acpi/acpica/evgpe.c | |||
@@ -115,12 +115,13 @@ acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info) | |||
115 | ACPI_FUNCTION_TRACE(ev_enable_gpe); | 115 | ACPI_FUNCTION_TRACE(ev_enable_gpe); |
116 | 116 | ||
117 | /* | 117 | /* |
118 | * We will only allow a GPE to be enabled if it has either an | 118 | * We will only allow a GPE to be enabled if it has either an associated |
119 | * associated method (_Lxx/_Exx) or a handler. Otherwise, the | 119 | * method (_Lxx/_Exx) or a handler, or is using the implicit notify |
120 | * GPE will be immediately disabled by acpi_ev_gpe_dispatch the | 120 | * feature. Otherwise, the GPE will be immediately disabled by |
121 | * first time it fires. | 121 | * acpi_ev_gpe_dispatch the first time it fires. |
122 | */ | 122 | */ |
123 | if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)) { | 123 | if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == |
124 | ACPI_GPE_DISPATCH_NONE) { | ||
124 | return_ACPI_STATUS(AE_NO_HANDLER); | 125 | return_ACPI_STATUS(AE_NO_HANDLER); |
125 | } | 126 | } |
126 | 127 | ||
@@ -486,12 +487,26 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) | |||
486 | return_VOID; | 487 | return_VOID; |
487 | } | 488 | } |
488 | 489 | ||
489 | /* | 490 | /* Do the correct dispatch - normal method or implicit notify */ |
490 | * Must check for control method type dispatch one more time to avoid a | 491 | |
491 | * race with ev_gpe_install_handler | 492 | switch (local_gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) { |
492 | */ | 493 | case ACPI_GPE_DISPATCH_NOTIFY: |
493 | if ((local_gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == | 494 | |
494 | ACPI_GPE_DISPATCH_METHOD) { | 495 | /* |
496 | * Implicit notify. | ||
497 | * Dispatch a DEVICE_WAKE notify to the appropriate handler. | ||
498 | * NOTE: the request is queued for execution after this method | ||
499 | * completes. The notify handlers are NOT invoked synchronously | ||
500 | * from this thread -- because handlers may in turn run other | ||
501 | * control methods. | ||
502 | */ | ||
503 | status = | ||
504 | acpi_ev_queue_notify_request(local_gpe_event_info->dispatch. | ||
505 | device_node, | ||
506 | ACPI_NOTIFY_DEVICE_WAKE); | ||
507 | break; | ||
508 | |||
509 | case ACPI_GPE_DISPATCH_METHOD: | ||
495 | 510 | ||
496 | /* Allocate the evaluation information block */ | 511 | /* Allocate the evaluation information block */ |
497 | 512 | ||
@@ -518,6 +533,11 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) | |||
518 | (local_gpe_event_info->dispatch. | 533 | (local_gpe_event_info->dispatch. |
519 | method_node))); | 534 | method_node))); |
520 | } | 535 | } |
536 | |||
537 | break; | ||
538 | |||
539 | default: | ||
540 | return_VOID; /* Should never happen */ | ||
521 | } | 541 | } |
522 | 542 | ||
523 | /* Defer enabling of GPE until all notify handlers are done */ | 543 | /* Defer enabling of GPE until all notify handlers are done */ |
@@ -531,6 +551,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) | |||
531 | return_VOID; | 551 | return_VOID; |
532 | } | 552 | } |
533 | 553 | ||
554 | |||
534 | /******************************************************************************* | 555 | /******************************************************************************* |
535 | * | 556 | * |
536 | * FUNCTION: acpi_ev_asynch_enable_gpe | 557 | * FUNCTION: acpi_ev_asynch_enable_gpe |
@@ -541,38 +562,60 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) | |||
541 | * RETURN: None | 562 | * RETURN: None |
542 | * | 563 | * |
543 | * DESCRIPTION: Asynchronous clear/enable for GPE. This allows the GPE to | 564 | * DESCRIPTION: Asynchronous clear/enable for GPE. This allows the GPE to |
544 | * complete. | 565 | * complete (i.e., finish execution of Notify) |
545 | * | 566 | * |
546 | ******************************************************************************/ | 567 | ******************************************************************************/ |
547 | 568 | ||
548 | static void ACPI_SYSTEM_XFACE acpi_ev_asynch_enable_gpe(void *context) | 569 | static void ACPI_SYSTEM_XFACE acpi_ev_asynch_enable_gpe(void *context) |
549 | { | 570 | { |
550 | struct acpi_gpe_event_info *gpe_event_info = context; | 571 | struct acpi_gpe_event_info *gpe_event_info = context; |
572 | |||
573 | (void)acpi_ev_finish_gpe(gpe_event_info); | ||
574 | |||
575 | ACPI_FREE(gpe_event_info); | ||
576 | return; | ||
577 | } | ||
578 | |||
579 | |||
580 | /******************************************************************************* | ||
581 | * | ||
582 | * FUNCTION: acpi_ev_finish_gpe | ||
583 | * | ||
584 | * PARAMETERS: gpe_event_info - Info for this GPE | ||
585 | * | ||
586 | * RETURN: Status | ||
587 | * | ||
588 | * DESCRIPTION: Clear/Enable a GPE. Common code that is used after execution | ||
589 | * of a GPE method or a synchronous or asynchronous GPE handler. | ||
590 | * | ||
591 | ******************************************************************************/ | ||
592 | |||
593 | acpi_status acpi_ev_finish_gpe(struct acpi_gpe_event_info *gpe_event_info) | ||
594 | { | ||
551 | acpi_status status; | 595 | acpi_status status; |
552 | 596 | ||
553 | if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) == | 597 | if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) == |
554 | ACPI_GPE_LEVEL_TRIGGERED) { | 598 | ACPI_GPE_LEVEL_TRIGGERED) { |
555 | /* | 599 | /* |
556 | * GPE is level-triggered, we clear the GPE status bit after handling | 600 | * GPE is level-triggered, we clear the GPE status bit after |
557 | * the event. | 601 | * handling the event. |
558 | */ | 602 | */ |
559 | status = acpi_hw_clear_gpe(gpe_event_info); | 603 | status = acpi_hw_clear_gpe(gpe_event_info); |
560 | if (ACPI_FAILURE(status)) { | 604 | if (ACPI_FAILURE(status)) { |
561 | goto exit; | 605 | return (status); |
562 | } | 606 | } |
563 | } | 607 | } |
564 | 608 | ||
565 | /* | 609 | /* |
566 | * Enable this GPE, conditionally. This means that the GPE will only be | 610 | * Enable this GPE, conditionally. This means that the GPE will |
567 | * physically enabled if the enable_for_run bit is set in the event_info | 611 | * only be physically enabled if the enable_for_run bit is set |
612 | * in the event_info. | ||
568 | */ | 613 | */ |
569 | (void)acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_CONDITIONAL_ENABLE); | 614 | (void)acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_CONDITIONAL_ENABLE); |
570 | 615 | return (AE_OK); | |
571 | exit: | ||
572 | ACPI_FREE(gpe_event_info); | ||
573 | return; | ||
574 | } | 616 | } |
575 | 617 | ||
618 | |||
576 | /******************************************************************************* | 619 | /******************************************************************************* |
577 | * | 620 | * |
578 | * FUNCTION: acpi_ev_gpe_dispatch | 621 | * FUNCTION: acpi_ev_gpe_dispatch |
@@ -595,6 +638,7 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device, | |||
595 | struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number) | 638 | struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number) |
596 | { | 639 | { |
597 | acpi_status status; | 640 | acpi_status status; |
641 | u32 return_value; | ||
598 | 642 | ||
599 | ACPI_FUNCTION_TRACE(ev_gpe_dispatch); | 643 | ACPI_FUNCTION_TRACE(ev_gpe_dispatch); |
600 | 644 | ||
@@ -616,54 +660,49 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device, | |||
616 | } | 660 | } |
617 | 661 | ||
618 | /* | 662 | /* |
619 | * Dispatch the GPE to either an installed handler, or the control method | 663 | * Always disable the GPE so that it does not keep firing before |
620 | * associated with this GPE (_Lxx or _Exx). If a handler exists, we invoke | 664 | * any asynchronous activity completes (either from the execution |
621 | * it and do not attempt to run the method. If there is neither a handler | 665 | * of a GPE method or an asynchronous GPE handler.) |
622 | * nor a method, we disable this GPE to prevent further such pointless | 666 | * |
623 | * events from firing. | 667 | * If there is no handler or method to run, just disable the |
668 | * GPE and leave it disabled permanently to prevent further such | ||
669 | * pointless events from firing. | ||
670 | */ | ||
671 | status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE); | ||
672 | if (ACPI_FAILURE(status)) { | ||
673 | ACPI_EXCEPTION((AE_INFO, status, | ||
674 | "Unable to disable GPE%02X", gpe_number)); | ||
675 | return_UINT32(ACPI_INTERRUPT_NOT_HANDLED); | ||
676 | } | ||
677 | |||
678 | /* | ||
679 | * Dispatch the GPE to either an installed handler or the control | ||
680 | * method associated with this GPE (_Lxx or _Exx). If a handler | ||
681 | * exists, we invoke it and do not attempt to run the method. | ||
682 | * If there is neither a handler nor a method, leave the GPE | ||
683 | * disabled. | ||
624 | */ | 684 | */ |
625 | switch (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) { | 685 | switch (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) { |
626 | case ACPI_GPE_DISPATCH_HANDLER: | 686 | case ACPI_GPE_DISPATCH_HANDLER: |
627 | 687 | ||
628 | /* | 688 | /* Invoke the installed handler (at interrupt level) */ |
629 | * Invoke the installed handler (at interrupt level) | 689 | |
630 | * Ignore return status for now. | 690 | return_value = |
631 | * TBD: leave GPE disabled on error? | 691 | gpe_event_info->dispatch.handler->address(gpe_device, |
632 | */ | 692 | gpe_number, |
633 | (void)gpe_event_info->dispatch.handler->address(gpe_device, | 693 | gpe_event_info-> |
634 | gpe_number, | 694 | dispatch.handler-> |
635 | gpe_event_info-> | 695 | context); |
636 | dispatch. | 696 | |
637 | handler-> | 697 | /* If requested, clear (if level-triggered) and reenable the GPE */ |
638 | context); | 698 | |
639 | 699 | if (return_value & ACPI_REENABLE_GPE) { | |
640 | /* It is now safe to clear level-triggered events. */ | 700 | (void)acpi_ev_finish_gpe(gpe_event_info); |
641 | |||
642 | if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) == | ||
643 | ACPI_GPE_LEVEL_TRIGGERED) { | ||
644 | status = acpi_hw_clear_gpe(gpe_event_info); | ||
645 | if (ACPI_FAILURE(status)) { | ||
646 | ACPI_EXCEPTION((AE_INFO, status, | ||
647 | "Unable to clear GPE[0x%2X]", | ||
648 | gpe_number)); | ||
649 | return_UINT32(ACPI_INTERRUPT_NOT_HANDLED); | ||
650 | } | ||
651 | } | 701 | } |
652 | break; | 702 | break; |
653 | 703 | ||
654 | case ACPI_GPE_DISPATCH_METHOD: | 704 | case ACPI_GPE_DISPATCH_METHOD: |
655 | 705 | case ACPI_GPE_DISPATCH_NOTIFY: | |
656 | /* | ||
657 | * Disable the GPE, so it doesn't keep firing before the method has a | ||
658 | * chance to run (it runs asynchronously with interrupts enabled). | ||
659 | */ | ||
660 | status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE); | ||
661 | if (ACPI_FAILURE(status)) { | ||
662 | ACPI_EXCEPTION((AE_INFO, status, | ||
663 | "Unable to disable GPE[0x%2X]", | ||
664 | gpe_number)); | ||
665 | return_UINT32(ACPI_INTERRUPT_NOT_HANDLED); | ||
666 | } | ||
667 | 706 | ||
668 | /* | 707 | /* |
669 | * Execute the method associated with the GPE | 708 | * Execute the method associated with the GPE |
@@ -690,17 +729,6 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device, | |||
690 | "No handler or method for GPE[0x%2X], disabling event", | 729 | "No handler or method for GPE[0x%2X], disabling event", |
691 | gpe_number)); | 730 | gpe_number)); |
692 | 731 | ||
693 | /* | ||
694 | * Disable the GPE. The GPE will remain disabled a handler | ||
695 | * is installed or ACPICA is restarted. | ||
696 | */ | ||
697 | status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE); | ||
698 | if (ACPI_FAILURE(status)) { | ||
699 | ACPI_EXCEPTION((AE_INFO, status, | ||
700 | "Unable to disable GPE[0x%2X]", | ||
701 | gpe_number)); | ||
702 | return_UINT32(ACPI_INTERRUPT_NOT_HANDLED); | ||
703 | } | ||
704 | break; | 732 | break; |
705 | } | 733 | } |
706 | 734 | ||