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