evgpe.c revision 206117
1114239Snjl/******************************************************************************
2114239Snjl *
3114239Snjl * Module Name: evgpe - General Purpose Event handling and dispatch
4114239Snjl *
5114239Snjl *****************************************************************************/
6114239Snjl
7114239Snjl/******************************************************************************
8114239Snjl *
9114239Snjl * 1. Copyright Notice
10114239Snjl *
11202771Sjkim * Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp.
12114239Snjl * All rights reserved.
13114239Snjl *
14114239Snjl * 2. License
15114239Snjl *
16114239Snjl * 2.1. This is your license from Intel Corp. under its intellectual property
17114239Snjl * rights.  You may have additional license terms from the party that provided
18114239Snjl * you this software, covering your right to use that party's intellectual
19114239Snjl * property rights.
20114239Snjl *
21114239Snjl * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22114239Snjl * copy of the source code appearing in this file ("Covered Code") an
23114239Snjl * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24114239Snjl * base code distributed originally by Intel ("Original Intel Code") to copy,
25114239Snjl * make derivatives, distribute, use and display any portion of the Covered
26114239Snjl * Code in any form, with the right to sublicense such rights; and
27114239Snjl *
28114239Snjl * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29114239Snjl * license (with the right to sublicense), under only those claims of Intel
30114239Snjl * patents that are infringed by the Original Intel Code, to make, use, sell,
31114239Snjl * offer to sell, and import the Covered Code and derivative works thereof
32114239Snjl * solely to the minimum extent necessary to exercise the above copyright
33114239Snjl * license, and in no event shall the patent license extend to any additions
34114239Snjl * to or modifications of the Original Intel Code.  No other license or right
35114239Snjl * is granted directly or by implication, estoppel or otherwise;
36114239Snjl *
37114239Snjl * The above copyright and patent license is granted only if the following
38114239Snjl * conditions are met:
39114239Snjl *
40114239Snjl * 3. Conditions
41114239Snjl *
42114239Snjl * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43114239Snjl * Redistribution of source code of any substantial portion of the Covered
44114239Snjl * Code or modification with rights to further distribute source must include
45114239Snjl * the above Copyright Notice, the above License, this list of Conditions,
46114239Snjl * and the following Disclaimer and Export Compliance provision.  In addition,
47114239Snjl * Licensee must cause all Covered Code to which Licensee contributes to
48114239Snjl * contain a file documenting the changes Licensee made to create that Covered
49114239Snjl * Code and the date of any change.  Licensee must include in that file the
50114239Snjl * documentation of any changes made by any predecessor Licensee.  Licensee
51114239Snjl * must include a prominent statement that the modification is derived,
52114239Snjl * directly or indirectly, from Original Intel Code.
53114239Snjl *
54114239Snjl * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55114239Snjl * Redistribution of source code of any substantial portion of the Covered
56114239Snjl * Code or modification without rights to further distribute source must
57114239Snjl * include the following Disclaimer and Export Compliance provision in the
58114239Snjl * documentation and/or other materials provided with distribution.  In
59114239Snjl * addition, Licensee may not authorize further sublicense of source of any
60114239Snjl * portion of the Covered Code, and must include terms to the effect that the
61114239Snjl * license from Licensee to its licensee is limited to the intellectual
62114239Snjl * property embodied in the software Licensee provides to its licensee, and
63114239Snjl * not to intellectual property embodied in modifications its licensee may
64114239Snjl * make.
65114239Snjl *
66114239Snjl * 3.3. Redistribution of Executable. Redistribution in executable form of any
67114239Snjl * substantial portion of the Covered Code or modification must reproduce the
68114239Snjl * above Copyright Notice, and the following Disclaimer and Export Compliance
69114239Snjl * provision in the documentation and/or other materials provided with the
70114239Snjl * distribution.
71114239Snjl *
72114239Snjl * 3.4. Intel retains all right, title, and interest in and to the Original
73114239Snjl * Intel Code.
74114239Snjl *
75114239Snjl * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76114239Snjl * Intel shall be used in advertising or otherwise to promote the sale, use or
77114239Snjl * other dealings in products derived from or relating to the Covered Code
78114239Snjl * without prior written authorization from Intel.
79114239Snjl *
80114239Snjl * 4. Disclaimer and Export Compliance
81114239Snjl *
82114239Snjl * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83114239Snjl * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84114239Snjl * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
85114239Snjl * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
86114239Snjl * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
87114239Snjl * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88114239Snjl * PARTICULAR PURPOSE.
89114239Snjl *
90114239Snjl * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91114239Snjl * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92114239Snjl * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93114239Snjl * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94114239Snjl * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95114239Snjl * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
96114239Snjl * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97114239Snjl * LIMITED REMEDY.
98114239Snjl *
99114239Snjl * 4.3. Licensee shall not export, either directly or indirectly, any of this
100114239Snjl * software or system incorporating such software without first obtaining any
101114239Snjl * required license or other approval from the U. S. Department of Commerce or
102114239Snjl * any other agency or department of the United States Government.  In the
103114239Snjl * event Licensee exports any such software from the United States or
104114239Snjl * re-exports any such software from a foreign destination, Licensee shall
105114239Snjl * ensure that the distribution and export/re-export of the software is in
106114239Snjl * compliance with all laws, regulations, orders, or other restrictions of the
107114239Snjl * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108114239Snjl * any of its subsidiaries will export/re-export any technical data, process,
109114239Snjl * software, or service, directly or indirectly, to any country for which the
110114239Snjl * United States government or any agency thereof requires an export license,
111114239Snjl * other governmental approval, or letter of assurance, without first obtaining
112114239Snjl * such license, approval or letter.
113114239Snjl *
114114239Snjl *****************************************************************************/
115114239Snjl
116193341Sjkim#include <contrib/dev/acpica/include/acpi.h>
117193341Sjkim#include <contrib/dev/acpica/include/accommon.h>
118193341Sjkim#include <contrib/dev/acpica/include/acevents.h>
119193341Sjkim#include <contrib/dev/acpica/include/acnamesp.h>
120114239Snjl
121114239Snjl#define _COMPONENT          ACPI_EVENTS
122114239Snjl        ACPI_MODULE_NAME    ("evgpe")
123114239Snjl
124151937Sjkim/* Local prototypes */
125114239Snjl
126193267Sjkimstatic void ACPI_SYSTEM_XFACE
127193267SjkimAcpiEvAsynchExecuteGpeMethod (
128175256Snjl    void                    *Context);
129175256Snjl
130151937Sjkimstatic void ACPI_SYSTEM_XFACE
131193267SjkimAcpiEvAsynchEnableGpe (
132151937Sjkim    void                    *Context);
133151937Sjkim
134151937Sjkim
135114239Snjl/*******************************************************************************
136114239Snjl *
137129684Snjl * FUNCTION:    AcpiEvUpdateGpeEnableMasks
138129684Snjl *
139129684Snjl * PARAMETERS:  GpeEventInfo            - GPE to update
140129684Snjl *
141129684Snjl * RETURN:      Status
142129684Snjl *
143206117Sjkim * DESCRIPTION: Updates GPE register enable masks based upon whether there are
144206117Sjkim *              references (either wake or run) to this GPE
145129684Snjl *
146129684Snjl ******************************************************************************/
147129684Snjl
148129684SnjlACPI_STATUS
149129684SnjlAcpiEvUpdateGpeEnableMasks (
150206117Sjkim    ACPI_GPE_EVENT_INFO     *GpeEventInfo)
151129684Snjl{
152129684Snjl    ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
153129684Snjl    UINT8                   RegisterBit;
154129684Snjl
155129684Snjl
156167802Sjkim    ACPI_FUNCTION_TRACE (EvUpdateGpeEnableMasks);
157129684Snjl
158129684Snjl
159129684Snjl    GpeRegisterInfo = GpeEventInfo->RegisterInfo;
160129684Snjl    if (!GpeRegisterInfo)
161129684Snjl    {
162129684Snjl        return_ACPI_STATUS (AE_NOT_EXIST);
163129684Snjl    }
164193267Sjkim
165167802Sjkim    RegisterBit = (UINT8)
166167802Sjkim        (1 << (GpeEventInfo->GpeNumber - GpeRegisterInfo->BaseGpeNumber));
167129684Snjl
168206117Sjkim    /* Clear the wake/run bits up front */
169129684Snjl
170206117Sjkim    ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, RegisterBit);
171206117Sjkim    ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForRun, RegisterBit);
172206117Sjkim
173206117Sjkim    /* Set the mask bits only if there are references to this GPE */
174206117Sjkim
175206117Sjkim    if (GpeEventInfo->RuntimeCount)
176129684Snjl    {
177206117Sjkim        ACPI_SET_BIT (GpeRegisterInfo->EnableForRun, RegisterBit);
178129684Snjl    }
179129684Snjl
180206117Sjkim    if (GpeEventInfo->WakeupCount)
181129684Snjl    {
182206117Sjkim        ACPI_SET_BIT (GpeRegisterInfo->EnableForWake, RegisterBit);
183129684Snjl    }
184129684Snjl
185129684Snjl    return_ACPI_STATUS (AE_OK);
186129684Snjl}
187129684Snjl
188129684Snjl
189129684Snjl/*******************************************************************************
190129684Snjl *
191129684Snjl * FUNCTION:    AcpiEvEnableGpe
192129684Snjl *
193129684Snjl * PARAMETERS:  GpeEventInfo            - GPE to enable
194129684Snjl *
195129684Snjl * RETURN:      Status
196129684Snjl *
197206117Sjkim * DESCRIPTION: Hardware-enable a GPE. Always enables the GPE, regardless
198206117Sjkim *              of type or number of references.
199129684Snjl *
200206117Sjkim * Note: The GPE lock should be already acquired when this function is called.
201206117Sjkim *
202129684Snjl ******************************************************************************/
203129684Snjl
204129684SnjlACPI_STATUS
205129684SnjlAcpiEvEnableGpe (
206206117Sjkim    ACPI_GPE_EVENT_INFO     *GpeEventInfo)
207129684Snjl{
208129684Snjl    ACPI_STATUS             Status;
209129684Snjl
210129684Snjl
211167802Sjkim    ACPI_FUNCTION_TRACE (EvEnableGpe);
212129684Snjl
213129684Snjl
214206117Sjkim    /*
215206117Sjkim     * We will only allow a GPE to be enabled if it has either an
216206117Sjkim     * associated method (_Lxx/_Exx) or a handler. Otherwise, the
217206117Sjkim     * GPE will be immediately disabled by AcpiEvGpeDispatch the
218206117Sjkim     * first time it fires.
219206117Sjkim     */
220206117Sjkim    if (!(GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK))
221206117Sjkim    {
222206117Sjkim        return_ACPI_STATUS (AE_NO_HANDLER);
223206117Sjkim    }
224129684Snjl
225206117Sjkim    /* Ensure the HW enable masks are current */
226206117Sjkim
227206117Sjkim    Status = AcpiEvUpdateGpeEnableMasks (GpeEventInfo);
228129684Snjl    if (ACPI_FAILURE (Status))
229129684Snjl    {
230129684Snjl        return_ACPI_STATUS (Status);
231129684Snjl    }
232129684Snjl
233206117Sjkim    /* Clear the GPE (of stale events) */
234129684Snjl
235206117Sjkim    Status = AcpiHwClearGpe (GpeEventInfo);
236206117Sjkim    if (ACPI_FAILURE (Status))
237129684Snjl    {
238206117Sjkim        return_ACPI_STATUS (Status);
239206117Sjkim    }
240131440Smarks
241206117Sjkim    /* Enable the requested GPE */
242129684Snjl
243206117Sjkim    Status = AcpiHwWriteGpeEnableReg (GpeEventInfo);
244206117Sjkim    return_ACPI_STATUS (Status);
245129684Snjl}
246129684Snjl
247129684Snjl
248129684Snjl/*******************************************************************************
249129684Snjl *
250129684Snjl * FUNCTION:    AcpiEvDisableGpe
251129684Snjl *
252129684Snjl * PARAMETERS:  GpeEventInfo            - GPE to disable
253129684Snjl *
254129684Snjl * RETURN:      Status
255129684Snjl *
256206117Sjkim * DESCRIPTION: Hardware-disable a GPE. Always disables the requested GPE,
257206117Sjkim *              regardless of the type or number of references.
258129684Snjl *
259206117Sjkim * Note: The GPE lock should be already acquired when this function is called.
260206117Sjkim *
261129684Snjl ******************************************************************************/
262129684Snjl
263129684SnjlACPI_STATUS
264129684SnjlAcpiEvDisableGpe (
265129684Snjl    ACPI_GPE_EVENT_INFO     *GpeEventInfo)
266129684Snjl{
267129684Snjl    ACPI_STATUS             Status;
268129684Snjl
269129684Snjl
270167802Sjkim    ACPI_FUNCTION_TRACE (EvDisableGpe);
271129684Snjl
272129684Snjl
273193267Sjkim    /*
274193267Sjkim     * Note: Always disable the GPE, even if we think that that it is already
275193267Sjkim     * disabled. It is possible that the AML or some other code has enabled
276193267Sjkim     * the GPE behind our back.
277193267Sjkim     */
278129684Snjl
279206117Sjkim    /* Ensure the HW enable masks are current */
280129684Snjl
281206117Sjkim    Status = AcpiEvUpdateGpeEnableMasks (GpeEventInfo);
282129684Snjl    if (ACPI_FAILURE (Status))
283129684Snjl    {
284129684Snjl        return_ACPI_STATUS (Status);
285129684Snjl    }
286129684Snjl
287193267Sjkim    /*
288193267Sjkim     * Always H/W disable this GPE, even if we don't know the GPE type.
289193267Sjkim     * Simply clear the enable bit for this particular GPE, but do not
290193267Sjkim     * write out the current GPE enable mask since this may inadvertently
291193267Sjkim     * enable GPEs too early. An example is a rogue GPE that has arrived
292193267Sjkim     * during ACPICA initialization - possibly because AML or other code
293193267Sjkim     * has enabled the GPE.
294193267Sjkim     */
295193267Sjkim    Status = AcpiHwLowDisableGpe (GpeEventInfo);
296193267Sjkim    return_ACPI_STATUS (Status);
297129684Snjl}
298129684Snjl
299129684Snjl
300129684Snjl/*******************************************************************************
301129684Snjl *
302206117Sjkim * FUNCTION:    AcpiEvLowGetGpeInfo
303206117Sjkim *
304206117Sjkim * PARAMETERS:  GpeNumber           - Raw GPE number
305206117Sjkim *              GpeBlock            - A GPE info block
306206117Sjkim *
307206117Sjkim * RETURN:      A GPE EventInfo struct. NULL if not a valid GPE (The GpeNumber
308206117Sjkim *              is not within the specified GPE block)
309206117Sjkim *
310206117Sjkim * DESCRIPTION: Returns the EventInfo struct associated with this GPE. This is
311206117Sjkim *              the low-level implementation of EvGetGpeEventInfo.
312206117Sjkim *
313206117Sjkim ******************************************************************************/
314206117Sjkim
315206117SjkimACPI_GPE_EVENT_INFO *
316206117SjkimAcpiEvLowGetGpeInfo (
317206117Sjkim    UINT32                  GpeNumber,
318206117Sjkim    ACPI_GPE_BLOCK_INFO     *GpeBlock)
319206117Sjkim{
320206117Sjkim    UINT32                  GpeIndex;
321206117Sjkim
322206117Sjkim
323206117Sjkim    /*
324206117Sjkim     * Validate that the GpeNumber is within the specified GpeBlock.
325206117Sjkim     * (Two steps)
326206117Sjkim     */
327206117Sjkim    if (!GpeBlock ||
328206117Sjkim        (GpeNumber < GpeBlock->BlockBaseNumber))
329206117Sjkim    {
330206117Sjkim        return (NULL);
331206117Sjkim    }
332206117Sjkim
333206117Sjkim    GpeIndex = GpeNumber - GpeBlock->BlockBaseNumber;
334206117Sjkim    if (GpeIndex >= GpeBlock->GpeCount)
335206117Sjkim    {
336206117Sjkim        return (NULL);
337206117Sjkim    }
338206117Sjkim
339206117Sjkim    return (&GpeBlock->EventInfo[GpeIndex]);
340206117Sjkim}
341206117Sjkim
342206117Sjkim
343206117Sjkim/*******************************************************************************
344206117Sjkim *
345114239Snjl * FUNCTION:    AcpiEvGetGpeEventInfo
346114239Snjl *
347193267Sjkim * PARAMETERS:  GpeDevice           - Device node. NULL for GPE0/GPE1
348117521Snjl *              GpeNumber           - Raw GPE number
349114239Snjl *
350193267Sjkim * RETURN:      A GPE EventInfo struct. NULL if not a valid GPE
351114239Snjl *
352117521Snjl * DESCRIPTION: Returns the EventInfo struct associated with this GPE.
353117521Snjl *              Validates the GpeBlock and the GpeNumber
354114239Snjl *
355117521Snjl *              Should be called only when the GPE lists are semaphore locked
356117521Snjl *              and not subject to change.
357114239Snjl *
358114239Snjl ******************************************************************************/
359114239Snjl
360114239SnjlACPI_GPE_EVENT_INFO *
361114239SnjlAcpiEvGetGpeEventInfo (
362117521Snjl    ACPI_HANDLE             GpeDevice,
363114239Snjl    UINT32                  GpeNumber)
364114239Snjl{
365117521Snjl    ACPI_OPERAND_OBJECT     *ObjDesc;
366206117Sjkim    ACPI_GPE_EVENT_INFO     *GpeInfo;
367193267Sjkim    UINT32                  i;
368114239Snjl
369114239Snjl
370117521Snjl    ACPI_FUNCTION_ENTRY ();
371114239Snjl
372117521Snjl
373117521Snjl    /* A NULL GpeBlock means use the FADT-defined GPE block(s) */
374117521Snjl
375117521Snjl    if (!GpeDevice)
376114239Snjl    {
377117521Snjl        /* Examine GPE Block 0 and 1 (These blocks are permanent) */
378117521Snjl
379117521Snjl        for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++)
380117521Snjl        {
381206117Sjkim            GpeInfo = AcpiEvLowGetGpeInfo (GpeNumber,
382206117Sjkim                        AcpiGbl_GpeFadtBlocks[i]);
383206117Sjkim            if (GpeInfo)
384117521Snjl            {
385206117Sjkim                return (GpeInfo);
386117521Snjl            }
387117521Snjl        }
388117521Snjl
389117521Snjl        /* The GpeNumber was not in the range of either FADT GPE block */
390117521Snjl
391114239Snjl        return (NULL);
392114239Snjl    }
393114239Snjl
394128212Snjl    /* A Non-NULL GpeDevice means this is a GPE Block Device */
395128212Snjl
396117521Snjl    ObjDesc = AcpiNsGetAttachedObject ((ACPI_NAMESPACE_NODE *) GpeDevice);
397117521Snjl    if (!ObjDesc ||
398117521Snjl        !ObjDesc->Device.GpeBlock)
399114239Snjl    {
400117521Snjl        return (NULL);
401114239Snjl    }
402114239Snjl
403206117Sjkim    return (AcpiEvLowGetGpeInfo (GpeNumber, ObjDesc->Device.GpeBlock));
404114239Snjl}
405114239Snjl
406117521Snjl
407114239Snjl/*******************************************************************************
408114239Snjl *
409114239Snjl * FUNCTION:    AcpiEvGpeDetect
410114239Snjl *
411117521Snjl * PARAMETERS:  GpeXruptList        - Interrupt block for this interrupt.
412117521Snjl *                                    Can have multiple GPE blocks attached.
413114239Snjl *
414114239Snjl * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
415114239Snjl *
416193267Sjkim * DESCRIPTION: Detect if any GP events have occurred. This function is
417114239Snjl *              executed at interrupt level.
418114239Snjl *
419114239Snjl ******************************************************************************/
420114239Snjl
421114239SnjlUINT32
422117521SnjlAcpiEvGpeDetect (
423117521Snjl    ACPI_GPE_XRUPT_INFO     *GpeXruptList)
424114239Snjl{
425151937Sjkim    ACPI_STATUS             Status;
426151937Sjkim    ACPI_GPE_BLOCK_INFO     *GpeBlock;
427151937Sjkim    ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
428114239Snjl    UINT32                  IntStatus = ACPI_INTERRUPT_NOT_HANDLED;
429114239Snjl    UINT8                   EnabledStatusByte;
430129684Snjl    UINT32                  StatusReg;
431129684Snjl    UINT32                  EnableReg;
432167802Sjkim    ACPI_CPU_FLAGS          Flags;
433193267Sjkim    UINT32                  i;
434193267Sjkim    UINT32                  j;
435114239Snjl
436114239Snjl
437167802Sjkim    ACPI_FUNCTION_NAME (EvGpeDetect);
438114239Snjl
439127175Snjl    /* Check for the case where there are no GPEs */
440114239Snjl
441127175Snjl    if (!GpeXruptList)
442127175Snjl    {
443127175Snjl        return (IntStatus);
444127175Snjl    }
445127175Snjl
446167802Sjkim    /*
447167802Sjkim     * We need to obtain the GPE lock for both the data structs and registers
448193267Sjkim     * Note: Not necessary to obtain the hardware lock, since the GPE
449193267Sjkim     * registers are owned by the GpeLock.
450167802Sjkim     */
451167802Sjkim    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
452167802Sjkim
453114239Snjl    /* Examine all GPE blocks attached to this interrupt level */
454114239Snjl
455117521Snjl    GpeBlock = GpeXruptList->GpeBlockListHead;
456114239Snjl    while (GpeBlock)
457114239Snjl    {
458114239Snjl        /*
459193267Sjkim         * Read all of the 8-bit GPE status and enable registers in this GPE
460193267Sjkim         * block, saving all of them. Find all currently active GP events.
461114239Snjl         */
462114239Snjl        for (i = 0; i < GpeBlock->RegisterCount; i++)
463114239Snjl        {
464114239Snjl            /* Get the next status/enable pair */
465114239Snjl
466114239Snjl            GpeRegisterInfo = &GpeBlock->RegisterInfo[i];
467114239Snjl
468117521Snjl            /* Read the Status Register */
469117521Snjl
470197104Sjkim            Status = AcpiHwRead (&StatusReg, &GpeRegisterInfo->StatusAddress);
471114239Snjl            if (ACPI_FAILURE (Status))
472114239Snjl            {
473117521Snjl                goto UnlockAndExit;
474114239Snjl            }
475114239Snjl
476117521Snjl            /* Read the Enable Register */
477117521Snjl
478197104Sjkim            Status = AcpiHwRead (&EnableReg, &GpeRegisterInfo->EnableAddress);
479114239Snjl            if (ACPI_FAILURE (Status))
480114239Snjl            {
481117521Snjl                goto UnlockAndExit;
482114239Snjl            }
483114239Snjl
484114239Snjl            ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
485138287Smarks                "Read GPE Register at GPE%X: Status=%02X, Enable=%02X\n",
486138287Smarks                GpeRegisterInfo->BaseGpeNumber, StatusReg, EnableReg));
487114239Snjl
488151937Sjkim            /* Check if there is anything active at all in this register */
489114239Snjl
490129684Snjl            EnabledStatusByte = (UINT8) (StatusReg & EnableReg);
491114239Snjl            if (!EnabledStatusByte)
492114239Snjl            {
493114239Snjl                /* No active GPEs in this register, move on */
494114239Snjl
495114239Snjl                continue;
496114239Snjl            }
497114239Snjl
498114239Snjl            /* Now look at the individual GPEs in this byte register */
499114239Snjl
500123315Snjl            for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++)
501114239Snjl            {
502114239Snjl                /* Examine one GPE bit */
503114239Snjl
504167802Sjkim                if (EnabledStatusByte & (1 << j))
505114239Snjl                {
506114239Snjl                    /*
507114239Snjl                     * Found an active GPE. Dispatch the event to a handler
508114239Snjl                     * or method.
509114239Snjl                     */
510114239Snjl                    IntStatus |= AcpiEvGpeDispatch (
511193267Sjkim                        &GpeBlock->EventInfo[((ACPI_SIZE) i *
512193267Sjkim                            ACPI_GPE_REGISTER_WIDTH) + j],
513193267Sjkim                        j + GpeRegisterInfo->BaseGpeNumber);
514114239Snjl                }
515114239Snjl            }
516114239Snjl        }
517114239Snjl
518114239Snjl        GpeBlock = GpeBlock->Next;
519114239Snjl    }
520114239Snjl
521117521SnjlUnlockAndExit:
522117521Snjl
523151937Sjkim    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
524114239Snjl    return (IntStatus);
525114239Snjl}
526114239Snjl
527114239Snjl
528114239Snjl/*******************************************************************************
529114239Snjl *
530114239Snjl * FUNCTION:    AcpiEvAsynchExecuteGpeMethod
531114239Snjl *
532117521Snjl * PARAMETERS:  Context (GpeEventInfo) - Info for this GPE
533114239Snjl *
534114239Snjl * RETURN:      None
535114239Snjl *
536167802Sjkim * DESCRIPTION: Perform the actual execution of a GPE control method. This
537167802Sjkim *              function is called from an invocation of AcpiOsExecute and
538167802Sjkim *              therefore does NOT execute at interrupt level - so that
539114239Snjl *              the control method itself is not executed in the context of
540117521Snjl *              an interrupt handler.
541114239Snjl *
542114239Snjl ******************************************************************************/
543114239Snjl
544114239Snjlstatic void ACPI_SYSTEM_XFACE
545114239SnjlAcpiEvAsynchExecuteGpeMethod (
546114239Snjl    void                    *Context)
547114239Snjl{
548193267Sjkim    ACPI_GPE_EVENT_INFO     *GpeEventInfo = Context;
549114239Snjl    ACPI_STATUS             Status;
550193267Sjkim    ACPI_GPE_EVENT_INFO     *LocalGpeEventInfo;
551167802Sjkim    ACPI_EVALUATE_INFO      *Info;
552114239Snjl
553114239Snjl
554167802Sjkim    ACPI_FUNCTION_TRACE (EvAsynchExecuteGpeMethod);
555114239Snjl
556114239Snjl
557193267Sjkim    /* Allocate a local GPE block */
558193267Sjkim
559193267Sjkim    LocalGpeEventInfo = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_EVENT_INFO));
560193267Sjkim    if (!LocalGpeEventInfo)
561193267Sjkim    {
562193267Sjkim        ACPI_EXCEPTION ((AE_INFO, AE_NO_MEMORY,
563193267Sjkim            "while handling a GPE"));
564193267Sjkim        return_VOID;
565193267Sjkim    }
566193267Sjkim
567114239Snjl    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
568114239Snjl    if (ACPI_FAILURE (Status))
569114239Snjl    {
570114239Snjl        return_VOID;
571114239Snjl    }
572114239Snjl
573117521Snjl    /* Must revalidate the GpeNumber/GpeBlock */
574117521Snjl
575117521Snjl    if (!AcpiEvValidGpeEvent (GpeEventInfo))
576117521Snjl    {
577117521Snjl        Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
578117521Snjl        return_VOID;
579117521Snjl    }
580117521Snjl
581206117Sjkim    /* Update the GPE register masks for return to enabled state */
582129684Snjl
583206117Sjkim    (void) AcpiEvUpdateGpeEnableMasks (GpeEventInfo);
584129684Snjl
585117521Snjl    /*
586193267Sjkim     * Take a snapshot of the GPE info for this level - we copy the info to
587193267Sjkim     * prevent a race condition with RemoveHandler/RemoveBlock.
588117521Snjl     */
589193267Sjkim    ACPI_MEMCPY (LocalGpeEventInfo, GpeEventInfo,
590151937Sjkim        sizeof (ACPI_GPE_EVENT_INFO));
591117521Snjl
592114239Snjl    Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
593114239Snjl    if (ACPI_FAILURE (Status))
594114239Snjl    {
595114239Snjl        return_VOID;
596114239Snjl    }
597114239Snjl
598129684Snjl    /*
599193267Sjkim     * Must check for control method type dispatch one more time to avoid a
600193267Sjkim     * race with EvGpeInstallHandler
601129684Snjl     */
602193267Sjkim    if ((LocalGpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
603151937Sjkim            ACPI_GPE_DISPATCH_METHOD)
604114239Snjl    {
605167802Sjkim        /* Allocate the evaluation information block */
606129684Snjl
607167802Sjkim        Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
608167802Sjkim        if (!Info)
609167802Sjkim        {
610167802Sjkim            Status = AE_NO_MEMORY;
611167802Sjkim        }
612167802Sjkim        else
613167802Sjkim        {
614167802Sjkim            /*
615167802Sjkim             * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the _Lxx/_Exx
616167802Sjkim             * control method that corresponds to this GPE
617167802Sjkim             */
618193267Sjkim            Info->PrefixNode = LocalGpeEventInfo->Dispatch.MethodNode;
619167802Sjkim            Info->Flags = ACPI_IGNORE_RETURN_VALUE;
620167802Sjkim
621167802Sjkim            Status = AcpiNsEvaluate (Info);
622167802Sjkim            ACPI_FREE (Info);
623167802Sjkim        }
624167802Sjkim
625114239Snjl        if (ACPI_FAILURE (Status))
626114239Snjl        {
627167802Sjkim            ACPI_EXCEPTION ((AE_INFO, Status,
628167802Sjkim                "while evaluating GPE method [%4.4s]",
629193267Sjkim                AcpiUtGetNodeName (LocalGpeEventInfo->Dispatch.MethodNode)));
630114239Snjl        }
631114239Snjl    }
632114239Snjl
633175256Snjl    /* Defer enabling of GPE until all notify handlers are done */
634193267Sjkim
635193267Sjkim    Status = AcpiOsExecute (OSL_NOTIFY_HANDLER,
636193267Sjkim                AcpiEvAsynchEnableGpe, LocalGpeEventInfo);
637193267Sjkim    if (ACPI_FAILURE (Status))
638193267Sjkim    {
639193267Sjkim        ACPI_FREE (LocalGpeEventInfo);
640193267Sjkim    }
641175256Snjl    return_VOID;
642175256Snjl}
643175256Snjl
644193267Sjkim
645193267Sjkim/*******************************************************************************
646193267Sjkim *
647193267Sjkim * FUNCTION:    AcpiEvAsynchEnableGpe
648193267Sjkim *
649193267Sjkim * PARAMETERS:  Context (GpeEventInfo) - Info for this GPE
650193267Sjkim *
651193267Sjkim * RETURN:      None
652193267Sjkim *
653193267Sjkim * DESCRIPTION: Asynchronous clear/enable for GPE. This allows the GPE to
654193267Sjkim *              complete (i.e., finish execution of Notify)
655193267Sjkim *
656193267Sjkim ******************************************************************************/
657193267Sjkim
658193267Sjkimstatic void ACPI_SYSTEM_XFACE
659175256SnjlAcpiEvAsynchEnableGpe (
660175256Snjl    void                    *Context)
661175256Snjl{
662193267Sjkim    ACPI_GPE_EVENT_INFO     *GpeEventInfo = Context;
663175256Snjl    ACPI_STATUS             Status;
664175256Snjl
665193267Sjkim
666175256Snjl    if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
667151937Sjkim            ACPI_GPE_LEVEL_TRIGGERED)
668114239Snjl    {
669114239Snjl        /*
670193267Sjkim         * GPE is level-triggered, we clear the GPE status bit after handling
671193267Sjkim         * the event.
672114239Snjl         */
673175256Snjl        Status = AcpiHwClearGpe (GpeEventInfo);
674114239Snjl        if (ACPI_FAILURE (Status))
675114239Snjl        {
676193267Sjkim            goto Exit;
677114239Snjl        }
678114239Snjl    }
679114239Snjl
680114239Snjl    /* Enable this GPE */
681114239Snjl
682175256Snjl    (void) AcpiHwWriteGpeEnableReg (GpeEventInfo);
683193267Sjkim
684193267SjkimExit:
685193267Sjkim    ACPI_FREE (GpeEventInfo);
686193267Sjkim    return;
687114239Snjl}
688114239Snjl
689114239Snjl
690114239Snjl/*******************************************************************************
691114239Snjl *
692114239Snjl * FUNCTION:    AcpiEvGpeDispatch
693114239Snjl *
694151937Sjkim * PARAMETERS:  GpeEventInfo    - Info for this GPE
695117521Snjl *              GpeNumber       - Number relative to the parent GPE block
696114239Snjl *
697114239Snjl * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
698114239Snjl *
699114239Snjl * DESCRIPTION: Dispatch a General Purpose Event to either a function (e.g. EC)
700117521Snjl *              or method (e.g. _Lxx/_Exx) handler.
701114239Snjl *
702117521Snjl *              This function executes at interrupt level.
703117521Snjl *
704114239Snjl ******************************************************************************/
705114239Snjl
706114239SnjlUINT32
707114239SnjlAcpiEvGpeDispatch (
708117521Snjl    ACPI_GPE_EVENT_INFO     *GpeEventInfo,
709117521Snjl    UINT32                  GpeNumber)
710114239Snjl{
711114239Snjl    ACPI_STATUS             Status;
712114239Snjl
713114239Snjl
714167802Sjkim    ACPI_FUNCTION_TRACE (EvGpeDispatch);
715114239Snjl
716114239Snjl
717167802Sjkim    AcpiGpeCount++;
718167802Sjkim
719114239Snjl    /*
720193267Sjkim     * If edge-triggered, clear the GPE status bit now. Note that
721114239Snjl     * level-triggered events are cleared after the GPE is serviced.
722114239Snjl     */
723151937Sjkim    if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
724151937Sjkim            ACPI_GPE_EDGE_TRIGGERED)
725114239Snjl    {
726114239Snjl        Status = AcpiHwClearGpe (GpeEventInfo);
727114239Snjl        if (ACPI_FAILURE (Status))
728114239Snjl        {
729167802Sjkim            ACPI_EXCEPTION ((AE_INFO, Status,
730204773Sjkim                "Unable to clear GPE[0x%2X]", GpeNumber));
731151937Sjkim            return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
732114239Snjl        }
733114239Snjl    }
734114239Snjl
735114239Snjl    /*
736167802Sjkim     * Dispatch the GPE to either an installed handler, or the control method
737167802Sjkim     * associated with this GPE (_Lxx or _Exx). If a handler exists, we invoke
738167802Sjkim     * it and do not attempt to run the method. If there is neither a handler
739167802Sjkim     * nor a method, we disable this GPE to prevent further such pointless
740167802Sjkim     * events from firing.
741114239Snjl     */
742129684Snjl    switch (GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK)
743114239Snjl    {
744129684Snjl    case ACPI_GPE_DISPATCH_HANDLER:
745129684Snjl
746131440Smarks        /*
747131440Smarks         * Invoke the installed handler (at interrupt level)
748193267Sjkim         * Ignore return status for now.
749193267Sjkim         * TBD: leave GPE disabled on error?
750131440Smarks         */
751131440Smarks        (void) GpeEventInfo->Dispatch.Handler->Address (
752129684Snjl                        GpeEventInfo->Dispatch.Handler->Context);
753123315Snjl
754123315Snjl        /* It is now safe to clear level-triggered events. */
755123315Snjl
756151937Sjkim        if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
757151937Sjkim                ACPI_GPE_LEVEL_TRIGGERED)
758123315Snjl        {
759123315Snjl            Status = AcpiHwClearGpe (GpeEventInfo);
760123315Snjl            if (ACPI_FAILURE (Status))
761123315Snjl            {
762167802Sjkim                ACPI_EXCEPTION ((AE_INFO, Status,
763204773Sjkim                    "Unable to clear GPE[0x%2X]", GpeNumber));
764151937Sjkim                return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
765123315Snjl            }
766123315Snjl        }
767129684Snjl        break;
768129684Snjl
769129684Snjl    case ACPI_GPE_DISPATCH_METHOD:
770129684Snjl
771114239Snjl        /*
772167802Sjkim         * Disable the GPE, so it doesn't keep firing before the method has a
773167802Sjkim         * chance to run (it runs asynchronously with interrupts enabled).
774114239Snjl         */
775129684Snjl        Status = AcpiEvDisableGpe (GpeEventInfo);
776114239Snjl        if (ACPI_FAILURE (Status))
777114239Snjl        {
778167802Sjkim            ACPI_EXCEPTION ((AE_INFO, Status,
779204773Sjkim                "Unable to disable GPE[0x%2X]", GpeNumber));
780151937Sjkim            return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
781114239Snjl        }
782114239Snjl
783126372Snjl        /*
784123315Snjl         * Execute the method associated with the GPE
785123315Snjl         * NOTE: Level-triggered GPEs are cleared after the method completes.
786123315Snjl         */
787167802Sjkim        Status = AcpiOsExecute (OSL_GPE_HANDLER,
788151937Sjkim                    AcpiEvAsynchExecuteGpeMethod, GpeEventInfo);
789151937Sjkim        if (ACPI_FAILURE (Status))
790114239Snjl        {
791167802Sjkim            ACPI_EXCEPTION ((AE_INFO, Status,
792204773Sjkim                "Unable to queue handler for GPE[0x%2X] - event disabled",
793167802Sjkim                GpeNumber));
794114239Snjl        }
795129684Snjl        break;
796129684Snjl
797129684Snjl    default:
798129684Snjl
799206117Sjkim        /*
800206117Sjkim         * No handler or method to run!
801206117Sjkim         * 03/2010: This case should no longer be possible. We will not allow
802206117Sjkim         * a GPE to be enabled if it has no handler or method.
803206117Sjkim         */
804167802Sjkim        ACPI_ERROR ((AE_INFO,
805204773Sjkim            "No handler or method for GPE[0x%2X], disabling event",
806114239Snjl            GpeNumber));
807114239Snjl
808114239Snjl        /*
809206117Sjkim         * Disable the GPE. The GPE will remain disabled a handler
810206117Sjkim         * is installed or ACPICA is restarted.
811114239Snjl         */
812129684Snjl        Status = AcpiEvDisableGpe (GpeEventInfo);
813114239Snjl        if (ACPI_FAILURE (Status))
814114239Snjl        {
815167802Sjkim            ACPI_EXCEPTION ((AE_INFO, Status,
816204773Sjkim                "Unable to disable GPE[0x%2X]", GpeNumber));
817151937Sjkim            return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
818114239Snjl        }
819129684Snjl        break;
820114239Snjl    }
821114239Snjl
822151937Sjkim    return_UINT32 (ACPI_INTERRUPT_HANDLED);
823114239Snjl}
824114239Snjl
825