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
AcpiEvUpdateGpeEnableMask(ACPI_GPE_EVENT_INFO * GpeEventInfo)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
AcpiEvEnableGpe(ACPI_GPE_EVENT_INFO * GpeEventInfo)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
AcpiEvAddGpeReference(ACPI_GPE_EVENT_INFO * GpeEventInfo)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
AcpiEvRemoveGpeReference(ACPI_GPE_EVENT_INFO * GpeEventInfo)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 *
AcpiEvLowGetGpeInfo(UINT32 GpeNumber,ACPI_GPE_BLOCK_INFO * GpeBlock)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 *
AcpiEvGetGpeEventInfo(ACPI_HANDLE GpeDevice,UINT32 GpeNumber)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
AcpiEvGpeDetect(ACPI_GPE_XRUPT_INFO * GpeXruptList)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
AcpiEvAsynchExecuteGpeMethod(void * Context)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
AcpiEvAsynchEnableGpe(void * Context)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
AcpiEvFinishGpe(ACPI_GPE_EVENT_INFO * GpeEventInfo)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
AcpiEvGpeDispatch(ACPI_NAMESPACE_NODE * GpeDevice,ACPI_GPE_EVENT_INFO * GpeEventInfo,UINT32 GpeNumber)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