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