xref: /titanic_44/usr/src/uts/intel/io/acpica/events/evgpe.c (revision a38ddfee9c8c6b6c5a2947ff52fd2338362a4444)
1 /******************************************************************************
2  *
3  * Module Name: evgpe - General Purpose Event handling and dispatch
4  *              $Revision: 1.72 $
5  *
6  *****************************************************************************/
7 
8 /******************************************************************************
9  *
10  * 1. Copyright Notice
11  *
12  * Some or all of this work - Copyright (c) 1999 - 2008, Intel Corp.
13  * All rights reserved.
14  *
15  * 2. License
16  *
17  * 2.1. This is your license from Intel Corp. under its intellectual property
18  * rights.  You may have additional license terms from the party that provided
19  * you this software, covering your right to use that party's intellectual
20  * property rights.
21  *
22  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
23  * copy of the source code appearing in this file ("Covered Code") an
24  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
25  * base code distributed originally by Intel ("Original Intel Code") to copy,
26  * make derivatives, distribute, use and display any portion of the Covered
27  * Code in any form, with the right to sublicense such rights; and
28  *
29  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
30  * license (with the right to sublicense), under only those claims of Intel
31  * patents that are infringed by the Original Intel Code, to make, use, sell,
32  * offer to sell, and import the Covered Code and derivative works thereof
33  * solely to the minimum extent necessary to exercise the above copyright
34  * license, and in no event shall the patent license extend to any additions
35  * to or modifications of the Original Intel Code.  No other license or right
36  * is granted directly or by implication, estoppel or otherwise;
37  *
38  * The above copyright and patent license is granted only if the following
39  * conditions are met:
40  *
41  * 3. Conditions
42  *
43  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
44  * Redistribution of source code of any substantial portion of the Covered
45  * Code or modification with rights to further distribute source must include
46  * the above Copyright Notice, the above License, this list of Conditions,
47  * and the following Disclaimer and Export Compliance provision.  In addition,
48  * Licensee must cause all Covered Code to which Licensee contributes to
49  * contain a file documenting the changes Licensee made to create that Covered
50  * Code and the date of any change.  Licensee must include in that file the
51  * documentation of any changes made by any predecessor Licensee.  Licensee
52  * must include a prominent statement that the modification is derived,
53  * directly or indirectly, from Original Intel Code.
54  *
55  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
56  * Redistribution of source code of any substantial portion of the Covered
57  * Code or modification without rights to further distribute source must
58  * include the following Disclaimer and Export Compliance provision in the
59  * documentation and/or other materials provided with distribution.  In
60  * addition, Licensee may not authorize further sublicense of source of any
61  * portion of the Covered Code, and must include terms to the effect that the
62  * license from Licensee to its licensee is limited to the intellectual
63  * property embodied in the software Licensee provides to its licensee, and
64  * not to intellectual property embodied in modifications its licensee may
65  * make.
66  *
67  * 3.3. Redistribution of Executable. Redistribution in executable form of any
68  * substantial portion of the Covered Code or modification must reproduce the
69  * above Copyright Notice, and the following Disclaimer and Export Compliance
70  * provision in the documentation and/or other materials provided with the
71  * distribution.
72  *
73  * 3.4. Intel retains all right, title, and interest in and to the Original
74  * Intel Code.
75  *
76  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
77  * Intel shall be used in advertising or otherwise to promote the sale, use or
78  * other dealings in products derived from or relating to the Covered Code
79  * without prior written authorization from Intel.
80  *
81  * 4. Disclaimer and Export Compliance
82  *
83  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
84  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
85  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
86  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
87  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
88  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
89  * PARTICULAR PURPOSE.
90  *
91  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
94  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
97  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
98  * LIMITED REMEDY.
99  *
100  * 4.3. Licensee shall not export, either directly or indirectly, any of this
101  * software or system incorporating such software without first obtaining any
102  * required license or other approval from the U. S. Department of Commerce or
103  * any other agency or department of the United States Government.  In the
104  * event Licensee exports any such software from the United States or
105  * re-exports any such software from a foreign destination, Licensee shall
106  * ensure that the distribution and export/re-export of the software is in
107  * compliance with all laws, regulations, orders, or other restrictions of the
108  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109  * any of its subsidiaries will export/re-export any technical data, process,
110  * software, or service, directly or indirectly, to any country for which the
111  * United States government or any agency thereof requires an export license,
112  * other governmental approval, or letter of assurance, without first obtaining
113  * such license, approval or letter.
114  *
115  *****************************************************************************/
116 
117 #include "acpi.h"
118 #include "acevents.h"
119 #include "acnamesp.h"
120 
121 #define _COMPONENT          ACPI_EVENTS
122         ACPI_MODULE_NAME    ("evgpe")
123 
124 /* Local prototypes */
125 
126 static void ACPI_SYSTEM_XFACE
127 AcpiEvAsynchExecuteGpeMethod (
128     void                    *Context);
129 
130 static void ACPI_SYSTEM_XFACE
131 AcpiEvAsynchEnableGpe (
132     void                    *Context);
133 
134 
135 /*******************************************************************************
136  *
137  * FUNCTION:    AcpiEvSetGpeType
138  *
139  * PARAMETERS:  GpeEventInfo            - GPE to set
140  *              Type                    - New type
141  *
142  * RETURN:      Status
143  *
144  * DESCRIPTION: Sets the new type for the GPE (wake, run, or wake/run)
145  *
146  ******************************************************************************/
147 
148 ACPI_STATUS
149 AcpiEvSetGpeType (
150     ACPI_GPE_EVENT_INFO     *GpeEventInfo,
151     UINT8                   Type)
152 {
153     ACPI_STATUS             Status;
154 
155 
156     ACPI_FUNCTION_TRACE (EvSetGpeType);
157 
158 
159     /* Validate type and update register enable masks */
160 
161     switch (Type)
162     {
163     case ACPI_GPE_TYPE_WAKE:
164     case ACPI_GPE_TYPE_RUNTIME:
165     case ACPI_GPE_TYPE_WAKE_RUN:
166         break;
167 
168     default:
169         return_ACPI_STATUS (AE_BAD_PARAMETER);
170     }
171 
172     /* Disable the GPE if currently enabled */
173 
174     Status = AcpiEvDisableGpe (GpeEventInfo);
175 
176     /* Type was validated above */
177 
178     GpeEventInfo->Flags &= ~ACPI_GPE_TYPE_MASK; /* Clear type bits */
179     GpeEventInfo->Flags |= Type;                /* Insert type */
180     return_ACPI_STATUS (Status);
181 }
182 
183 
184 /*******************************************************************************
185  *
186  * FUNCTION:    AcpiEvUpdateGpeEnableMasks
187  *
188  * PARAMETERS:  GpeEventInfo            - GPE to update
189  *              Type                    - What to do: ACPI_GPE_DISABLE or
190  *                                        ACPI_GPE_ENABLE
191  *
192  * RETURN:      Status
193  *
194  * DESCRIPTION: Updates GPE register enable masks based on the GPE type
195  *
196  ******************************************************************************/
197 
198 ACPI_STATUS
199 AcpiEvUpdateGpeEnableMasks (
200     ACPI_GPE_EVENT_INFO     *GpeEventInfo,
201     UINT8                   Type)
202 {
203     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
204     UINT8                   RegisterBit;
205 
206 
207     ACPI_FUNCTION_TRACE (EvUpdateGpeEnableMasks);
208 
209 
210     GpeRegisterInfo = GpeEventInfo->RegisterInfo;
211     if (!GpeRegisterInfo)
212     {
213         return_ACPI_STATUS (AE_NOT_EXIST);
214     }
215     RegisterBit = (UINT8)
216         (1 << (GpeEventInfo->GpeNumber - GpeRegisterInfo->BaseGpeNumber));
217 
218     /* 1) Disable case.  Simply clear all enable bits */
219 
220     if (Type == ACPI_GPE_DISABLE)
221     {
222         ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, RegisterBit);
223         ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForRun, RegisterBit);
224         return_ACPI_STATUS (AE_OK);
225     }
226 
227     /* 2) Enable case.  Set/Clear the appropriate enable bits */
228 
229     switch (GpeEventInfo->Flags & ACPI_GPE_TYPE_MASK)
230     {
231     case ACPI_GPE_TYPE_WAKE:
232         ACPI_SET_BIT   (GpeRegisterInfo->EnableForWake, RegisterBit);
233         ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForRun, RegisterBit);
234         break;
235 
236     case ACPI_GPE_TYPE_RUNTIME:
237         ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, RegisterBit);
238         ACPI_SET_BIT   (GpeRegisterInfo->EnableForRun, RegisterBit);
239         break;
240 
241     case ACPI_GPE_TYPE_WAKE_RUN:
242         ACPI_SET_BIT   (GpeRegisterInfo->EnableForWake, RegisterBit);
243         ACPI_SET_BIT   (GpeRegisterInfo->EnableForRun, RegisterBit);
244         break;
245 
246     default:
247         return_ACPI_STATUS (AE_BAD_PARAMETER);
248     }
249 
250     return_ACPI_STATUS (AE_OK);
251 }
252 
253 
254 /*******************************************************************************
255  *
256  * FUNCTION:    AcpiEvEnableGpe
257  *
258  * PARAMETERS:  GpeEventInfo            - GPE to enable
259  *              WriteToHardware         - Enable now, or just mark data structs
260  *                                        (WAKE GPEs should be deferred)
261  *
262  * RETURN:      Status
263  *
264  * DESCRIPTION: Enable a GPE based on the GPE type
265  *
266  ******************************************************************************/
267 
268 ACPI_STATUS
269 AcpiEvEnableGpe (
270     ACPI_GPE_EVENT_INFO     *GpeEventInfo,
271     BOOLEAN                 WriteToHardware)
272 {
273     ACPI_STATUS             Status;
274 
275 
276     ACPI_FUNCTION_TRACE (EvEnableGpe);
277 
278 
279     /* Make sure HW enable masks are updated */
280 
281     Status = AcpiEvUpdateGpeEnableMasks (GpeEventInfo, ACPI_GPE_ENABLE);
282     if (ACPI_FAILURE (Status))
283     {
284         return_ACPI_STATUS (Status);
285     }
286 
287     /* Mark wake-enabled or HW enable, or both */
288 
289     switch (GpeEventInfo->Flags & ACPI_GPE_TYPE_MASK)
290     {
291     case ACPI_GPE_TYPE_WAKE:
292 
293         ACPI_SET_BIT (GpeEventInfo->Flags, ACPI_GPE_WAKE_ENABLED);
294         break;
295 
296     case ACPI_GPE_TYPE_WAKE_RUN:
297 
298         ACPI_SET_BIT (GpeEventInfo->Flags, ACPI_GPE_WAKE_ENABLED);
299 
300         /*lint -fallthrough */
301 
302     case ACPI_GPE_TYPE_RUNTIME:
303 
304         ACPI_SET_BIT (GpeEventInfo->Flags, ACPI_GPE_RUN_ENABLED);
305 
306         if (WriteToHardware)
307         {
308             /* Clear the GPE (of stale events), then enable it */
309 
310             Status = AcpiHwClearGpe (GpeEventInfo);
311             if (ACPI_FAILURE (Status))
312             {
313                 return_ACPI_STATUS (Status);
314             }
315 
316             /* Enable the requested runtime GPE */
317 
318             Status = AcpiHwWriteGpeEnableReg (GpeEventInfo);
319         }
320         break;
321 
322     default:
323         return_ACPI_STATUS (AE_BAD_PARAMETER);
324     }
325 
326     return_ACPI_STATUS (AE_OK);
327 }
328 
329 
330 /*******************************************************************************
331  *
332  * FUNCTION:    AcpiEvDisableGpe
333  *
334  * PARAMETERS:  GpeEventInfo            - GPE to disable
335  *
336  * RETURN:      Status
337  *
338  * DESCRIPTION: Disable a GPE based on the GPE type
339  *
340  ******************************************************************************/
341 
342 ACPI_STATUS
343 AcpiEvDisableGpe (
344     ACPI_GPE_EVENT_INFO     *GpeEventInfo)
345 {
346     ACPI_STATUS             Status;
347 
348 
349     ACPI_FUNCTION_TRACE (EvDisableGpe);
350 
351 
352     /*
353      * Note: Always disable the GPE, even if we think that that it is already
354      * disabled. It is possible that the AML or some other code has enabled
355      * the GPE behind our back.
356      */
357 
358     /* Make sure HW enable masks are updated */
359 
360     Status = AcpiEvUpdateGpeEnableMasks (GpeEventInfo, ACPI_GPE_DISABLE);
361     if (ACPI_FAILURE (Status))
362     {
363         return_ACPI_STATUS (Status);
364     }
365 
366     /* Clear the appropriate enabled flags for this GPE */
367 
368     switch (GpeEventInfo->Flags & ACPI_GPE_TYPE_MASK)
369     {
370     case ACPI_GPE_TYPE_WAKE:
371 
372         ACPI_CLEAR_BIT (GpeEventInfo->Flags, ACPI_GPE_WAKE_ENABLED);
373         break;
374 
375     case ACPI_GPE_TYPE_WAKE_RUN:
376 
377         ACPI_CLEAR_BIT (GpeEventInfo->Flags, ACPI_GPE_WAKE_ENABLED);
378 
379         /*lint -fallthrough */
380 
381     case ACPI_GPE_TYPE_RUNTIME:
382 
383         /* Disable the requested runtime GPE */
384 
385         ACPI_CLEAR_BIT (GpeEventInfo->Flags, ACPI_GPE_RUN_ENABLED);
386         break;
387 
388     default:
389         break;
390     }
391 
392     /*
393      * Always H/W disable this GPE, even if we don't know the GPE type.
394      * Simply clear the enable bit for this particular GPE, but do not
395      * write out the current GPE enable mask since this may inadvertently
396      * enable GPEs too early. An example is a rogue GPE that has arrived
397      * during ACPICA initialization - possibly because AML or other code
398      * has enabled the GPE.
399      */
400     Status = AcpiHwLowDisableGpe (GpeEventInfo);
401     return_ACPI_STATUS (Status);
402 }
403 
404 
405 /*******************************************************************************
406  *
407  * FUNCTION:    AcpiEvGetGpeEventInfo
408  *
409  * PARAMETERS:  GpeDevice           - Device node.  NULL for GPE0/GPE1
410  *              GpeNumber           - Raw GPE number
411  *
412  * RETURN:      A GPE EventInfo struct.  NULL if not a valid GPE
413  *
414  * DESCRIPTION: Returns the EventInfo struct associated with this GPE.
415  *              Validates the GpeBlock and the GpeNumber
416  *
417  *              Should be called only when the GPE lists are semaphore locked
418  *              and not subject to change.
419  *
420  ******************************************************************************/
421 
422 ACPI_GPE_EVENT_INFO *
423 AcpiEvGetGpeEventInfo (
424     ACPI_HANDLE             GpeDevice,
425     UINT32                  GpeNumber)
426 {
427     ACPI_OPERAND_OBJECT     *ObjDesc;
428     ACPI_GPE_BLOCK_INFO     *GpeBlock;
429     UINT32                  i;
430 
431 
432     ACPI_FUNCTION_ENTRY ();
433 
434 
435     /* A NULL GpeBlock means use the FADT-defined GPE block(s) */
436 
437     if (!GpeDevice)
438     {
439         /* Examine GPE Block 0 and 1 (These blocks are permanent) */
440 
441         for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++)
442         {
443             GpeBlock = AcpiGbl_GpeFadtBlocks[i];
444             if (GpeBlock)
445             {
446                 if ((GpeNumber >= GpeBlock->BlockBaseNumber) &&
447                     (GpeNumber < GpeBlock->BlockBaseNumber +
448                         (GpeBlock->RegisterCount * 8)))
449                 {
450                     return (&GpeBlock->EventInfo[GpeNumber -
451                         GpeBlock->BlockBaseNumber]);
452                 }
453             }
454         }
455 
456         /* The GpeNumber was not in the range of either FADT GPE block */
457 
458         return (NULL);
459     }
460 
461     /* A Non-NULL GpeDevice means this is a GPE Block Device */
462 
463     ObjDesc = AcpiNsGetAttachedObject ((ACPI_NAMESPACE_NODE *) GpeDevice);
464     if (!ObjDesc ||
465         !ObjDesc->Device.GpeBlock)
466     {
467         return (NULL);
468     }
469 
470     GpeBlock = ObjDesc->Device.GpeBlock;
471 
472     if ((GpeNumber >= GpeBlock->BlockBaseNumber) &&
473         (GpeNumber < GpeBlock->BlockBaseNumber + (GpeBlock->RegisterCount * 8)))
474     {
475         return (&GpeBlock->EventInfo[GpeNumber - GpeBlock->BlockBaseNumber]);
476     }
477 
478     return (NULL);
479 }
480 
481 
482 /*******************************************************************************
483  *
484  * FUNCTION:    AcpiEvGpeDetect
485  *
486  * PARAMETERS:  GpeXruptList        - Interrupt block for this interrupt.
487  *                                    Can have multiple GPE blocks attached.
488  *
489  * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
490  *
491  * DESCRIPTION: Detect if any GP events have occurred.  This function is
492  *              executed at interrupt level.
493  *
494  ******************************************************************************/
495 
496 UINT32
497 AcpiEvGpeDetect (
498     ACPI_GPE_XRUPT_INFO     *GpeXruptList)
499 {
500     ACPI_STATUS             Status;
501     ACPI_GPE_BLOCK_INFO     *GpeBlock;
502     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
503     UINT32                  IntStatus = ACPI_INTERRUPT_NOT_HANDLED;
504     UINT8                   EnabledStatusByte;
505     UINT32                  StatusReg;
506     UINT32                  EnableReg;
507     ACPI_CPU_FLAGS          Flags;
508     UINT32                  i;
509     UINT32                  j;
510 
511 
512     ACPI_FUNCTION_NAME (EvGpeDetect);
513 
514     /* Check for the case where there are no GPEs */
515 
516     if (!GpeXruptList)
517     {
518         return (IntStatus);
519     }
520 
521     /*
522      * We need to obtain the GPE lock for both the data structs and registers
523      * Note: Not necessary to obtain the hardware lock, since the GPE registers
524      * are owned by the GpeLock.
525      */
526     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
527 
528     /* Examine all GPE blocks attached to this interrupt level */
529 
530     GpeBlock = GpeXruptList->GpeBlockListHead;
531     while (GpeBlock)
532     {
533         /*
534          * Read all of the 8-bit GPE status and enable registers
535          * in this GPE block, saving all of them.
536          * Find all currently active GP events.
537          */
538         for (i = 0; i < GpeBlock->RegisterCount; i++)
539         {
540             /* Get the next status/enable pair */
541 
542             GpeRegisterInfo = &GpeBlock->RegisterInfo[i];
543 
544             /* Read the Status Register */
545 
546             Status = AcpiHwLowLevelRead (ACPI_GPE_REGISTER_WIDTH, &StatusReg,
547                         &GpeRegisterInfo->StatusAddress);
548             if (ACPI_FAILURE (Status))
549             {
550                 goto UnlockAndExit;
551             }
552 
553             /* Read the Enable Register */
554 
555             Status = AcpiHwLowLevelRead (ACPI_GPE_REGISTER_WIDTH, &EnableReg,
556                         &GpeRegisterInfo->EnableAddress);
557             if (ACPI_FAILURE (Status))
558             {
559                 goto UnlockAndExit;
560             }
561 
562             ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
563                 "Read GPE Register at GPE%X: Status=%02X, Enable=%02X\n",
564                 GpeRegisterInfo->BaseGpeNumber, StatusReg, EnableReg));
565 
566             /* Check if there is anything active at all in this register */
567 
568             EnabledStatusByte = (UINT8) (StatusReg & EnableReg);
569             if (!EnabledStatusByte)
570             {
571                 /* No active GPEs in this register, move on */
572 
573                 continue;
574             }
575 
576             /* Now look at the individual GPEs in this byte register */
577 
578             for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++)
579             {
580                 /* Examine one GPE bit */
581 
582                 if (EnabledStatusByte & (1 << j))
583                 {
584                     /*
585                      * Found an active GPE. Dispatch the event to a handler
586                      * or method.
587                      */
588                     IntStatus |= AcpiEvGpeDispatch (
589                         &GpeBlock->EventInfo[((ACPI_SIZE) i * ACPI_GPE_REGISTER_WIDTH) + j],
590                         j + GpeRegisterInfo->BaseGpeNumber);
591                 }
592             }
593         }
594 
595         GpeBlock = GpeBlock->Next;
596     }
597 
598 UnlockAndExit:
599 
600     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
601     return (IntStatus);
602 }
603 
604 
605 /*******************************************************************************
606  *
607  * FUNCTION:    AcpiEvAsynchExecuteGpeMethod
608  *
609  * PARAMETERS:  Context (GpeEventInfo) - Info for this GPE
610  *
611  * RETURN:      None
612  *
613  * DESCRIPTION: Perform the actual execution of a GPE control method. This
614  *              function is called from an invocation of AcpiOsExecute and
615  *              therefore does NOT execute at interrupt level - so that
616  *              the control method itself is not executed in the context of
617  *              an interrupt handler.
618  *
619  ******************************************************************************/
620 
621 static void ACPI_SYSTEM_XFACE
622 AcpiEvAsynchExecuteGpeMethod (
623     void                    *Context)
624 {
625     ACPI_GPE_EVENT_INFO     *GpeEventInfo = Context;
626     ACPI_STATUS             Status;
627     ACPI_GPE_EVENT_INFO     *LocalGpeEventInfo;
628     ACPI_EVALUATE_INFO      *Info;
629 
630 
631     ACPI_FUNCTION_TRACE (EvAsynchExecuteGpeMethod);
632 
633 
634     /* Allocate a local GPE block */
635 
636     LocalGpeEventInfo = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_EVENT_INFO));
637     if (!LocalGpeEventInfo)
638     {
639         ACPI_EXCEPTION ((AE_INFO, AE_NO_MEMORY,
640             "while handling a GPE"));
641         return_VOID;
642     }
643 
644     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
645     if (ACPI_FAILURE (Status))
646     {
647         return_VOID;
648     }
649 
650     /* Must revalidate the GpeNumber/GpeBlock */
651 
652     if (!AcpiEvValidGpeEvent (GpeEventInfo))
653     {
654         Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
655         return_VOID;
656     }
657 
658     /* Set the GPE flags for return to enabled state */
659 
660     (void) AcpiEvEnableGpe (GpeEventInfo, FALSE);
661 
662     /*
663      * Take a snapshot of the GPE info for this level - we copy the
664      * info to prevent a race condition with RemoveHandler/RemoveBlock.
665      */
666     ACPI_MEMCPY (LocalGpeEventInfo, GpeEventInfo,
667         sizeof (ACPI_GPE_EVENT_INFO));
668 
669     Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
670     if (ACPI_FAILURE (Status))
671     {
672         return_VOID;
673     }
674 
675     /*
676      * Must check for control method type dispatch one more
677      * time to avoid race with EvGpeInstallHandler
678      */
679     if ((LocalGpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
680             ACPI_GPE_DISPATCH_METHOD)
681     {
682         /* Allocate the evaluation information block */
683 
684         Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
685         if (!Info)
686         {
687             Status = AE_NO_MEMORY;
688         }
689         else
690         {
691             /*
692              * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the _Lxx/_Exx
693              * control method that corresponds to this GPE
694              */
695             Info->PrefixNode = LocalGpeEventInfo->Dispatch.MethodNode;
696             Info->Flags = ACPI_IGNORE_RETURN_VALUE;
697 
698             Status = AcpiNsEvaluate (Info);
699             ACPI_FREE (Info);
700         }
701 
702         if (ACPI_FAILURE (Status))
703         {
704             ACPI_EXCEPTION ((AE_INFO, Status,
705                 "while evaluating GPE method [%4.4s]",
706                 AcpiUtGetNodeName (LocalGpeEventInfo->Dispatch.MethodNode)));
707         }
708     }
709 
710     /* Defer enabling of GPE until all notify handlers are done */
711 
712     Status = AcpiOsExecute (OSL_NOTIFY_HANDLER,
713                 AcpiEvAsynchEnableGpe, LocalGpeEventInfo);
714     if (ACPI_FAILURE (Status))
715     {
716         ACPI_FREE (LocalGpeEventInfo);
717     }
718     return_VOID;
719 }
720 
721 
722 /*******************************************************************************
723  *
724  * FUNCTION:    AcpiEvAsynchEnableGpe
725  *
726  * PARAMETERS:  Context (GpeEventInfo) - Info for this GPE
727  *
728  * RETURN:      None
729  *
730  * DESCRIPTION: Asynchronous clear/enable for GPE. This allows the GPE to
731  *              complete (i.e., finish execution of Notify)
732  *
733  ******************************************************************************/
734 
735 static void ACPI_SYSTEM_XFACE
736 AcpiEvAsynchEnableGpe (
737     void                    *Context)
738 {
739     ACPI_GPE_EVENT_INFO     *GpeEventInfo = Context;
740     ACPI_STATUS             Status;
741 
742 
743     if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
744             ACPI_GPE_LEVEL_TRIGGERED)
745     {
746         /*
747          * GPE is level-triggered, we clear the GPE status bit after
748          * handling the event.
749          */
750         Status = AcpiHwClearGpe (GpeEventInfo);
751         if (ACPI_FAILURE (Status))
752         {
753             goto Exit;
754         }
755     }
756 
757     /* Enable this GPE */
758 
759     (void) AcpiHwWriteGpeEnableReg (GpeEventInfo);
760 
761 Exit:
762     ACPI_FREE (GpeEventInfo);
763     return;
764 }
765 
766 
767 /*******************************************************************************
768  *
769  * FUNCTION:    AcpiEvGpeDispatch
770  *
771  * PARAMETERS:  GpeEventInfo    - Info for this GPE
772  *              GpeNumber       - Number relative to the parent GPE block
773  *
774  * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
775  *
776  * DESCRIPTION: Dispatch a General Purpose Event to either a function (e.g. EC)
777  *              or method (e.g. _Lxx/_Exx) handler.
778  *
779  *              This function executes at interrupt level.
780  *
781  ******************************************************************************/
782 
783 UINT32
784 AcpiEvGpeDispatch (
785     ACPI_GPE_EVENT_INFO     *GpeEventInfo,
786     UINT32                  GpeNumber)
787 {
788     ACPI_STATUS             Status;
789 
790 
791     ACPI_FUNCTION_TRACE (EvGpeDispatch);
792 
793 
794     AcpiGpeCount++;
795 
796     /*
797      * If edge-triggered, clear the GPE status bit now.  Note that
798      * level-triggered events are cleared after the GPE is serviced.
799      */
800     if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
801             ACPI_GPE_EDGE_TRIGGERED)
802     {
803         Status = AcpiHwClearGpe (GpeEventInfo);
804         if (ACPI_FAILURE (Status))
805         {
806             ACPI_EXCEPTION ((AE_INFO, Status,
807                 "Unable to clear GPE[%2X]", GpeNumber));
808             return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
809         }
810     }
811 
812     /*
813      * Dispatch the GPE to either an installed handler, or the control method
814      * associated with this GPE (_Lxx or _Exx). If a handler exists, we invoke
815      * it and do not attempt to run the method. If there is neither a handler
816      * nor a method, we disable this GPE to prevent further such pointless
817      * events from firing.
818      */
819     switch (GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK)
820     {
821     case ACPI_GPE_DISPATCH_HANDLER:
822 
823         /*
824          * Invoke the installed handler (at interrupt level)
825          * Ignore return status for now.  TBD: leave GPE disabled on error?
826          */
827         (void) GpeEventInfo->Dispatch.Handler->Address (
828                         GpeEventInfo->Dispatch.Handler->Context);
829 
830         /* It is now safe to clear level-triggered events. */
831 
832         if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
833                 ACPI_GPE_LEVEL_TRIGGERED)
834         {
835             Status = AcpiHwClearGpe (GpeEventInfo);
836             if (ACPI_FAILURE (Status))
837             {
838                 ACPI_EXCEPTION ((AE_INFO, Status,
839                     "Unable to clear GPE[%2X]", GpeNumber));
840                 return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
841             }
842         }
843         break;
844 
845     case ACPI_GPE_DISPATCH_METHOD:
846 
847         /*
848          * Disable the GPE, so it doesn't keep firing before the method has a
849          * chance to run (it runs asynchronously with interrupts enabled).
850          */
851         Status = AcpiEvDisableGpe (GpeEventInfo);
852         if (ACPI_FAILURE (Status))
853         {
854             ACPI_EXCEPTION ((AE_INFO, Status,
855                 "Unable to disable GPE[%2X]", GpeNumber));
856             return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
857         }
858 
859         /*
860          * Execute the method associated with the GPE
861          * NOTE: Level-triggered GPEs are cleared after the method completes.
862          */
863         Status = AcpiOsExecute (OSL_GPE_HANDLER,
864                     AcpiEvAsynchExecuteGpeMethod, GpeEventInfo);
865         if (ACPI_FAILURE (Status))
866         {
867             ACPI_EXCEPTION ((AE_INFO, Status,
868                 "Unable to queue handler for GPE[%2X] - event disabled",
869                 GpeNumber));
870         }
871         break;
872 
873     default:
874 
875         /* No handler or method to run! */
876 
877         ACPI_ERROR ((AE_INFO,
878             "No handler or method for GPE[%2X], disabling event",
879             GpeNumber));
880 
881         /*
882          * Disable the GPE. The GPE will remain disabled until the ACPI
883          * Core Subsystem is restarted, or a handler is installed.
884          */
885         Status = AcpiEvDisableGpe (GpeEventInfo);
886         if (ACPI_FAILURE (Status))
887         {
888             ACPI_EXCEPTION ((AE_INFO, Status,
889                 "Unable to disable GPE[%2X]", GpeNumber));
890             return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
891         }
892         break;
893     }
894 
895     return_UINT32 (ACPI_INTERRUPT_HANDLED);
896 }
897 
898