1 /****************************************************************************** 2 * 3 * Module Name: evxfgpe - External Interfaces for General Purpose Events (GPEs) 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 #define EXPORT_ACPI_INTERFACES 45 46 #include "acpi.h" 47 #include "accommon.h" 48 #include "acevents.h" 49 #include "acnamesp.h" 50 51 #define _COMPONENT ACPI_EVENTS 52 ACPI_MODULE_NAME ("evxfgpe") 53 54 55 #if (!ACPI_REDUCED_HARDWARE) /* Entire module */ 56 /******************************************************************************* 57 * 58 * FUNCTION: AcpiUpdateAllGpes 59 * 60 * PARAMETERS: None 61 * 62 * RETURN: Status 63 * 64 * DESCRIPTION: Complete GPE initialization and enable all GPEs that have 65 * associated _Lxx or _Exx methods and are not pointed to by any 66 * device _PRW methods (this indicates that these GPEs are 67 * generally intended for system or device wakeup. Such GPEs 68 * have to be enabled directly when the devices whose _PRW 69 * methods point to them are set up for wakeup signaling.) 70 * 71 * NOTE: Should be called after any GPEs are added to the system. Primarily, 72 * after the system _PRW methods have been run, but also after a GPE Block 73 * Device has been added or if any new GPE methods have been added via a 74 * dynamic table load. 75 * 76 ******************************************************************************/ 77 78 ACPI_STATUS 79 AcpiUpdateAllGpes ( 80 void) 81 { 82 ACPI_STATUS Status; 83 BOOLEAN IsPollingNeeded = FALSE; 84 85 86 ACPI_FUNCTION_TRACE (AcpiUpdateAllGpes); 87 88 89 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 90 if (ACPI_FAILURE (Status)) 91 { 92 return_ACPI_STATUS (Status); 93 } 94 95 if (AcpiGbl_AllGpesInitialized) 96 { 97 goto UnlockAndExit; 98 } 99 100 Status = AcpiEvWalkGpeList (AcpiEvInitializeGpeBlock, 101 &IsPollingNeeded); 102 if (ACPI_SUCCESS (Status)) 103 { 104 AcpiGbl_AllGpesInitialized = TRUE; 105 } 106 107 UnlockAndExit: 108 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 109 110 if (IsPollingNeeded && AcpiGbl_AllGpesInitialized) 111 { 112 /* Poll GPEs to handle already triggered events */ 113 114 AcpiEvGpeDetect (AcpiGbl_GpeXruptListHead); 115 } 116 return_ACPI_STATUS (Status); 117 } 118 119 ACPI_EXPORT_SYMBOL (AcpiUpdateAllGpes) 120 121 122 /******************************************************************************* 123 * 124 * FUNCTION: AcpiEnableGpe 125 * 126 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 127 * GpeNumber - GPE level within the GPE block 128 * 129 * RETURN: Status 130 * 131 * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is 132 * hardware-enabled. 133 * 134 ******************************************************************************/ 135 136 ACPI_STATUS 137 AcpiEnableGpe ( 138 ACPI_HANDLE GpeDevice, 139 UINT32 GpeNumber) 140 { 141 ACPI_STATUS Status = AE_BAD_PARAMETER; 142 ACPI_GPE_EVENT_INFO *GpeEventInfo; 143 ACPI_CPU_FLAGS Flags; 144 145 146 ACPI_FUNCTION_TRACE (AcpiEnableGpe); 147 148 149 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 150 151 /* 152 * Ensure that we have a valid GPE number and that there is some way 153 * of handling the GPE (handler or a GPE method). In other words, we 154 * won't allow a valid GPE to be enabled if there is no way to handle it. 155 */ 156 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 157 if (GpeEventInfo) 158 { 159 if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) != 160 ACPI_GPE_DISPATCH_NONE) 161 { 162 Status = AcpiEvAddGpeReference (GpeEventInfo, TRUE); 163 if (ACPI_SUCCESS (Status) && 164 ACPI_GPE_IS_POLLING_NEEDED (GpeEventInfo)) 165 { 166 /* Poll edge-triggered GPEs to handle existing events */ 167 168 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 169 (void) AcpiEvDetectGpe ( 170 GpeDevice, GpeEventInfo, GpeNumber); 171 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 172 } 173 } 174 else 175 { 176 Status = AE_NO_HANDLER; 177 } 178 } 179 180 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 181 return_ACPI_STATUS (Status); 182 } 183 184 ACPI_EXPORT_SYMBOL (AcpiEnableGpe) 185 186 187 /******************************************************************************* 188 * 189 * FUNCTION: AcpiDisableGpe 190 * 191 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 192 * GpeNumber - GPE level within the GPE block 193 * 194 * RETURN: Status 195 * 196 * DESCRIPTION: Remove a reference to a GPE. When the last reference is 197 * removed, only then is the GPE disabled (for runtime GPEs), or 198 * the GPE mask bit disabled (for wake GPEs) 199 * 200 ******************************************************************************/ 201 202 ACPI_STATUS 203 AcpiDisableGpe ( 204 ACPI_HANDLE GpeDevice, 205 UINT32 GpeNumber) 206 { 207 ACPI_STATUS Status = AE_BAD_PARAMETER; 208 ACPI_GPE_EVENT_INFO *GpeEventInfo; 209 ACPI_CPU_FLAGS Flags; 210 211 212 ACPI_FUNCTION_TRACE (AcpiDisableGpe); 213 214 215 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 216 217 /* Ensure that we have a valid GPE number */ 218 219 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 220 if (GpeEventInfo) 221 { 222 Status = AcpiEvRemoveGpeReference (GpeEventInfo); 223 } 224 225 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 226 return_ACPI_STATUS (Status); 227 } 228 229 ACPI_EXPORT_SYMBOL (AcpiDisableGpe) 230 231 232 /******************************************************************************* 233 * 234 * FUNCTION: AcpiSetGpe 235 * 236 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 237 * GpeNumber - GPE level within the GPE block 238 * Action - ACPI_GPE_ENABLE or ACPI_GPE_DISABLE 239 * 240 * RETURN: Status 241 * 242 * DESCRIPTION: Enable or disable an individual GPE. This function bypasses 243 * the reference count mechanism used in the AcpiEnableGpe(), 244 * AcpiDisableGpe() interfaces. 245 * This API is typically used by the GPE raw handler mode driver 246 * to switch between the polling mode and the interrupt mode after 247 * the driver has enabled the GPE. 248 * The APIs should be invoked in this order: 249 * AcpiEnableGpe() <- Ensure the reference count > 0 250 * AcpiSetGpe(ACPI_GPE_DISABLE) <- Enter polling mode 251 * AcpiSetGpe(ACPI_GPE_ENABLE) <- Leave polling mode 252 * AcpiDisableGpe() <- Decrease the reference count 253 * 254 * Note: If a GPE is shared by 2 silicon components, then both the drivers 255 * should support GPE polling mode or disabling the GPE for long period 256 * for one driver may break the other. So use it with care since all 257 * firmware _Lxx/_Exx handlers currently rely on the GPE interrupt mode. 258 * 259 ******************************************************************************/ 260 261 ACPI_STATUS 262 AcpiSetGpe ( 263 ACPI_HANDLE GpeDevice, 264 UINT32 GpeNumber, 265 UINT8 Action) 266 { 267 ACPI_GPE_EVENT_INFO *GpeEventInfo; 268 ACPI_STATUS Status; 269 ACPI_CPU_FLAGS Flags; 270 271 272 ACPI_FUNCTION_TRACE (AcpiSetGpe); 273 274 275 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 276 277 /* Ensure that we have a valid GPE number */ 278 279 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 280 if (!GpeEventInfo) 281 { 282 Status = AE_BAD_PARAMETER; 283 goto UnlockAndExit; 284 } 285 286 /* Perform the action */ 287 288 switch (Action) 289 { 290 case ACPI_GPE_ENABLE: 291 292 Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_ENABLE); 293 GpeEventInfo->DisableForDispatch = FALSE; 294 break; 295 296 case ACPI_GPE_DISABLE: 297 298 Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE); 299 GpeEventInfo->DisableForDispatch = TRUE; 300 break; 301 302 default: 303 304 Status = AE_BAD_PARAMETER; 305 break; 306 } 307 308 UnlockAndExit: 309 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 310 return_ACPI_STATUS (Status); 311 } 312 313 ACPI_EXPORT_SYMBOL (AcpiSetGpe) 314 315 316 /******************************************************************************* 317 * 318 * FUNCTION: AcpiMaskGpe 319 * 320 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 321 * GpeNumber - GPE level within the GPE block 322 * IsMasked - Whether the GPE is masked or not 323 * 324 * RETURN: Status 325 * 326 * DESCRIPTION: Unconditionally mask/unmask the an individual GPE, ex., to 327 * prevent a GPE flooding. 328 * 329 ******************************************************************************/ 330 331 ACPI_STATUS 332 AcpiMaskGpe ( 333 ACPI_HANDLE GpeDevice, 334 UINT32 GpeNumber, 335 BOOLEAN IsMasked) 336 { 337 ACPI_GPE_EVENT_INFO *GpeEventInfo; 338 ACPI_STATUS Status; 339 ACPI_CPU_FLAGS Flags; 340 341 342 ACPI_FUNCTION_TRACE (AcpiMaskGpe); 343 344 345 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 346 347 /* Ensure that we have a valid GPE number */ 348 349 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 350 if (!GpeEventInfo) 351 { 352 Status = AE_BAD_PARAMETER; 353 goto UnlockAndExit; 354 } 355 356 Status = AcpiEvMaskGpe (GpeEventInfo, IsMasked); 357 358 UnlockAndExit: 359 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 360 return_ACPI_STATUS (Status); 361 } 362 363 ACPI_EXPORT_SYMBOL (AcpiMaskGpe) 364 365 366 /******************************************************************************* 367 * 368 * FUNCTION: AcpiMarkGpeForWake 369 * 370 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 371 * GpeNumber - GPE level within the GPE block 372 * 373 * RETURN: Status 374 * 375 * DESCRIPTION: Mark a GPE as having the ability to wake the system. Simply 376 * sets the ACPI_GPE_CAN_WAKE flag. 377 * 378 * Some potential callers of AcpiSetupGpeForWake may know in advance that 379 * there won't be any notify handlers installed for device wake notifications 380 * from the given GPE (one example is a button GPE in Linux). For these cases, 381 * AcpiMarkGpeForWake should be used instead of AcpiSetupGpeForWake. 382 * This will set the ACPI_GPE_CAN_WAKE flag for the GPE without trying to 383 * setup implicit wake notification for it (since there's no handler method). 384 * 385 ******************************************************************************/ 386 387 ACPI_STATUS 388 AcpiMarkGpeForWake ( 389 ACPI_HANDLE GpeDevice, 390 UINT32 GpeNumber) 391 { 392 ACPI_GPE_EVENT_INFO *GpeEventInfo; 393 ACPI_STATUS Status = AE_BAD_PARAMETER; 394 ACPI_CPU_FLAGS Flags; 395 396 397 ACPI_FUNCTION_TRACE (AcpiMarkGpeForWake); 398 399 400 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 401 402 /* Ensure that we have a valid GPE number */ 403 404 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 405 if (GpeEventInfo) 406 { 407 /* Mark the GPE as a possible wake event */ 408 409 GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE; 410 Status = AE_OK; 411 } 412 413 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 414 return_ACPI_STATUS (Status); 415 } 416 417 ACPI_EXPORT_SYMBOL (AcpiMarkGpeForWake) 418 419 420 /******************************************************************************* 421 * 422 * FUNCTION: AcpiSetupGpeForWake 423 * 424 * PARAMETERS: WakeDevice - Device associated with the GPE (via _PRW) 425 * GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 426 * GpeNumber - GPE level within the GPE block 427 * 428 * RETURN: Status 429 * 430 * DESCRIPTION: Mark a GPE as having the ability to wake the system. This 431 * interface is intended to be used as the host executes the 432 * _PRW methods (Power Resources for Wake) in the system tables. 433 * Each _PRW appears under a Device Object (The WakeDevice), and 434 * contains the info for the wake GPE associated with the 435 * WakeDevice. 436 * 437 ******************************************************************************/ 438 439 ACPI_STATUS 440 AcpiSetupGpeForWake ( 441 ACPI_HANDLE WakeDevice, 442 ACPI_HANDLE GpeDevice, 443 UINT32 GpeNumber) 444 { 445 ACPI_STATUS Status; 446 ACPI_GPE_EVENT_INFO *GpeEventInfo; 447 ACPI_NAMESPACE_NODE *DeviceNode; 448 ACPI_GPE_NOTIFY_INFO *Notify; 449 ACPI_GPE_NOTIFY_INFO *NewNotify; 450 ACPI_CPU_FLAGS Flags; 451 452 453 ACPI_FUNCTION_TRACE (AcpiSetupGpeForWake); 454 455 456 /* Parameter Validation */ 457 458 if (!WakeDevice) 459 { 460 /* 461 * By forcing WakeDevice to be valid, we automatically enable the 462 * implicit notify feature on all hosts. 463 */ 464 return_ACPI_STATUS (AE_BAD_PARAMETER); 465 } 466 467 /* Handle root object case */ 468 469 if (WakeDevice == ACPI_ROOT_OBJECT) 470 { 471 DeviceNode = AcpiGbl_RootNode; 472 } 473 else 474 { 475 DeviceNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, WakeDevice); 476 } 477 478 /* Validate WakeDevice is of type Device */ 479 480 if (DeviceNode->Type != ACPI_TYPE_DEVICE) 481 { 482 return_ACPI_STATUS (AE_BAD_PARAMETER); 483 } 484 485 /* 486 * Allocate a new notify object up front, in case it is needed. 487 * Memory allocation while holding a spinlock is a big no-no 488 * on some hosts. 489 */ 490 NewNotify = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_NOTIFY_INFO)); 491 if (!NewNotify) 492 { 493 return_ACPI_STATUS (AE_NO_MEMORY); 494 } 495 496 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 497 498 /* Ensure that we have a valid GPE number */ 499 500 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 501 if (!GpeEventInfo) 502 { 503 Status = AE_BAD_PARAMETER; 504 goto UnlockAndExit; 505 } 506 507 /* 508 * If there is no method or handler for this GPE, then the 509 * WakeDevice will be notified whenever this GPE fires. This is 510 * known as an "implicit notify". Note: The GPE is assumed to be 511 * level-triggered (for windows compatibility). 512 */ 513 if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) == 514 ACPI_GPE_DISPATCH_NONE) 515 { 516 /* 517 * This is the first device for implicit notify on this GPE. 518 * Just set the flags here, and enter the NOTIFY block below. 519 */ 520 GpeEventInfo->Flags = 521 (ACPI_GPE_DISPATCH_NOTIFY | ACPI_GPE_LEVEL_TRIGGERED); 522 } 523 else if (GpeEventInfo->Flags & ACPI_GPE_AUTO_ENABLED) 524 { 525 /* 526 * A reference to this GPE has been added during the GPE block 527 * initialization, so drop it now to prevent the GPE from being 528 * permanently enabled and clear its ACPI_GPE_AUTO_ENABLED flag. 529 */ 530 (void) AcpiEvRemoveGpeReference (GpeEventInfo); 531 GpeEventInfo->Flags &= ~~ACPI_GPE_AUTO_ENABLED; 532 } 533 534 /* 535 * If we already have an implicit notify on this GPE, add 536 * this device to the notify list. 537 */ 538 if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) == 539 ACPI_GPE_DISPATCH_NOTIFY) 540 { 541 /* Ensure that the device is not already in the list */ 542 543 Notify = GpeEventInfo->Dispatch.NotifyList; 544 while (Notify) 545 { 546 if (Notify->DeviceNode == DeviceNode) 547 { 548 Status = AE_ALREADY_EXISTS; 549 goto UnlockAndExit; 550 } 551 Notify = Notify->Next; 552 } 553 554 /* Add this device to the notify list for this GPE */ 555 556 NewNotify->DeviceNode = DeviceNode; 557 NewNotify->Next = GpeEventInfo->Dispatch.NotifyList; 558 GpeEventInfo->Dispatch.NotifyList = NewNotify; 559 NewNotify = NULL; 560 } 561 562 /* Mark the GPE as a possible wake event */ 563 564 GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE; 565 Status = AE_OK; 566 567 568 UnlockAndExit: 569 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 570 571 /* Delete the notify object if it was not used above */ 572 573 if (NewNotify) 574 { 575 ACPI_FREE (NewNotify); 576 } 577 return_ACPI_STATUS (Status); 578 } 579 580 ACPI_EXPORT_SYMBOL (AcpiSetupGpeForWake) 581 582 583 /******************************************************************************* 584 * 585 * FUNCTION: AcpiSetGpeWakeMask 586 * 587 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 588 * GpeNumber - GPE level within the GPE block 589 * Action - Enable or Disable 590 * 591 * RETURN: Status 592 * 593 * DESCRIPTION: Set or clear the GPE's wakeup enable mask bit. The GPE must 594 * already be marked as a WAKE GPE. 595 * 596 ******************************************************************************/ 597 598 ACPI_STATUS 599 AcpiSetGpeWakeMask ( 600 ACPI_HANDLE GpeDevice, 601 UINT32 GpeNumber, 602 UINT8 Action) 603 { 604 ACPI_STATUS Status = AE_OK; 605 ACPI_GPE_EVENT_INFO *GpeEventInfo; 606 ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; 607 ACPI_CPU_FLAGS Flags; 608 UINT32 RegisterBit; 609 610 611 ACPI_FUNCTION_TRACE (AcpiSetGpeWakeMask); 612 613 614 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 615 616 /* 617 * Ensure that we have a valid GPE number and that this GPE is in 618 * fact a wake GPE 619 */ 620 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 621 if (!GpeEventInfo) 622 { 623 Status = AE_BAD_PARAMETER; 624 goto UnlockAndExit; 625 } 626 627 if (!(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE)) 628 { 629 Status = AE_TYPE; 630 goto UnlockAndExit; 631 } 632 633 GpeRegisterInfo = GpeEventInfo->RegisterInfo; 634 if (!GpeRegisterInfo) 635 { 636 Status = AE_NOT_EXIST; 637 goto UnlockAndExit; 638 } 639 640 RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo); 641 642 /* Perform the action */ 643 644 switch (Action) 645 { 646 case ACPI_GPE_ENABLE: 647 648 ACPI_SET_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit); 649 break; 650 651 case ACPI_GPE_DISABLE: 652 653 ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit); 654 break; 655 656 default: 657 658 ACPI_ERROR ((AE_INFO, "%u, Invalid action", Action)); 659 Status = AE_BAD_PARAMETER; 660 break; 661 } 662 663 UnlockAndExit: 664 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 665 return_ACPI_STATUS (Status); 666 } 667 668 ACPI_EXPORT_SYMBOL (AcpiSetGpeWakeMask) 669 670 671 /******************************************************************************* 672 * 673 * FUNCTION: AcpiClearGpe 674 * 675 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 676 * GpeNumber - GPE level within the GPE block 677 * 678 * RETURN: Status 679 * 680 * DESCRIPTION: Clear an ACPI event (general purpose) 681 * 682 ******************************************************************************/ 683 684 ACPI_STATUS 685 AcpiClearGpe ( 686 ACPI_HANDLE GpeDevice, 687 UINT32 GpeNumber) 688 { 689 ACPI_STATUS Status = AE_OK; 690 ACPI_GPE_EVENT_INFO *GpeEventInfo; 691 ACPI_CPU_FLAGS Flags; 692 693 694 ACPI_FUNCTION_TRACE (AcpiClearGpe); 695 696 697 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 698 699 /* Ensure that we have a valid GPE number */ 700 701 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 702 if (!GpeEventInfo) 703 { 704 Status = AE_BAD_PARAMETER; 705 goto UnlockAndExit; 706 } 707 708 Status = AcpiHwClearGpe (GpeEventInfo); 709 710 UnlockAndExit: 711 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 712 return_ACPI_STATUS (Status); 713 } 714 715 ACPI_EXPORT_SYMBOL (AcpiClearGpe) 716 717 718 /******************************************************************************* 719 * 720 * FUNCTION: AcpiGetGpeStatus 721 * 722 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 723 * GpeNumber - GPE level within the GPE block 724 * EventStatus - Where the current status of the event 725 * will be returned 726 * 727 * RETURN: Status 728 * 729 * DESCRIPTION: Get the current status of a GPE (signalled/not_signalled) 730 * 731 ******************************************************************************/ 732 733 ACPI_STATUS 734 AcpiGetGpeStatus ( 735 ACPI_HANDLE GpeDevice, 736 UINT32 GpeNumber, 737 ACPI_EVENT_STATUS *EventStatus) 738 { 739 ACPI_STATUS Status = AE_OK; 740 ACPI_GPE_EVENT_INFO *GpeEventInfo; 741 ACPI_CPU_FLAGS Flags; 742 743 744 ACPI_FUNCTION_TRACE (AcpiGetGpeStatus); 745 746 747 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 748 749 /* Ensure that we have a valid GPE number */ 750 751 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 752 if (!GpeEventInfo) 753 { 754 Status = AE_BAD_PARAMETER; 755 goto UnlockAndExit; 756 } 757 758 /* Obtain status on the requested GPE number */ 759 760 Status = AcpiHwGetGpeStatus (GpeEventInfo, EventStatus); 761 762 UnlockAndExit: 763 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 764 return_ACPI_STATUS (Status); 765 } 766 767 ACPI_EXPORT_SYMBOL (AcpiGetGpeStatus) 768 769 770 /******************************************************************************* 771 * 772 * FUNCTION: AcpiDispatchGpe 773 * 774 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 775 * GpeNumber - GPE level within the GPE block 776 * 777 * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED 778 * 779 * DESCRIPTION: Detect and dispatch a General Purpose Event to either a function 780 * (e.g. EC) or method (e.g. _Lxx/_Exx) handler. 781 * 782 ******************************************************************************/ 783 784 UINT32 785 AcpiDispatchGpe( 786 ACPI_HANDLE GpeDevice, 787 UINT32 GpeNumber) 788 { 789 ACPI_FUNCTION_TRACE(acpi_dispatch_gpe); 790 791 return (AcpiEvDetectGpe (GpeDevice, NULL, GpeNumber)); 792 } 793 794 ACPI_EXPORT_SYMBOL (AcpiDispatchGpe) 795 796 797 /******************************************************************************* 798 * 799 * FUNCTION: AcpiFinishGpe 800 * 801 * PARAMETERS: GpeDevice - Namespace node for the GPE Block 802 * (NULL for FADT defined GPEs) 803 * GpeNumber - GPE level within the GPE block 804 * 805 * RETURN: Status 806 * 807 * DESCRIPTION: Clear and conditionally re-enable a GPE. This completes the GPE 808 * processing. Intended for use by asynchronous host-installed 809 * GPE handlers. The GPE is only re-enabled if the EnableForRun bit 810 * is set in the GPE info. 811 * 812 ******************************************************************************/ 813 814 ACPI_STATUS 815 AcpiFinishGpe ( 816 ACPI_HANDLE GpeDevice, 817 UINT32 GpeNumber) 818 { 819 ACPI_GPE_EVENT_INFO *GpeEventInfo; 820 ACPI_STATUS Status; 821 ACPI_CPU_FLAGS Flags; 822 823 824 ACPI_FUNCTION_TRACE (AcpiFinishGpe); 825 826 827 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 828 829 /* Ensure that we have a valid GPE number */ 830 831 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 832 if (!GpeEventInfo) 833 { 834 Status = AE_BAD_PARAMETER; 835 goto UnlockAndExit; 836 } 837 838 Status = AcpiEvFinishGpe (GpeEventInfo); 839 840 UnlockAndExit: 841 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 842 return_ACPI_STATUS (Status); 843 } 844 845 ACPI_EXPORT_SYMBOL (AcpiFinishGpe) 846 847 848 /****************************************************************************** 849 * 850 * FUNCTION: AcpiDisableAllGpes 851 * 852 * PARAMETERS: None 853 * 854 * RETURN: Status 855 * 856 * DESCRIPTION: Disable and clear all GPEs in all GPE blocks 857 * 858 ******************************************************************************/ 859 860 ACPI_STATUS 861 AcpiDisableAllGpes ( 862 void) 863 { 864 ACPI_STATUS Status; 865 866 867 ACPI_FUNCTION_TRACE (AcpiDisableAllGpes); 868 869 870 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 871 if (ACPI_FAILURE (Status)) 872 { 873 return_ACPI_STATUS (Status); 874 } 875 876 Status = AcpiHwDisableAllGpes (); 877 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 878 879 return_ACPI_STATUS (Status); 880 } 881 882 ACPI_EXPORT_SYMBOL (AcpiDisableAllGpes) 883 884 885 /****************************************************************************** 886 * 887 * FUNCTION: AcpiEnableAllRuntimeGpes 888 * 889 * PARAMETERS: None 890 * 891 * RETURN: Status 892 * 893 * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks 894 * 895 ******************************************************************************/ 896 897 ACPI_STATUS 898 AcpiEnableAllRuntimeGpes ( 899 void) 900 { 901 ACPI_STATUS Status; 902 903 904 ACPI_FUNCTION_TRACE (AcpiEnableAllRuntimeGpes); 905 906 907 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 908 if (ACPI_FAILURE (Status)) 909 { 910 return_ACPI_STATUS (Status); 911 } 912 913 Status = AcpiHwEnableAllRuntimeGpes (); 914 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 915 916 return_ACPI_STATUS (Status); 917 } 918 919 ACPI_EXPORT_SYMBOL (AcpiEnableAllRuntimeGpes) 920 921 922 /****************************************************************************** 923 * 924 * FUNCTION: AcpiEnableAllWakeupGpes 925 * 926 * PARAMETERS: None 927 * 928 * RETURN: Status 929 * 930 * DESCRIPTION: Enable all "wakeup" GPEs and disable all of the other GPEs, in 931 * all GPE blocks. 932 * 933 ******************************************************************************/ 934 935 ACPI_STATUS 936 AcpiEnableAllWakeupGpes ( 937 void) 938 { 939 ACPI_STATUS Status; 940 941 942 ACPI_FUNCTION_TRACE (AcpiEnableAllWakeupGpes); 943 944 945 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 946 if (ACPI_FAILURE (Status)) 947 { 948 return_ACPI_STATUS (Status); 949 } 950 951 Status = AcpiHwEnableAllWakeupGpes (); 952 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 953 954 return_ACPI_STATUS (Status); 955 } 956 957 ACPI_EXPORT_SYMBOL (AcpiEnableAllWakeupGpes) 958 959 960 /****************************************************************************** 961 * 962 * FUNCTION: AcpiAnyGpeStatusSet 963 * 964 * PARAMETERS: None 965 * 966 * RETURN: Whether or not the status bit is set for any GPE 967 * 968 * DESCRIPTION: Check the status bits of all enabled GPEs and return TRUE if any 969 * of them is set or FALSE otherwise. 970 * 971 ******************************************************************************/ 972 973 UINT32 974 AcpiAnyGpeStatusSet ( 975 void) 976 { 977 ACPI_STATUS Status; 978 UINT8 Ret; 979 980 981 ACPI_FUNCTION_TRACE (AcpiAnyGpeStatusSet); 982 983 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 984 if (ACPI_FAILURE (Status)) 985 { 986 return (FALSE); 987 } 988 989 Ret = AcpiHwCheckAllGpes (); 990 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 991 992 return (Ret); 993 } 994 995 ACPI_EXPORT_SYMBOL(AcpiAnyGpeStatusSet) 996 997 998 /******************************************************************************* 999 * 1000 * FUNCTION: AcpiInstallGpeBlock 1001 * 1002 * PARAMETERS: GpeDevice - Handle to the parent GPE Block Device 1003 * GpeBlockAddress - Address and SpaceID 1004 * RegisterCount - Number of GPE register pairs in the block 1005 * InterruptNumber - H/W interrupt for the block 1006 * 1007 * RETURN: Status 1008 * 1009 * DESCRIPTION: Create and Install a block of GPE registers. The GPEs are not 1010 * enabled here. 1011 * 1012 ******************************************************************************/ 1013 1014 ACPI_STATUS 1015 AcpiInstallGpeBlock ( 1016 ACPI_HANDLE GpeDevice, 1017 ACPI_GENERIC_ADDRESS *GpeBlockAddress, 1018 UINT32 RegisterCount, 1019 UINT32 InterruptNumber) 1020 { 1021 ACPI_STATUS Status; 1022 ACPI_OPERAND_OBJECT *ObjDesc; 1023 ACPI_NAMESPACE_NODE *Node; 1024 ACPI_GPE_BLOCK_INFO *GpeBlock; 1025 1026 1027 ACPI_FUNCTION_TRACE (AcpiInstallGpeBlock); 1028 1029 1030 if ((!GpeDevice) || 1031 (!GpeBlockAddress) || 1032 (!RegisterCount)) 1033 { 1034 return_ACPI_STATUS (AE_BAD_PARAMETER); 1035 } 1036 1037 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 1038 if (ACPI_FAILURE (Status)) 1039 { 1040 return_ACPI_STATUS (Status); 1041 } 1042 1043 Node = AcpiNsValidateHandle (GpeDevice); 1044 if (!Node) 1045 { 1046 Status = AE_BAD_PARAMETER; 1047 goto UnlockAndExit; 1048 } 1049 1050 /* Validate the parent device */ 1051 1052 if (Node->Type != ACPI_TYPE_DEVICE) 1053 { 1054 Status = AE_TYPE; 1055 goto UnlockAndExit; 1056 } 1057 1058 if (Node->Object) 1059 { 1060 Status = AE_ALREADY_EXISTS; 1061 goto UnlockAndExit; 1062 } 1063 1064 /* 1065 * For user-installed GPE Block Devices, the GpeBlockBaseNumber 1066 * is always zero 1067 */ 1068 Status = AcpiEvCreateGpeBlock (Node, GpeBlockAddress->Address, 1069 GpeBlockAddress->SpaceId, RegisterCount, 1070 0, InterruptNumber, &GpeBlock); 1071 if (ACPI_FAILURE (Status)) 1072 { 1073 goto UnlockAndExit; 1074 } 1075 1076 /* Install block in the DeviceObject attached to the node */ 1077 1078 ObjDesc = AcpiNsGetAttachedObject (Node); 1079 if (!ObjDesc) 1080 { 1081 /* 1082 * No object, create a new one (Device nodes do not always have 1083 * an attached object) 1084 */ 1085 ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_DEVICE); 1086 if (!ObjDesc) 1087 { 1088 Status = AE_NO_MEMORY; 1089 goto UnlockAndExit; 1090 } 1091 1092 Status = AcpiNsAttachObject (Node, ObjDesc, ACPI_TYPE_DEVICE); 1093 1094 /* Remove local reference to the object */ 1095 1096 AcpiUtRemoveReference (ObjDesc); 1097 if (ACPI_FAILURE (Status)) 1098 { 1099 goto UnlockAndExit; 1100 } 1101 } 1102 1103 /* Now install the GPE block in the DeviceObject */ 1104 1105 ObjDesc->Device.GpeBlock = GpeBlock; 1106 1107 1108 UnlockAndExit: 1109 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 1110 return_ACPI_STATUS (Status); 1111 } 1112 1113 ACPI_EXPORT_SYMBOL (AcpiInstallGpeBlock) 1114 1115 1116 /******************************************************************************* 1117 * 1118 * FUNCTION: AcpiRemoveGpeBlock 1119 * 1120 * PARAMETERS: GpeDevice - Handle to the parent GPE Block Device 1121 * 1122 * RETURN: Status 1123 * 1124 * DESCRIPTION: Remove a previously installed block of GPE registers 1125 * 1126 ******************************************************************************/ 1127 1128 ACPI_STATUS 1129 AcpiRemoveGpeBlock ( 1130 ACPI_HANDLE GpeDevice) 1131 { 1132 ACPI_OPERAND_OBJECT *ObjDesc; 1133 ACPI_STATUS Status; 1134 ACPI_NAMESPACE_NODE *Node; 1135 1136 1137 ACPI_FUNCTION_TRACE (AcpiRemoveGpeBlock); 1138 1139 1140 if (!GpeDevice) 1141 { 1142 return_ACPI_STATUS (AE_BAD_PARAMETER); 1143 } 1144 1145 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 1146 if (ACPI_FAILURE (Status)) 1147 { 1148 return_ACPI_STATUS (Status); 1149 } 1150 1151 Node = AcpiNsValidateHandle (GpeDevice); 1152 if (!Node) 1153 { 1154 Status = AE_BAD_PARAMETER; 1155 goto UnlockAndExit; 1156 } 1157 1158 /* Validate the parent device */ 1159 1160 if (Node->Type != ACPI_TYPE_DEVICE) 1161 { 1162 Status = AE_TYPE; 1163 goto UnlockAndExit; 1164 } 1165 1166 /* Get the DeviceObject attached to the node */ 1167 1168 ObjDesc = AcpiNsGetAttachedObject (Node); 1169 if (!ObjDesc || 1170 !ObjDesc->Device.GpeBlock) 1171 { 1172 return_ACPI_STATUS (AE_NULL_OBJECT); 1173 } 1174 1175 /* Delete the GPE block (but not the DeviceObject) */ 1176 1177 Status = AcpiEvDeleteGpeBlock (ObjDesc->Device.GpeBlock); 1178 if (ACPI_SUCCESS (Status)) 1179 { 1180 ObjDesc->Device.GpeBlock = NULL; 1181 } 1182 1183 UnlockAndExit: 1184 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 1185 return_ACPI_STATUS (Status); 1186 } 1187 1188 ACPI_EXPORT_SYMBOL (AcpiRemoveGpeBlock) 1189 1190 1191 /******************************************************************************* 1192 * 1193 * FUNCTION: AcpiGetGpeDevice 1194 * 1195 * PARAMETERS: Index - System GPE index (0-CurrentGpeCount) 1196 * GpeDevice - Where the parent GPE Device is returned 1197 * 1198 * RETURN: Status 1199 * 1200 * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL 1201 * gpe device indicates that the gpe number is contained in one of 1202 * the FADT-defined gpe blocks. Otherwise, the GPE block device. 1203 * 1204 ******************************************************************************/ 1205 1206 ACPI_STATUS 1207 AcpiGetGpeDevice ( 1208 UINT32 Index, 1209 ACPI_HANDLE *GpeDevice) 1210 { 1211 ACPI_GPE_DEVICE_INFO Info; 1212 ACPI_STATUS Status; 1213 1214 1215 ACPI_FUNCTION_TRACE (AcpiGetGpeDevice); 1216 1217 1218 if (!GpeDevice) 1219 { 1220 return_ACPI_STATUS (AE_BAD_PARAMETER); 1221 } 1222 1223 if (Index >= AcpiCurrentGpeCount) 1224 { 1225 return_ACPI_STATUS (AE_NOT_EXIST); 1226 } 1227 1228 /* Setup and walk the GPE list */ 1229 1230 Info.Index = Index; 1231 Info.Status = AE_NOT_EXIST; 1232 Info.GpeDevice = NULL; 1233 Info.NextBlockBaseIndex = 0; 1234 1235 Status = AcpiEvWalkGpeList (AcpiEvGetGpeDevice, &Info); 1236 if (ACPI_FAILURE (Status)) 1237 { 1238 return_ACPI_STATUS (Status); 1239 } 1240 1241 *GpeDevice = ACPI_CAST_PTR (ACPI_HANDLE, Info.GpeDevice); 1242 return_ACPI_STATUS (Info.Status); 1243 } 1244 1245 ACPI_EXPORT_SYMBOL (AcpiGetGpeDevice) 1246 1247 #endif /* !ACPI_REDUCED_HARDWARE */ 1248