1 /****************************************************************************** 2 * 3 * Module Name: evgpe - General Purpose Event handling and dispatch 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2015, 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 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 124 ACPI_STATUS 125 AcpiEvEnableGpe ( 126 ACPI_GPE_EVENT_INFO *GpeEventInfo) 127 { 128 ACPI_STATUS Status; 129 130 131 ACPI_FUNCTION_TRACE (EvEnableGpe); 132 133 134 /* Clear the GPE (of stale events) */ 135 136 Status = AcpiHwClearGpe (GpeEventInfo); 137 if (ACPI_FAILURE (Status)) 138 { 139 return_ACPI_STATUS (Status); 140 } 141 142 /* Enable the requested GPE */ 143 144 Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_ENABLE_SAVE); 145 return_ACPI_STATUS (Status); 146 } 147 148 149 /******************************************************************************* 150 * 151 * FUNCTION: AcpiEvAddGpeReference 152 * 153 * PARAMETERS: GpeEventInfo - Add a reference to this GPE 154 * 155 * RETURN: Status 156 * 157 * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is 158 * hardware-enabled. 159 * 160 ******************************************************************************/ 161 162 ACPI_STATUS 163 AcpiEvAddGpeReference ( 164 ACPI_GPE_EVENT_INFO *GpeEventInfo) 165 { 166 ACPI_STATUS Status = AE_OK; 167 168 169 ACPI_FUNCTION_TRACE (EvAddGpeReference); 170 171 172 if (GpeEventInfo->RuntimeCount == ACPI_UINT8_MAX) 173 { 174 return_ACPI_STATUS (AE_LIMIT); 175 } 176 177 GpeEventInfo->RuntimeCount++; 178 if (GpeEventInfo->RuntimeCount == 1) 179 { 180 /* Enable on first reference */ 181 182 Status = AcpiEvUpdateGpeEnableMask (GpeEventInfo); 183 if (ACPI_SUCCESS (Status)) 184 { 185 Status = AcpiEvEnableGpe (GpeEventInfo); 186 } 187 188 if (ACPI_FAILURE (Status)) 189 { 190 GpeEventInfo->RuntimeCount--; 191 } 192 } 193 194 return_ACPI_STATUS (Status); 195 } 196 197 198 /******************************************************************************* 199 * 200 * FUNCTION: AcpiEvRemoveGpeReference 201 * 202 * PARAMETERS: GpeEventInfo - Remove a reference to this GPE 203 * 204 * RETURN: Status 205 * 206 * DESCRIPTION: Remove a reference to a GPE. When the last reference is 207 * removed, the GPE is hardware-disabled. 208 * 209 ******************************************************************************/ 210 211 ACPI_STATUS 212 AcpiEvRemoveGpeReference ( 213 ACPI_GPE_EVENT_INFO *GpeEventInfo) 214 { 215 ACPI_STATUS Status = AE_OK; 216 217 218 ACPI_FUNCTION_TRACE (EvRemoveGpeReference); 219 220 221 if (!GpeEventInfo->RuntimeCount) 222 { 223 return_ACPI_STATUS (AE_LIMIT); 224 } 225 226 GpeEventInfo->RuntimeCount--; 227 if (!GpeEventInfo->RuntimeCount) 228 { 229 /* Disable on last reference */ 230 231 Status = AcpiEvUpdateGpeEnableMask (GpeEventInfo); 232 if (ACPI_SUCCESS (Status)) 233 { 234 Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE_SAVE); 235 } 236 237 if (ACPI_FAILURE (Status)) 238 { 239 GpeEventInfo->RuntimeCount++; 240 } 241 } 242 243 return_ACPI_STATUS (Status); 244 } 245 246 247 /******************************************************************************* 248 * 249 * FUNCTION: AcpiEvLowGetGpeInfo 250 * 251 * PARAMETERS: GpeNumber - Raw GPE number 252 * GpeBlock - A GPE info block 253 * 254 * RETURN: A GPE EventInfo struct. NULL if not a valid GPE (The GpeNumber 255 * is not within the specified GPE block) 256 * 257 * DESCRIPTION: Returns the EventInfo struct associated with this GPE. This is 258 * the low-level implementation of EvGetGpeEventInfo. 259 * 260 ******************************************************************************/ 261 262 ACPI_GPE_EVENT_INFO * 263 AcpiEvLowGetGpeInfo ( 264 UINT32 GpeNumber, 265 ACPI_GPE_BLOCK_INFO *GpeBlock) 266 { 267 UINT32 GpeIndex; 268 269 270 /* 271 * Validate that the GpeNumber is within the specified GpeBlock. 272 * (Two steps) 273 */ 274 if (!GpeBlock || 275 (GpeNumber < GpeBlock->BlockBaseNumber)) 276 { 277 return (NULL); 278 } 279 280 GpeIndex = GpeNumber - GpeBlock->BlockBaseNumber; 281 if (GpeIndex >= GpeBlock->GpeCount) 282 { 283 return (NULL); 284 } 285 286 return (&GpeBlock->EventInfo[GpeIndex]); 287 } 288 289 290 /******************************************************************************* 291 * 292 * FUNCTION: AcpiEvGetGpeEventInfo 293 * 294 * PARAMETERS: GpeDevice - Device node. NULL for GPE0/GPE1 295 * GpeNumber - Raw GPE number 296 * 297 * RETURN: A GPE EventInfo struct. NULL if not a valid GPE 298 * 299 * DESCRIPTION: Returns the EventInfo struct associated with this GPE. 300 * Validates the GpeBlock and the GpeNumber 301 * 302 * Should be called only when the GPE lists are semaphore locked 303 * and not subject to change. 304 * 305 ******************************************************************************/ 306 307 ACPI_GPE_EVENT_INFO * 308 AcpiEvGetGpeEventInfo ( 309 ACPI_HANDLE GpeDevice, 310 UINT32 GpeNumber) 311 { 312 ACPI_OPERAND_OBJECT *ObjDesc; 313 ACPI_GPE_EVENT_INFO *GpeInfo; 314 UINT32 i; 315 316 317 ACPI_FUNCTION_ENTRY (); 318 319 320 /* A NULL GpeDevice means use the FADT-defined GPE block(s) */ 321 322 if (!GpeDevice) 323 { 324 /* Examine GPE Block 0 and 1 (These blocks are permanent) */ 325 326 for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++) 327 { 328 GpeInfo = AcpiEvLowGetGpeInfo (GpeNumber, 329 AcpiGbl_GpeFadtBlocks[i]); 330 if (GpeInfo) 331 { 332 return (GpeInfo); 333 } 334 } 335 336 /* The GpeNumber was not in the range of either FADT GPE block */ 337 338 return (NULL); 339 } 340 341 /* A Non-NULL GpeDevice means this is a GPE Block Device */ 342 343 ObjDesc = AcpiNsGetAttachedObject ((ACPI_NAMESPACE_NODE *) GpeDevice); 344 if (!ObjDesc || 345 !ObjDesc->Device.GpeBlock) 346 { 347 return (NULL); 348 } 349 350 return (AcpiEvLowGetGpeInfo (GpeNumber, ObjDesc->Device.GpeBlock)); 351 } 352 353 354 /******************************************************************************* 355 * 356 * FUNCTION: AcpiEvGpeDetect 357 * 358 * PARAMETERS: GpeXruptList - Interrupt block for this interrupt. 359 * Can have multiple GPE blocks attached. 360 * 361 * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED 362 * 363 * DESCRIPTION: Detect if any GP events have occurred. This function is 364 * executed at interrupt level. 365 * 366 ******************************************************************************/ 367 368 UINT32 369 AcpiEvGpeDetect ( 370 ACPI_GPE_XRUPT_INFO *GpeXruptList) 371 { 372 ACPI_STATUS Status; 373 ACPI_GPE_BLOCK_INFO *GpeBlock; 374 ACPI_NAMESPACE_NODE *GpeDevice; 375 ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; 376 ACPI_GPE_EVENT_INFO *GpeEventInfo; 377 UINT32 GpeNumber; 378 ACPI_GPE_HANDLER_INFO *GpeHandlerInfo; 379 UINT32 IntStatus = ACPI_INTERRUPT_NOT_HANDLED; 380 UINT8 EnabledStatusByte; 381 UINT32 StatusReg; 382 UINT32 EnableReg; 383 ACPI_CPU_FLAGS Flags; 384 UINT32 i; 385 UINT32 j; 386 387 388 ACPI_FUNCTION_NAME (EvGpeDetect); 389 390 /* Check for the case where there are no GPEs */ 391 392 if (!GpeXruptList) 393 { 394 return (IntStatus); 395 } 396 397 /* 398 * We need to obtain the GPE lock for both the data structs and registers 399 * Note: Not necessary to obtain the hardware lock, since the GPE 400 * registers are owned by the GpeLock. 401 */ 402 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 403 404 /* Examine all GPE blocks attached to this interrupt level */ 405 406 GpeBlock = GpeXruptList->GpeBlockListHead; 407 while (GpeBlock) 408 { 409 GpeDevice = GpeBlock->Node; 410 411 /* 412 * Read all of the 8-bit GPE status and enable registers in this GPE 413 * block, saving all of them. Find all currently active GP events. 414 */ 415 for (i = 0; i < GpeBlock->RegisterCount; i++) 416 { 417 /* Get the next status/enable pair */ 418 419 GpeRegisterInfo = &GpeBlock->RegisterInfo[i]; 420 421 /* 422 * Optimization: If there are no GPEs enabled within this 423 * register, we can safely ignore the entire register. 424 */ 425 if (!(GpeRegisterInfo->EnableForRun | 426 GpeRegisterInfo->EnableForWake)) 427 { 428 ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS, 429 "Ignore disabled registers for GPE %02X-%02X: " 430 "RunEnable=%02X, WakeEnable=%02X\n", 431 GpeRegisterInfo->BaseGpeNumber, 432 GpeRegisterInfo->BaseGpeNumber + (ACPI_GPE_REGISTER_WIDTH - 1), 433 GpeRegisterInfo->EnableForRun, 434 GpeRegisterInfo->EnableForWake)); 435 continue; 436 } 437 438 /* Read the Status Register */ 439 440 Status = AcpiHwRead (&StatusReg, &GpeRegisterInfo->StatusAddress); 441 if (ACPI_FAILURE (Status)) 442 { 443 goto UnlockAndExit; 444 } 445 446 /* Read the Enable Register */ 447 448 Status = AcpiHwRead (&EnableReg, &GpeRegisterInfo->EnableAddress); 449 if (ACPI_FAILURE (Status)) 450 { 451 goto UnlockAndExit; 452 } 453 454 ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS, 455 "Read registers for GPE %02X-%02X: Status=%02X, Enable=%02X, " 456 "RunEnable=%02X, WakeEnable=%02X\n", 457 GpeRegisterInfo->BaseGpeNumber, 458 GpeRegisterInfo->BaseGpeNumber + (ACPI_GPE_REGISTER_WIDTH - 1), 459 StatusReg, EnableReg, 460 GpeRegisterInfo->EnableForRun, 461 GpeRegisterInfo->EnableForWake)); 462 463 /* Check if there is anything active at all in this register */ 464 465 EnabledStatusByte = (UINT8) (StatusReg & EnableReg); 466 if (!EnabledStatusByte) 467 { 468 /* No active GPEs in this register, move on */ 469 470 continue; 471 } 472 473 /* Now look at the individual GPEs in this byte register */ 474 475 for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) 476 { 477 /* Examine one GPE bit */ 478 479 GpeEventInfo = &GpeBlock->EventInfo[((ACPI_SIZE) i * 480 ACPI_GPE_REGISTER_WIDTH) + j]; 481 GpeNumber = j + GpeRegisterInfo->BaseGpeNumber; 482 483 if (EnabledStatusByte & (1 << j)) 484 { 485 /* Invoke global event handler if present */ 486 487 AcpiGpeCount++; 488 if (AcpiGbl_GlobalEventHandler) 489 { 490 AcpiGbl_GlobalEventHandler (ACPI_EVENT_TYPE_GPE, 491 GpeDevice, GpeNumber, 492 AcpiGbl_GlobalEventHandlerContext); 493 } 494 495 /* Found an active GPE */ 496 497 if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) == 498 ACPI_GPE_DISPATCH_RAW_HANDLER) 499 { 500 /* Dispatch the event to a raw handler */ 501 502 GpeHandlerInfo = GpeEventInfo->Dispatch.Handler; 503 504 /* 505 * There is no protection around the namespace node 506 * and the GPE handler to ensure a safe destruction 507 * because: 508 * 1. The namespace node is expected to always 509 * exist after loading a table. 510 * 2. The GPE handler is expected to be flushed by 511 * AcpiOsWaitEventsComplete() before the 512 * destruction. 513 */ 514 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 515 IntStatus |= GpeHandlerInfo->Address ( 516 GpeDevice, GpeNumber, GpeHandlerInfo->Context); 517 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 518 } 519 else 520 { 521 /* 522 * Dispatch the event to a standard handler or 523 * method. 524 */ 525 IntStatus |= AcpiEvGpeDispatch (GpeDevice, 526 GpeEventInfo, GpeNumber); 527 } 528 } 529 } 530 } 531 532 GpeBlock = GpeBlock->Next; 533 } 534 535 UnlockAndExit: 536 537 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 538 return (IntStatus); 539 } 540 541 542 /******************************************************************************* 543 * 544 * FUNCTION: AcpiEvAsynchExecuteGpeMethod 545 * 546 * PARAMETERS: Context (GpeEventInfo) - Info for this GPE 547 * 548 * RETURN: None 549 * 550 * DESCRIPTION: Perform the actual execution of a GPE control method. This 551 * function is called from an invocation of AcpiOsExecute and 552 * therefore does NOT execute at interrupt level - so that 553 * the control method itself is not executed in the context of 554 * an interrupt handler. 555 * 556 ******************************************************************************/ 557 558 static void ACPI_SYSTEM_XFACE 559 AcpiEvAsynchExecuteGpeMethod ( 560 void *Context) 561 { 562 ACPI_GPE_EVENT_INFO *GpeEventInfo = Context; 563 ACPI_STATUS Status = AE_OK; 564 ACPI_EVALUATE_INFO *Info; 565 ACPI_GPE_NOTIFY_INFO *Notify; 566 567 568 ACPI_FUNCTION_TRACE (EvAsynchExecuteGpeMethod); 569 570 571 /* Do the correct dispatch - normal method or implicit notify */ 572 573 switch (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags)) 574 { 575 case ACPI_GPE_DISPATCH_NOTIFY: 576 /* 577 * Implicit notify. 578 * Dispatch a DEVICE_WAKE notify to the appropriate handler. 579 * NOTE: the request is queued for execution after this method 580 * completes. The notify handlers are NOT invoked synchronously 581 * from this thread -- because handlers may in turn run other 582 * control methods. 583 * 584 * June 2012: Expand implicit notify mechanism to support 585 * notifies on multiple device objects. 586 */ 587 Notify = GpeEventInfo->Dispatch.NotifyList; 588 while (ACPI_SUCCESS (Status) && Notify) 589 { 590 Status = AcpiEvQueueNotifyRequest (Notify->DeviceNode, 591 ACPI_NOTIFY_DEVICE_WAKE); 592 593 Notify = Notify->Next; 594 } 595 break; 596 597 case ACPI_GPE_DISPATCH_METHOD: 598 599 /* Allocate the evaluation information block */ 600 601 Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO)); 602 if (!Info) 603 { 604 Status = AE_NO_MEMORY; 605 } 606 else 607 { 608 /* 609 * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the 610 * _Lxx/_Exx control method that corresponds to this GPE 611 */ 612 Info->PrefixNode = GpeEventInfo->Dispatch.MethodNode; 613 Info->Flags = ACPI_IGNORE_RETURN_VALUE; 614 615 Status = AcpiNsEvaluate (Info); 616 ACPI_FREE (Info); 617 } 618 619 if (ACPI_FAILURE (Status)) 620 { 621 ACPI_EXCEPTION ((AE_INFO, Status, 622 "while evaluating GPE method [%4.4s]", 623 AcpiUtGetNodeName (GpeEventInfo->Dispatch.MethodNode))); 624 } 625 break; 626 627 default: 628 629 goto ErrorExit; /* Should never happen */ 630 } 631 632 /* Defer enabling of GPE until all notify handlers are done */ 633 634 Status = AcpiOsExecute (OSL_NOTIFY_HANDLER, 635 AcpiEvAsynchEnableGpe, GpeEventInfo); 636 if (ACPI_SUCCESS (Status)) 637 { 638 return_VOID; 639 } 640 641 ErrorExit: 642 AcpiEvAsynchEnableGpe (GpeEventInfo); 643 return_VOID; 644 } 645 646 647 /******************************************************************************* 648 * 649 * FUNCTION: AcpiEvAsynchEnableGpe 650 * 651 * PARAMETERS: Context (GpeEventInfo) - Info for this GPE 652 * Callback from AcpiOsExecute 653 * 654 * RETURN: None 655 * 656 * DESCRIPTION: Asynchronous clear/enable for GPE. This allows the GPE to 657 * complete (i.e., finish execution of Notify) 658 * 659 ******************************************************************************/ 660 661 static void ACPI_SYSTEM_XFACE 662 AcpiEvAsynchEnableGpe ( 663 void *Context) 664 { 665 ACPI_GPE_EVENT_INFO *GpeEventInfo = Context; 666 ACPI_CPU_FLAGS Flags; 667 668 669 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 670 (void) AcpiEvFinishGpe (GpeEventInfo); 671 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 672 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 690 ACPI_STATUS 691 AcpiEvFinishGpe ( 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 EnableMask 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 738 UINT32 739 AcpiEvGpeDispatch ( 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 /* 752 * Always disable the GPE so that it does not keep firing before 753 * any asynchronous activity completes (either from the execution 754 * of a GPE method or an asynchronous GPE handler.) 755 * 756 * If there is no handler or method to run, just disable the 757 * GPE and leave it disabled permanently to prevent further such 758 * pointless events from firing. 759 */ 760 Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE); 761 if (ACPI_FAILURE (Status)) 762 { 763 ACPI_EXCEPTION ((AE_INFO, Status, 764 "Unable to disable GPE %02X", GpeNumber)); 765 return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED); 766 } 767 768 /* 769 * If edge-triggered, clear the GPE status bit now. Note that 770 * level-triggered events are cleared after the GPE is serviced. 771 */ 772 if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) == 773 ACPI_GPE_EDGE_TRIGGERED) 774 { 775 Status = AcpiHwClearGpe (GpeEventInfo); 776 if (ACPI_FAILURE (Status)) 777 { 778 ACPI_EXCEPTION ((AE_INFO, Status, 779 "Unable to clear GPE %02X", GpeNumber)); 780 (void) AcpiHwLowSetGpe (GpeEventInfo, 781 ACPI_GPE_CONDITIONAL_ENABLE); 782 return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED); 783 } 784 } 785 786 /* 787 * Dispatch the GPE to either an installed handler or the control 788 * method associated with this GPE (_Lxx or _Exx). If a handler 789 * exists, we invoke it and do not attempt to run the method. 790 * If there is neither a handler nor a method, leave the GPE 791 * disabled. 792 */ 793 switch (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags)) 794 { 795 case ACPI_GPE_DISPATCH_HANDLER: 796 797 /* Invoke the installed handler (at interrupt level) */ 798 799 ReturnValue = GpeEventInfo->Dispatch.Handler->Address ( 800 GpeDevice, GpeNumber, 801 GpeEventInfo->Dispatch.Handler->Context); 802 803 /* If requested, clear (if level-triggered) and reenable the GPE */ 804 805 if (ReturnValue & ACPI_REENABLE_GPE) 806 { 807 (void) AcpiEvFinishGpe (GpeEventInfo); 808 } 809 break; 810 811 case ACPI_GPE_DISPATCH_METHOD: 812 case ACPI_GPE_DISPATCH_NOTIFY: 813 /* 814 * Execute the method associated with the GPE 815 * NOTE: Level-triggered GPEs are cleared after the method completes. 816 */ 817 Status = AcpiOsExecute (OSL_GPE_HANDLER, 818 AcpiEvAsynchExecuteGpeMethod, GpeEventInfo); 819 if (ACPI_FAILURE (Status)) 820 { 821 ACPI_EXCEPTION ((AE_INFO, Status, 822 "Unable to queue handler for GPE %02X - event disabled", 823 GpeNumber)); 824 } 825 break; 826 827 default: 828 /* 829 * No handler or method to run! 830 * 03/2010: This case should no longer be possible. We will not allow 831 * a GPE to be enabled if it has no handler or method. 832 */ 833 ACPI_ERROR ((AE_INFO, 834 "No handler or method for GPE %02X, disabling event", 835 GpeNumber)); 836 break; 837 } 838 839 return_UINT32 (ACPI_INTERRUPT_HANDLED); 840 } 841 842 #endif /* !ACPI_REDUCED_HARDWARE */ 843