xref: /titanic_41/usr/src/uts/intel/io/acpica/events/evgpe.c (revision 2a9459bdd821c1cf59590a7a9069ac9c591e8a6b)
1 /******************************************************************************
2  *
3  * Module Name: evgpe - General Purpose Event handling and dispatch
4  *              $Revision: 1.63 $
5  *
6  *****************************************************************************/
7 
8 /******************************************************************************
9  *
10  * 1. Copyright Notice
11  *
12  * Some or all of this work - Copyright (c) 1999 - 2006, 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 
131 /*******************************************************************************
132  *
133  * FUNCTION:    AcpiEvSetGpeType
134  *
135  * PARAMETERS:  GpeEventInfo            - GPE to set
136  *              Type                    - New type
137  *
138  * RETURN:      Status
139  *
140  * DESCRIPTION: Sets the new type for the GPE (wake, run, or wake/run)
141  *
142  ******************************************************************************/
143 
144 ACPI_STATUS
145 AcpiEvSetGpeType (
146     ACPI_GPE_EVENT_INFO     *GpeEventInfo,
147     UINT8                   Type)
148 {
149     ACPI_STATUS             Status;
150 
151 
152     ACPI_FUNCTION_TRACE (EvSetGpeType);
153 
154 
155     /* Validate type and update register enable masks */
156 
157     switch (Type)
158     {
159     case ACPI_GPE_TYPE_WAKE:
160     case ACPI_GPE_TYPE_RUNTIME:
161     case ACPI_GPE_TYPE_WAKE_RUN:
162         break;
163 
164     default:
165         return_ACPI_STATUS (AE_BAD_PARAMETER);
166     }
167 
168     /* Disable the GPE if currently enabled */
169 
170     Status = AcpiEvDisableGpe (GpeEventInfo);
171 
172     /* Type was validated above */
173 
174     GpeEventInfo->Flags &= ~ACPI_GPE_TYPE_MASK; /* Clear type bits */
175     GpeEventInfo->Flags |= Type;                /* Insert type */
176     return_ACPI_STATUS (Status);
177 }
178 
179 
180 /*******************************************************************************
181  *
182  * FUNCTION:    AcpiEvUpdateGpeEnableMasks
183  *
184  * PARAMETERS:  GpeEventInfo            - GPE to update
185  *              Type                    - What to do: ACPI_GPE_DISABLE or
186  *                                        ACPI_GPE_ENABLE
187  *
188  * RETURN:      Status
189  *
190  * DESCRIPTION: Updates GPE register enable masks based on the GPE type
191  *
192  ******************************************************************************/
193 
194 ACPI_STATUS
195 AcpiEvUpdateGpeEnableMasks (
196     ACPI_GPE_EVENT_INFO     *GpeEventInfo,
197     UINT8                   Type)
198 {
199     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
200     UINT8                   RegisterBit;
201 
202 
203     ACPI_FUNCTION_TRACE (EvUpdateGpeEnableMasks);
204 
205 
206     GpeRegisterInfo = GpeEventInfo->RegisterInfo;
207     if (!GpeRegisterInfo)
208     {
209         return_ACPI_STATUS (AE_NOT_EXIST);
210     }
211     RegisterBit = GpeEventInfo->RegisterBit;
212 
213     /* 1) Disable case.  Simply clear all enable bits */
214 
215     if (Type == ACPI_GPE_DISABLE)
216     {
217         ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, RegisterBit);
218         ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForRun, RegisterBit);
219         return_ACPI_STATUS (AE_OK);
220     }
221 
222     /* 2) Enable case.  Set/Clear the appropriate enable bits */
223 
224     switch (GpeEventInfo->Flags & ACPI_GPE_TYPE_MASK)
225     {
226     case ACPI_GPE_TYPE_WAKE:
227         ACPI_SET_BIT   (GpeRegisterInfo->EnableForWake, RegisterBit);
228         ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForRun, RegisterBit);
229         break;
230 
231     case ACPI_GPE_TYPE_RUNTIME:
232         ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, RegisterBit);
233         ACPI_SET_BIT   (GpeRegisterInfo->EnableForRun, RegisterBit);
234         break;
235 
236     case ACPI_GPE_TYPE_WAKE_RUN:
237         ACPI_SET_BIT   (GpeRegisterInfo->EnableForWake, RegisterBit);
238         ACPI_SET_BIT   (GpeRegisterInfo->EnableForRun, RegisterBit);
239         break;
240 
241     default:
242         return_ACPI_STATUS (AE_BAD_PARAMETER);
243     }
244 
245     return_ACPI_STATUS (AE_OK);
246 }
247 
248 
249 /*******************************************************************************
250  *
251  * FUNCTION:    AcpiEvEnableGpe
252  *
253  * PARAMETERS:  GpeEventInfo            - GPE to enable
254  *              WriteToHardware         - Enable now, or just mark data structs
255  *                                        (WAKE GPEs should be deferred)
256  *
257  * RETURN:      Status
258  *
259  * DESCRIPTION: Enable a GPE based on the GPE type
260  *
261  ******************************************************************************/
262 
263 ACPI_STATUS
264 AcpiEvEnableGpe (
265     ACPI_GPE_EVENT_INFO     *GpeEventInfo,
266     BOOLEAN                 WriteToHardware)
267 {
268     ACPI_STATUS             Status;
269 
270 
271     ACPI_FUNCTION_TRACE (EvEnableGpe);
272 
273 
274     /* Make sure HW enable masks are updated */
275 
276     Status = AcpiEvUpdateGpeEnableMasks (GpeEventInfo, ACPI_GPE_ENABLE);
277     if (ACPI_FAILURE (Status))
278     {
279         return_ACPI_STATUS (Status);
280     }
281 
282     /* Mark wake-enabled or HW enable, or both */
283 
284     switch (GpeEventInfo->Flags & ACPI_GPE_TYPE_MASK)
285     {
286     case ACPI_GPE_TYPE_WAKE:
287 
288         ACPI_SET_BIT (GpeEventInfo->Flags, ACPI_GPE_WAKE_ENABLED);
289         break;
290 
291     case ACPI_GPE_TYPE_WAKE_RUN:
292 
293         ACPI_SET_BIT (GpeEventInfo->Flags, ACPI_GPE_WAKE_ENABLED);
294 
295         /*lint -fallthrough */
296 
297     case ACPI_GPE_TYPE_RUNTIME:
298 
299         ACPI_SET_BIT (GpeEventInfo->Flags, ACPI_GPE_RUN_ENABLED);
300 
301         if (WriteToHardware)
302         {
303             /* Clear the GPE (of stale events), then enable it */
304 
305             Status = AcpiHwClearGpe (GpeEventInfo);
306             if (ACPI_FAILURE (Status))
307             {
308                 return_ACPI_STATUS (Status);
309             }
310 
311             /* Enable the requested runtime GPE */
312 
313             Status = AcpiHwWriteGpeEnableReg (GpeEventInfo);
314         }
315         break;
316 
317     default:
318         return_ACPI_STATUS (AE_BAD_PARAMETER);
319     }
320 
321     return_ACPI_STATUS (AE_OK);
322 }
323 
324 
325 /*******************************************************************************
326  *
327  * FUNCTION:    AcpiEvDisableGpe
328  *
329  * PARAMETERS:  GpeEventInfo            - GPE to disable
330  *
331  * RETURN:      Status
332  *
333  * DESCRIPTION: Disable a GPE based on the GPE type
334  *
335  ******************************************************************************/
336 
337 ACPI_STATUS
338 AcpiEvDisableGpe (
339     ACPI_GPE_EVENT_INFO     *GpeEventInfo)
340 {
341     ACPI_STATUS             Status;
342 
343 
344     ACPI_FUNCTION_TRACE (EvDisableGpe);
345 
346 
347     if (!(GpeEventInfo->Flags & ACPI_GPE_ENABLE_MASK))
348     {
349         return_ACPI_STATUS (AE_OK);
350     }
351 
352     /* Make sure HW enable masks are updated */
353 
354     Status = AcpiEvUpdateGpeEnableMasks (GpeEventInfo, ACPI_GPE_DISABLE);
355     if (ACPI_FAILURE (Status))
356     {
357         return_ACPI_STATUS (Status);
358     }
359 
360     /* Mark wake-disabled or HW disable, or both */
361 
362     switch (GpeEventInfo->Flags & ACPI_GPE_TYPE_MASK)
363     {
364     case ACPI_GPE_TYPE_WAKE:
365         ACPI_CLEAR_BIT (GpeEventInfo->Flags, ACPI_GPE_WAKE_ENABLED);
366         break;
367 
368     case ACPI_GPE_TYPE_WAKE_RUN:
369         ACPI_CLEAR_BIT (GpeEventInfo->Flags, ACPI_GPE_WAKE_ENABLED);
370 
371         /*lint -fallthrough */
372 
373     case ACPI_GPE_TYPE_RUNTIME:
374 
375         /* Disable the requested runtime GPE */
376 
377         ACPI_CLEAR_BIT (GpeEventInfo->Flags, ACPI_GPE_RUN_ENABLED);
378         Status = AcpiHwWriteGpeEnableReg (GpeEventInfo);
379         break;
380 
381     default:
382         return_ACPI_STATUS (AE_BAD_PARAMETER);
383     }
384 
385     return_ACPI_STATUS (AE_OK);
386 }
387 
388 
389 /*******************************************************************************
390  *
391  * FUNCTION:    AcpiEvGetGpeEventInfo
392  *
393  * PARAMETERS:  GpeDevice           - Device node.  NULL for GPE0/GPE1
394  *              GpeNumber           - Raw GPE number
395  *
396  * RETURN:      A GPE EventInfo struct.  NULL if not a valid GPE
397  *
398  * DESCRIPTION: Returns the EventInfo struct associated with this GPE.
399  *              Validates the GpeBlock and the GpeNumber
400  *
401  *              Should be called only when the GPE lists are semaphore locked
402  *              and not subject to change.
403  *
404  ******************************************************************************/
405 
406 ACPI_GPE_EVENT_INFO *
407 AcpiEvGetGpeEventInfo (
408     ACPI_HANDLE             GpeDevice,
409     UINT32                  GpeNumber)
410 {
411     ACPI_OPERAND_OBJECT     *ObjDesc;
412     ACPI_GPE_BLOCK_INFO     *GpeBlock;
413     ACPI_NATIVE_UINT        i;
414 
415 
416     ACPI_FUNCTION_ENTRY ();
417 
418 
419     /* A NULL GpeBlock means use the FADT-defined GPE block(s) */
420 
421     if (!GpeDevice)
422     {
423         /* Examine GPE Block 0 and 1 (These blocks are permanent) */
424 
425         for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++)
426         {
427             GpeBlock = AcpiGbl_GpeFadtBlocks[i];
428             if (GpeBlock)
429             {
430                 if ((GpeNumber >= GpeBlock->BlockBaseNumber) &&
431                     (GpeNumber < GpeBlock->BlockBaseNumber +
432                         (GpeBlock->RegisterCount * 8)))
433                 {
434                     return (&GpeBlock->EventInfo[GpeNumber -
435                         GpeBlock->BlockBaseNumber]);
436                 }
437             }
438         }
439 
440         /* The GpeNumber was not in the range of either FADT GPE block */
441 
442         return (NULL);
443     }
444 
445     /* A Non-NULL GpeDevice means this is a GPE Block Device */
446 
447     ObjDesc = AcpiNsGetAttachedObject ((ACPI_NAMESPACE_NODE *) GpeDevice);
448     if (!ObjDesc ||
449         !ObjDesc->Device.GpeBlock)
450     {
451         return (NULL);
452     }
453 
454     GpeBlock = ObjDesc->Device.GpeBlock;
455 
456     if ((GpeNumber >= GpeBlock->BlockBaseNumber) &&
457         (GpeNumber < GpeBlock->BlockBaseNumber + (GpeBlock->RegisterCount * 8)))
458     {
459         return (&GpeBlock->EventInfo[GpeNumber - GpeBlock->BlockBaseNumber]);
460     }
461 
462     return (NULL);
463 }
464 
465 
466 /*******************************************************************************
467  *
468  * FUNCTION:    AcpiEvGpeDetect
469  *
470  * PARAMETERS:  GpeXruptList        - Interrupt block for this interrupt.
471  *                                    Can have multiple GPE blocks attached.
472  *
473  * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
474  *
475  * DESCRIPTION: Detect if any GP events have occurred.  This function is
476  *              executed at interrupt level.
477  *
478  ******************************************************************************/
479 
480 UINT32
481 AcpiEvGpeDetect (
482     ACPI_GPE_XRUPT_INFO     *GpeXruptList)
483 {
484     ACPI_STATUS             Status;
485     ACPI_GPE_BLOCK_INFO     *GpeBlock;
486     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
487     UINT32                  IntStatus = ACPI_INTERRUPT_NOT_HANDLED;
488     UINT8                   EnabledStatusByte;
489     UINT32                  StatusReg;
490     UINT32                  EnableReg;
491     ACPI_CPU_FLAGS          Flags;
492     ACPI_NATIVE_UINT        i;
493     ACPI_NATIVE_UINT        j;
494 
495 
496     ACPI_FUNCTION_NAME (EvGpeDetect);
497 
498     /* Check for the case where there are no GPEs */
499 
500     if (!GpeXruptList)
501     {
502         return (IntStatus);
503     }
504 
505     /*
506      * We need to obtain the GPE lock for both the data structs and registers
507      * Note: Not necessary to obtain the hardware lock, since the GPE registers
508      * are owned by the GpeLock.
509      */
510     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
511 
512     /* Examine all GPE blocks attached to this interrupt level */
513 
514     GpeBlock = GpeXruptList->GpeBlockListHead;
515     while (GpeBlock)
516     {
517         /*
518          * Read all of the 8-bit GPE status and enable registers
519          * in this GPE block, saving all of them.
520          * Find all currently active GP events.
521          */
522         for (i = 0; i < GpeBlock->RegisterCount; i++)
523         {
524             /* Get the next status/enable pair */
525 
526             GpeRegisterInfo = &GpeBlock->RegisterInfo[i];
527 
528             /* Read the Status Register */
529 
530             Status = AcpiHwLowLevelRead (ACPI_GPE_REGISTER_WIDTH, &StatusReg,
531                         &GpeRegisterInfo->StatusAddress);
532             if (ACPI_FAILURE (Status))
533             {
534                 goto UnlockAndExit;
535             }
536 
537             /* Read the Enable Register */
538 
539             Status = AcpiHwLowLevelRead (ACPI_GPE_REGISTER_WIDTH, &EnableReg,
540                         &GpeRegisterInfo->EnableAddress);
541             if (ACPI_FAILURE (Status))
542             {
543                 goto UnlockAndExit;
544             }
545 
546             ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
547                 "Read GPE Register at GPE%X: Status=%02X, Enable=%02X\n",
548                 GpeRegisterInfo->BaseGpeNumber, StatusReg, EnableReg));
549 
550             /* Check if there is anything active at all in this register */
551 
552             EnabledStatusByte = (UINT8) (StatusReg & EnableReg);
553             if (!EnabledStatusByte)
554             {
555                 /* No active GPEs in this register, move on */
556 
557                 continue;
558             }
559 
560             /* Now look at the individual GPEs in this byte register */
561 
562             for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++)
563             {
564                 /* Examine one GPE bit */
565 
566                 if (EnabledStatusByte & AcpiGbl_DecodeTo8bit[j])
567                 {
568                     /*
569                      * Found an active GPE. Dispatch the event to a handler
570                      * or method.
571                      */
572                     IntStatus |= AcpiEvGpeDispatch (
573                         &GpeBlock->EventInfo[(i * ACPI_GPE_REGISTER_WIDTH) + j],
574                         (UINT32) j + GpeRegisterInfo->BaseGpeNumber);
575                 }
576             }
577         }
578 
579         GpeBlock = GpeBlock->Next;
580     }
581 
582 UnlockAndExit:
583 
584     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
585     return (IntStatus);
586 }
587 
588 
589 /*******************************************************************************
590  *
591  * FUNCTION:    AcpiEvAsynchExecuteGpeMethod
592  *
593  * PARAMETERS:  Context (GpeEventInfo) - Info for this GPE
594  *
595  * RETURN:      None
596  *
597  * DESCRIPTION: Perform the actual execution of a GPE control method. This
598  *              function is called from an invocation of AcpiOsExecute and
599  *              therefore does NOT execute at interrupt level - so that
600  *              the control method itself is not executed in the context of
601  *              an interrupt handler.
602  *
603  ******************************************************************************/
604 
605 static void ACPI_SYSTEM_XFACE
606 AcpiEvAsynchExecuteGpeMethod (
607     void                    *Context)
608 {
609     ACPI_GPE_EVENT_INFO     *GpeEventInfo = (void *) Context;
610     ACPI_STATUS             Status;
611     ACPI_GPE_EVENT_INFO     LocalGpeEventInfo;
612     ACPI_EVALUATE_INFO      *Info;
613 
614 
615     ACPI_FUNCTION_TRACE (EvAsynchExecuteGpeMethod);
616 
617 
618     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
619     if (ACPI_FAILURE (Status))
620     {
621         return_VOID;
622     }
623 
624     /* Must revalidate the GpeNumber/GpeBlock */
625 
626     if (!AcpiEvValidGpeEvent (GpeEventInfo))
627     {
628         Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
629         return_VOID;
630     }
631 
632     /* Set the GPE flags for return to enabled state */
633 
634     (void) AcpiEvEnableGpe (GpeEventInfo, FALSE);
635 
636     /*
637      * Take a snapshot of the GPE info for this level - we copy the
638      * info to prevent a race condition with RemoveHandler/RemoveBlock.
639      */
640     ACPI_MEMCPY (&LocalGpeEventInfo, GpeEventInfo,
641         sizeof (ACPI_GPE_EVENT_INFO));
642 
643     Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
644     if (ACPI_FAILURE (Status))
645     {
646         return_VOID;
647     }
648 
649     /*
650      * Must check for control method type dispatch one more
651      * time to avoid race with EvGpeInstallHandler
652      */
653     if ((LocalGpeEventInfo.Flags & ACPI_GPE_DISPATCH_MASK) ==
654             ACPI_GPE_DISPATCH_METHOD)
655     {
656         /* Allocate the evaluation information block */
657 
658         Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
659         if (!Info)
660         {
661             Status = AE_NO_MEMORY;
662         }
663         else
664         {
665             /*
666              * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the _Lxx/_Exx
667              * control method that corresponds to this GPE
668              */
669             Info->PrefixNode = LocalGpeEventInfo.Dispatch.MethodNode;
670             Info->Parameters = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT *, GpeEventInfo);
671             Info->ParameterType = ACPI_PARAM_GPE;
672             Info->Flags = ACPI_IGNORE_RETURN_VALUE;
673 
674             Status = AcpiNsEvaluate (Info);
675             ACPI_FREE (Info);
676         }
677 
678         if (ACPI_FAILURE (Status))
679         {
680             ACPI_EXCEPTION ((AE_INFO, Status,
681                 "While evaluating GPE method [%4.4s]",
682                 AcpiUtGetNodeName (LocalGpeEventInfo.Dispatch.MethodNode)));
683         }
684     }
685 
686     if ((LocalGpeEventInfo.Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
687             ACPI_GPE_LEVEL_TRIGGERED)
688     {
689         /*
690          * GPE is level-triggered, we clear the GPE status bit after
691          * handling the event.
692          */
693         Status = AcpiHwClearGpe (&LocalGpeEventInfo);
694         if (ACPI_FAILURE (Status))
695         {
696             return_VOID;
697         }
698     }
699 
700     /* Enable this GPE */
701 
702     (void) AcpiHwWriteGpeEnableReg (&LocalGpeEventInfo);
703     return_VOID;
704 }
705 
706 
707 /*******************************************************************************
708  *
709  * FUNCTION:    AcpiEvGpeDispatch
710  *
711  * PARAMETERS:  GpeEventInfo    - Info for this GPE
712  *              GpeNumber       - Number relative to the parent GPE block
713  *
714  * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
715  *
716  * DESCRIPTION: Dispatch a General Purpose Event to either a function (e.g. EC)
717  *              or method (e.g. _Lxx/_Exx) handler.
718  *
719  *              This function executes at interrupt level.
720  *
721  ******************************************************************************/
722 
723 UINT32
724 AcpiEvGpeDispatch (
725     ACPI_GPE_EVENT_INFO     *GpeEventInfo,
726     UINT32                  GpeNumber)
727 {
728     ACPI_STATUS             Status;
729 
730 
731     ACPI_FUNCTION_TRACE (EvGpeDispatch);
732 
733 
734     /*
735      * If edge-triggered, clear the GPE status bit now.  Note that
736      * level-triggered events are cleared after the GPE is serviced.
737      */
738     if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
739             ACPI_GPE_EDGE_TRIGGERED)
740     {
741         Status = AcpiHwClearGpe (GpeEventInfo);
742         if (ACPI_FAILURE (Status))
743         {
744             ACPI_EXCEPTION ((AE_INFO, Status,
745                 "Unable to clear GPE[%2X]", GpeNumber));
746             return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
747         }
748     }
749 
750     /* Save current system state */
751 
752     if (AcpiGbl_SystemAwakeAndRunning)
753     {
754         ACPI_SET_BIT (GpeEventInfo->Flags, ACPI_GPE_SYSTEM_RUNNING);
755     }
756     else
757     {
758         ACPI_CLEAR_BIT (GpeEventInfo->Flags, ACPI_GPE_SYSTEM_RUNNING);
759     }
760 
761     /*
762      * Dispatch the GPE to either an installed handler, or the control
763      * method associated with this GPE (_Lxx or _Exx).
764      * If a handler exists, we invoke it and do not attempt to run the method.
765      * If there is neither a handler nor a method, we disable the level to
766      * prevent further events from coming in here.
767      */
768     switch (GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK)
769     {
770     case ACPI_GPE_DISPATCH_HANDLER:
771 
772         /*
773          * Invoke the installed handler (at interrupt level)
774          * Ignore return status for now.  TBD: leave GPE disabled on error?
775          */
776         (void) GpeEventInfo->Dispatch.Handler->Address (
777                         GpeEventInfo->Dispatch.Handler->Context);
778 
779         /* It is now safe to clear level-triggered events. */
780 
781         if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
782                 ACPI_GPE_LEVEL_TRIGGERED)
783         {
784             Status = AcpiHwClearGpe (GpeEventInfo);
785             if (ACPI_FAILURE (Status))
786             {
787                 ACPI_EXCEPTION ((AE_INFO, Status,
788                     "Unable to clear GPE[%2X]", GpeNumber));
789                 return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
790             }
791         }
792         break;
793 
794     case ACPI_GPE_DISPATCH_METHOD:
795 
796         /*
797          * Disable GPE, so it doesn't keep firing before the method has a
798          * chance to run.
799          */
800         Status = AcpiEvDisableGpe (GpeEventInfo);
801         if (ACPI_FAILURE (Status))
802         {
803             ACPI_EXCEPTION ((AE_INFO, Status,
804                 "Unable to disable GPE[%2X]", GpeNumber));
805             return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
806         }
807 
808         /*
809          * Execute the method associated with the GPE
810          * NOTE: Level-triggered GPEs are cleared after the method completes.
811          */
812         Status = AcpiOsExecute (OSL_GPE_HANDLER,
813                     AcpiEvAsynchExecuteGpeMethod, GpeEventInfo);
814         if (ACPI_FAILURE (Status))
815         {
816             ACPI_EXCEPTION ((AE_INFO, Status,
817                 "Unable to queue handler for GPE[%2X] - event disabled",
818                 GpeNumber));
819         }
820         break;
821 
822     default:
823 
824         /* No handler or method to run! */
825 
826         ACPI_ERROR ((AE_INFO,
827             "No handler or method for GPE[%2X], disabling event",
828             GpeNumber));
829 
830         /*
831          * Disable the GPE.  The GPE will remain disabled until the ACPI
832          * Core Subsystem is restarted, or a handler is installed.
833          */
834         Status = AcpiEvDisableGpe (GpeEventInfo);
835         if (ACPI_FAILURE (Status))
836         {
837             ACPI_EXCEPTION ((AE_INFO, Status,
838                 "Unable to disable GPE[%2X]", GpeNumber));
839             return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
840         }
841         break;
842     }
843 
844     return_UINT32 (ACPI_INTERRUPT_HANDLED);
845 }
846 
847 
848 #ifdef ACPI_GPE_NOTIFY_CHECK
849 /*******************************************************************************
850  * TBD: NOT USED, PROTOTYPE ONLY AND WILL PROBABLY BE REMOVED
851  *
852  * FUNCTION:    AcpiEvCheckForWakeOnlyGpe
853  *
854  * PARAMETERS:  GpeEventInfo    - info for this GPE
855  *
856  * RETURN:      Status
857  *
858  * DESCRIPTION: Determine if a a GPE is "wake-only".
859  *
860  *              Called from Notify() code in interpreter when a "DeviceWake"
861  *              Notify comes in.
862  *
863  ******************************************************************************/
864 
865 ACPI_STATUS
866 AcpiEvCheckForWakeOnlyGpe (
867     ACPI_GPE_EVENT_INFO     *GpeEventInfo)
868 {
869     ACPI_STATUS             Status;
870 
871 
872     ACPI_FUNCTION_TRACE (EvCheckForWakeOnlyGpe);
873 
874 
875     if ((GpeEventInfo)   &&  /* Only >0 for _Lxx/_Exx */
876        ((GpeEventInfo->Flags & ACPI_GPE_SYSTEM_MASK) == ACPI_GPE_SYSTEM_RUNNING)) /* System state at GPE time */
877     {
878         /* This must be a wake-only GPE, disable it */
879 
880         Status = AcpiEvDisableGpe (GpeEventInfo);
881 
882         /* Set GPE to wake-only.  Do not change wake disabled/enabled status */
883 
884         AcpiEvSetGpeType (GpeEventInfo, ACPI_GPE_TYPE_WAKE);
885 
886         ACPI_INFO ((AE_INFO, "GPE %p was updated from wake/run to wake-only",
887                 GpeEventInfo));
888 
889         /* This was a wake-only GPE */
890 
891         return_ACPI_STATUS (AE_WAKE_ONLY_GPE);
892     }
893 
894     return_ACPI_STATUS (AE_OK);
895 }
896 #endif
897 
898 
899