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 | |
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>
-rw-r--r-- | drivers/acpi/acpica/acevents.h | 2 | ||||
-rw-r--r-- | drivers/acpi/acpica/aclocal.h | 1 | ||||
-rw-r--r-- | drivers/acpi/acpica/evgpe.c | 172 | ||||
-rw-r--r-- | drivers/acpi/acpica/evgpeblk.c | 11 | ||||
-rw-r--r-- | drivers/acpi/acpica/evgpeinit.c | 1 | ||||
-rw-r--r-- | drivers/acpi/acpica/evxfgpe.c | 58 | ||||
-rw-r--r-- | drivers/acpi/ec.c | 2 | ||||
-rw-r--r-- | drivers/acpi/scan.c | 2 | ||||
-rw-r--r-- | include/acpi/acpixf.h | 6 | ||||
-rw-r--r-- | include/acpi/actypes.h | 37 |
10 files changed, 186 insertions, 106 deletions
diff --git a/drivers/acpi/acpica/acevents.h b/drivers/acpi/acpica/acevents.h index 04a83fe47d6f..70e0b28801aa 100644 --- a/drivers/acpi/acpica/acevents.h +++ b/drivers/acpi/acpica/acevents.h | |||
@@ -91,6 +91,8 @@ struct acpi_gpe_event_info *acpi_ev_low_get_gpe_info(u32 gpe_number, | |||
91 | struct acpi_gpe_block_info | 91 | struct acpi_gpe_block_info |
92 | *gpe_block); | 92 | *gpe_block); |
93 | 93 | ||
94 | acpi_status acpi_ev_finish_gpe(struct acpi_gpe_event_info *gpe_event_info); | ||
95 | |||
94 | /* | 96 | /* |
95 | * evgpeblk - Upper-level GPE block support | 97 | * evgpeblk - Upper-level GPE block support |
96 | */ | 98 | */ |
diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index 6a71f8e673e9..74000f5b7dab 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h | |||
@@ -419,6 +419,7 @@ struct acpi_gpe_handler_info { | |||
419 | union acpi_gpe_dispatch_info { | 419 | union acpi_gpe_dispatch_info { |
420 | struct acpi_namespace_node *method_node; /* Method node for this GPE level */ | 420 | struct acpi_namespace_node *method_node; /* Method node for this GPE level */ |
421 | struct acpi_gpe_handler_info *handler; /* Installed GPE handler */ | 421 | struct acpi_gpe_handler_info *handler; /* Installed GPE handler */ |
422 | struct acpi_namespace_node *device_node; /* Parent _PRW device for implicit notify */ | ||
422 | }; | 423 | }; |
423 | 424 | ||
424 | /* | 425 | /* |
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 | ||
diff --git a/drivers/acpi/acpica/evgpeblk.c b/drivers/acpi/acpica/evgpeblk.c index 2a445dfcfdb4..e2e8164bb811 100644 --- a/drivers/acpi/acpica/evgpeblk.c +++ b/drivers/acpi/acpica/evgpeblk.c | |||
@@ -472,9 +472,14 @@ acpi_ev_initialize_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, | |||
472 | gpe_index = (i * ACPI_GPE_REGISTER_WIDTH) + j; | 472 | gpe_index = (i * ACPI_GPE_REGISTER_WIDTH) + j; |
473 | gpe_event_info = &gpe_block->event_info[gpe_index]; | 473 | gpe_event_info = &gpe_block->event_info[gpe_index]; |
474 | 474 | ||
475 | /* Ignore GPEs that have no corresponding _Lxx/_Exx method */ | 475 | /* |
476 | 476 | * Ignore GPEs that have no corresponding _Lxx/_Exx method | |
477 | if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_METHOD) | 477 | * and GPEs that are used to wake the system |
478 | */ | ||
479 | if (((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == | ||
480 | ACPI_GPE_DISPATCH_NONE) | ||
481 | || ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) | ||
482 | == ACPI_GPE_DISPATCH_HANDLER) | ||
478 | || (gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) { | 483 | || (gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) { |
479 | continue; | 484 | continue; |
480 | } | 485 | } |
diff --git a/drivers/acpi/acpica/evgpeinit.c b/drivers/acpi/acpica/evgpeinit.c index 4c8dea513b66..734a494bd705 100644 --- a/drivers/acpi/acpica/evgpeinit.c +++ b/drivers/acpi/acpica/evgpeinit.c | |||
@@ -415,6 +415,7 @@ acpi_ev_match_gpe_method(acpi_handle obj_handle, | |||
415 | * Add the GPE information from above to the gpe_event_info block for | 415 | * Add the GPE information from above to the gpe_event_info block for |
416 | * use during dispatch of this GPE. | 416 | * use during dispatch of this GPE. |
417 | */ | 417 | */ |
418 | gpe_event_info->flags &= ~(ACPI_GPE_DISPATCH_MASK); | ||
418 | gpe_event_info->flags |= (u8)(type | ACPI_GPE_DISPATCH_METHOD); | 419 | gpe_event_info->flags |= (u8)(type | ACPI_GPE_DISPATCH_METHOD); |
419 | gpe_event_info->dispatch.method_node = method_node; | 420 | gpe_event_info->dispatch.method_node = method_node; |
420 | 421 | ||
diff --git a/drivers/acpi/acpica/evxfgpe.c b/drivers/acpi/acpica/evxfgpe.c index 99f77ab29729..fcf4a5cdc9a4 100644 --- a/drivers/acpi/acpica/evxfgpe.c +++ b/drivers/acpi/acpica/evxfgpe.c | |||
@@ -166,39 +166,75 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number) | |||
166 | } | 166 | } |
167 | ACPI_EXPORT_SYMBOL(acpi_disable_gpe) | 167 | ACPI_EXPORT_SYMBOL(acpi_disable_gpe) |
168 | 168 | ||
169 | |||
169 | /******************************************************************************* | 170 | /******************************************************************************* |
170 | * | 171 | * |
171 | * FUNCTION: acpi_setup_gpe_for_wake | 172 | * FUNCTION: acpi_setup_gpe_for_wake |
172 | * | 173 | * |
173 | * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 | 174 | * PARAMETERS: wake_device - Device associated with the GPE (via _PRW) |
174 | * gpe_number - GPE level within the GPE block | 175 | * gpe_device - Parent GPE Device. NULL for GPE0/GPE1 |
176 | * gpe_number - GPE level within the GPE block | ||
175 | * | 177 | * |
176 | * RETURN: Status | 178 | * RETURN: Status |
177 | * | 179 | * |
178 | * DESCRIPTION: Set the ACPI_GPE_CAN_WAKE flag for the given GPE. If the GPE | 180 | * DESCRIPTION: Mark a GPE as having the ability to wake the system. This |
179 | * has a corresponding method and is currently enabled, disable it | 181 | * interface is intended to be used as the host executes the |
180 | * (GPEs with corresponding methods are enabled unconditionally | 182 | * _PRW methods (Power Resources for Wake) in the system tables. |
181 | * during initialization, but GPEs that can wake up are expected | 183 | * Each _PRW appears under a Device Object (The wake_device), and |
182 | * to be initially disabled). | 184 | * contains the info for the wake GPE associated with the |
185 | * wake_device. | ||
183 | * | 186 | * |
184 | ******************************************************************************/ | 187 | ******************************************************************************/ |
185 | acpi_status acpi_setup_gpe_for_wake(acpi_handle gpe_device, u32 gpe_number) | 188 | acpi_status |
189 | acpi_setup_gpe_for_wake(acpi_handle wake_device, | ||
190 | acpi_handle gpe_device, u32 gpe_number) | ||
186 | { | 191 | { |
187 | acpi_status status = AE_OK; | 192 | acpi_status status = AE_BAD_PARAMETER; |
188 | struct acpi_gpe_event_info *gpe_event_info; | 193 | struct acpi_gpe_event_info *gpe_event_info; |
194 | struct acpi_namespace_node *device_node; | ||
189 | acpi_cpu_flags flags; | 195 | acpi_cpu_flags flags; |
190 | 196 | ||
191 | ACPI_FUNCTION_TRACE(acpi_setup_gpe_for_wake); | 197 | ACPI_FUNCTION_TRACE(acpi_setup_gpe_for_wake); |
192 | 198 | ||
199 | /* Parameter Validation */ | ||
200 | |||
201 | if (!wake_device) { | ||
202 | /* | ||
203 | * By forcing wake_device to be valid, we automatically enable the | ||
204 | * implicit notify feature on all hosts. | ||
205 | */ | ||
206 | return_ACPI_STATUS(AE_BAD_PARAMETER); | ||
207 | } | ||
208 | |||
209 | /* Validate wake_device is of type Device */ | ||
210 | |||
211 | device_node = ACPI_CAST_PTR(struct acpi_namespace_node, wake_device); | ||
212 | if (device_node->type != ACPI_TYPE_DEVICE) { | ||
213 | return_ACPI_STATUS(AE_BAD_PARAMETER); | ||
214 | } | ||
215 | |||
193 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); | 216 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); |
194 | 217 | ||
195 | /* Ensure that we have a valid GPE number */ | 218 | /* Ensure that we have a valid GPE number */ |
196 | 219 | ||
197 | gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); | 220 | gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); |
198 | if (gpe_event_info) { | 221 | if (gpe_event_info) { |
222 | /* | ||
223 | * If there is no method or handler for this GPE, then the | ||
224 | * wake_device will be notified whenever this GPE fires (aka | ||
225 | * "implicit notify") Note: The GPE is assumed to be | ||
226 | * level-triggered (for windows compatibility). | ||
227 | */ | ||
228 | if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == | ||
229 | ACPI_GPE_DISPATCH_NONE) { | ||
230 | gpe_event_info->flags = | ||
231 | (ACPI_GPE_DISPATCH_NOTIFY | | ||
232 | ACPI_GPE_LEVEL_TRIGGERED); | ||
233 | gpe_event_info->dispatch.device_node = device_node; | ||
234 | } | ||
235 | |||
199 | gpe_event_info->flags |= ACPI_GPE_CAN_WAKE; | 236 | gpe_event_info->flags |= ACPI_GPE_CAN_WAKE; |
200 | } else { | 237 | status = AE_OK; |
201 | status = AE_BAD_PARAMETER; | ||
202 | } | 238 | } |
203 | 239 | ||
204 | acpi_os_release_lock(acpi_gbl_gpe_lock, flags); | 240 | acpi_os_release_lock(acpi_gbl_gpe_lock, flags); |
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 81887724de80..fa848c4116a8 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c | |||
@@ -619,7 +619,7 @@ static u32 acpi_ec_gpe_handler(acpi_handle gpe_device, | |||
619 | wake_up(&ec->wait); | 619 | wake_up(&ec->wait); |
620 | ec_check_sci(ec, acpi_ec_read_status(ec)); | 620 | ec_check_sci(ec, acpi_ec_read_status(ec)); |
621 | } | 621 | } |
622 | return ACPI_INTERRUPT_HANDLED; | 622 | return ACPI_INTERRUPT_HANDLED | ACPI_REENABLE_GPE; |
623 | } | 623 | } |
624 | 624 | ||
625 | /* -------------------------------------------------------------------------- | 625 | /* -------------------------------------------------------------------------- |
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 70249b3d2934..ce6741ee1965 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -778,7 +778,7 @@ acpi_bus_extract_wakeup_device_power_package(acpi_handle handle, | |||
778 | wakeup->resources.handles[i] = element->reference.handle; | 778 | wakeup->resources.handles[i] = element->reference.handle; |
779 | } | 779 | } |
780 | 780 | ||
781 | acpi_setup_gpe_for_wake(wakeup->gpe_device, wakeup->gpe_number); | 781 | acpi_setup_gpe_for_wake(handle, wakeup->gpe_device, wakeup->gpe_number); |
782 | 782 | ||
783 | out: | 783 | out: |
784 | kfree(buffer.pointer); | 784 | kfree(buffer.pointer); |
diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index b806e5611c90..9de6a17cbd4c 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h | |||
@@ -292,10 +292,12 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number); | |||
292 | 292 | ||
293 | acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number); | 293 | acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number); |
294 | 294 | ||
295 | acpi_status acpi_setup_gpe_for_wake(acpi_handle gpe_device, u32 gpe_number); | ||
296 | |||
297 | acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number); | 295 | acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number); |
298 | 296 | ||
297 | acpi_status | ||
298 | acpi_setup_gpe_for_wake(acpi_handle parent_device, | ||
299 | acpi_handle gpe_device, u32 gpe_number); | ||
300 | |||
299 | acpi_status acpi_set_gpe_wake_mask(acpi_handle gpe_device, u32 gpe_number, u8 action); | 301 | acpi_status acpi_set_gpe_wake_mask(acpi_handle gpe_device, u32 gpe_number, u8 action); |
300 | 302 | ||
301 | acpi_status | 303 | acpi_status |
diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index b9575ad9b748..d7274ee4474f 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h | |||
@@ -664,25 +664,26 @@ typedef u32 acpi_event_status; | |||
664 | 664 | ||
665 | /* | 665 | /* |
666 | * GPE info flags - Per GPE | 666 | * GPE info flags - Per GPE |
667 | * +-------+---+-+-+ | 667 | * +-------+-+-+---+ |
668 | * | 7:4 |3:2|1|0| | 668 | * | 7:4 |3|2|1:0| |
669 | * +-------+---+-+-+ | 669 | * +-------+-+-+---+ |
670 | * | | | | | 670 | * | | | | |
671 | * | | | +--- Interrupt type: edge or level triggered | 671 | * | | | +-- Type of dispatch:to method, handler, notify, or none |
672 | * | | +----- GPE can wake the system | 672 | * | | +----- Interrupt type: edge or level triggered |
673 | * | +-------- Type of dispatch:to method, handler, or none | 673 | * | +------- Is a Wake GPE |
674 | * +-------------- <Reserved> | 674 | * +------------ <Reserved> |
675 | */ | 675 | */ |
676 | #define ACPI_GPE_XRUPT_TYPE_MASK (u8) 0x01 | 676 | #define ACPI_GPE_DISPATCH_NONE (u8) 0x00 |
677 | #define ACPI_GPE_LEVEL_TRIGGERED (u8) 0x01 | 677 | #define ACPI_GPE_DISPATCH_METHOD (u8) 0x01 |
678 | #define ACPI_GPE_EDGE_TRIGGERED (u8) 0x00 | 678 | #define ACPI_GPE_DISPATCH_HANDLER (u8) 0x02 |
679 | #define ACPI_GPE_DISPATCH_NOTIFY (u8) 0x03 | ||
680 | #define ACPI_GPE_DISPATCH_MASK (u8) 0x03 | ||
679 | 681 | ||
680 | #define ACPI_GPE_CAN_WAKE (u8) 0x02 | 682 | #define ACPI_GPE_LEVEL_TRIGGERED (u8) 0x04 |
683 | #define ACPI_GPE_EDGE_TRIGGERED (u8) 0x00 | ||
684 | #define ACPI_GPE_XRUPT_TYPE_MASK (u8) 0x04 | ||
681 | 685 | ||
682 | #define ACPI_GPE_DISPATCH_MASK (u8) 0x0C | 686 | #define ACPI_GPE_CAN_WAKE (u8) 0x08 |
683 | #define ACPI_GPE_DISPATCH_HANDLER (u8) 0x04 | ||
684 | #define ACPI_GPE_DISPATCH_METHOD (u8) 0x08 | ||
685 | #define ACPI_GPE_DISPATCH_NOT_USED (u8) 0x00 | ||
686 | 687 | ||
687 | /* | 688 | /* |
688 | * Flags for GPE and Lock interfaces | 689 | * Flags for GPE and Lock interfaces |
@@ -954,6 +955,10 @@ u32 (*acpi_interface_handler) (acpi_string interface_name, u32 supported); | |||
954 | #define ACPI_INTERRUPT_NOT_HANDLED 0x00 | 955 | #define ACPI_INTERRUPT_NOT_HANDLED 0x00 |
955 | #define ACPI_INTERRUPT_HANDLED 0x01 | 956 | #define ACPI_INTERRUPT_HANDLED 0x01 |
956 | 957 | ||
958 | /* GPE handler return values */ | ||
959 | |||
960 | #define ACPI_REENABLE_GPE 0x80 | ||
961 | |||
957 | /* Length of 32-bit EISAID values when converted back to a string */ | 962 | /* Length of 32-bit EISAID values when converted back to a string */ |
958 | 963 | ||
959 | #define ACPI_EISAID_STRING_SIZE 8 /* Includes null terminator */ | 964 | #define ACPI_EISAID_STRING_SIZE 8 /* Includes null terminator */ |