Rev 1498 | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1498 | Rev 2216 | ||
---|---|---|---|
Line 6... | Line 6... | ||
6 | 6 | ||
7 | /****************************************************************************** |
7 | /****************************************************************************** |
8 | * |
8 | * |
9 | * 1. Copyright Notice |
9 | * 1. Copyright Notice |
10 | * |
10 | * |
11 | * Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp. |
11 | * Some or all of this work - Copyright (c) 1999 - 2011, Intel Corp. |
12 | * All rights reserved. |
12 | * All rights reserved. |
13 | * |
13 | * |
14 | * 2. License |
14 | * 2. License |
15 | * |
15 | * |
Line 132... | Line 132... | ||
132 | void *Context); |
132 | void *Context); |
Line 133... | Line 133... | ||
133 | 133 | ||
134 | 134 | ||
135 | /******************************************************************************* |
135 | /******************************************************************************* |
136 | * |
136 | * |
137 | * FUNCTION: AcpiEvUpdateGpeEnableMasks |
137 | * FUNCTION: AcpiEvUpdateGpeEnableMask |
138 | * |
138 | * |
139 | * PARAMETERS: GpeEventInfo - GPE to update |
139 | * PARAMETERS: GpeEventInfo - GPE to update |
140 | * |
140 | * |
141 | * RETURN: Status |
141 | * RETURN: Status |
142 | * |
142 | * |
143 | * DESCRIPTION: Updates GPE register enable masks based upon whether there are |
143 | * DESCRIPTION: Updates GPE register enable mask based upon whether there are |
144 | * references (either wake or run) to this GPE |
144 | * runtime references to this GPE |
Line 145... | Line 145... | ||
145 | * |
145 | * |
146 | ******************************************************************************/ |
146 | ******************************************************************************/ |
147 | 147 | ||
148 | ACPI_STATUS |
148 | ACPI_STATUS |
149 | AcpiEvUpdateGpeEnableMasks ( |
149 | AcpiEvUpdateGpeEnableMask ( |
150 | ACPI_GPE_EVENT_INFO *GpeEventInfo) |
150 | ACPI_GPE_EVENT_INFO *GpeEventInfo) |
Line 151... | Line 151... | ||
151 | { |
151 | { |
Line 152... | Line 152... | ||
152 | ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; |
152 | ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; |
153 | UINT8 RegisterBit; |
153 | UINT32 RegisterBit; |
154 | 154 | ||
155 | 155 | ||
156 | ACPI_FUNCTION_TRACE (EvUpdateGpeEnableMasks); |
156 | ACPI_FUNCTION_TRACE (EvUpdateGpeEnableMask); |
Line 157... | Line -... | ||
157 | - | ||
158 | 157 | ||
Line 159... | Line 158... | ||
159 | GpeRegisterInfo = GpeEventInfo->RegisterInfo; |
158 | |
Line 160... | Line -... | ||
160 | if (!GpeRegisterInfo) |
- | |
161 | { |
159 | GpeRegisterInfo = GpeEventInfo->RegisterInfo; |
Line 162... | Line 160... | ||
162 | return_ACPI_STATUS (AE_NOT_EXIST); |
160 | if (!GpeRegisterInfo) |
Line 163... | Line 161... | ||
163 | } |
161 | { |
164 | 162 | return_ACPI_STATUS (AE_NOT_EXIST); |
|
165 | RegisterBit = (UINT8) |
163 | } |
166 | (1 << (GpeEventInfo->GpeNumber - GpeRegisterInfo->BaseGpeNumber)); |
- | |
167 | - | ||
168 | /* Clear the wake/run bits up front */ |
- | |
169 | - | ||
170 | ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, RegisterBit); |
- | |
171 | ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForRun, RegisterBit); |
164 | |
Line 172... | Line 165... | ||
172 | 165 | RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo, GpeRegisterInfo); |
|
173 | /* Set the mask bits only if there are references to this GPE */ |
166 | |
Line 192... | Line 185... | ||
192 | * |
185 | * |
193 | * PARAMETERS: GpeEventInfo - GPE to enable |
186 | * PARAMETERS: GpeEventInfo - GPE to enable |
194 | * |
187 | * |
195 | * RETURN: Status |
188 | * RETURN: Status |
196 | * |
189 | * |
197 | * DESCRIPTION: Hardware-enable a GPE. Always enables the GPE, regardless |
190 | * DESCRIPTION: Clear a GPE of stale events and enable it. |
198 | * of type or number of references. |
- | |
199 | * |
- | |
200 | * Note: The GPE lock should be already acquired when this function is called. |
- | |
201 | * |
191 | * |
202 | ******************************************************************************/ |
192 | ******************************************************************************/ |
Line 203... | Line 193... | ||
203 | 193 | ||
204 | ACPI_STATUS |
194 | ACPI_STATUS |
Line 210... | Line 200... | ||
210 | 200 | ||
Line 211... | Line 201... | ||
211 | ACPI_FUNCTION_TRACE (EvEnableGpe); |
201 | ACPI_FUNCTION_TRACE (EvEnableGpe); |
212 | 202 | ||
213 | 203 | ||
214 | /* |
204 | /* |
215 | * We will only allow a GPE to be enabled if it has either an |
205 | * We will only allow a GPE to be enabled if it has either an associated |
216 | * associated method (_Lxx/_Exx) or a handler. Otherwise, the |
206 | * method (_Lxx/_Exx) or a handler, or is using the implicit notify |
217 | * GPE will be immediately disabled by AcpiEvGpeDispatch the |
207 | * feature. Otherwise, the GPE will be immediately disabled by |
- | 208 | * AcpiEvGpeDispatch the first time it fires. |
|
218 | * first time it fires. |
209 | */ |
219 | */ |
210 | if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == |
220 | if (!(GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK)) |
211 | ACPI_GPE_DISPATCH_NONE) |
Line 221... | Line -... | ||
221 | { |
- | |
222 | return_ACPI_STATUS (AE_NO_HANDLER); |
- | |
223 | } |
- | |
224 | - | ||
225 | /* Ensure the HW enable masks are current */ |
- | |
226 | - | ||
227 | Status = AcpiEvUpdateGpeEnableMasks (GpeEventInfo); |
- | |
228 | if (ACPI_FAILURE (Status)) |
- | |
229 | { |
212 | { |
Line 230... | Line 213... | ||
230 | return_ACPI_STATUS (Status); |
213 | return_ACPI_STATUS (AE_NO_HANDLER); |
231 | } |
214 | } |
232 | 215 | ||
233 | /* Clear the GPE (of stale events) */ |
216 | /* Clear the GPE (of stale events) */ |
234 | 217 | ||
Line 235... | Line 218... | ||
235 | Status = AcpiHwClearGpe (GpeEventInfo); |
218 | Status = AcpiHwClearGpe (GpeEventInfo); |
Line 236... | Line 219... | ||
236 | if (ACPI_FAILURE (Status)) |
219 | if (ACPI_FAILURE (Status)) |
237 | { |
220 | { |
238 | return_ACPI_STATUS (Status); |
221 | return_ACPI_STATUS (Status); |
Line 239... | Line 222... | ||
239 | } |
222 | } |
240 | 223 | ||
241 | /* Enable the requested GPE */ |
224 | /* Enable the requested GPE */ |
242 | 225 | ||
243 | Status = AcpiHwWriteGpeEnableReg (GpeEventInfo); |
226 | Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_ENABLE); |
244 | return_ACPI_STATUS (Status); |
227 | return_ACPI_STATUS (Status); |
245 | } |
228 | } |
246 | 229 | ||
247 | 230 | ||
248 | /******************************************************************************* |
231 | /******************************************************************************* |
249 | * |
- | |
250 | * FUNCTION: AcpiEvDisableGpe |
- | |
251 | * |
232 | * |
252 | * PARAMETERS: GpeEventInfo - GPE to disable |
233 | * FUNCTION: AcpiEvAddGpeReference |
Line 253... | Line 234... | ||
253 | * |
234 | * |
254 | * RETURN: Status |
235 | * PARAMETERS: GpeEventInfo - Add a reference to this GPE |
255 | * |
236 | * |
256 | * DESCRIPTION: Hardware-disable a GPE. Always disables the requested GPE, |
237 | * RETURN: Status |
257 | * regardless of the type or number of references. |
238 | * |
Line 258... | Line 239... | ||
258 | * |
239 | * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is |
Line -... | Line 240... | ||
- | 240 | * hardware-enabled. |
|
259 | * Note: The GPE lock should be already acquired when this function is called. |
241 | * |
260 | * |
242 | ******************************************************************************/ |
- | 243 | ||
- | 244 | ACPI_STATUS |
|
261 | ******************************************************************************/ |
245 | AcpiEvAddGpeReference ( |
262 | 246 | ACPI_GPE_EVENT_INFO *GpeEventInfo) |
|
263 | ACPI_STATUS |
247 | { |
- | 248 | ACPI_STATUS Status = AE_OK; |
|
Line 264... | Line 249... | ||
264 | AcpiEvDisableGpe ( |
249 | |
- | 250 | ||
- | 251 | ACPI_FUNCTION_TRACE (EvAddGpeReference); |
|
- | 252 | ||
- | 253 | ||
Line 265... | Line -... | ||
265 | ACPI_GPE_EVENT_INFO *GpeEventInfo) |
- | |
266 | { |
254 | if (GpeEventInfo->RuntimeCount == ACPI_UINT8_MAX) |
267 | ACPI_STATUS Status; |
255 | { |
- | 256 | return_ACPI_STATUS (AE_LIMIT); |
|
- | 257 | } |
|
- | 258 | ||
- | 259 | GpeEventInfo->RuntimeCount++; |
|
268 | 260 | if (GpeEventInfo->RuntimeCount == 1) |
|
269 | 261 | { |
|
Line -... | Line 262... | ||
- | 262 | /* Enable on first reference */ |
|
- | 263 | ||
- | 264 | Status = AcpiEvUpdateGpeEnableMask (GpeEventInfo); |
|
- | 265 | if (ACPI_SUCCESS (Status)) |
|
270 | ACPI_FUNCTION_TRACE (EvDisableGpe); |
266 | { |
271 | 267 | Status = AcpiEvEnableGpe (GpeEventInfo); |
|
- | 268 | } |
|
- | 269 | ||
- | 270 | if (ACPI_FAILURE (Status)) |
|
272 | 271 | { |
|
273 | /* |
272 | GpeEventInfo->RuntimeCount--; |
- | 273 | } |
|
- | 274 | } |
|
- | 275 | ||
- | 276 | return_ACPI_STATUS (Status); |
|
- | 277 | } |
|
- | 278 | ||
- | 279 | ||
274 | * Note: Always disable the GPE, even if we think that that it is already |
280 | /******************************************************************************* |
- | 281 | * |
|
- | 282 | * FUNCTION: AcpiEvRemoveGpeReference |
|
275 | * disabled. It is possible that the AML or some other code has enabled |
283 | * |
- | 284 | * PARAMETERS: GpeEventInfo - Remove a reference to this GPE |
|
- | 285 | * |
|
- | 286 | * RETURN: Status |
|
- | 287 | * |
|
- | 288 | * DESCRIPTION: Remove a reference to a GPE. When the last reference is |
|
- | 289 | * removed, the GPE is hardware-disabled. |
|
- | 290 | * |
|
- | 291 | ******************************************************************************/ |
|
276 | * the GPE behind our back. |
292 | |
277 | */ |
293 | ACPI_STATUS |
- | 294 | AcpiEvRemoveGpeReference ( |
|
- | 295 | ACPI_GPE_EVENT_INFO *GpeEventInfo) |
|
278 | 296 | { |
|
- | 297 | ACPI_STATUS Status = AE_OK; |
|
- | 298 | ||
- | 299 | ||
- | 300 | ACPI_FUNCTION_TRACE (EvRemoveGpeReference); |
|
- | 301 | ||
- | 302 | ||
- | 303 | if (!GpeEventInfo->RuntimeCount) |
|
- | 304 | { |
|
- | 305 | return_ACPI_STATUS (AE_LIMIT); |
|
- | 306 | } |
|
- | 307 | ||
279 | /* Ensure the HW enable masks are current */ |
308 | GpeEventInfo->RuntimeCount--; |
280 | 309 | if (!GpeEventInfo->RuntimeCount) |
|
Line 281... | Line 310... | ||
281 | Status = AcpiEvUpdateGpeEnableMasks (GpeEventInfo); |
310 | { |
Line 463... | Line 492... | ||
463 | { |
492 | { |
464 | /* Get the next status/enable pair */ |
493 | /* Get the next status/enable pair */ |
Line 465... | Line 494... | ||
465 | 494 | ||
Line -... | Line 495... | ||
- | 495 | GpeRegisterInfo = &GpeBlock->RegisterInfo[i]; |
|
- | 496 | ||
- | 497 | /* |
|
- | 498 | * Optimization: If there are no GPEs enabled within this |
|
- | 499 | * register, we can safely ignore the entire register. |
|
- | 500 | */ |
|
- | 501 | if (!(GpeRegisterInfo->EnableForRun | |
|
- | 502 | GpeRegisterInfo->EnableForWake)) |
|
- | 503 | { |
|
- | 504 | continue; |
|
466 | GpeRegisterInfo = &GpeBlock->RegisterInfo[i]; |
505 | } |
Line 467... | Line 506... | ||
467 | 506 | ||
468 | /* Read the Status Register */ |
507 | /* Read the Status Register */ |
469 | 508 | ||
Line 480... | Line 519... | ||
480 | { |
519 | { |
481 | goto UnlockAndExit; |
520 | goto UnlockAndExit; |
482 | } |
521 | } |
Line 483... | Line 522... | ||
483 | 522 | ||
484 | ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS, |
523 | ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS, |
485 | "Read GPE Register at GPE%X: Status=%02X, Enable=%02X\n", |
524 | "Read GPE Register at GPE%02X: Status=%02X, Enable=%02X\n", |
Line 486... | Line 525... | ||
486 | GpeRegisterInfo->BaseGpeNumber, StatusReg, EnableReg)); |
525 | GpeRegisterInfo->BaseGpeNumber, StatusReg, EnableReg)); |
Line 487... | Line 526... | ||
487 | 526 | ||
Line 505... | Line 544... | ||
505 | { |
544 | { |
506 | /* |
545 | /* |
507 | * Found an active GPE. Dispatch the event to a handler |
546 | * Found an active GPE. Dispatch the event to a handler |
508 | * or method. |
547 | * or method. |
509 | */ |
548 | */ |
510 | IntStatus |= AcpiEvGpeDispatch ( |
549 | IntStatus |= AcpiEvGpeDispatch (GpeBlock->Node, |
511 | &GpeBlock->EventInfo[((ACPI_SIZE) i * |
550 | &GpeBlock->EventInfo[((ACPI_SIZE) i * |
512 | ACPI_GPE_REGISTER_WIDTH) + j], |
551 | ACPI_GPE_REGISTER_WIDTH) + j], |
513 | j + GpeRegisterInfo->BaseGpeNumber); |
552 | j + GpeRegisterInfo->BaseGpeNumber); |
514 | } |
553 | } |
515 | } |
554 | } |
Line 576... | Line 615... | ||
576 | { |
615 | { |
577 | Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS); |
616 | Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS); |
578 | return_VOID; |
617 | return_VOID; |
579 | } |
618 | } |
Line 580... | Line -... | ||
580 | - | ||
581 | /* Update the GPE register masks for return to enabled state */ |
- | |
582 | - | ||
583 | (void) AcpiEvUpdateGpeEnableMasks (GpeEventInfo); |
- | |
584 | 619 | ||
585 | /* |
620 | /* |
586 | * Take a snapshot of the GPE info for this level - we copy the info to |
621 | * Take a snapshot of the GPE info for this level - we copy the info to |
587 | * prevent a race condition with RemoveHandler/RemoveBlock. |
622 | * prevent a race condition with RemoveHandler/RemoveBlock. |
588 | */ |
623 | */ |
Line 593... | Line 628... | ||
593 | if (ACPI_FAILURE (Status)) |
628 | if (ACPI_FAILURE (Status)) |
594 | { |
629 | { |
595 | return_VOID; |
630 | return_VOID; |
596 | } |
631 | } |
Line -... | Line 632... | ||
- | 632 | ||
- | 633 | /* Do the correct dispatch - normal method or implicit notify */ |
|
- | 634 | ||
- | 635 | switch (LocalGpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) |
|
- | 636 | { |
|
- | 637 | case ACPI_GPE_DISPATCH_NOTIFY: |
|
597 | 638 | ||
- | 639 | /* |
|
- | 640 | * Implicit notify. |
|
598 | /* |
641 | * Dispatch a DEVICE_WAKE notify to the appropriate handler. |
- | 642 | * NOTE: the request is queued for execution after this method |
|
- | 643 | * completes. The notify handlers are NOT invoked synchronously |
|
599 | * Must check for control method type dispatch one more time to avoid a |
644 | * from this thread -- because handlers may in turn run other |
600 | * race with EvGpeInstallHandler |
645 | * control methods. |
- | 646 | */ |
|
601 | */ |
647 | Status = AcpiEvQueueNotifyRequest ( |
- | 648 | LocalGpeEventInfo->Dispatch.DeviceNode, |
|
- | 649 | ACPI_NOTIFY_DEVICE_WAKE); |
|
- | 650 | break; |
|
602 | if ((LocalGpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == |
651 | |
603 | ACPI_GPE_DISPATCH_METHOD) |
652 | case ACPI_GPE_DISPATCH_METHOD: |
604 | { |
653 | |
Line 605... | Line 654... | ||
605 | /* Allocate the evaluation information block */ |
654 | /* Allocate the evaluation information block */ |
606 | 655 | ||
607 | Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO)); |
656 | Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO)); |
608 | if (!Info) |
657 | if (!Info) |
609 | { |
658 | { |
610 | Status = AE_NO_MEMORY; |
659 | Status = AE_NO_MEMORY; |
611 | } |
660 | } |
612 | else |
661 | else |
613 | { |
662 | { |
614 | /* |
663 | /* |
615 | * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the _Lxx/_Exx |
664 | * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the |
616 | * control method that corresponds to this GPE |
665 | * _Lxx/_Exx control method that corresponds to this GPE |
617 | */ |
666 | */ |
Line 618... | Line 667... | ||
618 | Info->PrefixNode = LocalGpeEventInfo->Dispatch.MethodNode; |
667 | Info->PrefixNode = LocalGpeEventInfo->Dispatch.MethodNode; |
Line 626... | Line 675... | ||
626 | { |
675 | { |
627 | ACPI_EXCEPTION ((AE_INFO, Status, |
676 | ACPI_EXCEPTION ((AE_INFO, Status, |
628 | "while evaluating GPE method [%4.4s]", |
677 | "while evaluating GPE method [%4.4s]", |
629 | AcpiUtGetNodeName (LocalGpeEventInfo->Dispatch.MethodNode))); |
678 | AcpiUtGetNodeName (LocalGpeEventInfo->Dispatch.MethodNode))); |
630 | } |
679 | } |
- | 680 | ||
- | 681 | break; |
|
- | 682 | ||
- | 683 | default: |
|
- | 684 | return_VOID; /* Should never happen */ |
|
631 | } |
685 | } |
Line 632... | Line 686... | ||
632 | 686 | ||
Line 633... | Line 687... | ||
633 | /* Defer enabling of GPE until all notify handlers are done */ |
687 | /* Defer enabling of GPE until all notify handlers are done */ |
Line 645... | Line 699... | ||
645 | /******************************************************************************* |
699 | /******************************************************************************* |
646 | * |
700 | * |
647 | * FUNCTION: AcpiEvAsynchEnableGpe |
701 | * FUNCTION: AcpiEvAsynchEnableGpe |
648 | * |
702 | * |
649 | * PARAMETERS: Context (GpeEventInfo) - Info for this GPE |
703 | * PARAMETERS: Context (GpeEventInfo) - Info for this GPE |
- | 704 | * Callback from AcpiOsExecute |
|
650 | * |
705 | * |
651 | * RETURN: None |
706 | * RETURN: None |
652 | * |
707 | * |
653 | * DESCRIPTION: Asynchronous clear/enable for GPE. This allows the GPE to |
708 | * DESCRIPTION: Asynchronous clear/enable for GPE. This allows the GPE to |
654 | * complete (i.e., finish execution of Notify) |
709 | * complete (i.e., finish execution of Notify) |
Line 658... | Line 713... | ||
658 | static void ACPI_SYSTEM_XFACE |
713 | static void ACPI_SYSTEM_XFACE |
659 | AcpiEvAsynchEnableGpe ( |
714 | AcpiEvAsynchEnableGpe ( |
660 | void *Context) |
715 | void *Context) |
661 | { |
716 | { |
662 | ACPI_GPE_EVENT_INFO *GpeEventInfo = Context; |
717 | ACPI_GPE_EVENT_INFO *GpeEventInfo = Context; |
- | 718 | ||
- | 719 | ||
- | 720 | (void) AcpiEvFinishGpe (GpeEventInfo); |
|
- | 721 | ||
- | 722 | ACPI_FREE (GpeEventInfo); |
|
- | 723 | return; |
|
- | 724 | } |
|
- | 725 | ||
- | 726 | ||
- | 727 | /******************************************************************************* |
|
- | 728 | * |
|
- | 729 | * FUNCTION: AcpiEvFinishGpe |
|
- | 730 | * |
|
- | 731 | * PARAMETERS: GpeEventInfo - Info for this GPE |
|
- | 732 | * |
|
- | 733 | * RETURN: Status |
|
- | 734 | * |
|
- | 735 | * DESCRIPTION: Clear/Enable a GPE. Common code that is used after execution |
|
- | 736 | * of a GPE method or a synchronous or asynchronous GPE handler. |
|
- | 737 | * |
|
- | 738 | ******************************************************************************/ |
|
- | 739 | ||
- | 740 | ACPI_STATUS |
|
- | 741 | AcpiEvFinishGpe ( |
|
- | 742 | ACPI_GPE_EVENT_INFO *GpeEventInfo) |
|
- | 743 | { |
|
663 | ACPI_STATUS Status; |
744 | ACPI_STATUS Status; |
Line 664... | Line 745... | ||
664 | 745 | ||
665 | 746 | ||
666 | if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) == |
747 | if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) == |
667 | ACPI_GPE_LEVEL_TRIGGERED) |
748 | ACPI_GPE_LEVEL_TRIGGERED) |
668 | { |
749 | { |
669 | /* |
750 | /* |
670 | * GPE is level-triggered, we clear the GPE status bit after handling |
751 | * GPE is level-triggered, we clear the GPE status bit after |
671 | * the event. |
752 | * handling the event. |
672 | */ |
753 | */ |
673 | Status = AcpiHwClearGpe (GpeEventInfo); |
754 | Status = AcpiHwClearGpe (GpeEventInfo); |
674 | if (ACPI_FAILURE (Status)) |
755 | if (ACPI_FAILURE (Status)) |
675 | { |
756 | { |
676 | goto Exit; |
757 | return (Status); |
Line -... | Line 758... | ||
- | 758 | } |
|
677 | } |
759 | } |
678 | } |
- | |
679 | 760 | ||
680 | /* Enable this GPE */ |
- | |
- | 761 | /* |
|
681 | 762 | * Enable this GPE, conditionally. This means that the GPE will |
|
682 | (void) AcpiHwWriteGpeEnableReg (GpeEventInfo); |
763 | * only be physically enabled if the EnableForRun bit is set |
683 | 764 | * in the EventInfo. |
|
684 | Exit: |
765 | */ |
Line 685... | Line 766... | ||
685 | ACPI_FREE (GpeEventInfo); |
766 | (void) AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_CONDITIONAL_ENABLE); |
686 | return; |
767 | return (AE_OK); |
687 | } |
768 | } |
688 | 769 | ||
- | 770 | ||
689 | 771 | /******************************************************************************* |
|
690 | /******************************************************************************* |
772 | * |
691 | * |
773 | * FUNCTION: AcpiEvGpeDispatch |
692 | * FUNCTION: AcpiEvGpeDispatch |
774 | * |
693 | * |
775 | * PARAMETERS: GpeDevice - Device node. NULL for GPE0/GPE1 |
694 | * PARAMETERS: GpeEventInfo - Info for this GPE |
776 | * GpeEventInfo - Info for this GPE |
Line 703... | Line 785... | ||
703 | * |
785 | * |
704 | ******************************************************************************/ |
786 | ******************************************************************************/ |
Line 705... | Line 787... | ||
705 | 787 | ||
706 | UINT32 |
788 | UINT32 |
- | 789 | AcpiEvGpeDispatch ( |
|
707 | AcpiEvGpeDispatch ( |
790 | ACPI_NAMESPACE_NODE *GpeDevice, |
708 | ACPI_GPE_EVENT_INFO *GpeEventInfo, |
791 | ACPI_GPE_EVENT_INFO *GpeEventInfo, |
709 | UINT32 GpeNumber) |
792 | UINT32 GpeNumber) |
710 | { |
793 | { |
- | 794 | ACPI_STATUS Status; |
|
Line 711... | Line 795... | ||
711 | ACPI_STATUS Status; |
795 | UINT32 ReturnValue; |
Line -... | Line 796... | ||
- | 796 | ||
- | 797 | ||
712 | 798 | ACPI_FUNCTION_TRACE (EvGpeDispatch); |
|
- | 799 | ||
- | 800 | ||
- | 801 | /* Invoke global event handler if present */ |
|
- | 802 | ||
- | 803 | AcpiGpeCount++; |
|
Line 713... | Line 804... | ||
713 | 804 | if (AcpiGbl_GlobalEventHandler) |
|
714 | ACPI_FUNCTION_TRACE (EvGpeDispatch); |
805 | { |
715 | 806 | AcpiGbl_GlobalEventHandler (ACPI_EVENT_TYPE_GPE, GpeDevice, |
|
716 | 807 | GpeNumber, AcpiGbl_GlobalEventHandlerContext); |
|
Line 725... | Line 816... | ||
725 | { |
816 | { |
726 | Status = AcpiHwClearGpe (GpeEventInfo); |
817 | Status = AcpiHwClearGpe (GpeEventInfo); |
727 | if (ACPI_FAILURE (Status)) |
818 | if (ACPI_FAILURE (Status)) |
728 | { |
819 | { |
729 | ACPI_EXCEPTION ((AE_INFO, Status, |
820 | ACPI_EXCEPTION ((AE_INFO, Status, |
730 | "Unable to clear GPE[0x%2X]", GpeNumber)); |
821 | "Unable to clear GPE%02X", GpeNumber)); |
731 | return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED); |
822 | return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED); |
732 | } |
823 | } |
733 | } |
824 | } |
Line 734... | Line 825... | ||
734 | 825 | ||
735 | /* |
826 | /* |
736 | * Dispatch the GPE to either an installed handler, or the control method |
827 | * Always disable the GPE so that it does not keep firing before |
- | 828 | * any asynchronous activity completes (either from the execution |
|
- | 829 | * of a GPE method or an asynchronous GPE handler.) |
|
737 | * associated with this GPE (_Lxx or _Exx). If a handler exists, we invoke |
830 | * |
738 | * it and do not attempt to run the method. If there is neither a handler |
831 | * If there is no handler or method to run, just disable the |
739 | * nor a method, we disable this GPE to prevent further such pointless |
832 | * GPE and leave it disabled permanently to prevent further such |
740 | * events from firing. |
833 | * pointless events from firing. |
741 | */ |
834 | */ |
- | 835 | Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE); |
|
742 | switch (GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) |
836 | if (ACPI_FAILURE (Status)) |
- | 837 | { |
|
- | 838 | ACPI_EXCEPTION ((AE_INFO, Status, |
|
743 | { |
839 | "Unable to disable GPE%02X", GpeNumber)); |
- | 840 | return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED); |
|
Line 744... | Line 841... | ||
744 | case ACPI_GPE_DISPATCH_HANDLER: |
841 | } |
745 | 842 | ||
- | 843 | /* |
|
746 | /* |
844 | * Dispatch the GPE to either an installed handler or the control |
747 | * Invoke the installed handler (at interrupt level) |
845 | * method associated with this GPE (_Lxx or _Exx). If a handler |
- | 846 | * exists, we invoke it and do not attempt to run the method. |
|
748 | * Ignore return status for now. |
847 | * If there is neither a handler nor a method, leave the GPE |
- | 848 | * disabled. |
|
- | 849 | */ |
|
- | 850 | switch (GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) |
|
- | 851 | { |
|
- | 852 | case ACPI_GPE_DISPATCH_HANDLER: |
|
- | 853 | ||
749 | * TBD: leave GPE disabled on error? |
854 | /* Invoke the installed handler (at interrupt level) */ |
- | 855 | ||
750 | */ |
856 | ReturnValue = GpeEventInfo->Dispatch.Handler->Address ( |
Line 751... | Line 857... | ||
751 | (void) GpeEventInfo->Dispatch.Handler->Address ( |
857 | GpeDevice, GpeNumber, |
Line 752... | Line 858... | ||
752 | GpeEventInfo->Dispatch.Handler->Context); |
858 | GpeEventInfo->Dispatch.Handler->Context); |
753 | - | ||
754 | /* It is now safe to clear level-triggered events. */ |
859 | |
755 | 860 | /* If requested, clear (if level-triggered) and reenable the GPE */ |
|
756 | if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) == |
- | |
757 | ACPI_GPE_LEVEL_TRIGGERED) |
- | |
758 | { |
- | |
759 | Status = AcpiHwClearGpe (GpeEventInfo); |
- | |
760 | if (ACPI_FAILURE (Status)) |
- | |
761 | { |
- | |
762 | ACPI_EXCEPTION ((AE_INFO, Status, |
861 | |
763 | "Unable to clear GPE[0x%2X]", GpeNumber)); |
862 | if (ReturnValue & ACPI_REENABLE_GPE) |
Line 764... | Line 863... | ||
764 | return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED); |
863 | { |
765 | } |
- | |
766 | } |
- | |
767 | break; |
- | |
768 | - | ||
769 | case ACPI_GPE_DISPATCH_METHOD: |
- | |
770 | - | ||
771 | /* |
864 | (void) AcpiEvFinishGpe (GpeEventInfo); |
772 | * Disable the GPE, so it doesn't keep firing before the method has a |
- | |
773 | * chance to run (it runs asynchronously with interrupts enabled). |
- | |
774 | */ |
- | |
775 | Status = AcpiEvDisableGpe (GpeEventInfo); |
- | |
776 | if (ACPI_FAILURE (Status)) |
- | |
Line 777... | Line 865... | ||
777 | { |
865 | } |
778 | ACPI_EXCEPTION ((AE_INFO, Status, |
866 | break; |
779 | "Unable to disable GPE[0x%2X]", GpeNumber)); |
867 | |
780 | return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED); |
868 | case ACPI_GPE_DISPATCH_METHOD: |
781 | } |
869 | case ACPI_GPE_DISPATCH_NOTIFY: |
782 | 870 | ||
783 | /* |
871 | /* |
784 | * Execute the method associated with the GPE |
872 | * Execute the method associated with the GPE |
785 | * NOTE: Level-triggered GPEs are cleared after the method completes. |
873 | * NOTE: Level-triggered GPEs are cleared after the method completes. |
786 | */ |
874 | */ |
787 | Status = AcpiOsExecute (OSL_GPE_HANDLER, |
875 | Status = AcpiOsExecute (OSL_GPE_HANDLER, |
788 | AcpiEvAsynchExecuteGpeMethod, GpeEventInfo); |
876 | AcpiEvAsynchExecuteGpeMethod, GpeEventInfo); |
789 | if (ACPI_FAILURE (Status)) |
877 | if (ACPI_FAILURE (Status)) |
Line 790... | Line 878... | ||
790 | { |
878 | { |
Line 800... | Line 888... | ||
800 | * No handler or method to run! |
888 | * No handler or method to run! |
801 | * 03/2010: This case should no longer be possible. We will not allow |
889 | * 03/2010: This case should no longer be possible. We will not allow |
802 | * a GPE to be enabled if it has no handler or method. |
890 | * a GPE to be enabled if it has no handler or method. |
803 | */ |
891 | */ |
804 | ACPI_ERROR ((AE_INFO, |
892 | ACPI_ERROR ((AE_INFO, |
805 | "No handler or method for GPE[0x%2X], disabling event", |
893 | "No handler or method for GPE%02X, disabling event", |
806 | GpeNumber)); |
894 | GpeNumber)); |
807 | - | ||
808 | /* |
- | |
809 | * Disable the GPE. The GPE will remain disabled a handler |
- | |
810 | * is installed or ACPICA is restarted. |
- | |
811 | */ |
- | |
812 | Status = AcpiEvDisableGpe (GpeEventInfo); |
- | |
813 | if (ACPI_FAILURE (Status)) |
- | |
814 | { |
- | |
815 | ACPI_EXCEPTION ((AE_INFO, Status, |
- | |
816 | "Unable to disable GPE[0x%2X]", GpeNumber)); |
- | |
817 | return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED); |
- | |
818 | } |
- | |
819 | break; |
895 | break; |
820 | } |
896 | } |
Line 821... | Line 897... | ||
821 | 897 | ||
822 | return_UINT32 (ACPI_INTERRUPT_HANDLED); |
898 | return_UINT32 (ACPI_INTERRUPT_HANDLED); |