aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/acpica
diff options
context:
space:
mode:
authorLin Ming <ming.m.lin@intel.com>2010-12-13 00:39:17 -0500
committerLen Brown <len.brown@intel.com>2011-01-12 04:27:00 -0500
commitbba63a296ffab20e08d9e8252d2f0d99050ac859 (patch)
tree53d4abf7dc5fcf8b563a6cce554312d800c760e0 /drivers/acpi/acpica
parent5a284cd75d635e3c5db0210dc9a9a44c6839f460 (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')
-rw-r--r--drivers/acpi/acpica/acevents.h2
-rw-r--r--drivers/acpi/acpica/aclocal.h1
-rw-r--r--drivers/acpi/acpica/evgpe.c172
-rw-r--r--drivers/acpi/acpica/evgpeblk.c11
-rw-r--r--drivers/acpi/acpica/evgpeinit.c1
-rw-r--r--drivers/acpi/acpica/evxfgpe.c58
6 files changed, 159 insertions, 86 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
94acpi_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 {
419union acpi_gpe_dispatch_info { 419union 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
548static void ACPI_SYSTEM_XFACE acpi_ev_asynch_enable_gpe(void *context) 569static 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
593acpi_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);
571exit:
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}
167ACPI_EXPORT_SYMBOL(acpi_disable_gpe) 167ACPI_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 ******************************************************************************/
185acpi_status acpi_setup_gpe_for_wake(acpi_handle gpe_device, u32 gpe_number) 188acpi_status
189acpi_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);