evgpe.c revision 245582
1251881Speter/****************************************************************************** 2251881Speter * 3251881Speter * Module Name: evgpe - General Purpose Event handling and dispatch 4251881Speter * 5251881Speter *****************************************************************************/ 6251881Speter 7251881Speter/* 8251881Speter * Copyright (C) 2000 - 2013, Intel Corp. 9251881Speter * All rights reserved. 10251881Speter * 11251881Speter * Redistribution and use in source and binary forms, with or without 12251881Speter * modification, are permitted provided that the following conditions 13251881Speter * are met: 14251881Speter * 1. Redistributions of source code must retain the above copyright 15251881Speter * notice, this list of conditions, and the following disclaimer, 16251881Speter * without modification. 17251881Speter * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18251881Speter * substantially similar to the "NO WARRANTY" disclaimer below 19251881Speter * ("Disclaimer") and any redistribution must be conditioned upon 20251881Speter * including a substantially similar Disclaimer requirement for further 21251881Speter * binary redistribution. 22251881Speter * 3. Neither the names of the above-listed copyright holders nor the names 23251881Speter * of any contributors may be used to endorse or promote products derived 24251881Speter * from this software without specific prior written permission. 25251881Speter * 26251881Speter * Alternatively, this software may be distributed under the terms of the 27251881Speter * GNU General Public License ("GPL") version 2 as published by the Free 28251881Speter * Software Foundation. 29251881Speter * 30251881Speter * NO WARRANTY 31251881Speter * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32251881Speter * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33251881Speter * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34251881Speter * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35251881Speter * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36251881Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37251881Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38251881Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39251881Speter * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40251881Speter * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41251881Speter * POSSIBILITY OF SUCH DAMAGES. 42251881Speter */ 43251881Speter 44251881Speter#include <contrib/dev/acpica/include/acpi.h> 45251881Speter#include <contrib/dev/acpica/include/accommon.h> 46251881Speter#include <contrib/dev/acpica/include/acevents.h> 47251881Speter#include <contrib/dev/acpica/include/acnamesp.h> 48251881Speter 49251881Speter#define _COMPONENT ACPI_EVENTS 50251881Speter ACPI_MODULE_NAME ("evgpe") 51251881Speter 52251881Speter#if (!ACPI_REDUCED_HARDWARE) /* Entire module */ 53251881Speter 54251881Speter/* Local prototypes */ 55251881Speter 56251881Speterstatic void ACPI_SYSTEM_XFACE 57251881SpeterAcpiEvAsynchExecuteGpeMethod ( 58251881Speter void *Context); 59251881Speter 60251881Speterstatic void ACPI_SYSTEM_XFACE 61251881SpeterAcpiEvAsynchEnableGpe ( 62251881Speter void *Context); 63251881Speter 64251881Speter 65251881Speter/******************************************************************************* 66251881Speter * 67251881Speter * FUNCTION: AcpiEvUpdateGpeEnableMask 68251881Speter * 69251881Speter * PARAMETERS: GpeEventInfo - GPE to update 70251881Speter * 71251881Speter * RETURN: Status 72251881Speter * 73251881Speter * DESCRIPTION: Updates GPE register enable mask based upon whether there are 74251881Speter * runtime references to this GPE 75251881Speter * 76251881Speter ******************************************************************************/ 77251881Speter 78251881SpeterACPI_STATUS 79251881SpeterAcpiEvUpdateGpeEnableMask ( 80251881Speter ACPI_GPE_EVENT_INFO *GpeEventInfo) 81251881Speter{ 82251881Speter ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; 83251881Speter UINT32 RegisterBit; 84251881Speter 85251881Speter 86251881Speter ACPI_FUNCTION_TRACE (EvUpdateGpeEnableMask); 87251881Speter 88251881Speter 89251881Speter GpeRegisterInfo = GpeEventInfo->RegisterInfo; 90251881Speter if (!GpeRegisterInfo) 91251881Speter { 92251881Speter return_ACPI_STATUS (AE_NOT_EXIST); 93251881Speter } 94251881Speter 95251881Speter RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo); 96251881Speter 97251881Speter /* Clear the run bit up front */ 98251881Speter 99251881Speter ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForRun, RegisterBit); 100251881Speter 101251881Speter /* Set the mask bit only if there are references to this GPE */ 102251881Speter 103251881Speter if (GpeEventInfo->RuntimeCount) 104251881Speter { 105251881Speter ACPI_SET_BIT (GpeRegisterInfo->EnableForRun, (UINT8) RegisterBit); 106251881Speter } 107251881Speter 108251881Speter return_ACPI_STATUS (AE_OK); 109251881Speter} 110251881Speter 111251881Speter 112251881Speter/******************************************************************************* 113251881Speter * 114251881Speter * FUNCTION: AcpiEvEnableGpe 115251881Speter * 116251881Speter * PARAMETERS: GpeEventInfo - GPE to enable 117251881Speter * 118251881Speter * RETURN: Status 119251881Speter * 120251881Speter * DESCRIPTION: Clear a GPE of stale events and enable it. 121251881Speter * 122251881Speter ******************************************************************************/ 123251881Speter 124251881SpeterACPI_STATUS 125251881SpeterAcpiEvEnableGpe ( 126251881Speter ACPI_GPE_EVENT_INFO *GpeEventInfo) 127251881Speter{ 128251881Speter ACPI_STATUS Status; 129251881Speter 130251881Speter 131251881Speter ACPI_FUNCTION_TRACE (EvEnableGpe); 132251881Speter 133251881Speter 134251881Speter /* 135251881Speter * We will only allow a GPE to be enabled if it has either an associated 136251881Speter * method (_Lxx/_Exx) or a handler, or is using the implicit notify 137251881Speter * feature. Otherwise, the GPE will be immediately disabled by 138251881Speter * AcpiEvGpeDispatch the first time it fires. 139251881Speter */ 140251881Speter if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == 141251881Speter ACPI_GPE_DISPATCH_NONE) 142251881Speter { 143251881Speter return_ACPI_STATUS (AE_NO_HANDLER); 144251881Speter } 145251881Speter 146251881Speter /* Clear the GPE (of stale events) */ 147251881Speter 148251881Speter Status = AcpiHwClearGpe (GpeEventInfo); 149251881Speter if (ACPI_FAILURE (Status)) 150251881Speter { 151251881Speter return_ACPI_STATUS (Status); 152251881Speter } 153251881Speter 154251881Speter /* Enable the requested GPE */ 155251881Speter 156251881Speter Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_ENABLE); 157251881Speter return_ACPI_STATUS (Status); 158251881Speter} 159251881Speter 160251881Speter 161251881Speter/******************************************************************************* 162251881Speter * 163251881Speter * FUNCTION: AcpiEvAddGpeReference 164251881Speter * 165251881Speter * PARAMETERS: GpeEventInfo - Add a reference to this GPE 166251881Speter * 167251881Speter * RETURN: Status 168251881Speter * 169251881Speter * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is 170251881Speter * hardware-enabled. 171251881Speter * 172251881Speter ******************************************************************************/ 173251881Speter 174251881SpeterACPI_STATUS 175251881SpeterAcpiEvAddGpeReference ( 176251881Speter ACPI_GPE_EVENT_INFO *GpeEventInfo) 177251881Speter{ 178251881Speter ACPI_STATUS Status = AE_OK; 179251881Speter 180251881Speter 181251881Speter ACPI_FUNCTION_TRACE (EvAddGpeReference); 182251881Speter 183251881Speter 184251881Speter if (GpeEventInfo->RuntimeCount == ACPI_UINT8_MAX) 185251881Speter { 186251881Speter return_ACPI_STATUS (AE_LIMIT); 187251881Speter } 188251881Speter 189251881Speter GpeEventInfo->RuntimeCount++; 190251881Speter if (GpeEventInfo->RuntimeCount == 1) 191251881Speter { 192251881Speter /* Enable on first reference */ 193251881Speter 194251881Speter Status = AcpiEvUpdateGpeEnableMask (GpeEventInfo); 195251881Speter if (ACPI_SUCCESS (Status)) 196251881Speter { 197251881Speter Status = AcpiEvEnableGpe (GpeEventInfo); 198251881Speter } 199251881Speter 200251881Speter if (ACPI_FAILURE (Status)) 201251881Speter { 202251881Speter GpeEventInfo->RuntimeCount--; 203251881Speter } 204251881Speter } 205251881Speter 206251881Speter return_ACPI_STATUS (Status); 207251881Speter} 208251881Speter 209251881Speter 210251881Speter/******************************************************************************* 211251881Speter * 212251881Speter * FUNCTION: AcpiEvRemoveGpeReference 213251881Speter * 214251881Speter * PARAMETERS: GpeEventInfo - Remove a reference to this GPE 215251881Speter * 216251881Speter * RETURN: Status 217251881Speter * 218251881Speter * DESCRIPTION: Remove a reference to a GPE. When the last reference is 219251881Speter * removed, the GPE is hardware-disabled. 220251881Speter * 221251881Speter ******************************************************************************/ 222251881Speter 223251881SpeterACPI_STATUS 224251881SpeterAcpiEvRemoveGpeReference ( 225251881Speter ACPI_GPE_EVENT_INFO *GpeEventInfo) 226251881Speter{ 227251881Speter ACPI_STATUS Status = AE_OK; 228251881Speter 229251881Speter 230251881Speter ACPI_FUNCTION_TRACE (EvRemoveGpeReference); 231251881Speter 232251881Speter 233251881Speter if (!GpeEventInfo->RuntimeCount) 234251881Speter { 235251881Speter return_ACPI_STATUS (AE_LIMIT); 236251881Speter } 237251881Speter 238251881Speter GpeEventInfo->RuntimeCount--; 239251881Speter if (!GpeEventInfo->RuntimeCount) 240251881Speter { 241251881Speter /* Disable on last reference */ 242251881Speter 243251881Speter Status = AcpiEvUpdateGpeEnableMask (GpeEventInfo); 244251881Speter if (ACPI_SUCCESS (Status)) 245251881Speter { 246251881Speter Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE); 247251881Speter } 248251881Speter 249251881Speter if (ACPI_FAILURE (Status)) 250251881Speter { 251251881Speter GpeEventInfo->RuntimeCount++; 252251881Speter } 253251881Speter } 254251881Speter 255251881Speter return_ACPI_STATUS (Status); 256251881Speter} 257251881Speter 258251881Speter 259251881Speter/******************************************************************************* 260251881Speter * 261251881Speter * FUNCTION: AcpiEvLowGetGpeInfo 262251881Speter * 263251881Speter * PARAMETERS: GpeNumber - Raw GPE number 264251881Speter * GpeBlock - A GPE info block 265251881Speter * 266251881Speter * RETURN: A GPE EventInfo struct. NULL if not a valid GPE (The GpeNumber 267251881Speter * is not within the specified GPE block) 268251881Speter * 269251881Speter * DESCRIPTION: Returns the EventInfo struct associated with this GPE. This is 270251881Speter * the low-level implementation of EvGetGpeEventInfo. 271251881Speter * 272251881Speter ******************************************************************************/ 273251881Speter 274251881SpeterACPI_GPE_EVENT_INFO * 275251881SpeterAcpiEvLowGetGpeInfo ( 276251881Speter UINT32 GpeNumber, 277251881Speter ACPI_GPE_BLOCK_INFO *GpeBlock) 278251881Speter{ 279251881Speter UINT32 GpeIndex; 280251881Speter 281251881Speter 282251881Speter /* 283251881Speter * Validate that the GpeNumber is within the specified GpeBlock. 284251881Speter * (Two steps) 285251881Speter */ 286251881Speter if (!GpeBlock || 287251881Speter (GpeNumber < GpeBlock->BlockBaseNumber)) 288251881Speter { 289251881Speter return (NULL); 290251881Speter } 291251881Speter 292251881Speter GpeIndex = GpeNumber - GpeBlock->BlockBaseNumber; 293251881Speter if (GpeIndex >= GpeBlock->GpeCount) 294251881Speter { 295251881Speter return (NULL); 296251881Speter } 297251881Speter 298251881Speter return (&GpeBlock->EventInfo[GpeIndex]); 299251881Speter} 300251881Speter 301251881Speter 302251881Speter/******************************************************************************* 303251881Speter * 304251881Speter * FUNCTION: AcpiEvGetGpeEventInfo 305251881Speter * 306251881Speter * PARAMETERS: GpeDevice - Device node. NULL for GPE0/GPE1 307251881Speter * GpeNumber - Raw GPE number 308251881Speter * 309251881Speter * RETURN: A GPE EventInfo struct. NULL if not a valid GPE 310251881Speter * 311251881Speter * DESCRIPTION: Returns the EventInfo struct associated with this GPE. 312251881Speter * Validates the GpeBlock and the GpeNumber 313251881Speter * 314251881Speter * Should be called only when the GPE lists are semaphore locked 315251881Speter * and not subject to change. 316251881Speter * 317251881Speter ******************************************************************************/ 318251881Speter 319251881SpeterACPI_GPE_EVENT_INFO * 320251881SpeterAcpiEvGetGpeEventInfo ( 321251881Speter ACPI_HANDLE GpeDevice, 322251881Speter UINT32 GpeNumber) 323251881Speter{ 324251881Speter ACPI_OPERAND_OBJECT *ObjDesc; 325251881Speter ACPI_GPE_EVENT_INFO *GpeInfo; 326251881Speter UINT32 i; 327251881Speter 328251881Speter 329251881Speter ACPI_FUNCTION_ENTRY (); 330251881Speter 331251881Speter 332251881Speter /* A NULL GpeDevice means use the FADT-defined GPE block(s) */ 333251881Speter 334251881Speter if (!GpeDevice) 335251881Speter { 336251881Speter /* Examine GPE Block 0 and 1 (These blocks are permanent) */ 337251881Speter 338251881Speter for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++) 339251881Speter { 340251881Speter GpeInfo = AcpiEvLowGetGpeInfo (GpeNumber, 341251881Speter AcpiGbl_GpeFadtBlocks[i]); 342251881Speter if (GpeInfo) 343251881Speter { 344251881Speter return (GpeInfo); 345251881Speter } 346251881Speter } 347251881Speter 348251881Speter /* The GpeNumber was not in the range of either FADT GPE block */ 349251881Speter 350251881Speter return (NULL); 351251881Speter } 352251881Speter 353251881Speter /* A Non-NULL GpeDevice means this is a GPE Block Device */ 354251881Speter 355251881Speter ObjDesc = AcpiNsGetAttachedObject ((ACPI_NAMESPACE_NODE *) GpeDevice); 356251881Speter if (!ObjDesc || 357251881Speter !ObjDesc->Device.GpeBlock) 358251881Speter { 359251881Speter return (NULL); 360251881Speter } 361251881Speter 362251881Speter return (AcpiEvLowGetGpeInfo (GpeNumber, ObjDesc->Device.GpeBlock)); 363251881Speter} 364251881Speter 365251881Speter 366251881Speter/******************************************************************************* 367251881Speter * 368251881Speter * FUNCTION: AcpiEvGpeDetect 369251881Speter * 370251881Speter * PARAMETERS: GpeXruptList - Interrupt block for this interrupt. 371251881Speter * Can have multiple GPE blocks attached. 372251881Speter * 373251881Speter * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED 374251881Speter * 375251881Speter * DESCRIPTION: Detect if any GP events have occurred. This function is 376251881Speter * executed at interrupt level. 377251881Speter * 378251881Speter ******************************************************************************/ 379251881Speter 380251881SpeterUINT32 381251881SpeterAcpiEvGpeDetect ( 382251881Speter ACPI_GPE_XRUPT_INFO *GpeXruptList) 383251881Speter{ 384251881Speter ACPI_STATUS Status; 385251881Speter ACPI_GPE_BLOCK_INFO *GpeBlock; 386251881Speter ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; 387251881Speter UINT32 IntStatus = ACPI_INTERRUPT_NOT_HANDLED; 388251881Speter UINT8 EnabledStatusByte; 389251881Speter UINT32 StatusReg; 390251881Speter UINT32 EnableReg; 391251881Speter ACPI_CPU_FLAGS Flags; 392251881Speter UINT32 i; 393251881Speter UINT32 j; 394251881Speter 395251881Speter 396251881Speter ACPI_FUNCTION_NAME (EvGpeDetect); 397251881Speter 398251881Speter /* Check for the case where there are no GPEs */ 399251881Speter 400251881Speter if (!GpeXruptList) 401251881Speter { 402251881Speter return (IntStatus); 403251881Speter } 404251881Speter 405251881Speter /* 406251881Speter * We need to obtain the GPE lock for both the data structs and registers 407251881Speter * Note: Not necessary to obtain the hardware lock, since the GPE 408251881Speter * registers are owned by the GpeLock. 409251881Speter */ 410251881Speter Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 411251881Speter 412251881Speter /* Examine all GPE blocks attached to this interrupt level */ 413251881Speter 414251881Speter GpeBlock = GpeXruptList->GpeBlockListHead; 415251881Speter while (GpeBlock) 416251881Speter { 417251881Speter /* 418251881Speter * Read all of the 8-bit GPE status and enable registers in this GPE 419251881Speter * block, saving all of them. Find all currently active GP events. 420251881Speter */ 421251881Speter for (i = 0; i < GpeBlock->RegisterCount; i++) 422251881Speter { 423251881Speter /* Get the next status/enable pair */ 424251881Speter 425251881Speter GpeRegisterInfo = &GpeBlock->RegisterInfo[i]; 426251881Speter 427251881Speter /* 428251881Speter * Optimization: If there are no GPEs enabled within this 429251881Speter * register, we can safely ignore the entire register. 430251881Speter */ 431251881Speter if (!(GpeRegisterInfo->EnableForRun | 432251881Speter GpeRegisterInfo->EnableForWake)) 433251881Speter { 434251881Speter ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS, 435251881Speter "Ignore disabled registers for GPE%02X-GPE%02X: " 436251881Speter "RunEnable=%02X, WakeEnable=%02X\n", 437251881Speter GpeRegisterInfo->BaseGpeNumber, 438251881Speter GpeRegisterInfo->BaseGpeNumber + (ACPI_GPE_REGISTER_WIDTH - 1), 439251881Speter GpeRegisterInfo->EnableForRun, 440251881Speter GpeRegisterInfo->EnableForWake)); 441251881Speter continue; 442251881Speter } 443251881Speter 444251881Speter /* Read the Status Register */ 445251881Speter 446251881Speter Status = AcpiHwRead (&StatusReg, &GpeRegisterInfo->StatusAddress); 447251881Speter if (ACPI_FAILURE (Status)) 448251881Speter { 449251881Speter goto UnlockAndExit; 450251881Speter } 451251881Speter 452251881Speter /* Read the Enable Register */ 453251881Speter 454251881Speter Status = AcpiHwRead (&EnableReg, &GpeRegisterInfo->EnableAddress); 455251881Speter if (ACPI_FAILURE (Status)) 456251881Speter { 457251881Speter goto UnlockAndExit; 458251881Speter } 459251881Speter 460251881Speter ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS, 461251881Speter "Read registers for GPE%02X-GPE%02X: Status=%02X, Enable=%02X, " 462251881Speter "RunEnable=%02X, WakeEnable=%02X\n", 463251881Speter GpeRegisterInfo->BaseGpeNumber, 464251881Speter GpeRegisterInfo->BaseGpeNumber + (ACPI_GPE_REGISTER_WIDTH - 1), 465251881Speter StatusReg, EnableReg, 466251881Speter GpeRegisterInfo->EnableForRun, 467251881Speter GpeRegisterInfo->EnableForWake)); 468251881Speter 469251881Speter /* Check if there is anything active at all in this register */ 470251881Speter 471251881Speter EnabledStatusByte = (UINT8) (StatusReg & EnableReg); 472251881Speter if (!EnabledStatusByte) 473251881Speter { 474251881Speter /* No active GPEs in this register, move on */ 475251881Speter 476251881Speter continue; 477251881Speter } 478251881Speter 479251881Speter /* Now look at the individual GPEs in this byte register */ 480251881Speter 481251881Speter for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) 482251881Speter { 483251881Speter /* Examine one GPE bit */ 484251881Speter 485251881Speter if (EnabledStatusByte & (1 << j)) 486251881Speter { 487251881Speter /* 488251881Speter * Found an active GPE. Dispatch the event to a handler 489251881Speter * or method. 490251881Speter */ 491251881Speter IntStatus |= AcpiEvGpeDispatch (GpeBlock->Node, 492251881Speter &GpeBlock->EventInfo[((ACPI_SIZE) i * 493251881Speter ACPI_GPE_REGISTER_WIDTH) + j], 494251881Speter j + GpeRegisterInfo->BaseGpeNumber); 495251881Speter } 496251881Speter } 497251881Speter } 498251881Speter 499251881Speter GpeBlock = GpeBlock->Next; 500251881Speter } 501251881Speter 502251881SpeterUnlockAndExit: 503251881Speter 504251881Speter AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 505251881Speter return (IntStatus); 506251881Speter} 507251881Speter 508251881Speter 509251881Speter/******************************************************************************* 510251881Speter * 511251881Speter * FUNCTION: AcpiEvAsynchExecuteGpeMethod 512251881Speter * 513251881Speter * PARAMETERS: Context (GpeEventInfo) - Info for this GPE 514251881Speter * 515251881Speter * RETURN: None 516251881Speter * 517251881Speter * DESCRIPTION: Perform the actual execution of a GPE control method. This 518251881Speter * function is called from an invocation of AcpiOsExecute and 519251881Speter * therefore does NOT execute at interrupt level - so that 520251881Speter * the control method itself is not executed in the context of 521251881Speter * an interrupt handler. 522251881Speter * 523251881Speter ******************************************************************************/ 524251881Speter 525251881Speterstatic void ACPI_SYSTEM_XFACE 526251881SpeterAcpiEvAsynchExecuteGpeMethod ( 527251881Speter void *Context) 528251881Speter{ 529251881Speter ACPI_GPE_EVENT_INFO *GpeEventInfo = Context; 530251881Speter ACPI_STATUS Status; 531251881Speter ACPI_GPE_EVENT_INFO *LocalGpeEventInfo; 532251881Speter ACPI_EVALUATE_INFO *Info; 533251881Speter ACPI_GPE_NOTIFY_INFO *Notify; 534251881Speter 535251881Speter 536251881Speter ACPI_FUNCTION_TRACE (EvAsynchExecuteGpeMethod); 537251881Speter 538251881Speter 539251881Speter /* Allocate a local GPE block */ 540251881Speter 541251881Speter LocalGpeEventInfo = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_EVENT_INFO)); 542251881Speter if (!LocalGpeEventInfo) 543251881Speter { 544251881Speter ACPI_EXCEPTION ((AE_INFO, AE_NO_MEMORY, 545251881Speter "while handling a GPE")); 546251881Speter return_VOID; 547251881Speter } 548251881Speter 549251881Speter Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 550251881Speter if (ACPI_FAILURE (Status)) 551251881Speter { 552251881Speter return_VOID; 553251881Speter } 554251881Speter 555251881Speter /* Must revalidate the GpeNumber/GpeBlock */ 556251881Speter 557251881Speter if (!AcpiEvValidGpeEvent (GpeEventInfo)) 558251881Speter { 559251881Speter Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 560251881Speter return_VOID; 561251881Speter } 562251881Speter 563251881Speter /* 564251881Speter * Take a snapshot of the GPE info for this level - we copy the info to 565251881Speter * prevent a race condition with RemoveHandler/RemoveBlock. 566251881Speter */ 567251881Speter ACPI_MEMCPY (LocalGpeEventInfo, GpeEventInfo, 568251881Speter sizeof (ACPI_GPE_EVENT_INFO)); 569251881Speter 570251881Speter Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 571251881Speter if (ACPI_FAILURE (Status)) 572251881Speter { 573251881Speter return_VOID; 574251881Speter } 575251881Speter 576251881Speter /* Do the correct dispatch - normal method or implicit notify */ 577251881Speter 578251881Speter switch (LocalGpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) 579251881Speter { 580251881Speter case ACPI_GPE_DISPATCH_NOTIFY: 581251881Speter 582251881Speter /* 583251881Speter * Implicit notify. 584251881Speter * Dispatch a DEVICE_WAKE notify to the appropriate handler. 585251881Speter * NOTE: the request is queued for execution after this method 586251881Speter * completes. The notify handlers are NOT invoked synchronously 587251881Speter * from this thread -- because handlers may in turn run other 588251881Speter * control methods. 589251881Speter * 590251881Speter * June 2012: Expand implicit notify mechanism to support 591251881Speter * notifies on multiple device objects. 592251881Speter */ 593251881Speter Notify = LocalGpeEventInfo->Dispatch.NotifyList; 594251881Speter while (ACPI_SUCCESS (Status) && Notify) 595251881Speter { 596251881Speter Status = AcpiEvQueueNotifyRequest (Notify->DeviceNode, 597251881Speter ACPI_NOTIFY_DEVICE_WAKE); 598251881Speter 599251881Speter Notify = Notify->Next; 600251881Speter } 601251881Speter break; 602251881Speter 603251881Speter case ACPI_GPE_DISPATCH_METHOD: 604251881Speter 605251881Speter /* Allocate the evaluation information block */ 606251881Speter 607251881Speter Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO)); 608251881Speter if (!Info) 609251881Speter { 610251881Speter Status = AE_NO_MEMORY; 611251881Speter } 612251881Speter else 613251881Speter { 614251881Speter /* 615251881Speter * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the 616251881Speter * _Lxx/_Exx control method that corresponds to this GPE 617251881Speter */ 618251881Speter Info->PrefixNode = LocalGpeEventInfo->Dispatch.MethodNode; 619251881Speter Info->Flags = ACPI_IGNORE_RETURN_VALUE; 620251881Speter 621251881Speter Status = AcpiNsEvaluate (Info); 622251881Speter ACPI_FREE (Info); 623251881Speter } 624251881Speter 625251881Speter if (ACPI_FAILURE (Status)) 626251881Speter { 627251881Speter ACPI_EXCEPTION ((AE_INFO, Status, 628251881Speter "while evaluating GPE method [%4.4s]", 629251881Speter AcpiUtGetNodeName (LocalGpeEventInfo->Dispatch.MethodNode))); 630251881Speter } 631251881Speter 632251881Speter break; 633251881Speter 634251881Speter default: 635251881Speter return_VOID; /* Should never happen */ 636251881Speter } 637251881Speter 638251881Speter /* Defer enabling of GPE until all notify handlers are done */ 639251881Speter 640251881Speter Status = AcpiOsExecute (OSL_NOTIFY_HANDLER, 641251881Speter AcpiEvAsynchEnableGpe, LocalGpeEventInfo); 642251881Speter if (ACPI_FAILURE (Status)) 643251881Speter { 644251881Speter ACPI_FREE (LocalGpeEventInfo); 645251881Speter } 646251881Speter return_VOID; 647251881Speter} 648251881Speter 649251881Speter 650251881Speter/******************************************************************************* 651251881Speter * 652251881Speter * FUNCTION: AcpiEvAsynchEnableGpe 653251881Speter * 654251881Speter * PARAMETERS: Context (GpeEventInfo) - Info for this GPE 655251881Speter * Callback from AcpiOsExecute 656251881Speter * 657251881Speter * RETURN: None 658251881Speter * 659251881Speter * DESCRIPTION: Asynchronous clear/enable for GPE. This allows the GPE to 660251881Speter * complete (i.e., finish execution of Notify) 661251881Speter * 662251881Speter ******************************************************************************/ 663251881Speter 664251881Speterstatic void ACPI_SYSTEM_XFACE 665251881SpeterAcpiEvAsynchEnableGpe ( 666251881Speter void *Context) 667251881Speter{ 668251881Speter ACPI_GPE_EVENT_INFO *GpeEventInfo = Context; 669251881Speter 670251881Speter 671251881Speter (void) AcpiEvFinishGpe (GpeEventInfo); 672251881Speter 673251881Speter ACPI_FREE (GpeEventInfo); 674251881Speter return; 675251881Speter} 676251881Speter 677251881Speter 678251881Speter/******************************************************************************* 679251881Speter * 680251881Speter * FUNCTION: AcpiEvFinishGpe 681251881Speter * 682251881Speter * PARAMETERS: GpeEventInfo - Info for this GPE 683251881Speter * 684251881Speter * RETURN: Status 685251881Speter * 686251881Speter * DESCRIPTION: Clear/Enable a GPE. Common code that is used after execution 687251881Speter * of a GPE method or a synchronous or asynchronous GPE handler. 688251881Speter * 689251881Speter ******************************************************************************/ 690251881Speter 691251881SpeterACPI_STATUS 692251881SpeterAcpiEvFinishGpe ( 693251881Speter ACPI_GPE_EVENT_INFO *GpeEventInfo) 694251881Speter{ 695251881Speter ACPI_STATUS Status; 696251881Speter 697251881Speter 698251881Speter if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) == 699251881Speter ACPI_GPE_LEVEL_TRIGGERED) 700251881Speter { 701251881Speter /* 702251881Speter * GPE is level-triggered, we clear the GPE status bit after 703251881Speter * handling the event. 704251881Speter */ 705251881Speter Status = AcpiHwClearGpe (GpeEventInfo); 706251881Speter if (ACPI_FAILURE (Status)) 707251881Speter { 708251881Speter return (Status); 709251881Speter } 710251881Speter } 711251881Speter 712251881Speter /* 713251881Speter * Enable this GPE, conditionally. This means that the GPE will 714251881Speter * only be physically enabled if the EnableForRun bit is set 715251881Speter * in the EventInfo. 716251881Speter */ 717251881Speter (void) AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_CONDITIONAL_ENABLE); 718251881Speter return (AE_OK); 719251881Speter} 720251881Speter 721251881Speter 722251881Speter/******************************************************************************* 723251881Speter * 724251881Speter * FUNCTION: AcpiEvGpeDispatch 725251881Speter * 726251881Speter * PARAMETERS: GpeDevice - Device node. NULL for GPE0/GPE1 727251881Speter * GpeEventInfo - Info for this GPE 728251881Speter * GpeNumber - Number relative to the parent GPE block 729251881Speter * 730251881Speter * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED 731251881Speter * 732251881Speter * DESCRIPTION: Dispatch a General Purpose Event to either a function (e.g. EC) 733251881Speter * or method (e.g. _Lxx/_Exx) handler. 734251881Speter * 735251881Speter * This function executes at interrupt level. 736251881Speter * 737251881Speter ******************************************************************************/ 738251881Speter 739251881SpeterUINT32 740251881SpeterAcpiEvGpeDispatch ( 741251881Speter ACPI_NAMESPACE_NODE *GpeDevice, 742251881Speter ACPI_GPE_EVENT_INFO *GpeEventInfo, 743251881Speter UINT32 GpeNumber) 744251881Speter{ 745251881Speter ACPI_STATUS Status; 746251881Speter UINT32 ReturnValue; 747251881Speter 748251881Speter 749251881Speter ACPI_FUNCTION_TRACE (EvGpeDispatch); 750251881Speter 751251881Speter 752251881Speter /* Invoke global event handler if present */ 753251881Speter 754251881Speter AcpiGpeCount++; 755251881Speter if (AcpiGbl_GlobalEventHandler) 756251881Speter { 757251881Speter AcpiGbl_GlobalEventHandler (ACPI_EVENT_TYPE_GPE, GpeDevice, 758251881Speter GpeNumber, AcpiGbl_GlobalEventHandlerContext); 759251881Speter } 760251881Speter 761251881Speter /* 762251881Speter * If edge-triggered, clear the GPE status bit now. Note that 763251881Speter * level-triggered events are cleared after the GPE is serviced. 764251881Speter */ 765251881Speter if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) == 766251881Speter ACPI_GPE_EDGE_TRIGGERED) 767251881Speter { 768251881Speter Status = AcpiHwClearGpe (GpeEventInfo); 769251881Speter if (ACPI_FAILURE (Status)) 770251881Speter { 771251881Speter ACPI_EXCEPTION ((AE_INFO, Status, 772251881Speter "Unable to clear GPE%02X", GpeNumber)); 773251881Speter return_VALUE (ACPI_INTERRUPT_NOT_HANDLED); 774251881Speter } 775251881Speter } 776251881Speter 777251881Speter /* 778251881Speter * Always disable the GPE so that it does not keep firing before 779251881Speter * any asynchronous activity completes (either from the execution 780251881Speter * of a GPE method or an asynchronous GPE handler.) 781251881Speter * 782251881Speter * If there is no handler or method to run, just disable the 783251881Speter * GPE and leave it disabled permanently to prevent further such 784251881Speter * pointless events from firing. 785251881Speter */ 786251881Speter Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE); 787251881Speter if (ACPI_FAILURE (Status)) 788251881Speter { 789251881Speter ACPI_EXCEPTION ((AE_INFO, Status, 790251881Speter "Unable to disable GPE%02X", GpeNumber)); 791251881Speter return_VALUE (ACPI_INTERRUPT_NOT_HANDLED); 792251881Speter } 793251881Speter 794251881Speter /* 795251881Speter * Dispatch the GPE to either an installed handler or the control 796251881Speter * method associated with this GPE (_Lxx or _Exx). If a handler 797251881Speter * exists, we invoke it and do not attempt to run the method. 798251881Speter * If there is neither a handler nor a method, leave the GPE 799251881Speter * disabled. 800251881Speter */ 801251881Speter switch (GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) 802251881Speter { 803251881Speter case ACPI_GPE_DISPATCH_HANDLER: 804251881Speter 805251881Speter /* Invoke the installed handler (at interrupt level) */ 806251881Speter 807251881Speter ReturnValue = GpeEventInfo->Dispatch.Handler->Address ( 808251881Speter GpeDevice, GpeNumber, 809251881Speter GpeEventInfo->Dispatch.Handler->Context); 810251881Speter 811251881Speter /* If requested, clear (if level-triggered) and reenable the GPE */ 812251881Speter 813251881Speter if (ReturnValue & ACPI_REENABLE_GPE) 814251881Speter { 815251881Speter (void) AcpiEvFinishGpe (GpeEventInfo); 816251881Speter } 817251881Speter break; 818251881Speter 819251881Speter case ACPI_GPE_DISPATCH_METHOD: 820251881Speter case ACPI_GPE_DISPATCH_NOTIFY: 821251881Speter 822251881Speter /* 823251881Speter * Execute the method associated with the GPE 824251881Speter * NOTE: Level-triggered GPEs are cleared after the method completes. 825251881Speter */ 826251881Speter Status = AcpiOsExecute (OSL_GPE_HANDLER, 827251881Speter AcpiEvAsynchExecuteGpeMethod, GpeEventInfo); 828251881Speter if (ACPI_FAILURE (Status)) 829251881Speter { 830251881Speter ACPI_EXCEPTION ((AE_INFO, Status, 831251881Speter "Unable to queue handler for GPE%02X - event disabled", 832251881Speter GpeNumber)); 833251881Speter } 834251881Speter break; 835251881Speter 836251881Speter default: 837251881Speter 838251881Speter /* 839251881Speter * No handler or method to run! 840251881Speter * 03/2010: This case should no longer be possible. We will not allow 841251881Speter * a GPE to be enabled if it has no handler or method. 842251881Speter */ 843251881Speter ACPI_ERROR ((AE_INFO, 844251881Speter "No handler or method for GPE%02X, disabling event", 845251881Speter GpeNumber)); 846251881Speter break; 847251881Speter } 848251881Speter 849251881Speter return_VALUE (ACPI_INTERRUPT_HANDLED); 850251881Speter} 851251881Speter 852251881Speter#endif /* !ACPI_REDUCED_HARDWARE */ 853251881Speter