evgpe.c revision 126372
1114239Snjl/******************************************************************************
2114239Snjl *
3114239Snjl * Module Name: evgpe - General Purpose Event handling and dispatch
4126372Snjl *              $Revision: 33 $
5114239Snjl *
6114239Snjl *****************************************************************************/
7114239Snjl
8114239Snjl/******************************************************************************
9114239Snjl *
10114239Snjl * 1. Copyright Notice
11114239Snjl *
12126372Snjl * Some or all of this work - Copyright (c) 1999 - 2004, Intel Corp.
13114239Snjl * All rights reserved.
14114239Snjl *
15114239Snjl * 2. License
16114239Snjl *
17114239Snjl * 2.1. This is your license from Intel Corp. under its intellectual property
18114239Snjl * rights.  You may have additional license terms from the party that provided
19114239Snjl * you this software, covering your right to use that party's intellectual
20114239Snjl * property rights.
21114239Snjl *
22114239Snjl * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
23114239Snjl * copy of the source code appearing in this file ("Covered Code") an
24114239Snjl * irrevocable, perpetual, worldwide license under Intel's copyrights in the
25114239Snjl * base code distributed originally by Intel ("Original Intel Code") to copy,
26114239Snjl * make derivatives, distribute, use and display any portion of the Covered
27114239Snjl * Code in any form, with the right to sublicense such rights; and
28114239Snjl *
29114239Snjl * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
30114239Snjl * license (with the right to sublicense), under only those claims of Intel
31114239Snjl * patents that are infringed by the Original Intel Code, to make, use, sell,
32114239Snjl * offer to sell, and import the Covered Code and derivative works thereof
33114239Snjl * solely to the minimum extent necessary to exercise the above copyright
34114239Snjl * license, and in no event shall the patent license extend to any additions
35114239Snjl * to or modifications of the Original Intel Code.  No other license or right
36114239Snjl * is granted directly or by implication, estoppel or otherwise;
37114239Snjl *
38114239Snjl * The above copyright and patent license is granted only if the following
39114239Snjl * conditions are met:
40114239Snjl *
41114239Snjl * 3. Conditions
42114239Snjl *
43114239Snjl * 3.1. Redistribution of Source with Rights to Further Distribute Source.
44114239Snjl * Redistribution of source code of any substantial portion of the Covered
45114239Snjl * Code or modification with rights to further distribute source must include
46114239Snjl * the above Copyright Notice, the above License, this list of Conditions,
47114239Snjl * and the following Disclaimer and Export Compliance provision.  In addition,
48114239Snjl * Licensee must cause all Covered Code to which Licensee contributes to
49114239Snjl * contain a file documenting the changes Licensee made to create that Covered
50114239Snjl * Code and the date of any change.  Licensee must include in that file the
51114239Snjl * documentation of any changes made by any predecessor Licensee.  Licensee
52114239Snjl * must include a prominent statement that the modification is derived,
53114239Snjl * directly or indirectly, from Original Intel Code.
54114239Snjl *
55114239Snjl * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
56114239Snjl * Redistribution of source code of any substantial portion of the Covered
57114239Snjl * Code or modification without rights to further distribute source must
58114239Snjl * include the following Disclaimer and Export Compliance provision in the
59114239Snjl * documentation and/or other materials provided with distribution.  In
60114239Snjl * addition, Licensee may not authorize further sublicense of source of any
61114239Snjl * portion of the Covered Code, and must include terms to the effect that the
62114239Snjl * license from Licensee to its licensee is limited to the intellectual
63114239Snjl * property embodied in the software Licensee provides to its licensee, and
64114239Snjl * not to intellectual property embodied in modifications its licensee may
65114239Snjl * make.
66114239Snjl *
67114239Snjl * 3.3. Redistribution of Executable. Redistribution in executable form of any
68114239Snjl * substantial portion of the Covered Code or modification must reproduce the
69114239Snjl * above Copyright Notice, and the following Disclaimer and Export Compliance
70114239Snjl * provision in the documentation and/or other materials provided with the
71114239Snjl * distribution.
72114239Snjl *
73114239Snjl * 3.4. Intel retains all right, title, and interest in and to the Original
74114239Snjl * Intel Code.
75114239Snjl *
76114239Snjl * 3.5. Neither the name Intel nor any other trademark owned or controlled by
77114239Snjl * Intel shall be used in advertising or otherwise to promote the sale, use or
78114239Snjl * other dealings in products derived from or relating to the Covered Code
79114239Snjl * without prior written authorization from Intel.
80114239Snjl *
81114239Snjl * 4. Disclaimer and Export Compliance
82114239Snjl *
83114239Snjl * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
84114239Snjl * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
85114239Snjl * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
86114239Snjl * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
87114239Snjl * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
88114239Snjl * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
89114239Snjl * PARTICULAR PURPOSE.
90114239Snjl *
91114239Snjl * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92114239Snjl * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93114239Snjl * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
94114239Snjl * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95114239Snjl * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96114239Snjl * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
97114239Snjl * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
98114239Snjl * LIMITED REMEDY.
99114239Snjl *
100114239Snjl * 4.3. Licensee shall not export, either directly or indirectly, any of this
101114239Snjl * software or system incorporating such software without first obtaining any
102114239Snjl * required license or other approval from the U. S. Department of Commerce or
103114239Snjl * any other agency or department of the United States Government.  In the
104114239Snjl * event Licensee exports any such software from the United States or
105114239Snjl * re-exports any such software from a foreign destination, Licensee shall
106114239Snjl * ensure that the distribution and export/re-export of the software is in
107114239Snjl * compliance with all laws, regulations, orders, or other restrictions of the
108114239Snjl * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109114239Snjl * any of its subsidiaries will export/re-export any technical data, process,
110114239Snjl * software, or service, directly or indirectly, to any country for which the
111114239Snjl * United States government or any agency thereof requires an export license,
112114239Snjl * other governmental approval, or letter of assurance, without first obtaining
113114239Snjl * such license, approval or letter.
114114239Snjl *
115114239Snjl *****************************************************************************/
116114239Snjl
117114239Snjl#include "acpi.h"
118114239Snjl#include "acevents.h"
119114239Snjl#include "acnamesp.h"
120114239Snjl
121114239Snjl#define _COMPONENT          ACPI_EVENTS
122114239Snjl        ACPI_MODULE_NAME    ("evgpe")
123114239Snjl
124114239Snjl
125114239Snjl/*******************************************************************************
126114239Snjl *
127114239Snjl * FUNCTION:    AcpiEvGetGpeEventInfo
128114239Snjl *
129117521Snjl * PARAMETERS:  GpeDevice           - Device node.  NULL for GPE0/GPE1
130117521Snjl *              GpeNumber           - Raw GPE number
131114239Snjl *
132117521Snjl * RETURN:      A GPE EventInfo struct.  NULL if not a valid GPE
133114239Snjl *
134117521Snjl * DESCRIPTION: Returns the EventInfo struct associated with this GPE.
135117521Snjl *              Validates the GpeBlock and the GpeNumber
136114239Snjl *
137117521Snjl *              Should be called only when the GPE lists are semaphore locked
138117521Snjl *              and not subject to change.
139114239Snjl *
140114239Snjl ******************************************************************************/
141114239Snjl
142114239SnjlACPI_GPE_EVENT_INFO *
143114239SnjlAcpiEvGetGpeEventInfo (
144117521Snjl    ACPI_HANDLE             GpeDevice,
145114239Snjl    UINT32                  GpeNumber)
146114239Snjl{
147117521Snjl    ACPI_OPERAND_OBJECT     *ObjDesc;
148114239Snjl    ACPI_GPE_BLOCK_INFO     *GpeBlock;
149117521Snjl    ACPI_NATIVE_UINT        i;
150114239Snjl
151114239Snjl
152117521Snjl    ACPI_FUNCTION_ENTRY ();
153114239Snjl
154117521Snjl
155117521Snjl    /* A NULL GpeBlock means use the FADT-defined GPE block(s) */
156117521Snjl
157117521Snjl    if (!GpeDevice)
158114239Snjl    {
159117521Snjl        /* Examine GPE Block 0 and 1 (These blocks are permanent) */
160117521Snjl
161117521Snjl        for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++)
162117521Snjl        {
163117521Snjl            GpeBlock = AcpiGbl_GpeFadtBlocks[i];
164117521Snjl            if (GpeBlock)
165117521Snjl            {
166117521Snjl                if ((GpeNumber >= GpeBlock->BlockBaseNumber) &&
167117521Snjl                    (GpeNumber < GpeBlock->BlockBaseNumber + (GpeBlock->RegisterCount * 8)))
168117521Snjl                {
169117521Snjl                    return (&GpeBlock->EventInfo[GpeNumber - GpeBlock->BlockBaseNumber]);
170117521Snjl                }
171117521Snjl            }
172117521Snjl        }
173117521Snjl
174117521Snjl        /* The GpeNumber was not in the range of either FADT GPE block */
175117521Snjl
176114239Snjl        return (NULL);
177114239Snjl    }
178114239Snjl
179117521Snjl    /*
180117521Snjl     * A Non-null GpeDevice means this is a GPE Block Device.
181117521Snjl     */
182117521Snjl    ObjDesc = AcpiNsGetAttachedObject ((ACPI_NAMESPACE_NODE *) GpeDevice);
183117521Snjl    if (!ObjDesc ||
184117521Snjl        !ObjDesc->Device.GpeBlock)
185114239Snjl    {
186117521Snjl        return (NULL);
187114239Snjl    }
188114239Snjl
189117521Snjl    GpeBlock = ObjDesc->Device.GpeBlock;
190114239Snjl
191114239Snjl    if ((GpeNumber >= GpeBlock->BlockBaseNumber) &&
192114239Snjl        (GpeNumber < GpeBlock->BlockBaseNumber + (GpeBlock->RegisterCount * 8)))
193114239Snjl    {
194114239Snjl        return (&GpeBlock->EventInfo[GpeNumber - GpeBlock->BlockBaseNumber]);
195114239Snjl    }
196114239Snjl
197114239Snjl    return (NULL);
198114239Snjl}
199114239Snjl
200117521Snjl
201114239Snjl/*******************************************************************************
202114239Snjl *
203114239Snjl * FUNCTION:    AcpiEvGpeDetect
204114239Snjl *
205117521Snjl * PARAMETERS:  GpeXruptList        - Interrupt block for this interrupt.
206117521Snjl *                                    Can have multiple GPE blocks attached.
207114239Snjl *
208114239Snjl * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
209114239Snjl *
210114239Snjl * DESCRIPTION: Detect if any GP events have occurred.  This function is
211114239Snjl *              executed at interrupt level.
212114239Snjl *
213114239Snjl ******************************************************************************/
214114239Snjl
215114239SnjlUINT32
216117521SnjlAcpiEvGpeDetect (
217117521Snjl    ACPI_GPE_XRUPT_INFO     *GpeXruptList)
218114239Snjl{
219114239Snjl    UINT32                  IntStatus = ACPI_INTERRUPT_NOT_HANDLED;
220114239Snjl    UINT8                   EnabledStatusByte;
221114239Snjl    ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
222114239Snjl    UINT32                  InValue;
223114239Snjl    ACPI_STATUS             Status;
224114239Snjl    ACPI_GPE_BLOCK_INFO     *GpeBlock;
225117521Snjl    UINT32                  i;
226117521Snjl    UINT32                  j;
227114239Snjl
228114239Snjl
229114239Snjl    ACPI_FUNCTION_NAME ("EvGpeDetect");
230114239Snjl
231114239Snjl
232114239Snjl    /* Examine all GPE blocks attached to this interrupt level */
233114239Snjl
234117521Snjl    AcpiOsAcquireLock (AcpiGbl_GpeLock, ACPI_ISR);
235117521Snjl    GpeBlock = GpeXruptList->GpeBlockListHead;
236114239Snjl    while (GpeBlock)
237114239Snjl    {
238114239Snjl        /*
239114239Snjl         * Read all of the 8-bit GPE status and enable registers
240114239Snjl         * in this GPE block, saving all of them.
241114239Snjl         * Find all currently active GP events.
242114239Snjl         */
243114239Snjl        for (i = 0; i < GpeBlock->RegisterCount; i++)
244114239Snjl        {
245114239Snjl            /* Get the next status/enable pair */
246114239Snjl
247114239Snjl            GpeRegisterInfo = &GpeBlock->RegisterInfo[i];
248114239Snjl
249117521Snjl            /* Read the Status Register */
250117521Snjl
251114239Snjl            Status = AcpiHwLowLevelRead (ACPI_GPE_REGISTER_WIDTH, &InValue,
252117521Snjl                        &GpeRegisterInfo->StatusAddress);
253114239Snjl            GpeRegisterInfo->Status = (UINT8) InValue;
254114239Snjl            if (ACPI_FAILURE (Status))
255114239Snjl            {
256117521Snjl                goto UnlockAndExit;
257114239Snjl            }
258114239Snjl
259117521Snjl            /* Read the Enable Register */
260117521Snjl
261114239Snjl            Status = AcpiHwLowLevelRead (ACPI_GPE_REGISTER_WIDTH, &InValue,
262117521Snjl                        &GpeRegisterInfo->EnableAddress);
263114239Snjl            GpeRegisterInfo->Enable = (UINT8) InValue;
264114239Snjl            if (ACPI_FAILURE (Status))
265114239Snjl            {
266117521Snjl                goto UnlockAndExit;
267114239Snjl            }
268114239Snjl
269114239Snjl            ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
270117521Snjl                "GPE pair: Status %8.8X%8.8X = %02X, Enable %8.8X%8.8X = %02X\n",
271123315Snjl                ACPI_FORMAT_UINT64 (ACPI_GET_ADDRESS (GpeRegisterInfo->StatusAddress.Address)),
272117521Snjl                GpeRegisterInfo->Status,
273123315Snjl                ACPI_FORMAT_UINT64 (ACPI_GET_ADDRESS (GpeRegisterInfo->EnableAddress.Address)),
274117521Snjl                GpeRegisterInfo->Enable));
275114239Snjl
276114239Snjl            /* First check if there is anything active at all in this register */
277114239Snjl
278114239Snjl            EnabledStatusByte = (UINT8) (GpeRegisterInfo->Status &
279114239Snjl                                         GpeRegisterInfo->Enable);
280114239Snjl            if (!EnabledStatusByte)
281114239Snjl            {
282114239Snjl                /* No active GPEs in this register, move on */
283114239Snjl
284114239Snjl                continue;
285114239Snjl            }
286114239Snjl
287114239Snjl            /* Now look at the individual GPEs in this byte register */
288114239Snjl
289123315Snjl            for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++)
290114239Snjl            {
291114239Snjl                /* Examine one GPE bit */
292114239Snjl
293123315Snjl                if (EnabledStatusByte & AcpiGbl_DecodeTo8bit[j])
294114239Snjl                {
295114239Snjl                    /*
296114239Snjl                     * Found an active GPE. Dispatch the event to a handler
297114239Snjl                     * or method.
298114239Snjl                     */
299114239Snjl                    IntStatus |= AcpiEvGpeDispatch (
300123315Snjl                                    &GpeBlock->EventInfo[(i * ACPI_GPE_REGISTER_WIDTH) + j],
301123315Snjl                                    j + GpeRegisterInfo->BaseGpeNumber);
302114239Snjl                }
303114239Snjl            }
304114239Snjl        }
305114239Snjl
306114239Snjl        GpeBlock = GpeBlock->Next;
307114239Snjl    }
308114239Snjl
309117521SnjlUnlockAndExit:
310117521Snjl
311117521Snjl    AcpiOsReleaseLock (AcpiGbl_GpeLock, ACPI_ISR);
312114239Snjl    return (IntStatus);
313114239Snjl}
314114239Snjl
315114239Snjl
316114239Snjl/*******************************************************************************
317114239Snjl *
318114239Snjl * FUNCTION:    AcpiEvAsynchExecuteGpeMethod
319114239Snjl *
320117521Snjl * PARAMETERS:  Context (GpeEventInfo) - Info for this GPE
321114239Snjl *
322114239Snjl * RETURN:      None
323114239Snjl *
324114239Snjl * DESCRIPTION: Perform the actual execution of a GPE control method.  This
325114239Snjl *              function is called from an invocation of AcpiOsQueueForExecution
326114239Snjl *              (and therefore does NOT execute at interrupt level) so that
327114239Snjl *              the control method itself is not executed in the context of
328117521Snjl *              an interrupt handler.
329114239Snjl *
330114239Snjl ******************************************************************************/
331114239Snjl
332114239Snjlstatic void ACPI_SYSTEM_XFACE
333114239SnjlAcpiEvAsynchExecuteGpeMethod (
334114239Snjl    void                    *Context)
335114239Snjl{
336114239Snjl    ACPI_GPE_EVENT_INFO     *GpeEventInfo = (void *) Context;
337114239Snjl    UINT32                  GpeNumber = 0;
338114239Snjl    ACPI_STATUS             Status;
339117521Snjl    ACPI_GPE_EVENT_INFO     LocalGpeEventInfo;
340114239Snjl
341114239Snjl
342114239Snjl    ACPI_FUNCTION_TRACE ("EvAsynchExecuteGpeMethod");
343114239Snjl
344114239Snjl
345114239Snjl    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
346114239Snjl    if (ACPI_FAILURE (Status))
347114239Snjl    {
348114239Snjl        return_VOID;
349114239Snjl    }
350114239Snjl
351117521Snjl    /* Must revalidate the GpeNumber/GpeBlock */
352117521Snjl
353117521Snjl    if (!AcpiEvValidGpeEvent (GpeEventInfo))
354117521Snjl    {
355117521Snjl        Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
356117521Snjl        return_VOID;
357117521Snjl    }
358117521Snjl
359117521Snjl    /*
360117521Snjl     * Take a snapshot of the GPE info for this level - we copy the
361117521Snjl     * info to prevent a race condition with RemoveHandler/RemoveBlock.
362117521Snjl     */
363117521Snjl    ACPI_MEMCPY (&LocalGpeEventInfo, GpeEventInfo, sizeof (ACPI_GPE_EVENT_INFO));
364117521Snjl
365114239Snjl    Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
366114239Snjl    if (ACPI_FAILURE (Status))
367114239Snjl    {
368114239Snjl        return_VOID;
369114239Snjl    }
370114239Snjl
371117521Snjl    if (LocalGpeEventInfo.MethodNode)
372114239Snjl    {
373114239Snjl        /*
374114239Snjl         * Invoke the GPE Method (_Lxx, _Exx):
375114239Snjl         * (Evaluate the _Lxx/_Exx control method that corresponds to this GPE.)
376114239Snjl         */
377117521Snjl        Status = AcpiNsEvaluateByHandle (LocalGpeEventInfo.MethodNode, NULL, NULL);
378114239Snjl        if (ACPI_FAILURE (Status))
379114239Snjl        {
380117521Snjl            ACPI_REPORT_ERROR (("%s while evaluating method [%4.4s] for GPE[%2X]\n",
381114239Snjl                AcpiFormatException (Status),
382123315Snjl                AcpiUtGetNodeName (LocalGpeEventInfo.MethodNode), GpeNumber));
383114239Snjl        }
384114239Snjl    }
385114239Snjl
386117521Snjl    if (LocalGpeEventInfo.Flags & ACPI_EVENT_LEVEL_TRIGGERED)
387114239Snjl    {
388114239Snjl        /*
389114239Snjl         * GPE is level-triggered, we clear the GPE status bit after handling
390114239Snjl         * the event.
391114239Snjl         */
392117521Snjl        Status = AcpiHwClearGpe (&LocalGpeEventInfo);
393114239Snjl        if (ACPI_FAILURE (Status))
394114239Snjl        {
395114239Snjl            return_VOID;
396114239Snjl        }
397114239Snjl    }
398114239Snjl
399114239Snjl    /* Enable this GPE */
400114239Snjl
401117521Snjl    (void) AcpiHwEnableGpe (&LocalGpeEventInfo);
402114239Snjl    return_VOID;
403114239Snjl}
404114239Snjl
405114239Snjl
406114239Snjl/*******************************************************************************
407114239Snjl *
408114239Snjl * FUNCTION:    AcpiEvGpeDispatch
409114239Snjl *
410117521Snjl * PARAMETERS:  GpeEventInfo    - info for this GPE
411117521Snjl *              GpeNumber       - Number relative to the parent GPE block
412114239Snjl *
413114239Snjl * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
414114239Snjl *
415114239Snjl * DESCRIPTION: Dispatch a General Purpose Event to either a function (e.g. EC)
416117521Snjl *              or method (e.g. _Lxx/_Exx) handler.
417114239Snjl *
418117521Snjl *              This function executes at interrupt level.
419117521Snjl *
420114239Snjl ******************************************************************************/
421114239Snjl
422114239SnjlUINT32
423114239SnjlAcpiEvGpeDispatch (
424117521Snjl    ACPI_GPE_EVENT_INFO     *GpeEventInfo,
425117521Snjl    UINT32                  GpeNumber)
426114239Snjl{
427114239Snjl    ACPI_STATUS             Status;
428114239Snjl
429114239Snjl
430114239Snjl    ACPI_FUNCTION_TRACE ("EvGpeDispatch");
431114239Snjl
432114239Snjl
433114239Snjl    /*
434114239Snjl     * If edge-triggered, clear the GPE status bit now.  Note that
435114239Snjl     * level-triggered events are cleared after the GPE is serviced.
436114239Snjl     */
437117521Snjl    if (GpeEventInfo->Flags & ACPI_EVENT_EDGE_TRIGGERED)
438114239Snjl    {
439114239Snjl        Status = AcpiHwClearGpe (GpeEventInfo);
440114239Snjl        if (ACPI_FAILURE (Status))
441114239Snjl        {
442117521Snjl            ACPI_REPORT_ERROR (("AcpiEvGpeDispatch: Unable to clear GPE[%2X]\n",
443114239Snjl                GpeNumber));
444114239Snjl            return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
445114239Snjl        }
446114239Snjl    }
447114239Snjl
448114239Snjl    /*
449114239Snjl     * Dispatch the GPE to either an installed handler, or the control
450114239Snjl     * method associated with this GPE (_Lxx or _Exx).
451114239Snjl     * If a handler exists, we invoke it and do not attempt to run the method.
452114239Snjl     * If there is neither a handler nor a method, we disable the level to
453114239Snjl     * prevent further events from coming in here.
454114239Snjl     */
455114239Snjl    if (GpeEventInfo->Handler)
456114239Snjl    {
457114239Snjl        /* Invoke the installed handler (at interrupt level) */
458114239Snjl
459114239Snjl        GpeEventInfo->Handler (GpeEventInfo->Context);
460123315Snjl
461123315Snjl        /* It is now safe to clear level-triggered events. */
462123315Snjl
463123315Snjl        if (GpeEventInfo->Flags & ACPI_EVENT_LEVEL_TRIGGERED)
464123315Snjl        {
465123315Snjl            Status = AcpiHwClearGpe (GpeEventInfo);
466123315Snjl            if (ACPI_FAILURE (Status))
467123315Snjl            {
468123315Snjl                ACPI_REPORT_ERROR ((
469123315Snjl                    "AcpiEvGpeDispatch: Unable to clear GPE[%2X]\n",
470123315Snjl                    GpeNumber));
471123315Snjl                return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
472123315Snjl            }
473123315Snjl        }
474114239Snjl    }
475114239Snjl    else if (GpeEventInfo->MethodNode)
476114239Snjl    {
477114239Snjl        /*
478114239Snjl         * Disable GPE, so it doesn't keep firing before the method has a
479114239Snjl         * chance to run.
480114239Snjl         */
481114239Snjl        Status = AcpiHwDisableGpe (GpeEventInfo);
482114239Snjl        if (ACPI_FAILURE (Status))
483114239Snjl        {
484123315Snjl            ACPI_REPORT_ERROR ((
485123315Snjl                "AcpiEvGpeDispatch: Unable to disable GPE[%2X]\n",
486114239Snjl                GpeNumber));
487114239Snjl            return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
488114239Snjl        }
489114239Snjl
490126372Snjl        /*
491123315Snjl         * Execute the method associated with the GPE
492123315Snjl         * NOTE: Level-triggered GPEs are cleared after the method completes.
493123315Snjl         */
494114239Snjl        if (ACPI_FAILURE (AcpiOsQueueForExecution (OSD_PRIORITY_GPE,
495114239Snjl                                AcpiEvAsynchExecuteGpeMethod,
496114239Snjl                                GpeEventInfo)))
497114239Snjl        {
498114239Snjl            ACPI_REPORT_ERROR ((
499117521Snjl                "AcpiEvGpeDispatch: Unable to queue handler for GPE[%2X], event is disabled\n",
500114239Snjl                GpeNumber));
501114239Snjl        }
502114239Snjl    }
503114239Snjl    else
504114239Snjl    {
505114239Snjl        /* No handler or method to run! */
506114239Snjl
507114239Snjl        ACPI_REPORT_ERROR ((
508117521Snjl            "AcpiEvGpeDispatch: No handler or method for GPE[%2X], disabling event\n",
509114239Snjl            GpeNumber));
510114239Snjl
511114239Snjl        /*
512114239Snjl         * Disable the GPE.  The GPE will remain disabled until the ACPI
513123315Snjl         * Core Subsystem is restarted, or a handler is installed.
514114239Snjl         */
515114239Snjl        Status = AcpiHwDisableGpe (GpeEventInfo);
516114239Snjl        if (ACPI_FAILURE (Status))
517114239Snjl        {
518123315Snjl            ACPI_REPORT_ERROR ((
519123315Snjl                "AcpiEvGpeDispatch: Unable to disable GPE[%2X]\n",
520114239Snjl                GpeNumber));
521114239Snjl            return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
522114239Snjl        }
523114239Snjl    }
524114239Snjl
525114239Snjl    return_VALUE (ACPI_INTERRUPT_HANDLED);
526114239Snjl}
527114239Snjl
528