1 /****************************************************************************** 2 * 3 * Module Name: evxfgpe - External Interfaces for General Purpose Events (GPEs) 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 #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); 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: AcpiFinishGpe 773 * 774 * PARAMETERS: GpeDevice - Namespace node for the GPE Block 775 * (NULL for FADT defined GPEs) 776 * GpeNumber - GPE level within the GPE block 777 * 778 * RETURN: Status 779 * 780 * DESCRIPTION: Clear and conditionally re-enable a GPE. This completes the GPE 781 * processing. Intended for use by asynchronous host-installed 782 * GPE handlers. The GPE is only re-enabled if the EnableForRun bit 783 * is set in the GPE info. 784 * 785 ******************************************************************************/ 786 787 ACPI_STATUS 788 AcpiFinishGpe ( 789 ACPI_HANDLE GpeDevice, 790 UINT32 GpeNumber) 791 { 792 ACPI_GPE_EVENT_INFO *GpeEventInfo; 793 ACPI_STATUS Status; 794 ACPI_CPU_FLAGS Flags; 795 796 797 ACPI_FUNCTION_TRACE (AcpiFinishGpe); 798 799 800 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 801 802 /* Ensure that we have a valid GPE number */ 803 804 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 805 if (!GpeEventInfo) 806 { 807 Status = AE_BAD_PARAMETER; 808 goto UnlockAndExit; 809 } 810 811 Status = AcpiEvFinishGpe (GpeEventInfo); 812 813 UnlockAndExit: 814 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 815 return_ACPI_STATUS (Status); 816 } 817 818 ACPI_EXPORT_SYMBOL (AcpiFinishGpe) 819 820 821 /****************************************************************************** 822 * 823 * FUNCTION: AcpiDisableAllGpes 824 * 825 * PARAMETERS: None 826 * 827 * RETURN: Status 828 * 829 * DESCRIPTION: Disable and clear all GPEs in all GPE blocks 830 * 831 ******************************************************************************/ 832 833 ACPI_STATUS 834 AcpiDisableAllGpes ( 835 void) 836 { 837 ACPI_STATUS Status; 838 839 840 ACPI_FUNCTION_TRACE (AcpiDisableAllGpes); 841 842 843 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 844 if (ACPI_FAILURE (Status)) 845 { 846 return_ACPI_STATUS (Status); 847 } 848 849 Status = AcpiHwDisableAllGpes (); 850 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 851 852 return_ACPI_STATUS (Status); 853 } 854 855 ACPI_EXPORT_SYMBOL (AcpiDisableAllGpes) 856 857 858 /****************************************************************************** 859 * 860 * FUNCTION: AcpiEnableAllRuntimeGpes 861 * 862 * PARAMETERS: None 863 * 864 * RETURN: Status 865 * 866 * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks 867 * 868 ******************************************************************************/ 869 870 ACPI_STATUS 871 AcpiEnableAllRuntimeGpes ( 872 void) 873 { 874 ACPI_STATUS Status; 875 876 877 ACPI_FUNCTION_TRACE (AcpiEnableAllRuntimeGpes); 878 879 880 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 881 if (ACPI_FAILURE (Status)) 882 { 883 return_ACPI_STATUS (Status); 884 } 885 886 Status = AcpiHwEnableAllRuntimeGpes (); 887 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 888 889 return_ACPI_STATUS (Status); 890 } 891 892 ACPI_EXPORT_SYMBOL (AcpiEnableAllRuntimeGpes) 893 894 895 /****************************************************************************** 896 * 897 * FUNCTION: AcpiEnableAllWakeupGpes 898 * 899 * PARAMETERS: None 900 * 901 * RETURN: Status 902 * 903 * DESCRIPTION: Enable all "wakeup" GPEs and disable all of the other GPEs, in 904 * all GPE blocks. 905 * 906 ******************************************************************************/ 907 908 ACPI_STATUS 909 AcpiEnableAllWakeupGpes ( 910 void) 911 { 912 ACPI_STATUS Status; 913 914 915 ACPI_FUNCTION_TRACE (AcpiEnableAllWakeupGpes); 916 917 918 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 919 if (ACPI_FAILURE (Status)) 920 { 921 return_ACPI_STATUS (Status); 922 } 923 924 Status = AcpiHwEnableAllWakeupGpes (); 925 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 926 927 return_ACPI_STATUS (Status); 928 } 929 930 ACPI_EXPORT_SYMBOL (AcpiEnableAllWakeupGpes) 931 932 933 /******************************************************************************* 934 * 935 * FUNCTION: AcpiInstallGpeBlock 936 * 937 * PARAMETERS: GpeDevice - Handle to the parent GPE Block Device 938 * GpeBlockAddress - Address and SpaceID 939 * RegisterCount - Number of GPE register pairs in the block 940 * InterruptNumber - H/W interrupt for the block 941 * 942 * RETURN: Status 943 * 944 * DESCRIPTION: Create and Install a block of GPE registers. The GPEs are not 945 * enabled here. 946 * 947 ******************************************************************************/ 948 949 ACPI_STATUS 950 AcpiInstallGpeBlock ( 951 ACPI_HANDLE GpeDevice, 952 ACPI_GENERIC_ADDRESS *GpeBlockAddress, 953 UINT32 RegisterCount, 954 UINT32 InterruptNumber) 955 { 956 ACPI_STATUS Status; 957 ACPI_OPERAND_OBJECT *ObjDesc; 958 ACPI_NAMESPACE_NODE *Node; 959 ACPI_GPE_BLOCK_INFO *GpeBlock; 960 961 962 ACPI_FUNCTION_TRACE (AcpiInstallGpeBlock); 963 964 965 if ((!GpeDevice) || 966 (!GpeBlockAddress) || 967 (!RegisterCount)) 968 { 969 return_ACPI_STATUS (AE_BAD_PARAMETER); 970 } 971 972 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 973 if (ACPI_FAILURE (Status)) 974 { 975 return_ACPI_STATUS (Status); 976 } 977 978 Node = AcpiNsValidateHandle (GpeDevice); 979 if (!Node) 980 { 981 Status = AE_BAD_PARAMETER; 982 goto UnlockAndExit; 983 } 984 985 /* Validate the parent device */ 986 987 if (Node->Type != ACPI_TYPE_DEVICE) 988 { 989 Status = AE_TYPE; 990 goto UnlockAndExit; 991 } 992 993 if (Node->Object) 994 { 995 Status = AE_ALREADY_EXISTS; 996 goto UnlockAndExit; 997 } 998 999 /* 1000 * For user-installed GPE Block Devices, the GpeBlockBaseNumber 1001 * is always zero 1002 */ 1003 Status = AcpiEvCreateGpeBlock (Node, GpeBlockAddress->Address, 1004 GpeBlockAddress->SpaceId, RegisterCount, 1005 0, InterruptNumber, &GpeBlock); 1006 if (ACPI_FAILURE (Status)) 1007 { 1008 goto UnlockAndExit; 1009 } 1010 1011 /* Install block in the DeviceObject attached to the node */ 1012 1013 ObjDesc = AcpiNsGetAttachedObject (Node); 1014 if (!ObjDesc) 1015 { 1016 /* 1017 * No object, create a new one (Device nodes do not always have 1018 * an attached object) 1019 */ 1020 ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_DEVICE); 1021 if (!ObjDesc) 1022 { 1023 Status = AE_NO_MEMORY; 1024 goto UnlockAndExit; 1025 } 1026 1027 Status = AcpiNsAttachObject (Node, ObjDesc, ACPI_TYPE_DEVICE); 1028 1029 /* Remove local reference to the object */ 1030 1031 AcpiUtRemoveReference (ObjDesc); 1032 if (ACPI_FAILURE (Status)) 1033 { 1034 goto UnlockAndExit; 1035 } 1036 } 1037 1038 /* Now install the GPE block in the DeviceObject */ 1039 1040 ObjDesc->Device.GpeBlock = GpeBlock; 1041 1042 1043 UnlockAndExit: 1044 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 1045 return_ACPI_STATUS (Status); 1046 } 1047 1048 ACPI_EXPORT_SYMBOL (AcpiInstallGpeBlock) 1049 1050 1051 /******************************************************************************* 1052 * 1053 * FUNCTION: AcpiRemoveGpeBlock 1054 * 1055 * PARAMETERS: GpeDevice - Handle to the parent GPE Block Device 1056 * 1057 * RETURN: Status 1058 * 1059 * DESCRIPTION: Remove a previously installed block of GPE registers 1060 * 1061 ******************************************************************************/ 1062 1063 ACPI_STATUS 1064 AcpiRemoveGpeBlock ( 1065 ACPI_HANDLE GpeDevice) 1066 { 1067 ACPI_OPERAND_OBJECT *ObjDesc; 1068 ACPI_STATUS Status; 1069 ACPI_NAMESPACE_NODE *Node; 1070 1071 1072 ACPI_FUNCTION_TRACE (AcpiRemoveGpeBlock); 1073 1074 1075 if (!GpeDevice) 1076 { 1077 return_ACPI_STATUS (AE_BAD_PARAMETER); 1078 } 1079 1080 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 1081 if (ACPI_FAILURE (Status)) 1082 { 1083 return_ACPI_STATUS (Status); 1084 } 1085 1086 Node = AcpiNsValidateHandle (GpeDevice); 1087 if (!Node) 1088 { 1089 Status = AE_BAD_PARAMETER; 1090 goto UnlockAndExit; 1091 } 1092 1093 /* Validate the parent device */ 1094 1095 if (Node->Type != ACPI_TYPE_DEVICE) 1096 { 1097 Status = AE_TYPE; 1098 goto UnlockAndExit; 1099 } 1100 1101 /* Get the DeviceObject attached to the node */ 1102 1103 ObjDesc = AcpiNsGetAttachedObject (Node); 1104 if (!ObjDesc || 1105 !ObjDesc->Device.GpeBlock) 1106 { 1107 return_ACPI_STATUS (AE_NULL_OBJECT); 1108 } 1109 1110 /* Delete the GPE block (but not the DeviceObject) */ 1111 1112 Status = AcpiEvDeleteGpeBlock (ObjDesc->Device.GpeBlock); 1113 if (ACPI_SUCCESS (Status)) 1114 { 1115 ObjDesc->Device.GpeBlock = NULL; 1116 } 1117 1118 UnlockAndExit: 1119 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 1120 return_ACPI_STATUS (Status); 1121 } 1122 1123 ACPI_EXPORT_SYMBOL (AcpiRemoveGpeBlock) 1124 1125 1126 /******************************************************************************* 1127 * 1128 * FUNCTION: AcpiGetGpeDevice 1129 * 1130 * PARAMETERS: Index - System GPE index (0-CurrentGpeCount) 1131 * GpeDevice - Where the parent GPE Device is returned 1132 * 1133 * RETURN: Status 1134 * 1135 * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL 1136 * gpe device indicates that the gpe number is contained in one of 1137 * the FADT-defined gpe blocks. Otherwise, the GPE block device. 1138 * 1139 ******************************************************************************/ 1140 1141 ACPI_STATUS 1142 AcpiGetGpeDevice ( 1143 UINT32 Index, 1144 ACPI_HANDLE *GpeDevice) 1145 { 1146 ACPI_GPE_DEVICE_INFO Info; 1147 ACPI_STATUS Status; 1148 1149 1150 ACPI_FUNCTION_TRACE (AcpiGetGpeDevice); 1151 1152 1153 if (!GpeDevice) 1154 { 1155 return_ACPI_STATUS (AE_BAD_PARAMETER); 1156 } 1157 1158 if (Index >= AcpiCurrentGpeCount) 1159 { 1160 return_ACPI_STATUS (AE_NOT_EXIST); 1161 } 1162 1163 /* Setup and walk the GPE list */ 1164 1165 Info.Index = Index; 1166 Info.Status = AE_NOT_EXIST; 1167 Info.GpeDevice = NULL; 1168 Info.NextBlockBaseIndex = 0; 1169 1170 Status = AcpiEvWalkGpeList (AcpiEvGetGpeDevice, &Info); 1171 if (ACPI_FAILURE (Status)) 1172 { 1173 return_ACPI_STATUS (Status); 1174 } 1175 1176 *GpeDevice = ACPI_CAST_PTR (ACPI_HANDLE, Info.GpeDevice); 1177 return_ACPI_STATUS (Info.Status); 1178 } 1179 1180 ACPI_EXPORT_SYMBOL (AcpiGetGpeDevice) 1181 1182 #endif /* !ACPI_REDUCED_HARDWARE */ 1183