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