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