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