evgpe.c revision 249663
150476Speter/****************************************************************************** 213546Sjulian * 394797Sobrien * Module Name: evgpe - General Purpose Event handling and dispatch 413546Sjulian * 594797Sobrien *****************************************************************************/ 694797Sobrien 794797Sobrien/* 894797Sobrien * Copyright (C) 2000 - 2013, Intel Corp. 994797Sobrien * All rights reserved. 10169524Sdeischen * 11169648Sdeischen * Redistribution and use in source and binary forms, with or without 12169648Sdeischen * modification, are permitted provided that the following conditions 13174092Sbrooks * are met: 14174092Sbrooks * 1. Redistributions of source code must retain the above copyright 15174092Sbrooks * notice, this list of conditions, and the following disclaimer, 16169648Sdeischen * without modification. 17125230Sdeischen * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18174092Sbrooks * substantially similar to the "NO WARRANTY" disclaimer below 19174092Sbrooks * ("Disclaimer") and any redistribution must be conditioned upon 20174092Sbrooks * including a substantially similar Disclaimer requirement for further 21169524Sdeischen * binary redistribution. 22195767Skensmith * 3. Neither the names of the above-listed copyright holders nor the names 23113658Sdeischen * of any contributors may be used to endorse or promote products derived 24103388Smini * from this software without specific prior written permission. 2594797Sobrien * 26113658Sdeischen * Alternatively, this software may be distributed under the terms of the 27113658Sdeischen * GNU General Public License ("GPL") version 2 as published by the Free 28115399Skan * Software Foundation. 29133801Sdavidxu * 30115399Skan * NO WARRANTY 3136831Sjb * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32172491Sobrien * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3336831Sjb * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34113786Sdeischen * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35174112Sdeischen * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3636831Sjb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37117706Sdavidxu * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38117706Sdavidxu * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39117706Sdavidxu * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40117706Sdavidxu * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41156774Sdeischen * POSSIBILITY OF SUCH DAMAGES. 42156774Sdeischen */ 43115399Skan 44176055Sdes#include <contrib/dev/acpica/include/acpi.h> 45176056Sdes#include <contrib/dev/acpica/include/accommon.h> 46156774Sdeischen#include <contrib/dev/acpica/include/acevents.h> 47136910Sru#include <contrib/dev/acpica/include/acnamesp.h> 4813546Sjulian 49116705Smarcel#define _COMPONENT ACPI_EVENTS 50116705Smarcel ACPI_MODULE_NAME ("evgpe") 51116705Smarcel 52103388Smini#if (!ACPI_REDUCED_HARDWARE) /* Entire module */ 5313546Sjulian 54172491Sobrien/* Local prototypes */ 55188583Sjkim 56169524Sdeischenstatic void ACPI_SYSTEM_XFACE 57188583SjkimAcpiEvAsynchExecuteGpeMethod ( 58169524Sdeischen void *Context); 59169524Sdeischen 60169524Sdeischenstatic void ACPI_SYSTEM_XFACE 61169524SdeischenAcpiEvAsynchEnableGpe ( 62169524Sdeischen void *Context); 63169524Sdeischen 64169524Sdeischen 65169524Sdeischen/******************************************************************************* 6613546Sjulian * 67 * FUNCTION: AcpiEvUpdateGpeEnableMask 68 * 69 * PARAMETERS: GpeEventInfo - GPE to update 70 * 71 * RETURN: Status 72 * 73 * DESCRIPTION: Updates GPE register enable mask based upon whether there are 74 * runtime references to this GPE 75 * 76 ******************************************************************************/ 77 78ACPI_STATUS 79AcpiEvUpdateGpeEnableMask ( 80 ACPI_GPE_EVENT_INFO *GpeEventInfo) 81{ 82 ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; 83 UINT32 RegisterBit; 84 85 86 ACPI_FUNCTION_TRACE (EvUpdateGpeEnableMask); 87 88 89 GpeRegisterInfo = GpeEventInfo->RegisterInfo; 90 if (!GpeRegisterInfo) 91 { 92 return_ACPI_STATUS (AE_NOT_EXIST); 93 } 94 95 RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo); 96 97 /* Clear the run bit up front */ 98 99 ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForRun, RegisterBit); 100 101 /* Set the mask bit only if there are references to this GPE */ 102 103 if (GpeEventInfo->RuntimeCount) 104 { 105 ACPI_SET_BIT (GpeRegisterInfo->EnableForRun, (UINT8) RegisterBit); 106 } 107 108 return_ACPI_STATUS (AE_OK); 109} 110 111 112/******************************************************************************* 113 * 114 * FUNCTION: AcpiEvEnableGpe 115 * 116 * PARAMETERS: GpeEventInfo - GPE to enable 117 * 118 * RETURN: Status 119 * 120 * DESCRIPTION: Clear a GPE of stale events and enable it. 121 * 122 ******************************************************************************/ 123 124ACPI_STATUS 125AcpiEvEnableGpe ( 126 ACPI_GPE_EVENT_INFO *GpeEventInfo) 127{ 128 ACPI_STATUS Status; 129 130 131 ACPI_FUNCTION_TRACE (EvEnableGpe); 132 133 134 /* 135 * We will only allow a GPE to be enabled if it has either an associated 136 * method (_Lxx/_Exx) or a handler, or is using the implicit notify 137 * feature. Otherwise, the GPE will be immediately disabled by 138 * AcpiEvGpeDispatch the first time it fires. 139 */ 140 if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == 141 ACPI_GPE_DISPATCH_NONE) 142 { 143 return_ACPI_STATUS (AE_NO_HANDLER); 144 } 145 146 /* Clear the GPE (of stale events) */ 147 148 Status = AcpiHwClearGpe (GpeEventInfo); 149 if (ACPI_FAILURE (Status)) 150 { 151 return_ACPI_STATUS (Status); 152 } 153 154 /* Enable the requested GPE */ 155 156 Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_ENABLE); 157 return_ACPI_STATUS (Status); 158} 159 160 161/******************************************************************************* 162 * 163 * FUNCTION: AcpiEvAddGpeReference 164 * 165 * PARAMETERS: GpeEventInfo - Add a reference to this GPE 166 * 167 * RETURN: Status 168 * 169 * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is 170 * hardware-enabled. 171 * 172 ******************************************************************************/ 173 174ACPI_STATUS 175AcpiEvAddGpeReference ( 176 ACPI_GPE_EVENT_INFO *GpeEventInfo) 177{ 178 ACPI_STATUS Status = AE_OK; 179 180 181 ACPI_FUNCTION_TRACE (EvAddGpeReference); 182 183 184 if (GpeEventInfo->RuntimeCount == ACPI_UINT8_MAX) 185 { 186 return_ACPI_STATUS (AE_LIMIT); 187 } 188 189 GpeEventInfo->RuntimeCount++; 190 if (GpeEventInfo->RuntimeCount == 1) 191 { 192 /* Enable on first reference */ 193 194 Status = AcpiEvUpdateGpeEnableMask (GpeEventInfo); 195 if (ACPI_SUCCESS (Status)) 196 { 197 Status = AcpiEvEnableGpe (GpeEventInfo); 198 } 199 200 if (ACPI_FAILURE (Status)) 201 { 202 GpeEventInfo->RuntimeCount--; 203 } 204 } 205 206 return_ACPI_STATUS (Status); 207} 208 209 210/******************************************************************************* 211 * 212 * FUNCTION: AcpiEvRemoveGpeReference 213 * 214 * PARAMETERS: GpeEventInfo - Remove a reference to this GPE 215 * 216 * RETURN: Status 217 * 218 * DESCRIPTION: Remove a reference to a GPE. When the last reference is 219 * removed, the GPE is hardware-disabled. 220 * 221 ******************************************************************************/ 222 223ACPI_STATUS 224AcpiEvRemoveGpeReference ( 225 ACPI_GPE_EVENT_INFO *GpeEventInfo) 226{ 227 ACPI_STATUS Status = AE_OK; 228 229 230 ACPI_FUNCTION_TRACE (EvRemoveGpeReference); 231 232 233 if (!GpeEventInfo->RuntimeCount) 234 { 235 return_ACPI_STATUS (AE_LIMIT); 236 } 237 238 GpeEventInfo->RuntimeCount--; 239 if (!GpeEventInfo->RuntimeCount) 240 { 241 /* Disable on last reference */ 242 243 Status = AcpiEvUpdateGpeEnableMask (GpeEventInfo); 244 if (ACPI_SUCCESS (Status)) 245 { 246 Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE); 247 } 248 249 if (ACPI_FAILURE (Status)) 250 { 251 GpeEventInfo->RuntimeCount++; 252 } 253 } 254 255 return_ACPI_STATUS (Status); 256} 257 258 259/******************************************************************************* 260 * 261 * FUNCTION: AcpiEvLowGetGpeInfo 262 * 263 * PARAMETERS: GpeNumber - Raw GPE number 264 * GpeBlock - A GPE info block 265 * 266 * RETURN: A GPE EventInfo struct. NULL if not a valid GPE (The GpeNumber 267 * is not within the specified GPE block) 268 * 269 * DESCRIPTION: Returns the EventInfo struct associated with this GPE. This is 270 * the low-level implementation of EvGetGpeEventInfo. 271 * 272 ******************************************************************************/ 273 274ACPI_GPE_EVENT_INFO * 275AcpiEvLowGetGpeInfo ( 276 UINT32 GpeNumber, 277 ACPI_GPE_BLOCK_INFO *GpeBlock) 278{ 279 UINT32 GpeIndex; 280 281 282 /* 283 * Validate that the GpeNumber is within the specified GpeBlock. 284 * (Two steps) 285 */ 286 if (!GpeBlock || 287 (GpeNumber < GpeBlock->BlockBaseNumber)) 288 { 289 return (NULL); 290 } 291 292 GpeIndex = GpeNumber - GpeBlock->BlockBaseNumber; 293 if (GpeIndex >= GpeBlock->GpeCount) 294 { 295 return (NULL); 296 } 297 298 return (&GpeBlock->EventInfo[GpeIndex]); 299} 300 301 302/******************************************************************************* 303 * 304 * FUNCTION: AcpiEvGetGpeEventInfo 305 * 306 * PARAMETERS: GpeDevice - Device node. NULL for GPE0/GPE1 307 * GpeNumber - Raw GPE number 308 * 309 * RETURN: A GPE EventInfo struct. NULL if not a valid GPE 310 * 311 * DESCRIPTION: Returns the EventInfo struct associated with this GPE. 312 * Validates the GpeBlock and the GpeNumber 313 * 314 * Should be called only when the GPE lists are semaphore locked 315 * and not subject to change. 316 * 317 ******************************************************************************/ 318 319ACPI_GPE_EVENT_INFO * 320AcpiEvGetGpeEventInfo ( 321 ACPI_HANDLE GpeDevice, 322 UINT32 GpeNumber) 323{ 324 ACPI_OPERAND_OBJECT *ObjDesc; 325 ACPI_GPE_EVENT_INFO *GpeInfo; 326 UINT32 i; 327 328 329 ACPI_FUNCTION_ENTRY (); 330 331 332 /* A NULL GpeDevice means use the FADT-defined GPE block(s) */ 333 334 if (!GpeDevice) 335 { 336 /* Examine GPE Block 0 and 1 (These blocks are permanent) */ 337 338 for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++) 339 { 340 GpeInfo = AcpiEvLowGetGpeInfo (GpeNumber, 341 AcpiGbl_GpeFadtBlocks[i]); 342 if (GpeInfo) 343 { 344 return (GpeInfo); 345 } 346 } 347 348 /* The GpeNumber was not in the range of either FADT GPE block */ 349 350 return (NULL); 351 } 352 353 /* A Non-NULL GpeDevice means this is a GPE Block Device */ 354 355 ObjDesc = AcpiNsGetAttachedObject ((ACPI_NAMESPACE_NODE *) GpeDevice); 356 if (!ObjDesc || 357 !ObjDesc->Device.GpeBlock) 358 { 359 return (NULL); 360 } 361 362 return (AcpiEvLowGetGpeInfo (GpeNumber, ObjDesc->Device.GpeBlock)); 363} 364 365 366/******************************************************************************* 367 * 368 * FUNCTION: AcpiEvGpeDetect 369 * 370 * PARAMETERS: GpeXruptList - Interrupt block for this interrupt. 371 * Can have multiple GPE blocks attached. 372 * 373 * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED 374 * 375 * DESCRIPTION: Detect if any GP events have occurred. This function is 376 * executed at interrupt level. 377 * 378 ******************************************************************************/ 379 380UINT32 381AcpiEvGpeDetect ( 382 ACPI_GPE_XRUPT_INFO *GpeXruptList) 383{ 384 ACPI_STATUS Status; 385 ACPI_GPE_BLOCK_INFO *GpeBlock; 386 ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; 387 UINT32 IntStatus = ACPI_INTERRUPT_NOT_HANDLED; 388 UINT8 EnabledStatusByte; 389 UINT32 StatusReg; 390 UINT32 EnableReg; 391 ACPI_CPU_FLAGS Flags; 392 UINT32 i; 393 UINT32 j; 394 395 396 ACPI_FUNCTION_NAME (EvGpeDetect); 397 398 /* Check for the case where there are no GPEs */ 399 400 if (!GpeXruptList) 401 { 402 return (IntStatus); 403 } 404 405 /* 406 * We need to obtain the GPE lock for both the data structs and registers 407 * Note: Not necessary to obtain the hardware lock, since the GPE 408 * registers are owned by the GpeLock. 409 */ 410 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 411 412 /* Examine all GPE blocks attached to this interrupt level */ 413 414 GpeBlock = GpeXruptList->GpeBlockListHead; 415 while (GpeBlock) 416 { 417 /* 418 * Read all of the 8-bit GPE status and enable registers in this GPE 419 * block, saving all of them. Find all currently active GP events. 420 */ 421 for (i = 0; i < GpeBlock->RegisterCount; i++) 422 { 423 /* Get the next status/enable pair */ 424 425 GpeRegisterInfo = &GpeBlock->RegisterInfo[i]; 426 427 /* 428 * Optimization: If there are no GPEs enabled within this 429 * register, we can safely ignore the entire register. 430 */ 431 if (!(GpeRegisterInfo->EnableForRun | 432 GpeRegisterInfo->EnableForWake)) 433 { 434 ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS, 435 "Ignore disabled registers for GPE%02X-GPE%02X: " 436 "RunEnable=%02X, WakeEnable=%02X\n", 437 GpeRegisterInfo->BaseGpeNumber, 438 GpeRegisterInfo->BaseGpeNumber + (ACPI_GPE_REGISTER_WIDTH - 1), 439 GpeRegisterInfo->EnableForRun, 440 GpeRegisterInfo->EnableForWake)); 441 continue; 442 } 443 444 /* Read the Status Register */ 445 446 Status = AcpiHwRead (&StatusReg, &GpeRegisterInfo->StatusAddress); 447 if (ACPI_FAILURE (Status)) 448 { 449 goto UnlockAndExit; 450 } 451 452 /* Read the Enable Register */ 453 454 Status = AcpiHwRead (&EnableReg, &GpeRegisterInfo->EnableAddress); 455 if (ACPI_FAILURE (Status)) 456 { 457 goto UnlockAndExit; 458 } 459 460 ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS, 461 "Read registers for GPE%02X-GPE%02X: Status=%02X, Enable=%02X, " 462 "RunEnable=%02X, WakeEnable=%02X\n", 463 GpeRegisterInfo->BaseGpeNumber, 464 GpeRegisterInfo->BaseGpeNumber + (ACPI_GPE_REGISTER_WIDTH - 1), 465 StatusReg, EnableReg, 466 GpeRegisterInfo->EnableForRun, 467 GpeRegisterInfo->EnableForWake)); 468 469 /* Check if there is anything active at all in this register */ 470 471 EnabledStatusByte = (UINT8) (StatusReg & EnableReg); 472 if (!EnabledStatusByte) 473 { 474 /* No active GPEs in this register, move on */ 475 476 continue; 477 } 478 479 /* Now look at the individual GPEs in this byte register */ 480 481 for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) 482 { 483 /* Examine one GPE bit */ 484 485 if (EnabledStatusByte & (1 << j)) 486 { 487 /* 488 * Found an active GPE. Dispatch the event to a handler 489 * or method. 490 */ 491 IntStatus |= AcpiEvGpeDispatch (GpeBlock->Node, 492 &GpeBlock->EventInfo[((ACPI_SIZE) i * 493 ACPI_GPE_REGISTER_WIDTH) + j], 494 j + GpeRegisterInfo->BaseGpeNumber); 495 } 496 } 497 } 498 499 GpeBlock = GpeBlock->Next; 500 } 501 502UnlockAndExit: 503 504 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 505 return (IntStatus); 506} 507 508 509/******************************************************************************* 510 * 511 * FUNCTION: AcpiEvAsynchExecuteGpeMethod 512 * 513 * PARAMETERS: Context (GpeEventInfo) - Info for this GPE 514 * 515 * RETURN: None 516 * 517 * DESCRIPTION: Perform the actual execution of a GPE control method. This 518 * function is called from an invocation of AcpiOsExecute and 519 * therefore does NOT execute at interrupt level - so that 520 * the control method itself is not executed in the context of 521 * an interrupt handler. 522 * 523 ******************************************************************************/ 524 525static void ACPI_SYSTEM_XFACE 526AcpiEvAsynchExecuteGpeMethod ( 527 void *Context) 528{ 529 ACPI_GPE_EVENT_INFO *GpeEventInfo = Context; 530 ACPI_STATUS Status; 531 ACPI_GPE_EVENT_INFO *LocalGpeEventInfo; 532 ACPI_EVALUATE_INFO *Info; 533 ACPI_GPE_NOTIFY_INFO *Notify; 534 535 536 ACPI_FUNCTION_TRACE (EvAsynchExecuteGpeMethod); 537 538 539 /* Allocate a local GPE block */ 540 541 LocalGpeEventInfo = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_EVENT_INFO)); 542 if (!LocalGpeEventInfo) 543 { 544 ACPI_EXCEPTION ((AE_INFO, AE_NO_MEMORY, 545 "while handling a GPE")); 546 return_VOID; 547 } 548 549 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 550 if (ACPI_FAILURE (Status)) 551 { 552 return_VOID; 553 } 554 555 /* Must revalidate the GpeNumber/GpeBlock */ 556 557 if (!AcpiEvValidGpeEvent (GpeEventInfo)) 558 { 559 Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 560 return_VOID; 561 } 562 563 /* 564 * Take a snapshot of the GPE info for this level - we copy the info to 565 * prevent a race condition with RemoveHandler/RemoveBlock. 566 */ 567 ACPI_MEMCPY (LocalGpeEventInfo, GpeEventInfo, 568 sizeof (ACPI_GPE_EVENT_INFO)); 569 570 Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 571 if (ACPI_FAILURE (Status)) 572 { 573 return_VOID; 574 } 575 576 /* Do the correct dispatch - normal method or implicit notify */ 577 578 switch (LocalGpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) 579 { 580 case ACPI_GPE_DISPATCH_NOTIFY: 581 582 /* 583 * Implicit notify. 584 * Dispatch a DEVICE_WAKE notify to the appropriate handler. 585 * NOTE: the request is queued for execution after this method 586 * completes. The notify handlers are NOT invoked synchronously 587 * from this thread -- because handlers may in turn run other 588 * control methods. 589 * 590 * June 2012: Expand implicit notify mechanism to support 591 * notifies on multiple device objects. 592 */ 593 Notify = LocalGpeEventInfo->Dispatch.NotifyList; 594 while (ACPI_SUCCESS (Status) && Notify) 595 { 596 Status = AcpiEvQueueNotifyRequest (Notify->DeviceNode, 597 ACPI_NOTIFY_DEVICE_WAKE); 598 599 Notify = Notify->Next; 600 } 601 break; 602 603 case ACPI_GPE_DISPATCH_METHOD: 604 605 /* Allocate the evaluation information block */ 606 607 Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO)); 608 if (!Info) 609 { 610 Status = AE_NO_MEMORY; 611 } 612 else 613 { 614 /* 615 * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the 616 * _Lxx/_Exx control method that corresponds to this GPE 617 */ 618 Info->PrefixNode = LocalGpeEventInfo->Dispatch.MethodNode; 619 Info->Flags = ACPI_IGNORE_RETURN_VALUE; 620 621 Status = AcpiNsEvaluate (Info); 622 ACPI_FREE (Info); 623 } 624 625 if (ACPI_FAILURE (Status)) 626 { 627 ACPI_EXCEPTION ((AE_INFO, Status, 628 "while evaluating GPE method [%4.4s]", 629 AcpiUtGetNodeName (LocalGpeEventInfo->Dispatch.MethodNode))); 630 } 631 break; 632 633 default: 634 return_VOID; /* Should never happen */ 635 } 636 637 /* Defer enabling of GPE until all notify handlers are done */ 638 639 Status = AcpiOsExecute (OSL_NOTIFY_HANDLER, 640 AcpiEvAsynchEnableGpe, LocalGpeEventInfo); 641 if (ACPI_FAILURE (Status)) 642 { 643 ACPI_FREE (LocalGpeEventInfo); 644 } 645 return_VOID; 646} 647 648 649/******************************************************************************* 650 * 651 * FUNCTION: AcpiEvAsynchEnableGpe 652 * 653 * PARAMETERS: Context (GpeEventInfo) - Info for this GPE 654 * Callback from AcpiOsExecute 655 * 656 * RETURN: None 657 * 658 * DESCRIPTION: Asynchronous clear/enable for GPE. This allows the GPE to 659 * complete (i.e., finish execution of Notify) 660 * 661 ******************************************************************************/ 662 663static void ACPI_SYSTEM_XFACE 664AcpiEvAsynchEnableGpe ( 665 void *Context) 666{ 667 ACPI_GPE_EVENT_INFO *GpeEventInfo = Context; 668 669 670 (void) AcpiEvFinishGpe (GpeEventInfo); 671 672 ACPI_FREE (GpeEventInfo); 673 return; 674} 675 676 677/******************************************************************************* 678 * 679 * FUNCTION: AcpiEvFinishGpe 680 * 681 * PARAMETERS: GpeEventInfo - Info for this GPE 682 * 683 * RETURN: Status 684 * 685 * DESCRIPTION: Clear/Enable a GPE. Common code that is used after execution 686 * of a GPE method or a synchronous or asynchronous GPE handler. 687 * 688 ******************************************************************************/ 689 690ACPI_STATUS 691AcpiEvFinishGpe ( 692 ACPI_GPE_EVENT_INFO *GpeEventInfo) 693{ 694 ACPI_STATUS Status; 695 696 697 if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) == 698 ACPI_GPE_LEVEL_TRIGGERED) 699 { 700 /* 701 * GPE is level-triggered, we clear the GPE status bit after 702 * handling the event. 703 */ 704 Status = AcpiHwClearGpe (GpeEventInfo); 705 if (ACPI_FAILURE (Status)) 706 { 707 return (Status); 708 } 709 } 710 711 /* 712 * Enable this GPE, conditionally. This means that the GPE will 713 * only be physically enabled if the EnableForRun bit is set 714 * in the EventInfo. 715 */ 716 (void) AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_CONDITIONAL_ENABLE); 717 return (AE_OK); 718} 719 720 721/******************************************************************************* 722 * 723 * FUNCTION: AcpiEvGpeDispatch 724 * 725 * PARAMETERS: GpeDevice - Device node. NULL for GPE0/GPE1 726 * GpeEventInfo - Info for this GPE 727 * GpeNumber - Number relative to the parent GPE block 728 * 729 * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED 730 * 731 * DESCRIPTION: Dispatch a General Purpose Event to either a function (e.g. EC) 732 * or method (e.g. _Lxx/_Exx) handler. 733 * 734 * This function executes at interrupt level. 735 * 736 ******************************************************************************/ 737 738UINT32 739AcpiEvGpeDispatch ( 740 ACPI_NAMESPACE_NODE *GpeDevice, 741 ACPI_GPE_EVENT_INFO *GpeEventInfo, 742 UINT32 GpeNumber) 743{ 744 ACPI_STATUS Status; 745 UINT32 ReturnValue; 746 747 748 ACPI_FUNCTION_TRACE (EvGpeDispatch); 749 750 751 /* Invoke global event handler if present */ 752 753 AcpiGpeCount++; 754 if (AcpiGbl_GlobalEventHandler) 755 { 756 AcpiGbl_GlobalEventHandler (ACPI_EVENT_TYPE_GPE, GpeDevice, 757 GpeNumber, AcpiGbl_GlobalEventHandlerContext); 758 } 759 760 /* 761 * If edge-triggered, clear the GPE status bit now. Note that 762 * level-triggered events are cleared after the GPE is serviced. 763 */ 764 if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) == 765 ACPI_GPE_EDGE_TRIGGERED) 766 { 767 Status = AcpiHwClearGpe (GpeEventInfo); 768 if (ACPI_FAILURE (Status)) 769 { 770 ACPI_EXCEPTION ((AE_INFO, Status, 771 "Unable to clear GPE%02X", GpeNumber)); 772 return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED); 773 } 774 } 775 776 /* 777 * Always disable the GPE so that it does not keep firing before 778 * any asynchronous activity completes (either from the execution 779 * of a GPE method or an asynchronous GPE handler.) 780 * 781 * If there is no handler or method to run, just disable the 782 * GPE and leave it disabled permanently to prevent further such 783 * pointless events from firing. 784 */ 785 Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE); 786 if (ACPI_FAILURE (Status)) 787 { 788 ACPI_EXCEPTION ((AE_INFO, Status, 789 "Unable to disable GPE%02X", GpeNumber)); 790 return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED); 791 } 792 793 /* 794 * Dispatch the GPE to either an installed handler or the control 795 * method associated with this GPE (_Lxx or _Exx). If a handler 796 * exists, we invoke it and do not attempt to run the method. 797 * If there is neither a handler nor a method, leave the GPE 798 * disabled. 799 */ 800 switch (GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) 801 { 802 case ACPI_GPE_DISPATCH_HANDLER: 803 804 /* Invoke the installed handler (at interrupt level) */ 805 806 ReturnValue = GpeEventInfo->Dispatch.Handler->Address ( 807 GpeDevice, GpeNumber, 808 GpeEventInfo->Dispatch.Handler->Context); 809 810 /* If requested, clear (if level-triggered) and reenable the GPE */ 811 812 if (ReturnValue & ACPI_REENABLE_GPE) 813 { 814 (void) AcpiEvFinishGpe (GpeEventInfo); 815 } 816 break; 817 818 case ACPI_GPE_DISPATCH_METHOD: 819 case ACPI_GPE_DISPATCH_NOTIFY: 820 821 /* 822 * Execute the method associated with the GPE 823 * NOTE: Level-triggered GPEs are cleared after the method completes. 824 */ 825 Status = AcpiOsExecute (OSL_GPE_HANDLER, 826 AcpiEvAsynchExecuteGpeMethod, GpeEventInfo); 827 if (ACPI_FAILURE (Status)) 828 { 829 ACPI_EXCEPTION ((AE_INFO, Status, 830 "Unable to queue handler for GPE%02X - event disabled", 831 GpeNumber)); 832 } 833 break; 834 835 default: 836 837 /* 838 * No handler or method to run! 839 * 03/2010: This case should no longer be possible. We will not allow 840 * a GPE to be enabled if it has no handler or method. 841 */ 842 ACPI_ERROR ((AE_INFO, 843 "No handler or method for GPE%02X, disabling event", 844 GpeNumber)); 845 break; 846 } 847 848 return_UINT32 (ACPI_INTERRUPT_HANDLED); 849} 850 851#endif /* !ACPI_REDUCED_HARDWARE */ 852