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