1 /****************************************************************************** 2 * 3 * Module Name: evgpe - General Purpose Event handling and dispatch 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2019, 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 "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 /* 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_GPE_BLOCK_INFO *GpeBlock; 438 ACPI_NAMESPACE_NODE *GpeDevice; 439 ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; 440 ACPI_GPE_EVENT_INFO *GpeEventInfo; 441 UINT32 GpeNumber; 442 UINT32 IntStatus = ACPI_INTERRUPT_NOT_HANDLED; 443 ACPI_CPU_FLAGS Flags; 444 UINT32 i; 445 UINT32 j; 446 447 448 ACPI_FUNCTION_NAME (EvGpeDetect); 449 450 /* Check for the case where there are no GPEs */ 451 452 if (!GpeXruptList) 453 { 454 return (IntStatus); 455 } 456 457 /* 458 * We need to obtain the GPE lock for both the data structs and registers 459 * Note: Not necessary to obtain the hardware lock, since the GPE 460 * registers are owned by the GpeLock. 461 */ 462 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 463 464 /* Examine all GPE blocks attached to this interrupt level */ 465 466 GpeBlock = GpeXruptList->GpeBlockListHead; 467 while (GpeBlock) 468 { 469 GpeDevice = GpeBlock->Node; 470 471 /* 472 * Read all of the 8-bit GPE status and enable registers in this GPE 473 * block, saving all of them. Find all currently active GP events. 474 */ 475 for (i = 0; i < GpeBlock->RegisterCount; i++) 476 { 477 /* Get the next status/enable pair */ 478 479 GpeRegisterInfo = &GpeBlock->RegisterInfo[i]; 480 481 /* 482 * Optimization: If there are no GPEs enabled within this 483 * register, we can safely ignore the entire register. 484 */ 485 if (!(GpeRegisterInfo->EnableForRun | 486 GpeRegisterInfo->EnableForWake)) 487 { 488 ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS, 489 "Ignore disabled registers for GPE %02X-%02X: " 490 "RunEnable=%02X, WakeEnable=%02X\n", 491 GpeRegisterInfo->BaseGpeNumber, 492 GpeRegisterInfo->BaseGpeNumber + (ACPI_GPE_REGISTER_WIDTH - 1), 493 GpeRegisterInfo->EnableForRun, 494 GpeRegisterInfo->EnableForWake)); 495 continue; 496 } 497 498 /* Now look at the individual GPEs in this byte register */ 499 500 for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) 501 { 502 /* Detect and dispatch one GPE bit */ 503 504 GpeEventInfo = &GpeBlock->EventInfo[((ACPI_SIZE) i * 505 ACPI_GPE_REGISTER_WIDTH) + j]; 506 GpeNumber = j + GpeRegisterInfo->BaseGpeNumber; 507 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 508 IntStatus |= AcpiEvDetectGpe ( 509 GpeDevice, GpeEventInfo, GpeNumber); 510 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 511 } 512 } 513 514 GpeBlock = GpeBlock->Next; 515 } 516 517 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 518 return (IntStatus); 519 } 520 521 522 /******************************************************************************* 523 * 524 * FUNCTION: AcpiEvAsynchExecuteGpeMethod 525 * 526 * PARAMETERS: Context (GpeEventInfo) - Info for this GPE 527 * 528 * RETURN: None 529 * 530 * DESCRIPTION: Perform the actual execution of a GPE control method. This 531 * function is called from an invocation of AcpiOsExecute and 532 * therefore does NOT execute at interrupt level - so that 533 * the control method itself is not executed in the context of 534 * an interrupt handler. 535 * 536 ******************************************************************************/ 537 538 static void ACPI_SYSTEM_XFACE 539 AcpiEvAsynchExecuteGpeMethod ( 540 void *Context) 541 { 542 ACPI_GPE_EVENT_INFO *GpeEventInfo = Context; 543 ACPI_STATUS Status = AE_OK; 544 ACPI_EVALUATE_INFO *Info; 545 ACPI_GPE_NOTIFY_INFO *Notify; 546 547 548 ACPI_FUNCTION_TRACE (EvAsynchExecuteGpeMethod); 549 550 551 /* Do the correct dispatch - normal method or implicit notify */ 552 553 switch (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags)) 554 { 555 case ACPI_GPE_DISPATCH_NOTIFY: 556 /* 557 * Implicit notify. 558 * Dispatch a DEVICE_WAKE notify to the appropriate handler. 559 * NOTE: the request is queued for execution after this method 560 * completes. The notify handlers are NOT invoked synchronously 561 * from this thread -- because handlers may in turn run other 562 * control methods. 563 * 564 * June 2012: Expand implicit notify mechanism to support 565 * notifies on multiple device objects. 566 */ 567 Notify = GpeEventInfo->Dispatch.NotifyList; 568 while (ACPI_SUCCESS (Status) && Notify) 569 { 570 Status = AcpiEvQueueNotifyRequest ( 571 Notify->DeviceNode, ACPI_NOTIFY_DEVICE_WAKE); 572 573 Notify = Notify->Next; 574 } 575 break; 576 577 case ACPI_GPE_DISPATCH_METHOD: 578 579 /* Allocate the evaluation information block */ 580 581 Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO)); 582 if (!Info) 583 { 584 Status = AE_NO_MEMORY; 585 } 586 else 587 { 588 /* 589 * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the 590 * _Lxx/_Exx control method that corresponds to this GPE 591 */ 592 Info->PrefixNode = GpeEventInfo->Dispatch.MethodNode; 593 Info->Flags = ACPI_IGNORE_RETURN_VALUE; 594 595 Status = AcpiNsEvaluate (Info); 596 ACPI_FREE (Info); 597 } 598 599 if (ACPI_FAILURE (Status)) 600 { 601 ACPI_EXCEPTION ((AE_INFO, Status, 602 "while evaluating GPE method [%4.4s]", 603 AcpiUtGetNodeName (GpeEventInfo->Dispatch.MethodNode))); 604 } 605 break; 606 607 default: 608 609 goto ErrorExit; /* Should never happen */ 610 } 611 612 /* Defer enabling of GPE until all notify handlers are done */ 613 614 Status = AcpiOsExecute (OSL_NOTIFY_HANDLER, 615 AcpiEvAsynchEnableGpe, GpeEventInfo); 616 if (ACPI_SUCCESS (Status)) 617 { 618 return_VOID; 619 } 620 621 ErrorExit: 622 AcpiEvAsynchEnableGpe (GpeEventInfo); 623 return_VOID; 624 } 625 626 627 /******************************************************************************* 628 * 629 * FUNCTION: AcpiEvAsynchEnableGpe 630 * 631 * PARAMETERS: Context (GpeEventInfo) - Info for this GPE 632 * Callback from AcpiOsExecute 633 * 634 * RETURN: None 635 * 636 * DESCRIPTION: Asynchronous clear/enable for GPE. This allows the GPE to 637 * complete (i.e., finish execution of Notify) 638 * 639 ******************************************************************************/ 640 641 static void ACPI_SYSTEM_XFACE 642 AcpiEvAsynchEnableGpe ( 643 void *Context) 644 { 645 ACPI_GPE_EVENT_INFO *GpeEventInfo = Context; 646 ACPI_CPU_FLAGS Flags; 647 648 649 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 650 (void) AcpiEvFinishGpe (GpeEventInfo); 651 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 652 653 return; 654 } 655 656 657 /******************************************************************************* 658 * 659 * FUNCTION: AcpiEvFinishGpe 660 * 661 * PARAMETERS: GpeEventInfo - Info for this GPE 662 * 663 * RETURN: Status 664 * 665 * DESCRIPTION: Clear/Enable a GPE. Common code that is used after execution 666 * of a GPE method or a synchronous or asynchronous GPE handler. 667 * 668 ******************************************************************************/ 669 670 ACPI_STATUS 671 AcpiEvFinishGpe ( 672 ACPI_GPE_EVENT_INFO *GpeEventInfo) 673 { 674 ACPI_STATUS Status; 675 676 677 if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) == 678 ACPI_GPE_LEVEL_TRIGGERED) 679 { 680 /* 681 * GPE is level-triggered, we clear the GPE status bit after 682 * handling the event. 683 */ 684 Status = AcpiHwClearGpe (GpeEventInfo); 685 if (ACPI_FAILURE (Status)) 686 { 687 return (Status); 688 } 689 } 690 691 /* 692 * Enable this GPE, conditionally. This means that the GPE will 693 * only be physically enabled if the EnableMask bit is set 694 * in the EventInfo. 695 */ 696 (void) AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_CONDITIONAL_ENABLE); 697 GpeEventInfo->DisableForDispatch = FALSE; 698 return (AE_OK); 699 } 700 701 702 /******************************************************************************* 703 * 704 * FUNCTION: AcpiEvDetectGpe 705 * 706 * PARAMETERS: GpeDevice - Device node. NULL for GPE0/GPE1 707 * GpeEventInfo - Info for this GPE 708 * GpeNumber - Number relative to the parent GPE block 709 * 710 * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED 711 * 712 * DESCRIPTION: Detect and dispatch a General Purpose Event to either a function 713 * (e.g. EC) or method (e.g. _Lxx/_Exx) handler. 714 * NOTE: GPE is W1C, so it is possible to handle a single GPE from both 715 * task and irq context in parallel as long as the process to 716 * detect and mask the GPE is atomic. 717 * However the atomicity of ACPI_GPE_DISPATCH_RAW_HANDLER is 718 * dependent on the raw handler itself. 719 * 720 ******************************************************************************/ 721 722 UINT32 723 AcpiEvDetectGpe ( 724 ACPI_NAMESPACE_NODE *GpeDevice, 725 ACPI_GPE_EVENT_INFO *GpeEventInfo, 726 UINT32 GpeNumber) 727 { 728 UINT32 IntStatus = ACPI_INTERRUPT_NOT_HANDLED; 729 UINT8 EnabledStatusByte; 730 UINT64 StatusReg; 731 UINT64 EnableReg; 732 UINT32 RegisterBit; 733 ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; 734 ACPI_GPE_HANDLER_INFO *GpeHandlerInfo; 735 ACPI_CPU_FLAGS Flags; 736 ACPI_STATUS Status; 737 738 739 ACPI_FUNCTION_TRACE (EvGpeDetect); 740 741 742 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 743 744 /* Get the info block for the entire GPE register */ 745 746 GpeRegisterInfo = GpeEventInfo->RegisterInfo; 747 748 /* Get the register bitmask for this GPE */ 749 750 RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo); 751 752 /* GPE currently enabled (enable bit == 1)? */ 753 754 Status = AcpiHwRead (&EnableReg, &GpeRegisterInfo->EnableAddress); 755 if (ACPI_FAILURE (Status)) 756 { 757 goto ErrorExit; 758 } 759 760 /* GPE currently active (status bit == 1)? */ 761 762 Status = AcpiHwRead (&StatusReg, &GpeRegisterInfo->StatusAddress); 763 if (ACPI_FAILURE (Status)) 764 { 765 goto ErrorExit; 766 } 767 768 /* Check if there is anything active at all in this GPE */ 769 770 ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS, 771 "Read registers for GPE %02X: Status=%02X, Enable=%02X, " 772 "RunEnable=%02X, WakeEnable=%02X\n", 773 GpeNumber, 774 (UINT32) (StatusReg & RegisterBit), 775 (UINT32) (EnableReg & RegisterBit), 776 GpeRegisterInfo->EnableForRun, 777 GpeRegisterInfo->EnableForWake)); 778 779 EnabledStatusByte = (UINT8) (StatusReg & EnableReg); 780 if (!(EnabledStatusByte & RegisterBit)) 781 { 782 goto ErrorExit; 783 } 784 785 /* Invoke global event handler if present */ 786 787 AcpiGpeCount++; 788 if (AcpiGbl_GlobalEventHandler) 789 { 790 AcpiGbl_GlobalEventHandler (ACPI_EVENT_TYPE_GPE, 791 GpeDevice, GpeNumber, 792 AcpiGbl_GlobalEventHandlerContext); 793 } 794 795 /* Found an active GPE */ 796 797 if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) == 798 ACPI_GPE_DISPATCH_RAW_HANDLER) 799 { 800 /* Dispatch the event to a raw handler */ 801 802 GpeHandlerInfo = GpeEventInfo->Dispatch.Handler; 803 804 /* 805 * There is no protection around the namespace node 806 * and the GPE handler to ensure a safe destruction 807 * because: 808 * 1. The namespace node is expected to always 809 * exist after loading a table. 810 * 2. The GPE handler is expected to be flushed by 811 * AcpiOsWaitEventsComplete() before the 812 * destruction. 813 */ 814 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 815 IntStatus |= GpeHandlerInfo->Address ( 816 GpeDevice, GpeNumber, GpeHandlerInfo->Context); 817 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 818 } 819 else 820 { 821 /* Dispatch the event to a standard handler or method. */ 822 823 IntStatus |= AcpiEvGpeDispatch (GpeDevice, 824 GpeEventInfo, GpeNumber); 825 } 826 827 ErrorExit: 828 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 829 return (IntStatus); 830 } 831 832 833 /******************************************************************************* 834 * 835 * FUNCTION: AcpiEvGpeDispatch 836 * 837 * PARAMETERS: GpeDevice - Device node. NULL for GPE0/GPE1 838 * GpeEventInfo - Info for this GPE 839 * GpeNumber - Number relative to the parent GPE block 840 * 841 * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED 842 * 843 * DESCRIPTION: Dispatch a General Purpose Event to either a function (e.g. EC) 844 * or method (e.g. _Lxx/_Exx) handler. 845 * 846 ******************************************************************************/ 847 848 UINT32 849 AcpiEvGpeDispatch ( 850 ACPI_NAMESPACE_NODE *GpeDevice, 851 ACPI_GPE_EVENT_INFO *GpeEventInfo, 852 UINT32 GpeNumber) 853 { 854 ACPI_STATUS Status; 855 UINT32 ReturnValue; 856 857 858 ACPI_FUNCTION_TRACE (EvGpeDispatch); 859 860 861 /* 862 * Always disable the GPE so that it does not keep firing before 863 * any asynchronous activity completes (either from the execution 864 * of a GPE method or an asynchronous GPE handler.) 865 * 866 * If there is no handler or method to run, just disable the 867 * GPE and leave it disabled permanently to prevent further such 868 * pointless events from firing. 869 */ 870 Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE); 871 if (ACPI_FAILURE (Status)) 872 { 873 ACPI_EXCEPTION ((AE_INFO, Status, 874 "Unable to disable GPE %02X", GpeNumber)); 875 return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED); 876 } 877 878 /* 879 * If edge-triggered, clear the GPE status bit now. Note that 880 * level-triggered events are cleared after the GPE is serviced. 881 */ 882 if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) == 883 ACPI_GPE_EDGE_TRIGGERED) 884 { 885 Status = AcpiHwClearGpe (GpeEventInfo); 886 if (ACPI_FAILURE (Status)) 887 { 888 ACPI_EXCEPTION ((AE_INFO, Status, 889 "Unable to clear GPE %02X", GpeNumber)); 890 (void) AcpiHwLowSetGpe ( 891 GpeEventInfo, ACPI_GPE_CONDITIONAL_ENABLE); 892 return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED); 893 } 894 } 895 896 GpeEventInfo->DisableForDispatch = TRUE; 897 898 /* 899 * Dispatch the GPE to either an installed handler or the control 900 * method associated with this GPE (_Lxx or _Exx). If a handler 901 * exists, we invoke it and do not attempt to run the method. 902 * If there is neither a handler nor a method, leave the GPE 903 * disabled. 904 */ 905 switch (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags)) 906 { 907 case ACPI_GPE_DISPATCH_HANDLER: 908 909 /* Invoke the installed handler (at interrupt level) */ 910 911 ReturnValue = GpeEventInfo->Dispatch.Handler->Address ( 912 GpeDevice, GpeNumber, 913 GpeEventInfo->Dispatch.Handler->Context); 914 915 /* If requested, clear (if level-triggered) and re-enable the GPE */ 916 917 if (ReturnValue & ACPI_REENABLE_GPE) 918 { 919 (void) AcpiEvFinishGpe (GpeEventInfo); 920 } 921 break; 922 923 case ACPI_GPE_DISPATCH_METHOD: 924 case ACPI_GPE_DISPATCH_NOTIFY: 925 /* 926 * Execute the method associated with the GPE 927 * NOTE: Level-triggered GPEs are cleared after the method completes. 928 */ 929 Status = AcpiOsExecute (OSL_GPE_HANDLER, 930 AcpiEvAsynchExecuteGpeMethod, GpeEventInfo); 931 if (ACPI_FAILURE (Status)) 932 { 933 ACPI_EXCEPTION ((AE_INFO, Status, 934 "Unable to queue handler for GPE %02X - event disabled", 935 GpeNumber)); 936 } 937 break; 938 939 default: 940 /* 941 * No handler or method to run! 942 * 03/2010: This case should no longer be possible. We will not allow 943 * a GPE to be enabled if it has no handler or method. 944 */ 945 ACPI_ERROR ((AE_INFO, 946 "No handler or method for GPE %02X, disabling event", 947 GpeNumber)); 948 break; 949 } 950 951 return_UINT32 (ACPI_INTERRUPT_HANDLED); 952 } 953 954 #endif /* !ACPI_REDUCED_HARDWARE */ 955