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