1114239Snjl/******************************************************************************
2114239Snjl *
3114239Snjl * Module Name: evgpe - General Purpose Event handling and dispatch
4114239Snjl *
5114239Snjl *****************************************************************************/
6114239Snjl
7316303Sjkim/******************************************************************************
8316303Sjkim *
9316303Sjkim * 1. Copyright Notice
10316303Sjkim *
11316303Sjkim * Some or all of this work - Copyright (c) 1999 - 2017, Intel Corp.
12114239Snjl * All rights reserved.
13114239Snjl *
14316303Sjkim * 2. License
15316303Sjkim *
16316303Sjkim * 2.1. This is your license from Intel Corp. under its intellectual property
17316303Sjkim * rights. You may have additional license terms from the party that provided
18316303Sjkim * you this software, covering your right to use that party's intellectual
19316303Sjkim * property rights.
20316303Sjkim *
21316303Sjkim * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22316303Sjkim * copy of the source code appearing in this file ("Covered Code") an
23316303Sjkim * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24316303Sjkim * base code distributed originally by Intel ("Original Intel Code") to copy,
25316303Sjkim * make derivatives, distribute, use and display any portion of the Covered
26316303Sjkim * Code in any form, with the right to sublicense such rights; and
27316303Sjkim *
28316303Sjkim * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29316303Sjkim * license (with the right to sublicense), under only those claims of Intel
30316303Sjkim * patents that are infringed by the Original Intel Code, to make, use, sell,
31316303Sjkim * offer to sell, and import the Covered Code and derivative works thereof
32316303Sjkim * solely to the minimum extent necessary to exercise the above copyright
33316303Sjkim * license, and in no event shall the patent license extend to any additions
34316303Sjkim * to or modifications of the Original Intel Code. No other license or right
35316303Sjkim * is granted directly or by implication, estoppel or otherwise;
36316303Sjkim *
37316303Sjkim * The above copyright and patent license is granted only if the following
38316303Sjkim * conditions are met:
39316303Sjkim *
40316303Sjkim * 3. Conditions
41316303Sjkim *
42316303Sjkim * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43316303Sjkim * Redistribution of source code of any substantial portion of the Covered
44316303Sjkim * Code or modification with rights to further distribute source must include
45316303Sjkim * the above Copyright Notice, the above License, this list of Conditions,
46316303Sjkim * and the following Disclaimer and Export Compliance provision. In addition,
47316303Sjkim * Licensee must cause all Covered Code to which Licensee contributes to
48316303Sjkim * contain a file documenting the changes Licensee made to create that Covered
49316303Sjkim * Code and the date of any change. Licensee must include in that file the
50316303Sjkim * documentation of any changes made by any predecessor Licensee. Licensee
51316303Sjkim * must include a prominent statement that the modification is derived,
52316303Sjkim * directly or indirectly, from Original Intel Code.
53316303Sjkim *
54316303Sjkim * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55316303Sjkim * Redistribution of source code of any substantial portion of the Covered
56316303Sjkim * Code or modification without rights to further distribute source must
57316303Sjkim * include the following Disclaimer and Export Compliance provision in the
58316303Sjkim * documentation and/or other materials provided with distribution. In
59316303Sjkim * addition, Licensee may not authorize further sublicense of source of any
60316303Sjkim * portion of the Covered Code, and must include terms to the effect that the
61316303Sjkim * license from Licensee to its licensee is limited to the intellectual
62316303Sjkim * property embodied in the software Licensee provides to its licensee, and
63316303Sjkim * not to intellectual property embodied in modifications its licensee may
64316303Sjkim * make.
65316303Sjkim *
66316303Sjkim * 3.3. Redistribution of Executable. Redistribution in executable form of any
67316303Sjkim * substantial portion of the Covered Code or modification must reproduce the
68316303Sjkim * above Copyright Notice, and the following Disclaimer and Export Compliance
69316303Sjkim * provision in the documentation and/or other materials provided with the
70316303Sjkim * distribution.
71316303Sjkim *
72316303Sjkim * 3.4. Intel retains all right, title, and interest in and to the Original
73316303Sjkim * Intel Code.
74316303Sjkim *
75316303Sjkim * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76316303Sjkim * Intel shall be used in advertising or otherwise to promote the sale, use or
77316303Sjkim * other dealings in products derived from or relating to the Covered Code
78316303Sjkim * without prior written authorization from Intel.
79316303Sjkim *
80316303Sjkim * 4. Disclaimer and Export Compliance
81316303Sjkim *
82316303Sjkim * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83316303Sjkim * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84316303Sjkim * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
85316303Sjkim * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
86316303Sjkim * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
87316303Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88316303Sjkim * PARTICULAR PURPOSE.
89316303Sjkim *
90316303Sjkim * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91316303Sjkim * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92316303Sjkim * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93316303Sjkim * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94316303Sjkim * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95316303Sjkim * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
96316303Sjkim * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97316303Sjkim * LIMITED REMEDY.
98316303Sjkim *
99316303Sjkim * 4.3. Licensee shall not export, either directly or indirectly, any of this
100316303Sjkim * software or system incorporating such software without first obtaining any
101316303Sjkim * required license or other approval from the U. S. Department of Commerce or
102316303Sjkim * any other agency or department of the United States Government. In the
103316303Sjkim * event Licensee exports any such software from the United States or
104316303Sjkim * re-exports any such software from a foreign destination, Licensee shall
105316303Sjkim * ensure that the distribution and export/re-export of the software is in
106316303Sjkim * compliance with all laws, regulations, orders, or other restrictions of the
107316303Sjkim * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108316303Sjkim * any of its subsidiaries will export/re-export any technical data, process,
109316303Sjkim * software, or service, directly or indirectly, to any country for which the
110316303Sjkim * United States government or any agency thereof requires an export license,
111316303Sjkim * other governmental approval, or letter of assurance, without first obtaining
112316303Sjkim * such license, approval or letter.
113316303Sjkim *
114316303Sjkim *****************************************************************************
115316303Sjkim *
116316303Sjkim * Alternatively, you may choose to be licensed under the terms of the
117316303Sjkim * following license:
118316303Sjkim *
119217365Sjkim * Redistribution and use in source and binary forms, with or without
120217365Sjkim * modification, are permitted provided that the following conditions
121217365Sjkim * are met:
122217365Sjkim * 1. Redistributions of source code must retain the above copyright
123217365Sjkim *    notice, this list of conditions, and the following disclaimer,
124217365Sjkim *    without modification.
125217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
126217365Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
127217365Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
128217365Sjkim *    including a substantially similar Disclaimer requirement for further
129217365Sjkim *    binary redistribution.
130217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
131217365Sjkim *    of any contributors may be used to endorse or promote products derived
132217365Sjkim *    from this software without specific prior written permission.
133114239Snjl *
134316303Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
135316303Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
136316303Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
137316303Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
138316303Sjkim * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
139316303Sjkim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
140316303Sjkim * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
141316303Sjkim * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
142316303Sjkim * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
143316303Sjkim * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
144316303Sjkim * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
145316303Sjkim *
146316303Sjkim * Alternatively, you may choose to be licensed under the terms of the
147217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
148217365Sjkim * Software Foundation.
149114239Snjl *
150316303Sjkim *****************************************************************************/
151114239Snjl
152193341Sjkim#include <contrib/dev/acpica/include/acpi.h>
153193341Sjkim#include <contrib/dev/acpica/include/accommon.h>
154193341Sjkim#include <contrib/dev/acpica/include/acevents.h>
155193341Sjkim#include <contrib/dev/acpica/include/acnamesp.h>
156114239Snjl
157114239Snjl#define _COMPONENT          ACPI_EVENTS
158114239Snjl        ACPI_MODULE_NAME    ("evgpe")
159114239Snjl
160231844Sjkim#if (!ACPI_REDUCED_HARDWARE) /* Entire module */
161231844Sjkim
162151937Sjkim/* Local prototypes */
163114239Snjl
164193267Sjkimstatic void ACPI_SYSTEM_XFACE
165193267SjkimAcpiEvAsynchExecuteGpeMethod (
166175256Snjl    void                    *Context);
167175256Snjl
168151937Sjkimstatic void ACPI_SYSTEM_XFACE
169193267SjkimAcpiEvAsynchEnableGpe (
170151937Sjkim    void                    *Context);
171151937Sjkim
172151937Sjkim
173114239Snjl/*******************************************************************************
174114239Snjl *
175209746Sjkim * FUNCTION:    AcpiEvUpdateGpeEnableMask
176129684Snjl *
177129684Snjl * PARAMETERS:  GpeEventInfo            - GPE to update
178129684Snjl *
179129684Snjl * RETURN:      Status
180129684Snjl *
181209746Sjkim * DESCRIPTION: Updates GPE register enable mask based upon whether there are
182209746Sjkim *              runtime references to this GPE
183129684Snjl *
184129684Snjl ******************************************************************************/
185129684Snjl
186129684SnjlACPI_STATUS
187209746SjkimAcpiEvUpdateGpeEnableMask (
188206117Sjkim    ACPI_GPE_EVENT_INFO     *GpeEventInfo)
189129684Snjl{
190129684Snjl    ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
191209746Sjkim    UINT32                  RegisterBit;
192129684Snjl
193129684Snjl
194209746Sjkim    ACPI_FUNCTION_TRACE (EvUpdateGpeEnableMask);
195129684Snjl
196129684Snjl
197129684Snjl    GpeRegisterInfo = GpeEventInfo->RegisterInfo;
198129684Snjl    if (!GpeRegisterInfo)
199129684Snjl    {
200129684Snjl        return_ACPI_STATUS (AE_NOT_EXIST);
201129684Snjl    }
202193267Sjkim
203239340Sjkim    RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo);
204129684Snjl
205209746Sjkim    /* Clear the run bit up front */
206129684Snjl
207206117Sjkim    ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForRun, RegisterBit);
208206117Sjkim
209209746Sjkim    /* Set the mask bit only if there are references to this GPE */
210206117Sjkim
211206117Sjkim    if (GpeEventInfo->RuntimeCount)
212129684Snjl    {
213209746Sjkim        ACPI_SET_BIT (GpeRegisterInfo->EnableForRun, (UINT8) RegisterBit);
214129684Snjl    }
215298714Sjkim
216284583Sjkim    GpeRegisterInfo->EnableMask = GpeRegisterInfo->EnableForRun;
217129684Snjl    return_ACPI_STATUS (AE_OK);
218129684Snjl}
219129684Snjl
220129684Snjl
221129684Snjl/*******************************************************************************
222129684Snjl *
223129684Snjl * FUNCTION:    AcpiEvEnableGpe
224129684Snjl *
225129684Snjl * PARAMETERS:  GpeEventInfo            - GPE to enable
226129684Snjl *
227129684Snjl * RETURN:      Status
228129684Snjl *
229209746Sjkim * DESCRIPTION: Clear a GPE of stale events and enable it.
230129684Snjl *
231129684Snjl ******************************************************************************/
232129684Snjl
233129684SnjlACPI_STATUS
234129684SnjlAcpiEvEnableGpe (
235206117Sjkim    ACPI_GPE_EVENT_INFO     *GpeEventInfo)
236129684Snjl{
237129684Snjl    ACPI_STATUS             Status;
238129684Snjl
239129684Snjl
240167802Sjkim    ACPI_FUNCTION_TRACE (EvEnableGpe);
241129684Snjl
242129684Snjl
243206117Sjkim    /* Clear the GPE (of stale events) */
244129684Snjl
245206117Sjkim    Status = AcpiHwClearGpe (GpeEventInfo);
246206117Sjkim    if (ACPI_FAILURE (Status))
247129684Snjl    {
248206117Sjkim        return_ACPI_STATUS (Status);
249206117Sjkim    }
250131440Smarks
251206117Sjkim    /* Enable the requested GPE */
252129684Snjl
253284583Sjkim    Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_ENABLE);
254206117Sjkim    return_ACPI_STATUS (Status);
255129684Snjl}
256129684Snjl
257129684Snjl
258129684Snjl/*******************************************************************************
259129684Snjl *
260316303Sjkim * FUNCTION:    AcpiEvMaskGpe
261316303Sjkim *
262316303Sjkim * PARAMETERS:  GpeEventInfo            - GPE to be blocked/unblocked
263316303Sjkim *              IsMasked                - Whether the GPE is masked or not
264316303Sjkim *
265316303Sjkim * RETURN:      Status
266316303Sjkim *
267316303Sjkim * DESCRIPTION: Unconditionally mask/unmask a GPE during runtime.
268316303Sjkim *
269316303Sjkim ******************************************************************************/
270316303Sjkim
271316303SjkimACPI_STATUS
272316303SjkimAcpiEvMaskGpe (
273316303Sjkim    ACPI_GPE_EVENT_INFO     *GpeEventInfo,
274316303Sjkim    BOOLEAN                 IsMasked)
275316303Sjkim{
276316303Sjkim    ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
277316303Sjkim    UINT32                  RegisterBit;
278316303Sjkim
279316303Sjkim
280316303Sjkim    ACPI_FUNCTION_TRACE (EvMaskGpe);
281316303Sjkim
282316303Sjkim
283316303Sjkim    GpeRegisterInfo = GpeEventInfo->RegisterInfo;
284316303Sjkim    if (!GpeRegisterInfo)
285316303Sjkim    {
286316303Sjkim        return_ACPI_STATUS (AE_NOT_EXIST);
287316303Sjkim    }
288316303Sjkim
289316303Sjkim    RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo);
290316303Sjkim
291316303Sjkim    /* Perform the action */
292316303Sjkim
293316303Sjkim    if (IsMasked)
294316303Sjkim    {
295316303Sjkim        if (RegisterBit & GpeRegisterInfo->MaskForRun)
296316303Sjkim        {
297316303Sjkim            return_ACPI_STATUS (AE_BAD_PARAMETER);
298316303Sjkim        }
299316303Sjkim
300316303Sjkim        (void) AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE);
301316303Sjkim        ACPI_SET_BIT (GpeRegisterInfo->MaskForRun, (UINT8) RegisterBit);
302316303Sjkim    }
303316303Sjkim    else
304316303Sjkim    {
305316303Sjkim        if (!(RegisterBit & GpeRegisterInfo->MaskForRun))
306316303Sjkim        {
307316303Sjkim            return_ACPI_STATUS (AE_BAD_PARAMETER);
308316303Sjkim        }
309316303Sjkim
310316303Sjkim        ACPI_CLEAR_BIT (GpeRegisterInfo->MaskForRun, (UINT8) RegisterBit);
311316303Sjkim        if (GpeEventInfo->RuntimeCount &&
312316303Sjkim            !GpeEventInfo->DisableForDispatch)
313316303Sjkim        {
314316303Sjkim            (void) AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_ENABLE);
315316303Sjkim        }
316316303Sjkim    }
317316303Sjkim
318316303Sjkim    return_ACPI_STATUS (AE_OK);
319316303Sjkim}
320316303Sjkim
321316303Sjkim
322316303Sjkim/*******************************************************************************
323316303Sjkim *
324216471Sjkim * FUNCTION:    AcpiEvAddGpeReference
325216471Sjkim *
326216471Sjkim * PARAMETERS:  GpeEventInfo            - Add a reference to this GPE
327216471Sjkim *
328216471Sjkim * RETURN:      Status
329216471Sjkim *
330216471Sjkim * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is
331216471Sjkim *              hardware-enabled.
332216471Sjkim *
333216471Sjkim ******************************************************************************/
334216471Sjkim
335216471SjkimACPI_STATUS
336216471SjkimAcpiEvAddGpeReference (
337216471Sjkim    ACPI_GPE_EVENT_INFO     *GpeEventInfo)
338216471Sjkim{
339216471Sjkim    ACPI_STATUS             Status = AE_OK;
340216471Sjkim
341216471Sjkim
342216471Sjkim    ACPI_FUNCTION_TRACE (EvAddGpeReference);
343216471Sjkim
344216471Sjkim
345216471Sjkim    if (GpeEventInfo->RuntimeCount == ACPI_UINT8_MAX)
346216471Sjkim    {
347216471Sjkim        return_ACPI_STATUS (AE_LIMIT);
348216471Sjkim    }
349216471Sjkim
350216471Sjkim    GpeEventInfo->RuntimeCount++;
351216471Sjkim    if (GpeEventInfo->RuntimeCount == 1)
352216471Sjkim    {
353216471Sjkim        /* Enable on first reference */
354216471Sjkim
355216471Sjkim        Status = AcpiEvUpdateGpeEnableMask (GpeEventInfo);
356216471Sjkim        if (ACPI_SUCCESS (Status))
357216471Sjkim        {
358216471Sjkim            Status = AcpiEvEnableGpe (GpeEventInfo);
359216471Sjkim        }
360216471Sjkim
361216471Sjkim        if (ACPI_FAILURE (Status))
362216471Sjkim        {
363216471Sjkim            GpeEventInfo->RuntimeCount--;
364216471Sjkim        }
365216471Sjkim    }
366216471Sjkim
367216471Sjkim    return_ACPI_STATUS (Status);
368216471Sjkim}
369216471Sjkim
370216471Sjkim
371216471Sjkim/*******************************************************************************
372216471Sjkim *
373216471Sjkim * FUNCTION:    AcpiEvRemoveGpeReference
374216471Sjkim *
375216471Sjkim * PARAMETERS:  GpeEventInfo            - Remove a reference to this GPE
376216471Sjkim *
377216471Sjkim * RETURN:      Status
378216471Sjkim *
379216471Sjkim * DESCRIPTION: Remove a reference to a GPE. When the last reference is
380216471Sjkim *              removed, the GPE is hardware-disabled.
381216471Sjkim *
382216471Sjkim ******************************************************************************/
383216471Sjkim
384216471SjkimACPI_STATUS
385216471SjkimAcpiEvRemoveGpeReference (
386216471Sjkim    ACPI_GPE_EVENT_INFO     *GpeEventInfo)
387216471Sjkim{
388216471Sjkim    ACPI_STATUS             Status = AE_OK;
389216471Sjkim
390216471Sjkim
391216471Sjkim    ACPI_FUNCTION_TRACE (EvRemoveGpeReference);
392216471Sjkim
393216471Sjkim
394216471Sjkim    if (!GpeEventInfo->RuntimeCount)
395216471Sjkim    {
396216471Sjkim        return_ACPI_STATUS (AE_LIMIT);
397216471Sjkim    }
398216471Sjkim
399216471Sjkim    GpeEventInfo->RuntimeCount--;
400216471Sjkim    if (!GpeEventInfo->RuntimeCount)
401216471Sjkim    {
402216471Sjkim        /* Disable on last reference */
403216471Sjkim
404216471Sjkim        Status = AcpiEvUpdateGpeEnableMask (GpeEventInfo);
405216471Sjkim        if (ACPI_SUCCESS (Status))
406216471Sjkim        {
407284583Sjkim            Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE);
408216471Sjkim        }
409216471Sjkim
410216471Sjkim        if (ACPI_FAILURE (Status))
411216471Sjkim        {
412216471Sjkim            GpeEventInfo->RuntimeCount++;
413216471Sjkim        }
414216471Sjkim    }
415216471Sjkim
416216471Sjkim    return_ACPI_STATUS (Status);
417216471Sjkim}
418216471Sjkim
419216471Sjkim
420216471Sjkim/*******************************************************************************
421216471Sjkim *
422206117Sjkim * FUNCTION:    AcpiEvLowGetGpeInfo
423206117Sjkim *
424206117Sjkim * PARAMETERS:  GpeNumber           - Raw GPE number
425206117Sjkim *              GpeBlock            - A GPE info block
426206117Sjkim *
427206117Sjkim * RETURN:      A GPE EventInfo struct. NULL if not a valid GPE (The GpeNumber
428206117Sjkim *              is not within the specified GPE block)
429206117Sjkim *
430206117Sjkim * DESCRIPTION: Returns the EventInfo struct associated with this GPE. This is
431206117Sjkim *              the low-level implementation of EvGetGpeEventInfo.
432206117Sjkim *
433206117Sjkim ******************************************************************************/
434206117Sjkim
435206117SjkimACPI_GPE_EVENT_INFO *
436206117SjkimAcpiEvLowGetGpeInfo (
437206117Sjkim    UINT32                  GpeNumber,
438206117Sjkim    ACPI_GPE_BLOCK_INFO     *GpeBlock)
439206117Sjkim{
440206117Sjkim    UINT32                  GpeIndex;
441206117Sjkim
442206117Sjkim
443206117Sjkim    /*
444206117Sjkim     * Validate that the GpeNumber is within the specified GpeBlock.
445206117Sjkim     * (Two steps)
446206117Sjkim     */
447206117Sjkim    if (!GpeBlock ||
448206117Sjkim        (GpeNumber < GpeBlock->BlockBaseNumber))
449206117Sjkim    {
450206117Sjkim        return (NULL);
451206117Sjkim    }
452206117Sjkim
453206117Sjkim    GpeIndex = GpeNumber - GpeBlock->BlockBaseNumber;
454206117Sjkim    if (GpeIndex >= GpeBlock->GpeCount)
455206117Sjkim    {
456206117Sjkim        return (NULL);
457206117Sjkim    }
458206117Sjkim
459206117Sjkim    return (&GpeBlock->EventInfo[GpeIndex]);
460206117Sjkim}
461206117Sjkim
462206117Sjkim
463206117Sjkim/*******************************************************************************
464206117Sjkim *
465114239Snjl * FUNCTION:    AcpiEvGetGpeEventInfo
466114239Snjl *
467193267Sjkim * PARAMETERS:  GpeDevice           - Device node. NULL for GPE0/GPE1
468117521Snjl *              GpeNumber           - Raw GPE number
469114239Snjl *
470193267Sjkim * RETURN:      A GPE EventInfo struct. NULL if not a valid GPE
471114239Snjl *
472117521Snjl * DESCRIPTION: Returns the EventInfo struct associated with this GPE.
473117521Snjl *              Validates the GpeBlock and the GpeNumber
474114239Snjl *
475117521Snjl *              Should be called only when the GPE lists are semaphore locked
476117521Snjl *              and not subject to change.
477114239Snjl *
478114239Snjl ******************************************************************************/
479114239Snjl
480114239SnjlACPI_GPE_EVENT_INFO *
481114239SnjlAcpiEvGetGpeEventInfo (
482117521Snjl    ACPI_HANDLE             GpeDevice,
483114239Snjl    UINT32                  GpeNumber)
484114239Snjl{
485117521Snjl    ACPI_OPERAND_OBJECT     *ObjDesc;
486206117Sjkim    ACPI_GPE_EVENT_INFO     *GpeInfo;
487193267Sjkim    UINT32                  i;
488114239Snjl
489114239Snjl
490117521Snjl    ACPI_FUNCTION_ENTRY ();
491114239Snjl
492117521Snjl
493207344Sjkim    /* A NULL GpeDevice means use the FADT-defined GPE block(s) */
494117521Snjl
495117521Snjl    if (!GpeDevice)
496114239Snjl    {
497117521Snjl        /* Examine GPE Block 0 and 1 (These blocks are permanent) */
498117521Snjl
499117521Snjl        for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++)
500117521Snjl        {
501206117Sjkim            GpeInfo = AcpiEvLowGetGpeInfo (GpeNumber,
502298714Sjkim                AcpiGbl_GpeFadtBlocks[i]);
503206117Sjkim            if (GpeInfo)
504117521Snjl            {
505206117Sjkim                return (GpeInfo);
506117521Snjl            }
507117521Snjl        }
508117521Snjl
509117521Snjl        /* The GpeNumber was not in the range of either FADT GPE block */
510117521Snjl
511114239Snjl        return (NULL);
512114239Snjl    }
513114239Snjl
514128212Snjl    /* A Non-NULL GpeDevice means this is a GPE Block Device */
515128212Snjl
516117521Snjl    ObjDesc = AcpiNsGetAttachedObject ((ACPI_NAMESPACE_NODE *) GpeDevice);
517117521Snjl    if (!ObjDesc ||
518117521Snjl        !ObjDesc->Device.GpeBlock)
519114239Snjl    {
520117521Snjl        return (NULL);
521114239Snjl    }
522114239Snjl
523206117Sjkim    return (AcpiEvLowGetGpeInfo (GpeNumber, ObjDesc->Device.GpeBlock));
524114239Snjl}
525114239Snjl
526117521Snjl
527114239Snjl/*******************************************************************************
528114239Snjl *
529114239Snjl * FUNCTION:    AcpiEvGpeDetect
530114239Snjl *
531117521Snjl * PARAMETERS:  GpeXruptList        - Interrupt block for this interrupt.
532117521Snjl *                                    Can have multiple GPE blocks attached.
533114239Snjl *
534114239Snjl * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
535114239Snjl *
536193267Sjkim * DESCRIPTION: Detect if any GP events have occurred. This function is
537114239Snjl *              executed at interrupt level.
538114239Snjl *
539114239Snjl ******************************************************************************/
540114239Snjl
541114239SnjlUINT32
542117521SnjlAcpiEvGpeDetect (
543117521Snjl    ACPI_GPE_XRUPT_INFO     *GpeXruptList)
544114239Snjl{
545151937Sjkim    ACPI_STATUS             Status;
546151937Sjkim    ACPI_GPE_BLOCK_INFO     *GpeBlock;
547278970Sjkim    ACPI_NAMESPACE_NODE     *GpeDevice;
548151937Sjkim    ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
549278970Sjkim    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
550278970Sjkim    UINT32                  GpeNumber;
551278970Sjkim    ACPI_GPE_HANDLER_INFO   *GpeHandlerInfo;
552114239Snjl    UINT32                  IntStatus = ACPI_INTERRUPT_NOT_HANDLED;
553114239Snjl    UINT8                   EnabledStatusByte;
554327557Sjkim    UINT64                  StatusReg;
555327557Sjkim    UINT64                  EnableReg;
556167802Sjkim    ACPI_CPU_FLAGS          Flags;
557193267Sjkim    UINT32                  i;
558193267Sjkim    UINT32                  j;
559114239Snjl
560114239Snjl
561167802Sjkim    ACPI_FUNCTION_NAME (EvGpeDetect);
562114239Snjl
563127175Snjl    /* Check for the case where there are no GPEs */
564114239Snjl
565127175Snjl    if (!GpeXruptList)
566127175Snjl    {
567127175Snjl        return (IntStatus);
568127175Snjl    }
569127175Snjl
570167802Sjkim    /*
571167802Sjkim     * We need to obtain the GPE lock for both the data structs and registers
572193267Sjkim     * Note: Not necessary to obtain the hardware lock, since the GPE
573193267Sjkim     * registers are owned by the GpeLock.
574167802Sjkim     */
575167802Sjkim    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
576167802Sjkim
577114239Snjl    /* Examine all GPE blocks attached to this interrupt level */
578114239Snjl
579117521Snjl    GpeBlock = GpeXruptList->GpeBlockListHead;
580114239Snjl    while (GpeBlock)
581114239Snjl    {
582278970Sjkim        GpeDevice = GpeBlock->Node;
583278970Sjkim
584114239Snjl        /*
585193267Sjkim         * Read all of the 8-bit GPE status and enable registers in this GPE
586193267Sjkim         * block, saving all of them. Find all currently active GP events.
587114239Snjl         */
588114239Snjl        for (i = 0; i < GpeBlock->RegisterCount; i++)
589114239Snjl        {
590114239Snjl            /* Get the next status/enable pair */
591114239Snjl
592114239Snjl            GpeRegisterInfo = &GpeBlock->RegisterInfo[i];
593114239Snjl
594218590Sjkim            /*
595218590Sjkim             * Optimization: If there are no GPEs enabled within this
596218590Sjkim             * register, we can safely ignore the entire register.
597218590Sjkim             */
598218590Sjkim            if (!(GpeRegisterInfo->EnableForRun |
599218590Sjkim                  GpeRegisterInfo->EnableForWake))
600218590Sjkim            {
601239340Sjkim                ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
602272444Sjkim                    "Ignore disabled registers for GPE %02X-%02X: "
603239340Sjkim                    "RunEnable=%02X, WakeEnable=%02X\n",
604239340Sjkim                    GpeRegisterInfo->BaseGpeNumber,
605239340Sjkim                    GpeRegisterInfo->BaseGpeNumber + (ACPI_GPE_REGISTER_WIDTH - 1),
606239340Sjkim                    GpeRegisterInfo->EnableForRun,
607239340Sjkim                    GpeRegisterInfo->EnableForWake));
608218590Sjkim                continue;
609218590Sjkim            }
610218590Sjkim
611117521Snjl            /* Read the Status Register */
612117521Snjl
613197104Sjkim            Status = AcpiHwRead (&StatusReg, &GpeRegisterInfo->StatusAddress);
614114239Snjl            if (ACPI_FAILURE (Status))
615114239Snjl            {
616117521Snjl                goto UnlockAndExit;
617114239Snjl            }
618114239Snjl
619117521Snjl            /* Read the Enable Register */
620117521Snjl
621197104Sjkim            Status = AcpiHwRead (&EnableReg, &GpeRegisterInfo->EnableAddress);
622114239Snjl            if (ACPI_FAILURE (Status))
623114239Snjl            {
624117521Snjl                goto UnlockAndExit;
625114239Snjl            }
626114239Snjl
627114239Snjl            ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
628272444Sjkim                "Read registers for GPE %02X-%02X: Status=%02X, Enable=%02X, "
629239340Sjkim                "RunEnable=%02X, WakeEnable=%02X\n",
630239340Sjkim                GpeRegisterInfo->BaseGpeNumber,
631239340Sjkim                GpeRegisterInfo->BaseGpeNumber + (ACPI_GPE_REGISTER_WIDTH - 1),
632327557Sjkim                (UINT32) StatusReg, (UINT32) EnableReg,
633239340Sjkim                GpeRegisterInfo->EnableForRun,
634239340Sjkim                GpeRegisterInfo->EnableForWake));
635114239Snjl
636151937Sjkim            /* Check if there is anything active at all in this register */
637114239Snjl
638129684Snjl            EnabledStatusByte = (UINT8) (StatusReg & EnableReg);
639114239Snjl            if (!EnabledStatusByte)
640114239Snjl            {
641114239Snjl                /* No active GPEs in this register, move on */
642114239Snjl
643114239Snjl                continue;
644114239Snjl            }
645114239Snjl
646114239Snjl            /* Now look at the individual GPEs in this byte register */
647114239Snjl
648123315Snjl            for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++)
649114239Snjl            {
650114239Snjl                /* Examine one GPE bit */
651114239Snjl
652278970Sjkim                GpeEventInfo = &GpeBlock->EventInfo[((ACPI_SIZE) i *
653278970Sjkim                    ACPI_GPE_REGISTER_WIDTH) + j];
654278970Sjkim                GpeNumber = j + GpeRegisterInfo->BaseGpeNumber;
655278970Sjkim
656167802Sjkim                if (EnabledStatusByte & (1 << j))
657114239Snjl                {
658278970Sjkim                    /* Invoke global event handler if present */
659278970Sjkim
660278970Sjkim                    AcpiGpeCount++;
661278970Sjkim                    if (AcpiGbl_GlobalEventHandler)
662278970Sjkim                    {
663278970Sjkim                        AcpiGbl_GlobalEventHandler (ACPI_EVENT_TYPE_GPE,
664278970Sjkim                            GpeDevice, GpeNumber,
665278970Sjkim                            AcpiGbl_GlobalEventHandlerContext);
666278970Sjkim                    }
667278970Sjkim
668278970Sjkim                    /* Found an active GPE */
669278970Sjkim
670278970Sjkim                    if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) ==
671278970Sjkim                        ACPI_GPE_DISPATCH_RAW_HANDLER)
672278970Sjkim                    {
673278970Sjkim                        /* Dispatch the event to a raw handler */
674278970Sjkim
675278970Sjkim                        GpeHandlerInfo = GpeEventInfo->Dispatch.Handler;
676278970Sjkim
677278970Sjkim                        /*
678278970Sjkim                         * There is no protection around the namespace node
679278970Sjkim                         * and the GPE handler to ensure a safe destruction
680278970Sjkim                         * because:
681278970Sjkim                         * 1. The namespace node is expected to always
682278970Sjkim                         *    exist after loading a table.
683278970Sjkim                         * 2. The GPE handler is expected to be flushed by
684278970Sjkim                         *    AcpiOsWaitEventsComplete() before the
685278970Sjkim                         *    destruction.
686278970Sjkim                         */
687278970Sjkim                        AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
688278970Sjkim                        IntStatus |= GpeHandlerInfo->Address (
689278970Sjkim                            GpeDevice, GpeNumber, GpeHandlerInfo->Context);
690278970Sjkim                        Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
691278970Sjkim                    }
692278970Sjkim                    else
693278970Sjkim                    {
694278970Sjkim                        /*
695278970Sjkim                         * Dispatch the event to a standard handler or
696278970Sjkim                         * method.
697278970Sjkim                         */
698278970Sjkim                        IntStatus |= AcpiEvGpeDispatch (GpeDevice,
699278970Sjkim                            GpeEventInfo, GpeNumber);
700278970Sjkim                    }
701114239Snjl                }
702114239Snjl            }
703114239Snjl        }
704114239Snjl
705114239Snjl        GpeBlock = GpeBlock->Next;
706114239Snjl    }
707114239Snjl
708117521SnjlUnlockAndExit:
709117521Snjl
710151937Sjkim    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
711114239Snjl    return (IntStatus);
712114239Snjl}
713114239Snjl
714114239Snjl
715114239Snjl/*******************************************************************************
716114239Snjl *
717114239Snjl * FUNCTION:    AcpiEvAsynchExecuteGpeMethod
718114239Snjl *
719117521Snjl * PARAMETERS:  Context (GpeEventInfo) - Info for this GPE
720114239Snjl *
721114239Snjl * RETURN:      None
722114239Snjl *
723167802Sjkim * DESCRIPTION: Perform the actual execution of a GPE control method. This
724167802Sjkim *              function is called from an invocation of AcpiOsExecute and
725167802Sjkim *              therefore does NOT execute at interrupt level - so that
726114239Snjl *              the control method itself is not executed in the context of
727117521Snjl *              an interrupt handler.
728114239Snjl *
729114239Snjl ******************************************************************************/
730114239Snjl
731114239Snjlstatic void ACPI_SYSTEM_XFACE
732114239SnjlAcpiEvAsynchExecuteGpeMethod (
733114239Snjl    void                    *Context)
734114239Snjl{
735193267Sjkim    ACPI_GPE_EVENT_INFO     *GpeEventInfo = Context;
736278970Sjkim    ACPI_STATUS             Status = AE_OK;
737167802Sjkim    ACPI_EVALUATE_INFO      *Info;
738237412Sjkim    ACPI_GPE_NOTIFY_INFO    *Notify;
739114239Snjl
740114239Snjl
741167802Sjkim    ACPI_FUNCTION_TRACE (EvAsynchExecuteGpeMethod);
742114239Snjl
743114239Snjl
744216471Sjkim    /* Do the correct dispatch - normal method or implicit notify */
745216471Sjkim
746278970Sjkim    switch (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags))
747114239Snjl    {
748216471Sjkim    case ACPI_GPE_DISPATCH_NOTIFY:
749216471Sjkim        /*
750216471Sjkim         * Implicit notify.
751216471Sjkim         * Dispatch a DEVICE_WAKE notify to the appropriate handler.
752216471Sjkim         * NOTE: the request is queued for execution after this method
753216471Sjkim         * completes. The notify handlers are NOT invoked synchronously
754216471Sjkim         * from this thread -- because handlers may in turn run other
755216471Sjkim         * control methods.
756237412Sjkim         *
757237412Sjkim         * June 2012: Expand implicit notify mechanism to support
758237412Sjkim         * notifies on multiple device objects.
759216471Sjkim         */
760278970Sjkim        Notify = GpeEventInfo->Dispatch.NotifyList;
761237412Sjkim        while (ACPI_SUCCESS (Status) && Notify)
762237412Sjkim        {
763298714Sjkim            Status = AcpiEvQueueNotifyRequest (
764298714Sjkim                Notify->DeviceNode, ACPI_NOTIFY_DEVICE_WAKE);
765237412Sjkim
766237412Sjkim            Notify = Notify->Next;
767237412Sjkim        }
768216471Sjkim        break;
769216471Sjkim
770216471Sjkim    case ACPI_GPE_DISPATCH_METHOD:
771216471Sjkim
772167802Sjkim        /* Allocate the evaluation information block */
773129684Snjl
774167802Sjkim        Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
775167802Sjkim        if (!Info)
776167802Sjkim        {
777167802Sjkim            Status = AE_NO_MEMORY;
778167802Sjkim        }
779167802Sjkim        else
780167802Sjkim        {
781167802Sjkim            /*
782216471Sjkim             * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the
783216471Sjkim             * _Lxx/_Exx control method that corresponds to this GPE
784167802Sjkim             */
785278970Sjkim            Info->PrefixNode = GpeEventInfo->Dispatch.MethodNode;
786167802Sjkim            Info->Flags = ACPI_IGNORE_RETURN_VALUE;
787167802Sjkim
788167802Sjkim            Status = AcpiNsEvaluate (Info);
789167802Sjkim            ACPI_FREE (Info);
790167802Sjkim        }
791167802Sjkim
792114239Snjl        if (ACPI_FAILURE (Status))
793114239Snjl        {
794167802Sjkim            ACPI_EXCEPTION ((AE_INFO, Status,
795167802Sjkim                "while evaluating GPE method [%4.4s]",
796278970Sjkim                AcpiUtGetNodeName (GpeEventInfo->Dispatch.MethodNode)));
797114239Snjl        }
798216471Sjkim        break;
799216471Sjkim
800216471Sjkim    default:
801250838Sjkim
802278970Sjkim        goto ErrorExit; /* Should never happen */
803114239Snjl    }
804114239Snjl
805175256Snjl    /* Defer enabling of GPE until all notify handlers are done */
806193267Sjkim
807193267Sjkim    Status = AcpiOsExecute (OSL_NOTIFY_HANDLER,
808298714Sjkim        AcpiEvAsynchEnableGpe, GpeEventInfo);
809278970Sjkim    if (ACPI_SUCCESS (Status))
810193267Sjkim    {
811278970Sjkim        return_VOID;
812193267Sjkim    }
813278970Sjkim
814278970SjkimErrorExit:
815278970Sjkim    AcpiEvAsynchEnableGpe (GpeEventInfo);
816175256Snjl    return_VOID;
817175256Snjl}
818175256Snjl
819193267Sjkim
820193267Sjkim/*******************************************************************************
821193267Sjkim *
822193267Sjkim * FUNCTION:    AcpiEvAsynchEnableGpe
823193267Sjkim *
824193267Sjkim * PARAMETERS:  Context (GpeEventInfo) - Info for this GPE
825216471Sjkim *              Callback from AcpiOsExecute
826193267Sjkim *
827193267Sjkim * RETURN:      None
828193267Sjkim *
829193267Sjkim * DESCRIPTION: Asynchronous clear/enable for GPE. This allows the GPE to
830193267Sjkim *              complete (i.e., finish execution of Notify)
831193267Sjkim *
832193267Sjkim ******************************************************************************/
833193267Sjkim
834193267Sjkimstatic void ACPI_SYSTEM_XFACE
835175256SnjlAcpiEvAsynchEnableGpe (
836175256Snjl    void                    *Context)
837175256Snjl{
838193267Sjkim    ACPI_GPE_EVENT_INFO     *GpeEventInfo = Context;
839278970Sjkim    ACPI_CPU_FLAGS          Flags;
840216471Sjkim
841216471Sjkim
842278970Sjkim    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
843216471Sjkim    (void) AcpiEvFinishGpe (GpeEventInfo);
844278970Sjkim    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
845216471Sjkim
846216471Sjkim    return;
847216471Sjkim}
848216471Sjkim
849216471Sjkim
850216471Sjkim/*******************************************************************************
851216471Sjkim *
852216471Sjkim * FUNCTION:    AcpiEvFinishGpe
853216471Sjkim *
854216471Sjkim * PARAMETERS:  GpeEventInfo        - Info for this GPE
855216471Sjkim *
856216471Sjkim * RETURN:      Status
857216471Sjkim *
858216471Sjkim * DESCRIPTION: Clear/Enable a GPE. Common code that is used after execution
859216471Sjkim *              of a GPE method or a synchronous or asynchronous GPE handler.
860216471Sjkim *
861216471Sjkim ******************************************************************************/
862216471Sjkim
863216471SjkimACPI_STATUS
864216471SjkimAcpiEvFinishGpe (
865216471Sjkim    ACPI_GPE_EVENT_INFO     *GpeEventInfo)
866216471Sjkim{
867175256Snjl    ACPI_STATUS             Status;
868175256Snjl
869193267Sjkim
870175256Snjl    if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
871151937Sjkim            ACPI_GPE_LEVEL_TRIGGERED)
872114239Snjl    {
873114239Snjl        /*
874216471Sjkim         * GPE is level-triggered, we clear the GPE status bit after
875216471Sjkim         * handling the event.
876114239Snjl         */
877175256Snjl        Status = AcpiHwClearGpe (GpeEventInfo);
878114239Snjl        if (ACPI_FAILURE (Status))
879114239Snjl        {
880216471Sjkim            return (Status);
881114239Snjl        }
882114239Snjl    }
883114239Snjl
884209746Sjkim    /*
885216471Sjkim     * Enable this GPE, conditionally. This means that the GPE will
886278970Sjkim     * only be physically enabled if the EnableMask bit is set
887216471Sjkim     * in the EventInfo.
888209746Sjkim     */
889209746Sjkim    (void) AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_CONDITIONAL_ENABLE);
890316303Sjkim    GpeEventInfo->DisableForDispatch = FALSE;
891216471Sjkim    return (AE_OK);
892114239Snjl}
893114239Snjl
894114239Snjl
895114239Snjl/*******************************************************************************
896114239Snjl *
897114239Snjl * FUNCTION:    AcpiEvGpeDispatch
898114239Snjl *
899216471Sjkim * PARAMETERS:  GpeDevice           - Device node. NULL for GPE0/GPE1
900216471Sjkim *              GpeEventInfo        - Info for this GPE
901216471Sjkim *              GpeNumber           - Number relative to the parent GPE block
902114239Snjl *
903114239Snjl * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
904114239Snjl *
905114239Snjl * DESCRIPTION: Dispatch a General Purpose Event to either a function (e.g. EC)
906117521Snjl *              or method (e.g. _Lxx/_Exx) handler.
907114239Snjl *
908117521Snjl *              This function executes at interrupt level.
909117521Snjl *
910114239Snjl ******************************************************************************/
911114239Snjl
912114239SnjlUINT32
913114239SnjlAcpiEvGpeDispatch (
914216471Sjkim    ACPI_NAMESPACE_NODE     *GpeDevice,
915117521Snjl    ACPI_GPE_EVENT_INFO     *GpeEventInfo,
916117521Snjl    UINT32                  GpeNumber)
917114239Snjl{
918114239Snjl    ACPI_STATUS             Status;
919216471Sjkim    UINT32                  ReturnValue;
920114239Snjl
921114239Snjl
922167802Sjkim    ACPI_FUNCTION_TRACE (EvGpeDispatch);
923114239Snjl
924114239Snjl
925114239Snjl    /*
926216471Sjkim     * Always disable the GPE so that it does not keep firing before
927216471Sjkim     * any asynchronous activity completes (either from the execution
928216471Sjkim     * of a GPE method or an asynchronous GPE handler.)
929216471Sjkim     *
930216471Sjkim     * If there is no handler or method to run, just disable the
931216471Sjkim     * GPE and leave it disabled permanently to prevent further such
932216471Sjkim     * pointless events from firing.
933114239Snjl     */
934216471Sjkim    Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE);
935216471Sjkim    if (ACPI_FAILURE (Status))
936216471Sjkim    {
937216471Sjkim        ACPI_EXCEPTION ((AE_INFO, Status,
938272444Sjkim            "Unable to disable GPE %02X", GpeNumber));
939246849Sjkim        return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
940216471Sjkim    }
941216471Sjkim
942216471Sjkim    /*
943272444Sjkim     * If edge-triggered, clear the GPE status bit now. Note that
944272444Sjkim     * level-triggered events are cleared after the GPE is serviced.
945272444Sjkim     */
946272444Sjkim    if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
947272444Sjkim            ACPI_GPE_EDGE_TRIGGERED)
948272444Sjkim    {
949272444Sjkim        Status = AcpiHwClearGpe (GpeEventInfo);
950272444Sjkim        if (ACPI_FAILURE (Status))
951272444Sjkim        {
952272444Sjkim            ACPI_EXCEPTION ((AE_INFO, Status,
953272444Sjkim                "Unable to clear GPE %02X", GpeNumber));
954298714Sjkim            (void) AcpiHwLowSetGpe (
955298714Sjkim                GpeEventInfo, ACPI_GPE_CONDITIONAL_ENABLE);
956272444Sjkim            return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
957272444Sjkim        }
958272444Sjkim    }
959272444Sjkim
960316303Sjkim    GpeEventInfo->DisableForDispatch = TRUE;
961316303Sjkim
962272444Sjkim    /*
963216471Sjkim     * Dispatch the GPE to either an installed handler or the control
964216471Sjkim     * method associated with this GPE (_Lxx or _Exx). If a handler
965216471Sjkim     * exists, we invoke it and do not attempt to run the method.
966216471Sjkim     * If there is neither a handler nor a method, leave the GPE
967216471Sjkim     * disabled.
968216471Sjkim     */
969278970Sjkim    switch (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags))
970114239Snjl    {
971129684Snjl    case ACPI_GPE_DISPATCH_HANDLER:
972129684Snjl
973216471Sjkim        /* Invoke the installed handler (at interrupt level) */
974123315Snjl
975216471Sjkim        ReturnValue = GpeEventInfo->Dispatch.Handler->Address (
976216471Sjkim            GpeDevice, GpeNumber,
977216471Sjkim            GpeEventInfo->Dispatch.Handler->Context);
978123315Snjl
979216471Sjkim        /* If requested, clear (if level-triggered) and reenable the GPE */
980216471Sjkim
981216471Sjkim        if (ReturnValue & ACPI_REENABLE_GPE)
982123315Snjl        {
983216471Sjkim            (void) AcpiEvFinishGpe (GpeEventInfo);
984123315Snjl        }
985129684Snjl        break;
986129684Snjl
987129684Snjl    case ACPI_GPE_DISPATCH_METHOD:
988216471Sjkim    case ACPI_GPE_DISPATCH_NOTIFY:
989114239Snjl        /*
990123315Snjl         * Execute the method associated with the GPE
991123315Snjl         * NOTE: Level-triggered GPEs are cleared after the method completes.
992123315Snjl         */
993167802Sjkim        Status = AcpiOsExecute (OSL_GPE_HANDLER,
994298714Sjkim            AcpiEvAsynchExecuteGpeMethod, GpeEventInfo);
995151937Sjkim        if (ACPI_FAILURE (Status))
996114239Snjl        {
997167802Sjkim            ACPI_EXCEPTION ((AE_INFO, Status,
998272444Sjkim                "Unable to queue handler for GPE %02X - event disabled",
999167802Sjkim                GpeNumber));
1000114239Snjl        }
1001129684Snjl        break;
1002129684Snjl
1003129684Snjl    default:
1004206117Sjkim        /*
1005206117Sjkim         * No handler or method to run!
1006206117Sjkim         * 03/2010: This case should no longer be possible. We will not allow
1007206117Sjkim         * a GPE to be enabled if it has no handler or method.
1008206117Sjkim         */
1009167802Sjkim        ACPI_ERROR ((AE_INFO,
1010272444Sjkim            "No handler or method for GPE %02X, disabling event",
1011114239Snjl            GpeNumber));
1012129684Snjl        break;
1013114239Snjl    }
1014114239Snjl
1015246849Sjkim    return_UINT32 (ACPI_INTERRUPT_HANDLED);
1016114239Snjl}
1017114239Snjl
1018231844Sjkim#endif /* !ACPI_REDUCED_HARDWARE */
1019