xref: /titanic_52/usr/src/uts/intel/io/acpica/events/evgpe.c (revision 385cc6b4ad1792caef3f84eb61eed3f27085801f)
1ae115bc7Smrj /******************************************************************************
2ae115bc7Smrj  *
3ae115bc7Smrj  * Module Name: evgpe - General Purpose Event handling and dispatch
4ae115bc7Smrj  *
5ae115bc7Smrj  *****************************************************************************/
6ae115bc7Smrj 
726f3cdf0SGordon Ross /*
8*385cc6b4SJerry Jelinek  * Copyright (C) 2000 - 2016, Intel Corp.
9ae115bc7Smrj  * All rights reserved.
10ae115bc7Smrj  *
1126f3cdf0SGordon Ross  * Redistribution and use in source and binary forms, with or without
1226f3cdf0SGordon Ross  * modification, are permitted provided that the following conditions
1326f3cdf0SGordon Ross  * are met:
1426f3cdf0SGordon Ross  * 1. Redistributions of source code must retain the above copyright
1526f3cdf0SGordon Ross  *    notice, this list of conditions, and the following disclaimer,
1626f3cdf0SGordon Ross  *    without modification.
1726f3cdf0SGordon Ross  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
1826f3cdf0SGordon Ross  *    substantially similar to the "NO WARRANTY" disclaimer below
1926f3cdf0SGordon Ross  *    ("Disclaimer") and any redistribution must be conditioned upon
2026f3cdf0SGordon Ross  *    including a substantially similar Disclaimer requirement for further
2126f3cdf0SGordon Ross  *    binary redistribution.
2226f3cdf0SGordon Ross  * 3. Neither the names of the above-listed copyright holders nor the names
2326f3cdf0SGordon Ross  *    of any contributors may be used to endorse or promote products derived
2426f3cdf0SGordon Ross  *    from this software without specific prior written permission.
25ae115bc7Smrj  *
2626f3cdf0SGordon Ross  * Alternatively, this software may be distributed under the terms of the
2726f3cdf0SGordon Ross  * GNU General Public License ("GPL") version 2 as published by the Free
2826f3cdf0SGordon Ross  * Software Foundation.
29ae115bc7Smrj  *
3026f3cdf0SGordon Ross  * NO WARRANTY
3126f3cdf0SGordon Ross  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3226f3cdf0SGordon Ross  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3326f3cdf0SGordon Ross  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
3426f3cdf0SGordon Ross  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3526f3cdf0SGordon Ross  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3626f3cdf0SGordon Ross  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3726f3cdf0SGordon Ross  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3826f3cdf0SGordon Ross  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
3926f3cdf0SGordon Ross  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
4026f3cdf0SGordon Ross  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
4126f3cdf0SGordon Ross  * POSSIBILITY OF SUCH DAMAGES.
4226f3cdf0SGordon Ross  */
43ae115bc7Smrj 
44ae115bc7Smrj #include "acpi.h"
45aa2aa9a6SDana Myers #include "accommon.h"
46ae115bc7Smrj #include "acevents.h"
47ae115bc7Smrj #include "acnamesp.h"
48ae115bc7Smrj 
49ae115bc7Smrj #define _COMPONENT          ACPI_EVENTS
50ae115bc7Smrj         ACPI_MODULE_NAME    ("evgpe")
51ae115bc7Smrj 
52*385cc6b4SJerry Jelinek #if (!ACPI_REDUCED_HARDWARE) /* Entire module */
53*385cc6b4SJerry Jelinek 
54ae115bc7Smrj /* Local prototypes */
55ae115bc7Smrj 
56ae115bc7Smrj static void ACPI_SYSTEM_XFACE
57ae115bc7Smrj AcpiEvAsynchExecuteGpeMethod (
58ae115bc7Smrj     void                    *Context);
59ae115bc7Smrj 
60db2bae30SDana Myers static void ACPI_SYSTEM_XFACE
61db2bae30SDana Myers AcpiEvAsynchEnableGpe (
62db2bae30SDana Myers     void                    *Context);
63db2bae30SDana Myers 
64ae115bc7Smrj 
65ae115bc7Smrj /*******************************************************************************
66ae115bc7Smrj  *
6726f3cdf0SGordon Ross  * FUNCTION:    AcpiEvUpdateGpeEnableMask
68ae115bc7Smrj  *
69ae115bc7Smrj  * PARAMETERS:  GpeEventInfo            - GPE to update
70ae115bc7Smrj  *
71ae115bc7Smrj  * RETURN:      Status
72ae115bc7Smrj  *
7326f3cdf0SGordon Ross  * DESCRIPTION: Updates GPE register enable mask based upon whether there are
7426f3cdf0SGordon Ross  *              runtime references to this GPE
75ae115bc7Smrj  *
76ae115bc7Smrj  ******************************************************************************/
77ae115bc7Smrj 
78ae115bc7Smrj ACPI_STATUS
7926f3cdf0SGordon Ross AcpiEvUpdateGpeEnableMask (
8026f3cdf0SGordon Ross     ACPI_GPE_EVENT_INFO     *GpeEventInfo)
81ae115bc7Smrj {
82ae115bc7Smrj     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
8326f3cdf0SGordon Ross     UINT32                  RegisterBit;
84ae115bc7Smrj 
85ae115bc7Smrj 
8626f3cdf0SGordon Ross     ACPI_FUNCTION_TRACE (EvUpdateGpeEnableMask);
87ae115bc7Smrj 
88ae115bc7Smrj 
89ae115bc7Smrj     GpeRegisterInfo = GpeEventInfo->RegisterInfo;
90ae115bc7Smrj     if (!GpeRegisterInfo)
91ae115bc7Smrj     {
92ae115bc7Smrj         return_ACPI_STATUS (AE_NOT_EXIST);
93ae115bc7Smrj     }
94aa2aa9a6SDana Myers 
95*385cc6b4SJerry Jelinek     RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo);
96ae115bc7Smrj 
9726f3cdf0SGordon Ross     /* Clear the run bit up front */
98ae115bc7Smrj 
99ae115bc7Smrj     ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForRun, RegisterBit);
100ae115bc7Smrj 
10126f3cdf0SGordon Ross     /* Set the mask bit only if there are references to this GPE */
102ae115bc7Smrj 
10326f3cdf0SGordon Ross     if (GpeEventInfo->RuntimeCount)
104ae115bc7Smrj     {
10526f3cdf0SGordon Ross         ACPI_SET_BIT (GpeRegisterInfo->EnableForRun, (UINT8) RegisterBit);
106ae115bc7Smrj     }
107ae115bc7Smrj 
108*385cc6b4SJerry Jelinek     GpeRegisterInfo->EnableMask = GpeRegisterInfo->EnableForRun;
109ae115bc7Smrj     return_ACPI_STATUS (AE_OK);
110ae115bc7Smrj }
111ae115bc7Smrj 
112ae115bc7Smrj 
113ae115bc7Smrj /*******************************************************************************
114ae115bc7Smrj  *
115ae115bc7Smrj  * FUNCTION:    AcpiEvEnableGpe
116ae115bc7Smrj  *
117ae115bc7Smrj  * PARAMETERS:  GpeEventInfo            - GPE to enable
118ae115bc7Smrj  *
119ae115bc7Smrj  * RETURN:      Status
120ae115bc7Smrj  *
12126f3cdf0SGordon Ross  * DESCRIPTION: Clear a GPE of stale events and enable it.
122ae115bc7Smrj  *
123ae115bc7Smrj  ******************************************************************************/
124ae115bc7Smrj 
125ae115bc7Smrj ACPI_STATUS
126ae115bc7Smrj AcpiEvEnableGpe (
12726f3cdf0SGordon Ross     ACPI_GPE_EVENT_INFO     *GpeEventInfo)
128ae115bc7Smrj {
129ae115bc7Smrj     ACPI_STATUS             Status;
130ae115bc7Smrj 
131ae115bc7Smrj 
132ae115bc7Smrj     ACPI_FUNCTION_TRACE (EvEnableGpe);
133ae115bc7Smrj 
134ae115bc7Smrj 
13526f3cdf0SGordon Ross     /* Clear the GPE (of stale events) */
136ae115bc7Smrj 
137ae115bc7Smrj     Status = AcpiHwClearGpe (GpeEventInfo);
138ae115bc7Smrj     if (ACPI_FAILURE (Status))
139ae115bc7Smrj     {
140ae115bc7Smrj         return_ACPI_STATUS (Status);
141ae115bc7Smrj     }
142ae115bc7Smrj 
14326f3cdf0SGordon Ross     /* Enable the requested GPE */
144ae115bc7Smrj 
14526f3cdf0SGordon Ross     Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_ENABLE);
14626f3cdf0SGordon Ross     return_ACPI_STATUS (Status);
147ae115bc7Smrj }
148ae115bc7Smrj 
149ae115bc7Smrj 
150ae115bc7Smrj /*******************************************************************************
151ae115bc7Smrj  *
15226f3cdf0SGordon Ross  * FUNCTION:    AcpiEvAddGpeReference
153ae115bc7Smrj  *
15426f3cdf0SGordon Ross  * PARAMETERS:  GpeEventInfo            - Add a reference to this GPE
155ae115bc7Smrj  *
156ae115bc7Smrj  * RETURN:      Status
157ae115bc7Smrj  *
15826f3cdf0SGordon Ross  * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is
15926f3cdf0SGordon Ross  *              hardware-enabled.
160ae115bc7Smrj  *
161ae115bc7Smrj  ******************************************************************************/
162ae115bc7Smrj 
163ae115bc7Smrj ACPI_STATUS
16426f3cdf0SGordon Ross AcpiEvAddGpeReference (
165ae115bc7Smrj     ACPI_GPE_EVENT_INFO     *GpeEventInfo)
166ae115bc7Smrj {
16726f3cdf0SGordon Ross     ACPI_STATUS             Status = AE_OK;
168ae115bc7Smrj 
169ae115bc7Smrj 
17026f3cdf0SGordon Ross     ACPI_FUNCTION_TRACE (EvAddGpeReference);
171ae115bc7Smrj 
172ae115bc7Smrj 
17326f3cdf0SGordon Ross     if (GpeEventInfo->RuntimeCount == ACPI_UINT8_MAX)
17426f3cdf0SGordon Ross     {
17526f3cdf0SGordon Ross         return_ACPI_STATUS (AE_LIMIT);
17626f3cdf0SGordon Ross     }
177ae115bc7Smrj 
17826f3cdf0SGordon Ross     GpeEventInfo->RuntimeCount++;
17926f3cdf0SGordon Ross     if (GpeEventInfo->RuntimeCount == 1)
18026f3cdf0SGordon Ross     {
18126f3cdf0SGordon Ross         /* Enable on first reference */
182ae115bc7Smrj 
18326f3cdf0SGordon Ross         Status = AcpiEvUpdateGpeEnableMask (GpeEventInfo);
18426f3cdf0SGordon Ross         if (ACPI_SUCCESS (Status))
18526f3cdf0SGordon Ross         {
18626f3cdf0SGordon Ross             Status = AcpiEvEnableGpe (GpeEventInfo);
18726f3cdf0SGordon Ross         }
18826f3cdf0SGordon Ross 
189ae115bc7Smrj         if (ACPI_FAILURE (Status))
190ae115bc7Smrj         {
19126f3cdf0SGordon Ross             GpeEventInfo->RuntimeCount--;
19226f3cdf0SGordon Ross         }
19326f3cdf0SGordon Ross     }
19426f3cdf0SGordon Ross 
195ae115bc7Smrj     return_ACPI_STATUS (Status);
196ae115bc7Smrj }
197ae115bc7Smrj 
198ae115bc7Smrj 
19926f3cdf0SGordon Ross /*******************************************************************************
20026f3cdf0SGordon Ross  *
20126f3cdf0SGordon Ross  * FUNCTION:    AcpiEvRemoveGpeReference
20226f3cdf0SGordon Ross  *
20326f3cdf0SGordon Ross  * PARAMETERS:  GpeEventInfo            - Remove a reference to this GPE
20426f3cdf0SGordon Ross  *
20526f3cdf0SGordon Ross  * RETURN:      Status
20626f3cdf0SGordon Ross  *
20726f3cdf0SGordon Ross  * DESCRIPTION: Remove a reference to a GPE. When the last reference is
20826f3cdf0SGordon Ross  *              removed, the GPE is hardware-disabled.
20926f3cdf0SGordon Ross  *
21026f3cdf0SGordon Ross  ******************************************************************************/
21126f3cdf0SGordon Ross 
21226f3cdf0SGordon Ross ACPI_STATUS
21326f3cdf0SGordon Ross AcpiEvRemoveGpeReference (
21426f3cdf0SGordon Ross     ACPI_GPE_EVENT_INFO     *GpeEventInfo)
215ae115bc7Smrj {
21626f3cdf0SGordon Ross     ACPI_STATUS             Status = AE_OK;
217db2bae30SDana Myers 
218ae115bc7Smrj 
21926f3cdf0SGordon Ross     ACPI_FUNCTION_TRACE (EvRemoveGpeReference);
220db2bae30SDana Myers 
221ae115bc7Smrj 
22226f3cdf0SGordon Ross     if (!GpeEventInfo->RuntimeCount)
22326f3cdf0SGordon Ross     {
22426f3cdf0SGordon Ross         return_ACPI_STATUS (AE_LIMIT);
225ae115bc7Smrj     }
226ae115bc7Smrj 
22726f3cdf0SGordon Ross     GpeEventInfo->RuntimeCount--;
22826f3cdf0SGordon Ross     if (!GpeEventInfo->RuntimeCount)
22926f3cdf0SGordon Ross     {
23026f3cdf0SGordon Ross         /* Disable on last reference */
23126f3cdf0SGordon Ross 
23226f3cdf0SGordon Ross         Status = AcpiEvUpdateGpeEnableMask (GpeEventInfo);
23326f3cdf0SGordon Ross         if (ACPI_SUCCESS (Status))
23426f3cdf0SGordon Ross         {
23526f3cdf0SGordon Ross             Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE);
23626f3cdf0SGordon Ross         }
23726f3cdf0SGordon Ross 
23826f3cdf0SGordon Ross         if (ACPI_FAILURE (Status))
23926f3cdf0SGordon Ross         {
24026f3cdf0SGordon Ross             GpeEventInfo->RuntimeCount++;
24126f3cdf0SGordon Ross         }
24226f3cdf0SGordon Ross     }
24326f3cdf0SGordon Ross 
24426f3cdf0SGordon Ross     return_ACPI_STATUS (Status);
24526f3cdf0SGordon Ross }
24626f3cdf0SGordon Ross 
24726f3cdf0SGordon Ross 
24826f3cdf0SGordon Ross /*******************************************************************************
24926f3cdf0SGordon Ross  *
25026f3cdf0SGordon Ross  * FUNCTION:    AcpiEvLowGetGpeInfo
25126f3cdf0SGordon Ross  *
25226f3cdf0SGordon Ross  * PARAMETERS:  GpeNumber           - Raw GPE number
25326f3cdf0SGordon Ross  *              GpeBlock            - A GPE info block
25426f3cdf0SGordon Ross  *
25526f3cdf0SGordon Ross  * RETURN:      A GPE EventInfo struct. NULL if not a valid GPE (The GpeNumber
25626f3cdf0SGordon Ross  *              is not within the specified GPE block)
25726f3cdf0SGordon Ross  *
25826f3cdf0SGordon Ross  * DESCRIPTION: Returns the EventInfo struct associated with this GPE. This is
25926f3cdf0SGordon Ross  *              the low-level implementation of EvGetGpeEventInfo.
26026f3cdf0SGordon Ross  *
26126f3cdf0SGordon Ross  ******************************************************************************/
26226f3cdf0SGordon Ross 
26326f3cdf0SGordon Ross ACPI_GPE_EVENT_INFO *
26426f3cdf0SGordon Ross AcpiEvLowGetGpeInfo (
26526f3cdf0SGordon Ross     UINT32                  GpeNumber,
26626f3cdf0SGordon Ross     ACPI_GPE_BLOCK_INFO     *GpeBlock)
26726f3cdf0SGordon Ross {
26826f3cdf0SGordon Ross     UINT32                  GpeIndex;
26926f3cdf0SGordon Ross 
27026f3cdf0SGordon Ross 
271db2bae30SDana Myers     /*
27226f3cdf0SGordon Ross      * Validate that the GpeNumber is within the specified GpeBlock.
27326f3cdf0SGordon Ross      * (Two steps)
274db2bae30SDana Myers      */
27526f3cdf0SGordon Ross     if (!GpeBlock ||
27626f3cdf0SGordon Ross         (GpeNumber < GpeBlock->BlockBaseNumber))
27726f3cdf0SGordon Ross     {
27826f3cdf0SGordon Ross         return (NULL);
27926f3cdf0SGordon Ross     }
28026f3cdf0SGordon Ross 
28126f3cdf0SGordon Ross     GpeIndex = GpeNumber - GpeBlock->BlockBaseNumber;
28226f3cdf0SGordon Ross     if (GpeIndex >= GpeBlock->GpeCount)
28326f3cdf0SGordon Ross     {
28426f3cdf0SGordon Ross         return (NULL);
28526f3cdf0SGordon Ross     }
28626f3cdf0SGordon Ross 
28726f3cdf0SGordon Ross     return (&GpeBlock->EventInfo[GpeIndex]);
288ae115bc7Smrj }
289ae115bc7Smrj 
290ae115bc7Smrj 
291ae115bc7Smrj /*******************************************************************************
292ae115bc7Smrj  *
293ae115bc7Smrj  * FUNCTION:    AcpiEvGetGpeEventInfo
294ae115bc7Smrj  *
295ae115bc7Smrj  * PARAMETERS:  GpeDevice           - Device node. NULL for GPE0/GPE1
296ae115bc7Smrj  *              GpeNumber           - Raw GPE number
297ae115bc7Smrj  *
298ae115bc7Smrj  * RETURN:      A GPE EventInfo struct. NULL if not a valid GPE
299ae115bc7Smrj  *
300ae115bc7Smrj  * DESCRIPTION: Returns the EventInfo struct associated with this GPE.
301ae115bc7Smrj  *              Validates the GpeBlock and the GpeNumber
302ae115bc7Smrj  *
303ae115bc7Smrj  *              Should be called only when the GPE lists are semaphore locked
304ae115bc7Smrj  *              and not subject to change.
305ae115bc7Smrj  *
306ae115bc7Smrj  ******************************************************************************/
307ae115bc7Smrj 
308ae115bc7Smrj ACPI_GPE_EVENT_INFO *
309ae115bc7Smrj AcpiEvGetGpeEventInfo (
310ae115bc7Smrj     ACPI_HANDLE             GpeDevice,
311ae115bc7Smrj     UINT32                  GpeNumber)
312ae115bc7Smrj {
313ae115bc7Smrj     ACPI_OPERAND_OBJECT     *ObjDesc;
31426f3cdf0SGordon Ross     ACPI_GPE_EVENT_INFO     *GpeInfo;
315db2bae30SDana Myers     UINT32                  i;
316ae115bc7Smrj 
317ae115bc7Smrj 
318ae115bc7Smrj     ACPI_FUNCTION_ENTRY ();
319ae115bc7Smrj 
320ae115bc7Smrj 
32126f3cdf0SGordon Ross     /* A NULL GpeDevice means use the FADT-defined GPE block(s) */
322ae115bc7Smrj 
323ae115bc7Smrj     if (!GpeDevice)
324ae115bc7Smrj     {
325ae115bc7Smrj         /* Examine GPE Block 0 and 1 (These blocks are permanent) */
326ae115bc7Smrj 
327ae115bc7Smrj         for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++)
328ae115bc7Smrj         {
32926f3cdf0SGordon Ross             GpeInfo = AcpiEvLowGetGpeInfo (GpeNumber,
33026f3cdf0SGordon Ross                 AcpiGbl_GpeFadtBlocks[i]);
33126f3cdf0SGordon Ross             if (GpeInfo)
332ae115bc7Smrj             {
33326f3cdf0SGordon Ross                 return (GpeInfo);
334ae115bc7Smrj             }
335ae115bc7Smrj         }
336ae115bc7Smrj 
337ae115bc7Smrj         /* The GpeNumber was not in the range of either FADT GPE block */
338ae115bc7Smrj 
339ae115bc7Smrj         return (NULL);
340ae115bc7Smrj     }
341ae115bc7Smrj 
342ae115bc7Smrj     /* A Non-NULL GpeDevice means this is a GPE Block Device */
343ae115bc7Smrj 
344ae115bc7Smrj     ObjDesc = AcpiNsGetAttachedObject ((ACPI_NAMESPACE_NODE *) GpeDevice);
345ae115bc7Smrj     if (!ObjDesc ||
346ae115bc7Smrj         !ObjDesc->Device.GpeBlock)
347ae115bc7Smrj     {
348ae115bc7Smrj         return (NULL);
349ae115bc7Smrj     }
350ae115bc7Smrj 
35126f3cdf0SGordon Ross     return (AcpiEvLowGetGpeInfo (GpeNumber, ObjDesc->Device.GpeBlock));
352ae115bc7Smrj }
353ae115bc7Smrj 
354ae115bc7Smrj 
355ae115bc7Smrj /*******************************************************************************
356ae115bc7Smrj  *
357ae115bc7Smrj  * FUNCTION:    AcpiEvGpeDetect
358ae115bc7Smrj  *
359ae115bc7Smrj  * PARAMETERS:  GpeXruptList        - Interrupt block for this interrupt.
360ae115bc7Smrj  *                                    Can have multiple GPE blocks attached.
361ae115bc7Smrj  *
362ae115bc7Smrj  * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
363ae115bc7Smrj  *
364ae115bc7Smrj  * DESCRIPTION: Detect if any GP events have occurred. This function is
365ae115bc7Smrj  *              executed at interrupt level.
366ae115bc7Smrj  *
367ae115bc7Smrj  ******************************************************************************/
368ae115bc7Smrj 
369ae115bc7Smrj UINT32
370ae115bc7Smrj AcpiEvGpeDetect (
371ae115bc7Smrj     ACPI_GPE_XRUPT_INFO     *GpeXruptList)
372ae115bc7Smrj {
373ae115bc7Smrj     ACPI_STATUS             Status;
374ae115bc7Smrj     ACPI_GPE_BLOCK_INFO     *GpeBlock;
375*385cc6b4SJerry Jelinek     ACPI_NAMESPACE_NODE     *GpeDevice;
376ae115bc7Smrj     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
377*385cc6b4SJerry Jelinek     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
378*385cc6b4SJerry Jelinek     UINT32                  GpeNumber;
379*385cc6b4SJerry Jelinek     ACPI_GPE_HANDLER_INFO   *GpeHandlerInfo;
380ae115bc7Smrj     UINT32                  IntStatus = ACPI_INTERRUPT_NOT_HANDLED;
381ae115bc7Smrj     UINT8                   EnabledStatusByte;
382ae115bc7Smrj     UINT32                  StatusReg;
383ae115bc7Smrj     UINT32                  EnableReg;
384ae115bc7Smrj     ACPI_CPU_FLAGS          Flags;
385db2bae30SDana Myers     UINT32                  i;
386db2bae30SDana Myers     UINT32                  j;
387ae115bc7Smrj 
388ae115bc7Smrj 
389ae115bc7Smrj     ACPI_FUNCTION_NAME (EvGpeDetect);
390ae115bc7Smrj 
391ae115bc7Smrj     /* Check for the case where there are no GPEs */
392ae115bc7Smrj 
393ae115bc7Smrj     if (!GpeXruptList)
394ae115bc7Smrj     {
395ae115bc7Smrj         return (IntStatus);
396ae115bc7Smrj     }
397ae115bc7Smrj 
398ae115bc7Smrj     /*
399ae115bc7Smrj      * We need to obtain the GPE lock for both the data structs and registers
400aa2aa9a6SDana Myers      * Note: Not necessary to obtain the hardware lock, since the GPE
401aa2aa9a6SDana Myers      * registers are owned by the GpeLock.
402ae115bc7Smrj      */
403ae115bc7Smrj     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
404ae115bc7Smrj 
405ae115bc7Smrj     /* Examine all GPE blocks attached to this interrupt level */
406ae115bc7Smrj 
407ae115bc7Smrj     GpeBlock = GpeXruptList->GpeBlockListHead;
408ae115bc7Smrj     while (GpeBlock)
409ae115bc7Smrj     {
410*385cc6b4SJerry Jelinek         GpeDevice = GpeBlock->Node;
411*385cc6b4SJerry Jelinek 
412ae115bc7Smrj         /*
413aa2aa9a6SDana Myers          * Read all of the 8-bit GPE status and enable registers in this GPE
414aa2aa9a6SDana Myers          * block, saving all of them. Find all currently active GP events.
415ae115bc7Smrj          */
416ae115bc7Smrj         for (i = 0; i < GpeBlock->RegisterCount; i++)
417ae115bc7Smrj         {
418ae115bc7Smrj             /* Get the next status/enable pair */
419ae115bc7Smrj 
420ae115bc7Smrj             GpeRegisterInfo = &GpeBlock->RegisterInfo[i];
421ae115bc7Smrj 
42226f3cdf0SGordon Ross             /*
42326f3cdf0SGordon Ross              * Optimization: If there are no GPEs enabled within this
42426f3cdf0SGordon Ross              * register, we can safely ignore the entire register.
42526f3cdf0SGordon Ross              */
42626f3cdf0SGordon Ross             if (!(GpeRegisterInfo->EnableForRun |
42726f3cdf0SGordon Ross                   GpeRegisterInfo->EnableForWake))
42826f3cdf0SGordon Ross             {
429*385cc6b4SJerry Jelinek                 ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
430*385cc6b4SJerry Jelinek                     "Ignore disabled registers for GPE %02X-%02X: "
431*385cc6b4SJerry Jelinek                     "RunEnable=%02X, WakeEnable=%02X\n",
432*385cc6b4SJerry Jelinek                     GpeRegisterInfo->BaseGpeNumber,
433*385cc6b4SJerry Jelinek                     GpeRegisterInfo->BaseGpeNumber + (ACPI_GPE_REGISTER_WIDTH - 1),
434*385cc6b4SJerry Jelinek                     GpeRegisterInfo->EnableForRun,
435*385cc6b4SJerry Jelinek                     GpeRegisterInfo->EnableForWake));
43626f3cdf0SGordon Ross                 continue;
43726f3cdf0SGordon Ross             }
43826f3cdf0SGordon Ross 
439ae115bc7Smrj             /* Read the Status Register */
440ae115bc7Smrj 
44157190917SDana Myers             Status = AcpiHwRead (&StatusReg, &GpeRegisterInfo->StatusAddress);
442ae115bc7Smrj             if (ACPI_FAILURE (Status))
443ae115bc7Smrj             {
444ae115bc7Smrj                 goto UnlockAndExit;
445ae115bc7Smrj             }
446ae115bc7Smrj 
447ae115bc7Smrj             /* Read the Enable Register */
448ae115bc7Smrj 
44957190917SDana Myers             Status = AcpiHwRead (&EnableReg, &GpeRegisterInfo->EnableAddress);
450ae115bc7Smrj             if (ACPI_FAILURE (Status))
451ae115bc7Smrj             {
452ae115bc7Smrj                 goto UnlockAndExit;
453ae115bc7Smrj             }
454ae115bc7Smrj 
455ae115bc7Smrj             ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
456*385cc6b4SJerry Jelinek                 "Read registers for GPE %02X-%02X: Status=%02X, Enable=%02X, "
457*385cc6b4SJerry Jelinek                 "RunEnable=%02X, WakeEnable=%02X\n",
458*385cc6b4SJerry Jelinek                 GpeRegisterInfo->BaseGpeNumber,
459*385cc6b4SJerry Jelinek                 GpeRegisterInfo->BaseGpeNumber + (ACPI_GPE_REGISTER_WIDTH - 1),
460*385cc6b4SJerry Jelinek                 StatusReg, EnableReg,
461*385cc6b4SJerry Jelinek                 GpeRegisterInfo->EnableForRun,
462*385cc6b4SJerry Jelinek                 GpeRegisterInfo->EnableForWake));
463ae115bc7Smrj 
464ae115bc7Smrj             /* Check if there is anything active at all in this register */
465ae115bc7Smrj 
466ae115bc7Smrj             EnabledStatusByte = (UINT8) (StatusReg & EnableReg);
467ae115bc7Smrj             if (!EnabledStatusByte)
468ae115bc7Smrj             {
469ae115bc7Smrj                 /* No active GPEs in this register, move on */
470ae115bc7Smrj 
471ae115bc7Smrj                 continue;
472ae115bc7Smrj             }
473ae115bc7Smrj 
474ae115bc7Smrj             /* Now look at the individual GPEs in this byte register */
475ae115bc7Smrj 
476ae115bc7Smrj             for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++)
477ae115bc7Smrj             {
478ae115bc7Smrj                 /* Examine one GPE bit */
479ae115bc7Smrj 
480*385cc6b4SJerry Jelinek                 GpeEventInfo = &GpeBlock->EventInfo[((ACPI_SIZE) i *
481*385cc6b4SJerry Jelinek                     ACPI_GPE_REGISTER_WIDTH) + j];
482*385cc6b4SJerry Jelinek                 GpeNumber = j + GpeRegisterInfo->BaseGpeNumber;
483*385cc6b4SJerry Jelinek 
484db2bae30SDana Myers                 if (EnabledStatusByte & (1 << j))
485ae115bc7Smrj                 {
486*385cc6b4SJerry Jelinek                     /* Invoke global event handler if present */
487*385cc6b4SJerry Jelinek 
488*385cc6b4SJerry Jelinek                     AcpiGpeCount++;
489*385cc6b4SJerry Jelinek                     if (AcpiGbl_GlobalEventHandler)
490*385cc6b4SJerry Jelinek                     {
491*385cc6b4SJerry Jelinek                         AcpiGbl_GlobalEventHandler (ACPI_EVENT_TYPE_GPE,
492*385cc6b4SJerry Jelinek                             GpeDevice, GpeNumber,
493*385cc6b4SJerry Jelinek                             AcpiGbl_GlobalEventHandlerContext);
494*385cc6b4SJerry Jelinek                     }
495*385cc6b4SJerry Jelinek 
496*385cc6b4SJerry Jelinek                     /* Found an active GPE */
497*385cc6b4SJerry Jelinek 
498*385cc6b4SJerry Jelinek                     if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) ==
499*385cc6b4SJerry Jelinek                         ACPI_GPE_DISPATCH_RAW_HANDLER)
500*385cc6b4SJerry Jelinek                     {
501*385cc6b4SJerry Jelinek                         /* Dispatch the event to a raw handler */
502*385cc6b4SJerry Jelinek 
503*385cc6b4SJerry Jelinek                         GpeHandlerInfo = GpeEventInfo->Dispatch.Handler;
504*385cc6b4SJerry Jelinek 
505ae115bc7Smrj                         /*
506*385cc6b4SJerry Jelinek                          * There is no protection around the namespace node
507*385cc6b4SJerry Jelinek                          * and the GPE handler to ensure a safe destruction
508*385cc6b4SJerry Jelinek                          * because:
509*385cc6b4SJerry Jelinek                          * 1. The namespace node is expected to always
510*385cc6b4SJerry Jelinek                          *    exist after loading a table.
511*385cc6b4SJerry Jelinek                          * 2. The GPE handler is expected to be flushed by
512*385cc6b4SJerry Jelinek                          *    AcpiOsWaitEventsComplete() before the
513*385cc6b4SJerry Jelinek                          *    destruction.
514ae115bc7Smrj                          */
515*385cc6b4SJerry Jelinek                         AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
516*385cc6b4SJerry Jelinek                         IntStatus |= GpeHandlerInfo->Address (
517*385cc6b4SJerry Jelinek                             GpeDevice, GpeNumber, GpeHandlerInfo->Context);
518*385cc6b4SJerry Jelinek                         Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
519*385cc6b4SJerry Jelinek                     }
520*385cc6b4SJerry Jelinek                     else
521*385cc6b4SJerry Jelinek                     {
522*385cc6b4SJerry Jelinek                         /*
523*385cc6b4SJerry Jelinek                          * Dispatch the event to a standard handler or
524*385cc6b4SJerry Jelinek                          * method.
525*385cc6b4SJerry Jelinek                          */
526*385cc6b4SJerry Jelinek                         IntStatus |= AcpiEvGpeDispatch (GpeDevice,
527*385cc6b4SJerry Jelinek                             GpeEventInfo, GpeNumber);
528*385cc6b4SJerry Jelinek                     }
529ae115bc7Smrj                 }
530ae115bc7Smrj             }
531ae115bc7Smrj         }
532ae115bc7Smrj 
533ae115bc7Smrj         GpeBlock = GpeBlock->Next;
534ae115bc7Smrj     }
535ae115bc7Smrj 
536ae115bc7Smrj UnlockAndExit:
537ae115bc7Smrj 
538ae115bc7Smrj     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
539ae115bc7Smrj     return (IntStatus);
540ae115bc7Smrj }
541ae115bc7Smrj 
542ae115bc7Smrj 
543ae115bc7Smrj /*******************************************************************************
544ae115bc7Smrj  *
545ae115bc7Smrj  * FUNCTION:    AcpiEvAsynchExecuteGpeMethod
546ae115bc7Smrj  *
547ae115bc7Smrj  * PARAMETERS:  Context (GpeEventInfo) - Info for this GPE
548ae115bc7Smrj  *
549ae115bc7Smrj  * RETURN:      None
550ae115bc7Smrj  *
551ae115bc7Smrj  * DESCRIPTION: Perform the actual execution of a GPE control method. This
552ae115bc7Smrj  *              function is called from an invocation of AcpiOsExecute and
553ae115bc7Smrj  *              therefore does NOT execute at interrupt level - so that
554ae115bc7Smrj  *              the control method itself is not executed in the context of
555ae115bc7Smrj  *              an interrupt handler.
556ae115bc7Smrj  *
557ae115bc7Smrj  ******************************************************************************/
558ae115bc7Smrj 
559ae115bc7Smrj static void ACPI_SYSTEM_XFACE
560ae115bc7Smrj AcpiEvAsynchExecuteGpeMethod (
561ae115bc7Smrj     void                    *Context)
562ae115bc7Smrj {
563db2bae30SDana Myers     ACPI_GPE_EVENT_INFO     *GpeEventInfo = Context;
564*385cc6b4SJerry Jelinek     ACPI_STATUS             Status = AE_OK;
565ae115bc7Smrj     ACPI_EVALUATE_INFO      *Info;
566*385cc6b4SJerry Jelinek     ACPI_GPE_NOTIFY_INFO    *Notify;
567ae115bc7Smrj 
568ae115bc7Smrj 
569ae115bc7Smrj     ACPI_FUNCTION_TRACE (EvAsynchExecuteGpeMethod);
570ae115bc7Smrj 
571ae115bc7Smrj 
57226f3cdf0SGordon Ross     /* Do the correct dispatch - normal method or implicit notify */
57326f3cdf0SGordon Ross 
574*385cc6b4SJerry Jelinek     switch (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags))
575ae115bc7Smrj     {
57626f3cdf0SGordon Ross     case ACPI_GPE_DISPATCH_NOTIFY:
57726f3cdf0SGordon Ross         /*
57826f3cdf0SGordon Ross          * Implicit notify.
57926f3cdf0SGordon Ross          * Dispatch a DEVICE_WAKE notify to the appropriate handler.
58026f3cdf0SGordon Ross          * NOTE: the request is queued for execution after this method
58126f3cdf0SGordon Ross          * completes. The notify handlers are NOT invoked synchronously
58226f3cdf0SGordon Ross          * from this thread -- because handlers may in turn run other
58326f3cdf0SGordon Ross          * control methods.
584*385cc6b4SJerry Jelinek          *
585*385cc6b4SJerry Jelinek          * June 2012: Expand implicit notify mechanism to support
586*385cc6b4SJerry Jelinek          * notifies on multiple device objects.
58726f3cdf0SGordon Ross          */
588*385cc6b4SJerry Jelinek         Notify = GpeEventInfo->Dispatch.NotifyList;
589*385cc6b4SJerry Jelinek         while (ACPI_SUCCESS (Status) && Notify)
590*385cc6b4SJerry Jelinek         {
59126f3cdf0SGordon Ross             Status = AcpiEvQueueNotifyRequest (
592*385cc6b4SJerry Jelinek                 Notify->DeviceNode, ACPI_NOTIFY_DEVICE_WAKE);
593*385cc6b4SJerry Jelinek 
594*385cc6b4SJerry Jelinek             Notify = Notify->Next;
595*385cc6b4SJerry Jelinek         }
59626f3cdf0SGordon Ross         break;
59726f3cdf0SGordon Ross 
59826f3cdf0SGordon Ross     case ACPI_GPE_DISPATCH_METHOD:
59926f3cdf0SGordon Ross 
600ae115bc7Smrj         /* Allocate the evaluation information block */
601ae115bc7Smrj 
602ae115bc7Smrj         Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
603ae115bc7Smrj         if (!Info)
604ae115bc7Smrj         {
605ae115bc7Smrj             Status = AE_NO_MEMORY;
606ae115bc7Smrj         }
607ae115bc7Smrj         else
608ae115bc7Smrj         {
609ae115bc7Smrj             /*
61026f3cdf0SGordon Ross              * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the
61126f3cdf0SGordon Ross              * _Lxx/_Exx control method that corresponds to this GPE
612ae115bc7Smrj              */
613*385cc6b4SJerry Jelinek             Info->PrefixNode = GpeEventInfo->Dispatch.MethodNode;
614ae115bc7Smrj             Info->Flags = ACPI_IGNORE_RETURN_VALUE;
615ae115bc7Smrj 
616ae115bc7Smrj             Status = AcpiNsEvaluate (Info);
617ae115bc7Smrj             ACPI_FREE (Info);
618ae115bc7Smrj         }
619ae115bc7Smrj 
620ae115bc7Smrj         if (ACPI_FAILURE (Status))
621ae115bc7Smrj         {
622ae115bc7Smrj             ACPI_EXCEPTION ((AE_INFO, Status,
623db2bae30SDana Myers                 "while evaluating GPE method [%4.4s]",
624*385cc6b4SJerry Jelinek                 AcpiUtGetNodeName (GpeEventInfo->Dispatch.MethodNode)));
625ae115bc7Smrj         }
62626f3cdf0SGordon Ross         break;
62726f3cdf0SGordon Ross 
62826f3cdf0SGordon Ross     default:
629*385cc6b4SJerry Jelinek 
630*385cc6b4SJerry Jelinek         goto ErrorExit; /* Should never happen */
631ae115bc7Smrj     }
632ae115bc7Smrj 
633db2bae30SDana Myers     /* Defer enabling of GPE until all notify handlers are done */
634db2bae30SDana Myers 
635db2bae30SDana Myers     Status = AcpiOsExecute (OSL_NOTIFY_HANDLER,
636*385cc6b4SJerry Jelinek         AcpiEvAsynchEnableGpe, GpeEventInfo);
637*385cc6b4SJerry Jelinek     if (ACPI_SUCCESS (Status))
638db2bae30SDana Myers     {
639*385cc6b4SJerry Jelinek         return_VOID;
640db2bae30SDana Myers     }
641*385cc6b4SJerry Jelinek 
642*385cc6b4SJerry Jelinek ErrorExit:
643*385cc6b4SJerry Jelinek     AcpiEvAsynchEnableGpe (GpeEventInfo);
644db2bae30SDana Myers     return_VOID;
645db2bae30SDana Myers }
646db2bae30SDana Myers 
647db2bae30SDana Myers 
648db2bae30SDana Myers /*******************************************************************************
649db2bae30SDana Myers  *
650db2bae30SDana Myers  * FUNCTION:    AcpiEvAsynchEnableGpe
651db2bae30SDana Myers  *
652db2bae30SDana Myers  * PARAMETERS:  Context (GpeEventInfo) - Info for this GPE
65326f3cdf0SGordon Ross  *              Callback from AcpiOsExecute
654db2bae30SDana Myers  *
655db2bae30SDana Myers  * RETURN:      None
656db2bae30SDana Myers  *
657db2bae30SDana Myers  * DESCRIPTION: Asynchronous clear/enable for GPE. This allows the GPE to
658db2bae30SDana Myers  *              complete (i.e., finish execution of Notify)
659db2bae30SDana Myers  *
660db2bae30SDana Myers  ******************************************************************************/
661db2bae30SDana Myers 
662db2bae30SDana Myers static void ACPI_SYSTEM_XFACE
663db2bae30SDana Myers AcpiEvAsynchEnableGpe (
664db2bae30SDana Myers     void                    *Context)
665db2bae30SDana Myers {
666db2bae30SDana Myers     ACPI_GPE_EVENT_INFO     *GpeEventInfo = Context;
667*385cc6b4SJerry Jelinek     ACPI_CPU_FLAGS          Flags;
668db2bae30SDana Myers 
669db2bae30SDana Myers 
670*385cc6b4SJerry Jelinek     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
67126f3cdf0SGordon Ross     (void) AcpiEvFinishGpe (GpeEventInfo);
672*385cc6b4SJerry Jelinek     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
673ae115bc7Smrj 
674db2bae30SDana Myers     return;
675ae115bc7Smrj }
676ae115bc7Smrj 
677ae115bc7Smrj 
678ae115bc7Smrj /*******************************************************************************
679ae115bc7Smrj  *
68026f3cdf0SGordon Ross  * FUNCTION:    AcpiEvFinishGpe
681ae115bc7Smrj  *
682ae115bc7Smrj  * PARAMETERS:  GpeEventInfo        - Info for this GPE
68326f3cdf0SGordon Ross  *
68426f3cdf0SGordon Ross  * RETURN:      Status
68526f3cdf0SGordon Ross  *
68626f3cdf0SGordon Ross  * DESCRIPTION: Clear/Enable a GPE. Common code that is used after execution
68726f3cdf0SGordon Ross  *              of a GPE method or a synchronous or asynchronous GPE handler.
68826f3cdf0SGordon Ross  *
68926f3cdf0SGordon Ross  ******************************************************************************/
69026f3cdf0SGordon Ross 
69126f3cdf0SGordon Ross ACPI_STATUS
69226f3cdf0SGordon Ross AcpiEvFinishGpe (
69326f3cdf0SGordon Ross     ACPI_GPE_EVENT_INFO     *GpeEventInfo)
69426f3cdf0SGordon Ross {
69526f3cdf0SGordon Ross     ACPI_STATUS             Status;
69626f3cdf0SGordon Ross 
69726f3cdf0SGordon Ross 
69826f3cdf0SGordon Ross     if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
69926f3cdf0SGordon Ross             ACPI_GPE_LEVEL_TRIGGERED)
70026f3cdf0SGordon Ross     {
70126f3cdf0SGordon Ross         /*
70226f3cdf0SGordon Ross          * GPE is level-triggered, we clear the GPE status bit after
70326f3cdf0SGordon Ross          * handling the event.
70426f3cdf0SGordon Ross          */
70526f3cdf0SGordon Ross         Status = AcpiHwClearGpe (GpeEventInfo);
70626f3cdf0SGordon Ross         if (ACPI_FAILURE (Status))
70726f3cdf0SGordon Ross         {
70826f3cdf0SGordon Ross             return (Status);
70926f3cdf0SGordon Ross         }
71026f3cdf0SGordon Ross     }
71126f3cdf0SGordon Ross 
71226f3cdf0SGordon Ross     /*
71326f3cdf0SGordon Ross      * Enable this GPE, conditionally. This means that the GPE will
714*385cc6b4SJerry Jelinek      * only be physically enabled if the EnableMask bit is set
71526f3cdf0SGordon Ross      * in the EventInfo.
71626f3cdf0SGordon Ross      */
71726f3cdf0SGordon Ross     (void) AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_CONDITIONAL_ENABLE);
71826f3cdf0SGordon Ross     return (AE_OK);
71926f3cdf0SGordon Ross }
72026f3cdf0SGordon Ross 
72126f3cdf0SGordon Ross 
72226f3cdf0SGordon Ross /*******************************************************************************
72326f3cdf0SGordon Ross  *
72426f3cdf0SGordon Ross  * FUNCTION:    AcpiEvGpeDispatch
72526f3cdf0SGordon Ross  *
72626f3cdf0SGordon Ross  * PARAMETERS:  GpeDevice           - Device node. NULL for GPE0/GPE1
72726f3cdf0SGordon Ross  *              GpeEventInfo        - Info for this GPE
728ae115bc7Smrj  *              GpeNumber           - Number relative to the parent GPE block
729ae115bc7Smrj  *
730ae115bc7Smrj  * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
731ae115bc7Smrj  *
732ae115bc7Smrj  * DESCRIPTION: Dispatch a General Purpose Event to either a function (e.g. EC)
733ae115bc7Smrj  *              or method (e.g. _Lxx/_Exx) handler.
734ae115bc7Smrj  *
735ae115bc7Smrj  *              This function executes at interrupt level.
736ae115bc7Smrj  *
737ae115bc7Smrj  ******************************************************************************/
738ae115bc7Smrj 
739ae115bc7Smrj UINT32
740ae115bc7Smrj AcpiEvGpeDispatch (
74126f3cdf0SGordon Ross     ACPI_NAMESPACE_NODE     *GpeDevice,
742ae115bc7Smrj     ACPI_GPE_EVENT_INFO     *GpeEventInfo,
743ae115bc7Smrj     UINT32                  GpeNumber)
744ae115bc7Smrj {
745ae115bc7Smrj     ACPI_STATUS             Status;
74626f3cdf0SGordon Ross     UINT32                  ReturnValue;
747ae115bc7Smrj 
748ae115bc7Smrj 
749ae115bc7Smrj     ACPI_FUNCTION_TRACE (EvGpeDispatch);
750ae115bc7Smrj 
751ae115bc7Smrj 
752ae115bc7Smrj     /*
75326f3cdf0SGordon Ross      * Always disable the GPE so that it does not keep firing before
75426f3cdf0SGordon Ross      * any asynchronous activity completes (either from the execution
75526f3cdf0SGordon Ross      * of a GPE method or an asynchronous GPE handler.)
75626f3cdf0SGordon Ross      *
75726f3cdf0SGordon Ross      * If there is no handler or method to run, just disable the
75826f3cdf0SGordon Ross      * GPE and leave it disabled permanently to prevent further such
75926f3cdf0SGordon Ross      * pointless events from firing.
76026f3cdf0SGordon Ross      */
76126f3cdf0SGordon Ross     Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE);
76226f3cdf0SGordon Ross     if (ACPI_FAILURE (Status))
76326f3cdf0SGordon Ross     {
76426f3cdf0SGordon Ross         ACPI_EXCEPTION ((AE_INFO, Status,
76526f3cdf0SGordon Ross             "Unable to disable GPE %02X", GpeNumber));
76626f3cdf0SGordon Ross         return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
76726f3cdf0SGordon Ross     }
76826f3cdf0SGordon Ross 
76926f3cdf0SGordon Ross     /*
770*385cc6b4SJerry Jelinek      * If edge-triggered, clear the GPE status bit now. Note that
771*385cc6b4SJerry Jelinek      * level-triggered events are cleared after the GPE is serviced.
772*385cc6b4SJerry Jelinek      */
773*385cc6b4SJerry Jelinek     if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
774*385cc6b4SJerry Jelinek             ACPI_GPE_EDGE_TRIGGERED)
775*385cc6b4SJerry Jelinek     {
776*385cc6b4SJerry Jelinek         Status = AcpiHwClearGpe (GpeEventInfo);
777*385cc6b4SJerry Jelinek         if (ACPI_FAILURE (Status))
778*385cc6b4SJerry Jelinek         {
779*385cc6b4SJerry Jelinek             ACPI_EXCEPTION ((AE_INFO, Status,
780*385cc6b4SJerry Jelinek                 "Unable to clear GPE %02X", GpeNumber));
781*385cc6b4SJerry Jelinek             (void) AcpiHwLowSetGpe (
782*385cc6b4SJerry Jelinek                 GpeEventInfo, ACPI_GPE_CONDITIONAL_ENABLE);
783*385cc6b4SJerry Jelinek             return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
784*385cc6b4SJerry Jelinek         }
785*385cc6b4SJerry Jelinek     }
786*385cc6b4SJerry Jelinek 
787*385cc6b4SJerry Jelinek     /*
78826f3cdf0SGordon Ross      * Dispatch the GPE to either an installed handler or the control
78926f3cdf0SGordon Ross      * method associated with this GPE (_Lxx or _Exx). If a handler
79026f3cdf0SGordon Ross      * exists, we invoke it and do not attempt to run the method.
79126f3cdf0SGordon Ross      * If there is neither a handler nor a method, leave the GPE
79226f3cdf0SGordon Ross      * disabled.
793ae115bc7Smrj      */
794*385cc6b4SJerry Jelinek     switch (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags))
795ae115bc7Smrj     {
796ae115bc7Smrj     case ACPI_GPE_DISPATCH_HANDLER:
797ae115bc7Smrj 
79826f3cdf0SGordon Ross         /* Invoke the installed handler (at interrupt level) */
79926f3cdf0SGordon Ross 
80026f3cdf0SGordon Ross         ReturnValue = GpeEventInfo->Dispatch.Handler->Address (
80126f3cdf0SGordon Ross             GpeDevice, GpeNumber,
802ae115bc7Smrj             GpeEventInfo->Dispatch.Handler->Context);
803ae115bc7Smrj 
80426f3cdf0SGordon Ross         /* If requested, clear (if level-triggered) and reenable the GPE */
805ae115bc7Smrj 
80626f3cdf0SGordon Ross         if (ReturnValue & ACPI_REENABLE_GPE)
807ae115bc7Smrj         {
80826f3cdf0SGordon Ross             (void) AcpiEvFinishGpe (GpeEventInfo);
809ae115bc7Smrj         }
810ae115bc7Smrj         break;
811ae115bc7Smrj 
812ae115bc7Smrj     case ACPI_GPE_DISPATCH_METHOD:
81326f3cdf0SGordon Ross     case ACPI_GPE_DISPATCH_NOTIFY:
814ae115bc7Smrj         /*
815ae115bc7Smrj          * Execute the method associated with the GPE
816ae115bc7Smrj          * NOTE: Level-triggered GPEs are cleared after the method completes.
817ae115bc7Smrj          */
818ae115bc7Smrj         Status = AcpiOsExecute (OSL_GPE_HANDLER,
819ae115bc7Smrj             AcpiEvAsynchExecuteGpeMethod, GpeEventInfo);
820ae115bc7Smrj         if (ACPI_FAILURE (Status))
821ae115bc7Smrj         {
822ae115bc7Smrj             ACPI_EXCEPTION ((AE_INFO, Status,
82326f3cdf0SGordon Ross                 "Unable to queue handler for GPE %02X - event disabled",
824ae115bc7Smrj                 GpeNumber));
825ae115bc7Smrj         }
826ae115bc7Smrj         break;
827ae115bc7Smrj 
828ae115bc7Smrj     default:
829ae115bc7Smrj         /*
83026f3cdf0SGordon Ross          * No handler or method to run!
83126f3cdf0SGordon Ross          * 03/2010: This case should no longer be possible. We will not allow
83226f3cdf0SGordon Ross          * a GPE to be enabled if it has no handler or method.
833ae115bc7Smrj          */
83426f3cdf0SGordon Ross         ACPI_ERROR ((AE_INFO,
83526f3cdf0SGordon Ross             "No handler or method for GPE %02X, disabling event",
83626f3cdf0SGordon Ross             GpeNumber));
837ae115bc7Smrj         break;
838ae115bc7Smrj     }
839ae115bc7Smrj 
840ae115bc7Smrj     return_UINT32 (ACPI_INTERRUPT_HANDLED);
841ae115bc7Smrj }
842ae115bc7Smrj 
843*385cc6b4SJerry Jelinek #endif /* !ACPI_REDUCED_HARDWARE */
844