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 "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 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 break; 275 276 case ACPI_GPE_DISABLE: 277 278 Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE); 279 break; 280 281 default: 282 283 Status = AE_BAD_PARAMETER; 284 break; 285 } 286 287 UnlockAndExit: 288 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 289 return_ACPI_STATUS (Status); 290 } 291 292 ACPI_EXPORT_SYMBOL (AcpiSetGpe) 293 294 295 /******************************************************************************* 296 * 297 * FUNCTION: AcpiMarkGpeForWake 298 * 299 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 300 * GpeNumber - GPE level within the GPE block 301 * 302 * RETURN: Status 303 * 304 * DESCRIPTION: Mark a GPE as having the ability to wake the system. Simply 305 * sets the ACPI_GPE_CAN_WAKE flag. 306 * 307 * Some potential callers of AcpiSetupGpeForWake may know in advance that 308 * there won't be any notify handlers installed for device wake notifications 309 * from the given GPE (one example is a button GPE in Linux). For these cases, 310 * AcpiMarkGpeForWake should be used instead of AcpiSetupGpeForWake. 311 * This will set the ACPI_GPE_CAN_WAKE flag for the GPE without trying to 312 * setup implicit wake notification for it (since there's no handler method). 313 * 314 ******************************************************************************/ 315 316 ACPI_STATUS 317 AcpiMarkGpeForWake ( 318 ACPI_HANDLE GpeDevice, 319 UINT32 GpeNumber) 320 { 321 ACPI_GPE_EVENT_INFO *GpeEventInfo; 322 ACPI_STATUS Status = AE_BAD_PARAMETER; 323 ACPI_CPU_FLAGS Flags; 324 325 326 ACPI_FUNCTION_TRACE (AcpiMarkGpeForWake); 327 328 329 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 330 331 /* Ensure that we have a valid GPE number */ 332 333 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 334 if (GpeEventInfo) 335 { 336 /* Mark the GPE as a possible wake event */ 337 338 GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE; 339 Status = AE_OK; 340 } 341 342 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 343 return_ACPI_STATUS (Status); 344 } 345 346 ACPI_EXPORT_SYMBOL (AcpiMarkGpeForWake) 347 348 349 /******************************************************************************* 350 * 351 * FUNCTION: AcpiSetupGpeForWake 352 * 353 * PARAMETERS: WakeDevice - Device associated with the GPE (via _PRW) 354 * GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 355 * GpeNumber - GPE level within the GPE block 356 * 357 * RETURN: Status 358 * 359 * DESCRIPTION: Mark a GPE as having the ability to wake the system. This 360 * interface is intended to be used as the host executes the 361 * _PRW methods (Power Resources for Wake) in the system tables. 362 * Each _PRW appears under a Device Object (The WakeDevice), and 363 * contains the info for the wake GPE associated with the 364 * WakeDevice. 365 * 366 ******************************************************************************/ 367 368 ACPI_STATUS 369 AcpiSetupGpeForWake ( 370 ACPI_HANDLE WakeDevice, 371 ACPI_HANDLE GpeDevice, 372 UINT32 GpeNumber) 373 { 374 ACPI_STATUS Status; 375 ACPI_GPE_EVENT_INFO *GpeEventInfo; 376 ACPI_NAMESPACE_NODE *DeviceNode; 377 ACPI_GPE_NOTIFY_INFO *Notify; 378 ACPI_GPE_NOTIFY_INFO *NewNotify; 379 ACPI_CPU_FLAGS Flags; 380 381 382 ACPI_FUNCTION_TRACE (AcpiSetupGpeForWake); 383 384 385 /* Parameter Validation */ 386 387 if (!WakeDevice) 388 { 389 /* 390 * By forcing WakeDevice to be valid, we automatically enable the 391 * implicit notify feature on all hosts. 392 */ 393 return_ACPI_STATUS (AE_BAD_PARAMETER); 394 } 395 396 /* Handle root object case */ 397 398 if (WakeDevice == ACPI_ROOT_OBJECT) 399 { 400 DeviceNode = AcpiGbl_RootNode; 401 } 402 else 403 { 404 DeviceNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, WakeDevice); 405 } 406 407 /* Validate WakeDevice is of type Device */ 408 409 if (DeviceNode->Type != ACPI_TYPE_DEVICE) 410 { 411 return_ACPI_STATUS (AE_BAD_PARAMETER); 412 } 413 414 /* 415 * Allocate a new notify object up front, in case it is needed. 416 * Memory allocation while holding a spinlock is a big no-no 417 * on some hosts. 418 */ 419 NewNotify = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_NOTIFY_INFO)); 420 if (!NewNotify) 421 { 422 return_ACPI_STATUS (AE_NO_MEMORY); 423 } 424 425 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 426 427 /* Ensure that we have a valid GPE number */ 428 429 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 430 if (!GpeEventInfo) 431 { 432 Status = AE_BAD_PARAMETER; 433 goto UnlockAndExit; 434 } 435 436 /* 437 * If there is no method or handler for this GPE, then the 438 * WakeDevice will be notified whenever this GPE fires. This is 439 * known as an "implicit notify". Note: The GPE is assumed to be 440 * level-triggered (for windows compatibility). 441 */ 442 if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) == 443 ACPI_GPE_DISPATCH_NONE) 444 { 445 /* 446 * This is the first device for implicit notify on this GPE. 447 * Just set the flags here, and enter the NOTIFY block below. 448 */ 449 GpeEventInfo->Flags = 450 (ACPI_GPE_DISPATCH_NOTIFY | ACPI_GPE_LEVEL_TRIGGERED); 451 } 452 453 /* 454 * If we already have an implicit notify on this GPE, add 455 * this device to the notify list. 456 */ 457 if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) == 458 ACPI_GPE_DISPATCH_NOTIFY) 459 { 460 /* Ensure that the device is not already in the list */ 461 462 Notify = GpeEventInfo->Dispatch.NotifyList; 463 while (Notify) 464 { 465 if (Notify->DeviceNode == DeviceNode) 466 { 467 Status = AE_ALREADY_EXISTS; 468 goto UnlockAndExit; 469 } 470 Notify = Notify->Next; 471 } 472 473 /* Add this device to the notify list for this GPE */ 474 475 NewNotify->DeviceNode = DeviceNode; 476 NewNotify->Next = GpeEventInfo->Dispatch.NotifyList; 477 GpeEventInfo->Dispatch.NotifyList = NewNotify; 478 NewNotify = NULL; 479 } 480 481 /* Mark the GPE as a possible wake event */ 482 483 GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE; 484 Status = AE_OK; 485 486 487 UnlockAndExit: 488 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 489 490 /* Delete the notify object if it was not used above */ 491 492 if (NewNotify) 493 { 494 ACPI_FREE (NewNotify); 495 } 496 return_ACPI_STATUS (Status); 497 } 498 499 ACPI_EXPORT_SYMBOL (AcpiSetupGpeForWake) 500 501 502 /******************************************************************************* 503 * 504 * FUNCTION: AcpiSetGpeWakeMask 505 * 506 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 507 * GpeNumber - GPE level within the GPE block 508 * Action - Enable or Disable 509 * 510 * RETURN: Status 511 * 512 * DESCRIPTION: Set or clear the GPE's wakeup enable mask bit. The GPE must 513 * already be marked as a WAKE GPE. 514 * 515 ******************************************************************************/ 516 517 ACPI_STATUS 518 AcpiSetGpeWakeMask ( 519 ACPI_HANDLE GpeDevice, 520 UINT32 GpeNumber, 521 UINT8 Action) 522 { 523 ACPI_STATUS Status = AE_OK; 524 ACPI_GPE_EVENT_INFO *GpeEventInfo; 525 ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; 526 ACPI_CPU_FLAGS Flags; 527 UINT32 RegisterBit; 528 529 530 ACPI_FUNCTION_TRACE (AcpiSetGpeWakeMask); 531 532 533 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 534 535 /* 536 * Ensure that we have a valid GPE number and that this GPE is in 537 * fact a wake GPE 538 */ 539 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 540 if (!GpeEventInfo) 541 { 542 Status = AE_BAD_PARAMETER; 543 goto UnlockAndExit; 544 } 545 546 if (!(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE)) 547 { 548 Status = AE_TYPE; 549 goto UnlockAndExit; 550 } 551 552 GpeRegisterInfo = GpeEventInfo->RegisterInfo; 553 if (!GpeRegisterInfo) 554 { 555 Status = AE_NOT_EXIST; 556 goto UnlockAndExit; 557 } 558 559 RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo); 560 561 /* Perform the action */ 562 563 switch (Action) 564 { 565 case ACPI_GPE_ENABLE: 566 567 ACPI_SET_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit); 568 break; 569 570 case ACPI_GPE_DISABLE: 571 572 ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit); 573 break; 574 575 default: 576 577 ACPI_ERROR ((AE_INFO, "%u, Invalid action", Action)); 578 Status = AE_BAD_PARAMETER; 579 break; 580 } 581 582 UnlockAndExit: 583 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 584 return_ACPI_STATUS (Status); 585 } 586 587 ACPI_EXPORT_SYMBOL (AcpiSetGpeWakeMask) 588 589 590 /******************************************************************************* 591 * 592 * FUNCTION: AcpiClearGpe 593 * 594 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 595 * GpeNumber - GPE level within the GPE block 596 * 597 * RETURN: Status 598 * 599 * DESCRIPTION: Clear an ACPI event (general purpose) 600 * 601 ******************************************************************************/ 602 603 ACPI_STATUS 604 AcpiClearGpe ( 605 ACPI_HANDLE GpeDevice, 606 UINT32 GpeNumber) 607 { 608 ACPI_STATUS Status = AE_OK; 609 ACPI_GPE_EVENT_INFO *GpeEventInfo; 610 ACPI_CPU_FLAGS Flags; 611 612 613 ACPI_FUNCTION_TRACE (AcpiClearGpe); 614 615 616 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 617 618 /* Ensure that we have a valid GPE number */ 619 620 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 621 if (!GpeEventInfo) 622 { 623 Status = AE_BAD_PARAMETER; 624 goto UnlockAndExit; 625 } 626 627 Status = AcpiHwClearGpe (GpeEventInfo); 628 629 UnlockAndExit: 630 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 631 return_ACPI_STATUS (Status); 632 } 633 634 ACPI_EXPORT_SYMBOL (AcpiClearGpe) 635 636 637 /******************************************************************************* 638 * 639 * FUNCTION: AcpiGetGpeStatus 640 * 641 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 642 * GpeNumber - GPE level within the GPE block 643 * EventStatus - Where the current status of the event 644 * will be returned 645 * 646 * RETURN: Status 647 * 648 * DESCRIPTION: Get the current status of a GPE (signalled/not_signalled) 649 * 650 ******************************************************************************/ 651 652 ACPI_STATUS 653 AcpiGetGpeStatus ( 654 ACPI_HANDLE GpeDevice, 655 UINT32 GpeNumber, 656 ACPI_EVENT_STATUS *EventStatus) 657 { 658 ACPI_STATUS Status = AE_OK; 659 ACPI_GPE_EVENT_INFO *GpeEventInfo; 660 ACPI_CPU_FLAGS Flags; 661 662 663 ACPI_FUNCTION_TRACE (AcpiGetGpeStatus); 664 665 666 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 667 668 /* Ensure that we have a valid GPE number */ 669 670 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 671 if (!GpeEventInfo) 672 { 673 Status = AE_BAD_PARAMETER; 674 goto UnlockAndExit; 675 } 676 677 /* Obtain status on the requested GPE number */ 678 679 Status = AcpiHwGetGpeStatus (GpeEventInfo, EventStatus); 680 681 UnlockAndExit: 682 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 683 return_ACPI_STATUS (Status); 684 } 685 686 ACPI_EXPORT_SYMBOL (AcpiGetGpeStatus) 687 688 689 /******************************************************************************* 690 * 691 * FUNCTION: AcpiFinishGpe 692 * 693 * PARAMETERS: GpeDevice - Namespace node for the GPE Block 694 * (NULL for FADT defined GPEs) 695 * GpeNumber - GPE level within the GPE block 696 * 697 * RETURN: Status 698 * 699 * DESCRIPTION: Clear and conditionally reenable a GPE. This completes the GPE 700 * processing. Intended for use by asynchronous host-installed 701 * GPE handlers. The GPE is only reenabled if the EnableForRun bit 702 * is set in the GPE info. 703 * 704 ******************************************************************************/ 705 706 ACPI_STATUS 707 AcpiFinishGpe ( 708 ACPI_HANDLE GpeDevice, 709 UINT32 GpeNumber) 710 { 711 ACPI_GPE_EVENT_INFO *GpeEventInfo; 712 ACPI_STATUS Status; 713 ACPI_CPU_FLAGS Flags; 714 715 716 ACPI_FUNCTION_TRACE (AcpiFinishGpe); 717 718 719 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 720 721 /* Ensure that we have a valid GPE number */ 722 723 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 724 if (!GpeEventInfo) 725 { 726 Status = AE_BAD_PARAMETER; 727 goto UnlockAndExit; 728 } 729 730 Status = AcpiEvFinishGpe (GpeEventInfo); 731 732 UnlockAndExit: 733 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 734 return_ACPI_STATUS (Status); 735 } 736 737 ACPI_EXPORT_SYMBOL (AcpiFinishGpe) 738 739 740 /****************************************************************************** 741 * 742 * FUNCTION: AcpiDisableAllGpes 743 * 744 * PARAMETERS: None 745 * 746 * RETURN: Status 747 * 748 * DESCRIPTION: Disable and clear all GPEs in all GPE blocks 749 * 750 ******************************************************************************/ 751 752 ACPI_STATUS 753 AcpiDisableAllGpes ( 754 void) 755 { 756 ACPI_STATUS Status; 757 758 759 ACPI_FUNCTION_TRACE (AcpiDisableAllGpes); 760 761 762 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 763 if (ACPI_FAILURE (Status)) 764 { 765 return_ACPI_STATUS (Status); 766 } 767 768 Status = AcpiHwDisableAllGpes (); 769 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 770 771 return_ACPI_STATUS (Status); 772 } 773 774 ACPI_EXPORT_SYMBOL (AcpiDisableAllGpes) 775 776 777 /****************************************************************************** 778 * 779 * FUNCTION: AcpiEnableAllRuntimeGpes 780 * 781 * PARAMETERS: None 782 * 783 * RETURN: Status 784 * 785 * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks 786 * 787 ******************************************************************************/ 788 789 ACPI_STATUS 790 AcpiEnableAllRuntimeGpes ( 791 void) 792 { 793 ACPI_STATUS Status; 794 795 796 ACPI_FUNCTION_TRACE (AcpiEnableAllRuntimeGpes); 797 798 799 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 800 if (ACPI_FAILURE (Status)) 801 { 802 return_ACPI_STATUS (Status); 803 } 804 805 Status = AcpiHwEnableAllRuntimeGpes (); 806 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 807 808 return_ACPI_STATUS (Status); 809 } 810 811 ACPI_EXPORT_SYMBOL (AcpiEnableAllRuntimeGpes) 812 813 814 /****************************************************************************** 815 * 816 * FUNCTION: AcpiEnableAllWakeupGpes 817 * 818 * PARAMETERS: None 819 * 820 * RETURN: Status 821 * 822 * DESCRIPTION: Enable all "wakeup" GPEs and disable all of the other GPEs, in 823 * all GPE blocks. 824 * 825 ******************************************************************************/ 826 827 ACPI_STATUS 828 AcpiEnableAllWakeupGpes ( 829 void) 830 { 831 ACPI_STATUS Status; 832 833 834 ACPI_FUNCTION_TRACE (AcpiEnableAllWakeupGpes); 835 836 837 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 838 if (ACPI_FAILURE (Status)) 839 { 840 return_ACPI_STATUS (Status); 841 } 842 843 Status = AcpiHwEnableAllWakeupGpes (); 844 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 845 846 return_ACPI_STATUS (Status); 847 } 848 849 ACPI_EXPORT_SYMBOL (AcpiEnableAllWakeupGpes) 850 851 852 /******************************************************************************* 853 * 854 * FUNCTION: AcpiInstallGpeBlock 855 * 856 * PARAMETERS: GpeDevice - Handle to the parent GPE Block Device 857 * GpeBlockAddress - Address and SpaceID 858 * RegisterCount - Number of GPE register pairs in the block 859 * InterruptNumber - H/W interrupt for the block 860 * 861 * RETURN: Status 862 * 863 * DESCRIPTION: Create and Install a block of GPE registers. The GPEs are not 864 * enabled here. 865 * 866 ******************************************************************************/ 867 868 ACPI_STATUS 869 AcpiInstallGpeBlock ( 870 ACPI_HANDLE GpeDevice, 871 ACPI_GENERIC_ADDRESS *GpeBlockAddress, 872 UINT32 RegisterCount, 873 UINT32 InterruptNumber) 874 { 875 ACPI_STATUS Status; 876 ACPI_OPERAND_OBJECT *ObjDesc; 877 ACPI_NAMESPACE_NODE *Node; 878 ACPI_GPE_BLOCK_INFO *GpeBlock; 879 880 881 ACPI_FUNCTION_TRACE (AcpiInstallGpeBlock); 882 883 884 if ((!GpeDevice) || 885 (!GpeBlockAddress) || 886 (!RegisterCount)) 887 { 888 return_ACPI_STATUS (AE_BAD_PARAMETER); 889 } 890 891 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 892 if (ACPI_FAILURE (Status)) 893 { 894 return_ACPI_STATUS (Status); 895 } 896 897 Node = AcpiNsValidateHandle (GpeDevice); 898 if (!Node) 899 { 900 Status = AE_BAD_PARAMETER; 901 goto UnlockAndExit; 902 } 903 904 /* Validate the parent device */ 905 906 if (Node->Type != ACPI_TYPE_DEVICE) 907 { 908 Status = AE_TYPE; 909 goto UnlockAndExit; 910 } 911 912 if (Node->Object) 913 { 914 Status = AE_ALREADY_EXISTS; 915 goto UnlockAndExit; 916 } 917 918 /* 919 * For user-installed GPE Block Devices, the GpeBlockBaseNumber 920 * is always zero 921 */ 922 Status = AcpiEvCreateGpeBlock (Node, GpeBlockAddress->Address, 923 GpeBlockAddress->SpaceId, RegisterCount, 924 0, InterruptNumber, &GpeBlock); 925 if (ACPI_FAILURE (Status)) 926 { 927 goto UnlockAndExit; 928 } 929 930 /* Install block in the DeviceObject attached to the node */ 931 932 ObjDesc = AcpiNsGetAttachedObject (Node); 933 if (!ObjDesc) 934 { 935 /* 936 * No object, create a new one (Device nodes do not always have 937 * an attached object) 938 */ 939 ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_DEVICE); 940 if (!ObjDesc) 941 { 942 Status = AE_NO_MEMORY; 943 goto UnlockAndExit; 944 } 945 946 Status = AcpiNsAttachObject (Node, ObjDesc, ACPI_TYPE_DEVICE); 947 948 /* Remove local reference to the object */ 949 950 AcpiUtRemoveReference (ObjDesc); 951 if (ACPI_FAILURE (Status)) 952 { 953 goto UnlockAndExit; 954 } 955 } 956 957 /* Now install the GPE block in the DeviceObject */ 958 959 ObjDesc->Device.GpeBlock = GpeBlock; 960 961 962 UnlockAndExit: 963 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 964 return_ACPI_STATUS (Status); 965 } 966 967 ACPI_EXPORT_SYMBOL (AcpiInstallGpeBlock) 968 969 970 /******************************************************************************* 971 * 972 * FUNCTION: AcpiRemoveGpeBlock 973 * 974 * PARAMETERS: GpeDevice - Handle to the parent GPE Block Device 975 * 976 * RETURN: Status 977 * 978 * DESCRIPTION: Remove a previously installed block of GPE registers 979 * 980 ******************************************************************************/ 981 982 ACPI_STATUS 983 AcpiRemoveGpeBlock ( 984 ACPI_HANDLE GpeDevice) 985 { 986 ACPI_OPERAND_OBJECT *ObjDesc; 987 ACPI_STATUS Status; 988 ACPI_NAMESPACE_NODE *Node; 989 990 991 ACPI_FUNCTION_TRACE (AcpiRemoveGpeBlock); 992 993 994 if (!GpeDevice) 995 { 996 return_ACPI_STATUS (AE_BAD_PARAMETER); 997 } 998 999 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 1000 if (ACPI_FAILURE (Status)) 1001 { 1002 return_ACPI_STATUS (Status); 1003 } 1004 1005 Node = AcpiNsValidateHandle (GpeDevice); 1006 if (!Node) 1007 { 1008 Status = AE_BAD_PARAMETER; 1009 goto UnlockAndExit; 1010 } 1011 1012 /* Validate the parent device */ 1013 1014 if (Node->Type != ACPI_TYPE_DEVICE) 1015 { 1016 Status = AE_TYPE; 1017 goto UnlockAndExit; 1018 } 1019 1020 /* Get the DeviceObject attached to the node */ 1021 1022 ObjDesc = AcpiNsGetAttachedObject (Node); 1023 if (!ObjDesc || 1024 !ObjDesc->Device.GpeBlock) 1025 { 1026 return_ACPI_STATUS (AE_NULL_OBJECT); 1027 } 1028 1029 /* Delete the GPE block (but not the DeviceObject) */ 1030 1031 Status = AcpiEvDeleteGpeBlock (ObjDesc->Device.GpeBlock); 1032 if (ACPI_SUCCESS (Status)) 1033 { 1034 ObjDesc->Device.GpeBlock = NULL; 1035 } 1036 1037 UnlockAndExit: 1038 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 1039 return_ACPI_STATUS (Status); 1040 } 1041 1042 ACPI_EXPORT_SYMBOL (AcpiRemoveGpeBlock) 1043 1044 1045 /******************************************************************************* 1046 * 1047 * FUNCTION: AcpiGetGpeDevice 1048 * 1049 * PARAMETERS: Index - System GPE index (0-CurrentGpeCount) 1050 * GpeDevice - Where the parent GPE Device is returned 1051 * 1052 * RETURN: Status 1053 * 1054 * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL 1055 * gpe device indicates that the gpe number is contained in one of 1056 * the FADT-defined gpe blocks. Otherwise, the GPE block device. 1057 * 1058 ******************************************************************************/ 1059 1060 ACPI_STATUS 1061 AcpiGetGpeDevice ( 1062 UINT32 Index, 1063 ACPI_HANDLE *GpeDevice) 1064 { 1065 ACPI_GPE_DEVICE_INFO Info; 1066 ACPI_STATUS Status; 1067 1068 1069 ACPI_FUNCTION_TRACE (AcpiGetGpeDevice); 1070 1071 1072 if (!GpeDevice) 1073 { 1074 return_ACPI_STATUS (AE_BAD_PARAMETER); 1075 } 1076 1077 if (Index >= AcpiCurrentGpeCount) 1078 { 1079 return_ACPI_STATUS (AE_NOT_EXIST); 1080 } 1081 1082 /* Setup and walk the GPE list */ 1083 1084 Info.Index = Index; 1085 Info.Status = AE_NOT_EXIST; 1086 Info.GpeDevice = NULL; 1087 Info.NextBlockBaseIndex = 0; 1088 1089 Status = AcpiEvWalkGpeList (AcpiEvGetGpeDevice, &Info); 1090 if (ACPI_FAILURE (Status)) 1091 { 1092 return_ACPI_STATUS (Status); 1093 } 1094 1095 *GpeDevice = ACPI_CAST_PTR (ACPI_HANDLE, Info.GpeDevice); 1096 return_ACPI_STATUS (Info.Status); 1097 } 1098 1099 ACPI_EXPORT_SYMBOL (AcpiGetGpeDevice) 1100 1101 #endif /* !ACPI_REDUCED_HARDWARE */ 1102