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