evxfgpe.c revision 237412
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 *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 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 338 339 /* Ensure that we have a valid GPE number */ 340 341 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 342 if (!GpeEventInfo) 343 { 344 Status = AE_BAD_PARAMETER; 345 goto UnlockAndExit; 346 } 347 348 /* 349 * If there is no method or handler for this GPE, then the 350 * WakeDevice will be notified whenever this GPE fires. This is 351 * known as an "implicit notify". Note: The GPE is assumed to be 352 * level-triggered (for windows compatibility). 353 */ 354 if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == 355 ACPI_GPE_DISPATCH_NONE) 356 { 357 /* 358 * This is the first device for implicit notify on this GPE. 359 * Just set the flags here, and enter the NOTIFY block below. 360 */ 361 GpeEventInfo->Flags = 362 (ACPI_GPE_DISPATCH_NOTIFY | ACPI_GPE_LEVEL_TRIGGERED); 363 } 364 365 /* 366 * If we already have an implicit notify on this GPE, add 367 * this device to the notify list. 368 */ 369 if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == 370 ACPI_GPE_DISPATCH_NOTIFY) 371 { 372 /* Ensure that the device is not already in the list */ 373 374 Notify = GpeEventInfo->Dispatch.NotifyList; 375 while (Notify) 376 { 377 if (Notify->DeviceNode == DeviceNode) 378 { 379 Status = AE_ALREADY_EXISTS; 380 goto UnlockAndExit; 381 } 382 Notify = Notify->Next; 383 } 384 385 /* Add this device to the notify list for this GPE */ 386 387 Notify = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_NOTIFY_INFO)); 388 if (!Notify) 389 { 390 Status = AE_NO_MEMORY; 391 goto UnlockAndExit; 392 } 393 394 Notify->DeviceNode = DeviceNode; 395 Notify->Next = GpeEventInfo->Dispatch.NotifyList; 396 GpeEventInfo->Dispatch.NotifyList = Notify; 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 return_ACPI_STATUS (Status); 407} 408 409ACPI_EXPORT_SYMBOL (AcpiSetupGpeForWake) 410 411 412/******************************************************************************* 413 * 414 * FUNCTION: AcpiSetGpeWakeMask 415 * 416 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 417 * GpeNumber - GPE level within the GPE block 418 * Action - Enable or Disable 419 * 420 * RETURN: Status 421 * 422 * DESCRIPTION: Set or clear the GPE's wakeup enable mask bit. The GPE must 423 * already be marked as a WAKE GPE. 424 * 425 ******************************************************************************/ 426 427ACPI_STATUS 428AcpiSetGpeWakeMask ( 429 ACPI_HANDLE GpeDevice, 430 UINT32 GpeNumber, 431 UINT8 Action) 432{ 433 ACPI_STATUS Status = AE_OK; 434 ACPI_GPE_EVENT_INFO *GpeEventInfo; 435 ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; 436 ACPI_CPU_FLAGS Flags; 437 UINT32 RegisterBit; 438 439 440 ACPI_FUNCTION_TRACE (AcpiSetGpeWakeMask); 441 442 443 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 444 445 /* 446 * Ensure that we have a valid GPE number and that this GPE is in 447 * fact a wake GPE 448 */ 449 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 450 if (!GpeEventInfo) 451 { 452 Status = AE_BAD_PARAMETER; 453 goto UnlockAndExit; 454 } 455 456 if (!(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE)) 457 { 458 Status = AE_TYPE; 459 goto UnlockAndExit; 460 } 461 462 GpeRegisterInfo = GpeEventInfo->RegisterInfo; 463 if (!GpeRegisterInfo) 464 { 465 Status = AE_NOT_EXIST; 466 goto UnlockAndExit; 467 } 468 469 RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo, GpeRegisterInfo); 470 471 /* Perform the action */ 472 473 switch (Action) 474 { 475 case ACPI_GPE_ENABLE: 476 ACPI_SET_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit); 477 break; 478 479 case ACPI_GPE_DISABLE: 480 ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit); 481 break; 482 483 default: 484 ACPI_ERROR ((AE_INFO, "%u, Invalid action", Action)); 485 Status = AE_BAD_PARAMETER; 486 break; 487 } 488 489UnlockAndExit: 490 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 491 return_ACPI_STATUS (Status); 492} 493 494ACPI_EXPORT_SYMBOL (AcpiSetGpeWakeMask) 495 496 497/******************************************************************************* 498 * 499 * FUNCTION: AcpiClearGpe 500 * 501 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 502 * GpeNumber - GPE level within the GPE block 503 * 504 * RETURN: Status 505 * 506 * DESCRIPTION: Clear an ACPI event (general purpose) 507 * 508 ******************************************************************************/ 509 510ACPI_STATUS 511AcpiClearGpe ( 512 ACPI_HANDLE GpeDevice, 513 UINT32 GpeNumber) 514{ 515 ACPI_STATUS Status = AE_OK; 516 ACPI_GPE_EVENT_INFO *GpeEventInfo; 517 ACPI_CPU_FLAGS Flags; 518 519 520 ACPI_FUNCTION_TRACE (AcpiClearGpe); 521 522 523 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 524 525 /* Ensure that we have a valid GPE number */ 526 527 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 528 if (!GpeEventInfo) 529 { 530 Status = AE_BAD_PARAMETER; 531 goto UnlockAndExit; 532 } 533 534 Status = AcpiHwClearGpe (GpeEventInfo); 535 536UnlockAndExit: 537 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 538 return_ACPI_STATUS (Status); 539} 540 541ACPI_EXPORT_SYMBOL (AcpiClearGpe) 542 543 544/******************************************************************************* 545 * 546 * FUNCTION: AcpiGetGpeStatus 547 * 548 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 549 * GpeNumber - GPE level within the GPE block 550 * EventStatus - Where the current status of the event 551 * will be returned 552 * 553 * RETURN: Status 554 * 555 * DESCRIPTION: Get the current status of a GPE (signalled/not_signalled) 556 * 557 ******************************************************************************/ 558 559ACPI_STATUS 560AcpiGetGpeStatus ( 561 ACPI_HANDLE GpeDevice, 562 UINT32 GpeNumber, 563 ACPI_EVENT_STATUS *EventStatus) 564{ 565 ACPI_STATUS Status = AE_OK; 566 ACPI_GPE_EVENT_INFO *GpeEventInfo; 567 ACPI_CPU_FLAGS Flags; 568 569 570 ACPI_FUNCTION_TRACE (AcpiGetGpeStatus); 571 572 573 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 574 575 /* Ensure that we have a valid GPE number */ 576 577 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 578 if (!GpeEventInfo) 579 { 580 Status = AE_BAD_PARAMETER; 581 goto UnlockAndExit; 582 } 583 584 /* Obtain status on the requested GPE number */ 585 586 Status = AcpiHwGetGpeStatus (GpeEventInfo, EventStatus); 587 588UnlockAndExit: 589 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 590 return_ACPI_STATUS (Status); 591} 592 593ACPI_EXPORT_SYMBOL (AcpiGetGpeStatus) 594 595 596/******************************************************************************* 597 * 598 * FUNCTION: AcpiFinishGpe 599 * 600 * PARAMETERS: GpeDevice - Namespace node for the GPE Block 601 * (NULL for FADT defined GPEs) 602 * GpeNumber - GPE level within the GPE block 603 * 604 * RETURN: Status 605 * 606 * DESCRIPTION: Clear and conditionally reenable a GPE. This completes the GPE 607 * processing. Intended for use by asynchronous host-installed 608 * GPE handlers. The GPE is only reenabled if the EnableForRun bit 609 * is set in the GPE info. 610 * 611 ******************************************************************************/ 612 613ACPI_STATUS 614AcpiFinishGpe ( 615 ACPI_HANDLE GpeDevice, 616 UINT32 GpeNumber) 617{ 618 ACPI_GPE_EVENT_INFO *GpeEventInfo; 619 ACPI_STATUS Status; 620 ACPI_CPU_FLAGS Flags; 621 622 623 ACPI_FUNCTION_TRACE (AcpiFinishGpe); 624 625 626 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 627 628 /* Ensure that we have a valid GPE number */ 629 630 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 631 if (!GpeEventInfo) 632 { 633 Status = AE_BAD_PARAMETER; 634 goto UnlockAndExit; 635 } 636 637 Status = AcpiEvFinishGpe (GpeEventInfo); 638 639UnlockAndExit: 640 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 641 return_ACPI_STATUS (Status); 642} 643 644ACPI_EXPORT_SYMBOL (AcpiFinishGpe) 645 646 647/****************************************************************************** 648 * 649 * FUNCTION: AcpiDisableAllGpes 650 * 651 * PARAMETERS: None 652 * 653 * RETURN: Status 654 * 655 * DESCRIPTION: Disable and clear all GPEs in all GPE blocks 656 * 657 ******************************************************************************/ 658 659ACPI_STATUS 660AcpiDisableAllGpes ( 661 void) 662{ 663 ACPI_STATUS Status; 664 665 666 ACPI_FUNCTION_TRACE (AcpiDisableAllGpes); 667 668 669 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 670 if (ACPI_FAILURE (Status)) 671 { 672 return_ACPI_STATUS (Status); 673 } 674 675 Status = AcpiHwDisableAllGpes (); 676 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 677 678 return_ACPI_STATUS (Status); 679} 680 681ACPI_EXPORT_SYMBOL (AcpiDisableAllGpes) 682 683 684/****************************************************************************** 685 * 686 * FUNCTION: AcpiEnableAllRuntimeGpes 687 * 688 * PARAMETERS: None 689 * 690 * RETURN: Status 691 * 692 * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks 693 * 694 ******************************************************************************/ 695 696ACPI_STATUS 697AcpiEnableAllRuntimeGpes ( 698 void) 699{ 700 ACPI_STATUS Status; 701 702 703 ACPI_FUNCTION_TRACE (AcpiEnableAllRuntimeGpes); 704 705 706 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 707 if (ACPI_FAILURE (Status)) 708 { 709 return_ACPI_STATUS (Status); 710 } 711 712 Status = AcpiHwEnableAllRuntimeGpes (); 713 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 714 715 return_ACPI_STATUS (Status); 716} 717 718ACPI_EXPORT_SYMBOL (AcpiEnableAllRuntimeGpes) 719 720 721/******************************************************************************* 722 * 723 * FUNCTION: AcpiInstallGpeBlock 724 * 725 * PARAMETERS: GpeDevice - Handle to the parent GPE Block Device 726 * GpeBlockAddress - Address and SpaceID 727 * RegisterCount - Number of GPE register pairs in the block 728 * InterruptNumber - H/W interrupt for the block 729 * 730 * RETURN: Status 731 * 732 * DESCRIPTION: Create and Install a block of GPE registers. The GPEs are not 733 * enabled here. 734 * 735 ******************************************************************************/ 736 737ACPI_STATUS 738AcpiInstallGpeBlock ( 739 ACPI_HANDLE GpeDevice, 740 ACPI_GENERIC_ADDRESS *GpeBlockAddress, 741 UINT32 RegisterCount, 742 UINT32 InterruptNumber) 743{ 744 ACPI_STATUS Status; 745 ACPI_OPERAND_OBJECT *ObjDesc; 746 ACPI_NAMESPACE_NODE *Node; 747 ACPI_GPE_BLOCK_INFO *GpeBlock; 748 749 750 ACPI_FUNCTION_TRACE (AcpiInstallGpeBlock); 751 752 753 if ((!GpeDevice) || 754 (!GpeBlockAddress) || 755 (!RegisterCount)) 756 { 757 return_ACPI_STATUS (AE_BAD_PARAMETER); 758 } 759 760 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 761 if (ACPI_FAILURE (Status)) 762 { 763 return (Status); 764 } 765 766 Node = AcpiNsValidateHandle (GpeDevice); 767 if (!Node) 768 { 769 Status = AE_BAD_PARAMETER; 770 goto UnlockAndExit; 771 } 772 773 /* 774 * For user-installed GPE Block Devices, the GpeBlockBaseNumber 775 * is always zero 776 */ 777 Status = AcpiEvCreateGpeBlock (Node, GpeBlockAddress, RegisterCount, 778 0, InterruptNumber, &GpeBlock); 779 if (ACPI_FAILURE (Status)) 780 { 781 goto UnlockAndExit; 782 } 783 784 /* Install block in the DeviceObject attached to the node */ 785 786 ObjDesc = AcpiNsGetAttachedObject (Node); 787 if (!ObjDesc) 788 { 789 /* 790 * No object, create a new one (Device nodes do not always have 791 * an attached object) 792 */ 793 ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_DEVICE); 794 if (!ObjDesc) 795 { 796 Status = AE_NO_MEMORY; 797 goto UnlockAndExit; 798 } 799 800 Status = AcpiNsAttachObject (Node, ObjDesc, ACPI_TYPE_DEVICE); 801 802 /* Remove local reference to the object */ 803 804 AcpiUtRemoveReference (ObjDesc); 805 if (ACPI_FAILURE (Status)) 806 { 807 goto UnlockAndExit; 808 } 809 } 810 811 /* Now install the GPE block in the DeviceObject */ 812 813 ObjDesc->Device.GpeBlock = GpeBlock; 814 815 816UnlockAndExit: 817 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 818 return_ACPI_STATUS (Status); 819} 820 821ACPI_EXPORT_SYMBOL (AcpiInstallGpeBlock) 822 823 824/******************************************************************************* 825 * 826 * FUNCTION: AcpiRemoveGpeBlock 827 * 828 * PARAMETERS: GpeDevice - Handle to the parent GPE Block Device 829 * 830 * RETURN: Status 831 * 832 * DESCRIPTION: Remove a previously installed block of GPE registers 833 * 834 ******************************************************************************/ 835 836ACPI_STATUS 837AcpiRemoveGpeBlock ( 838 ACPI_HANDLE GpeDevice) 839{ 840 ACPI_OPERAND_OBJECT *ObjDesc; 841 ACPI_STATUS Status; 842 ACPI_NAMESPACE_NODE *Node; 843 844 845 ACPI_FUNCTION_TRACE (AcpiRemoveGpeBlock); 846 847 848 if (!GpeDevice) 849 { 850 return_ACPI_STATUS (AE_BAD_PARAMETER); 851 } 852 853 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 854 if (ACPI_FAILURE (Status)) 855 { 856 return (Status); 857 } 858 859 Node = AcpiNsValidateHandle (GpeDevice); 860 if (!Node) 861 { 862 Status = AE_BAD_PARAMETER; 863 goto UnlockAndExit; 864 } 865 866 /* Get the DeviceObject attached to the node */ 867 868 ObjDesc = AcpiNsGetAttachedObject (Node); 869 if (!ObjDesc || 870 !ObjDesc->Device.GpeBlock) 871 { 872 return_ACPI_STATUS (AE_NULL_OBJECT); 873 } 874 875 /* Delete the GPE block (but not the DeviceObject) */ 876 877 Status = AcpiEvDeleteGpeBlock (ObjDesc->Device.GpeBlock); 878 if (ACPI_SUCCESS (Status)) 879 { 880 ObjDesc->Device.GpeBlock = NULL; 881 } 882 883UnlockAndExit: 884 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 885 return_ACPI_STATUS (Status); 886} 887 888ACPI_EXPORT_SYMBOL (AcpiRemoveGpeBlock) 889 890 891/******************************************************************************* 892 * 893 * FUNCTION: AcpiGetGpeDevice 894 * 895 * PARAMETERS: Index - System GPE index (0-CurrentGpeCount) 896 * GpeDevice - Where the parent GPE Device is returned 897 * 898 * RETURN: Status 899 * 900 * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL 901 * gpe device indicates that the gpe number is contained in one of 902 * the FADT-defined gpe blocks. Otherwise, the GPE block device. 903 * 904 ******************************************************************************/ 905 906ACPI_STATUS 907AcpiGetGpeDevice ( 908 UINT32 Index, 909 ACPI_HANDLE *GpeDevice) 910{ 911 ACPI_GPE_DEVICE_INFO Info; 912 ACPI_STATUS Status; 913 914 915 ACPI_FUNCTION_TRACE (AcpiGetGpeDevice); 916 917 918 if (!GpeDevice) 919 { 920 return_ACPI_STATUS (AE_BAD_PARAMETER); 921 } 922 923 if (Index >= AcpiCurrentGpeCount) 924 { 925 return_ACPI_STATUS (AE_NOT_EXIST); 926 } 927 928 /* Setup and walk the GPE list */ 929 930 Info.Index = Index; 931 Info.Status = AE_NOT_EXIST; 932 Info.GpeDevice = NULL; 933 Info.NextBlockBaseIndex = 0; 934 935 Status = AcpiEvWalkGpeList (AcpiEvGetGpeDevice, &Info); 936 if (ACPI_FAILURE (Status)) 937 { 938 return_ACPI_STATUS (Status); 939 } 940 941 *GpeDevice = ACPI_CAST_PTR (ACPI_HANDLE, Info.GpeDevice); 942 return_ACPI_STATUS (Info.Status); 943} 944 945ACPI_EXPORT_SYMBOL (AcpiGetGpeDevice) 946 947#endif /* !ACPI_REDUCED_HARDWARE */ 948