1 /****************************************************************************** 2 * 3 * Module Name: evxfgpe - External Interfaces for General Purpose Events (GPEs) 4 * 5 *****************************************************************************/ 6 7 /****************************************************************************** 8 * 9 * 1. Copyright Notice 10 * 11 * Some or all of this work - Copyright (c) 1999 - 2018, Intel Corp. 12 * All rights reserved. 13 * 14 * 2. License 15 * 16 * 2.1. This is your license from Intel Corp. under its intellectual property 17 * rights. You may have additional license terms from the party that provided 18 * you this software, covering your right to use that party's intellectual 19 * property rights. 20 * 21 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 22 * copy of the source code appearing in this file ("Covered Code") an 23 * irrevocable, perpetual, worldwide license under Intel's copyrights in the 24 * base code distributed originally by Intel ("Original Intel Code") to copy, 25 * make derivatives, distribute, use and display any portion of the Covered 26 * Code in any form, with the right to sublicense such rights; and 27 * 28 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 29 * license (with the right to sublicense), under only those claims of Intel 30 * patents that are infringed by the Original Intel Code, to make, use, sell, 31 * offer to sell, and import the Covered Code and derivative works thereof 32 * solely to the minimum extent necessary to exercise the above copyright 33 * license, and in no event shall the patent license extend to any additions 34 * to or modifications of the Original Intel Code. No other license or right 35 * is granted directly or by implication, estoppel or otherwise; 36 * 37 * The above copyright and patent license is granted only if the following 38 * conditions are met: 39 * 40 * 3. Conditions 41 * 42 * 3.1. Redistribution of Source with Rights to Further Distribute Source. 43 * Redistribution of source code of any substantial portion of the Covered 44 * Code or modification with rights to further distribute source must include 45 * the above Copyright Notice, the above License, this list of Conditions, 46 * and the following Disclaimer and Export Compliance provision. In addition, 47 * Licensee must cause all Covered Code to which Licensee contributes to 48 * contain a file documenting the changes Licensee made to create that Covered 49 * Code and the date of any change. Licensee must include in that file the 50 * documentation of any changes made by any predecessor Licensee. Licensee 51 * must include a prominent statement that the modification is derived, 52 * directly or indirectly, from Original Intel Code. 53 * 54 * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 55 * Redistribution of source code of any substantial portion of the Covered 56 * Code or modification without rights to further distribute source must 57 * include the following Disclaimer and Export Compliance provision in the 58 * documentation and/or other materials provided with distribution. In 59 * addition, Licensee may not authorize further sublicense of source of any 60 * portion of the Covered Code, and must include terms to the effect that the 61 * license from Licensee to its licensee is limited to the intellectual 62 * property embodied in the software Licensee provides to its licensee, and 63 * not to intellectual property embodied in modifications its licensee may 64 * make. 65 * 66 * 3.3. Redistribution of Executable. Redistribution in executable form of any 67 * substantial portion of the Covered Code or modification must reproduce the 68 * above Copyright Notice, and the following Disclaimer and Export Compliance 69 * provision in the documentation and/or other materials provided with the 70 * distribution. 71 * 72 * 3.4. Intel retains all right, title, and interest in and to the Original 73 * Intel Code. 74 * 75 * 3.5. Neither the name Intel nor any other trademark owned or controlled by 76 * Intel shall be used in advertising or otherwise to promote the sale, use or 77 * other dealings in products derived from or relating to the Covered Code 78 * without prior written authorization from Intel. 79 * 80 * 4. Disclaimer and Export Compliance 81 * 82 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 83 * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 84 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 85 * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 86 * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 87 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 88 * PARTICULAR PURPOSE. 89 * 90 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 91 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 92 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 93 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 94 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 95 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 96 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 97 * LIMITED REMEDY. 98 * 99 * 4.3. Licensee shall not export, either directly or indirectly, any of this 100 * software or system incorporating such software without first obtaining any 101 * required license or other approval from the U. S. Department of Commerce or 102 * any other agency or department of the United States Government. In the 103 * event Licensee exports any such software from the United States or 104 * re-exports any such software from a foreign destination, Licensee shall 105 * ensure that the distribution and export/re-export of the software is in 106 * compliance with all laws, regulations, orders, or other restrictions of the 107 * U.S. Export Administration Regulations. Licensee agrees that neither it nor 108 * any of its subsidiaries will export/re-export any technical data, process, 109 * software, or service, directly or indirectly, to any country for which the 110 * United States government or any agency thereof requires an export license, 111 * other governmental approval, or letter of assurance, without first obtaining 112 * such license, approval or letter. 113 * 114 ***************************************************************************** 115 * 116 * Alternatively, you may choose to be licensed under the terms of the 117 * following license: 118 * 119 * Redistribution and use in source and binary forms, with or without 120 * modification, are permitted provided that the following conditions 121 * are met: 122 * 1. Redistributions of source code must retain the above copyright 123 * notice, this list of conditions, and the following disclaimer, 124 * without modification. 125 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 126 * substantially similar to the "NO WARRANTY" disclaimer below 127 * ("Disclaimer") and any redistribution must be conditioned upon 128 * including a substantially similar Disclaimer requirement for further 129 * binary redistribution. 130 * 3. Neither the names of the above-listed copyright holders nor the names 131 * of any contributors may be used to endorse or promote products derived 132 * from this software without specific prior written permission. 133 * 134 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 135 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 136 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 137 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 138 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 139 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 140 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 141 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 142 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 143 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 144 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 145 * 146 * Alternatively, you may choose to be licensed under the terms of the 147 * GNU General Public License ("GPL") version 2 as published by the Free 148 * Software Foundation. 149 * 150 *****************************************************************************/ 151 152 #define EXPORT_ACPI_INTERFACES 153 154 #include "acpi.h" 155 #include "accommon.h" 156 #include "acevents.h" 157 #include "acnamesp.h" 158 159 #define _COMPONENT ACPI_EVENTS 160 ACPI_MODULE_NAME ("evxfgpe") 161 162 163 #if (!ACPI_REDUCED_HARDWARE) /* Entire module */ 164 /******************************************************************************* 165 * 166 * FUNCTION: AcpiUpdateAllGpes 167 * 168 * PARAMETERS: None 169 * 170 * RETURN: Status 171 * 172 * DESCRIPTION: Complete GPE initialization and enable all GPEs that have 173 * associated _Lxx or _Exx methods and are not pointed to by any 174 * device _PRW methods (this indicates that these GPEs are 175 * generally intended for system or device wakeup. Such GPEs 176 * have to be enabled directly when the devices whose _PRW 177 * methods point to them are set up for wakeup signaling.) 178 * 179 * NOTE: Should be called after any GPEs are added to the system. Primarily, 180 * after the system _PRW methods have been run, but also after a GPE Block 181 * Device has been added or if any new GPE methods have been added via a 182 * dynamic table load. 183 * 184 ******************************************************************************/ 185 186 ACPI_STATUS 187 AcpiUpdateAllGpes ( 188 void) 189 { 190 ACPI_STATUS Status; 191 BOOLEAN IsPollingNeeded = FALSE; 192 193 194 ACPI_FUNCTION_TRACE (AcpiUpdateAllGpes); 195 196 197 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 198 if (ACPI_FAILURE (Status)) 199 { 200 return_ACPI_STATUS (Status); 201 } 202 203 if (AcpiGbl_AllGpesInitialized) 204 { 205 goto UnlockAndExit; 206 } 207 208 Status = AcpiEvWalkGpeList (AcpiEvInitializeGpeBlock, 209 &IsPollingNeeded); 210 if (ACPI_SUCCESS (Status)) 211 { 212 AcpiGbl_AllGpesInitialized = TRUE; 213 } 214 215 UnlockAndExit: 216 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 217 218 if (IsPollingNeeded && AcpiGbl_AllGpesInitialized) 219 { 220 /* Poll GPEs to handle already triggered events */ 221 222 AcpiEvGpeDetect (AcpiGbl_GpeXruptListHead); 223 } 224 return_ACPI_STATUS (Status); 225 } 226 227 ACPI_EXPORT_SYMBOL (AcpiUpdateAllGpes) 228 229 230 /******************************************************************************* 231 * 232 * FUNCTION: AcpiEnableGpe 233 * 234 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 235 * GpeNumber - GPE level within the GPE block 236 * 237 * RETURN: Status 238 * 239 * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is 240 * hardware-enabled. 241 * 242 ******************************************************************************/ 243 244 ACPI_STATUS 245 AcpiEnableGpe ( 246 ACPI_HANDLE GpeDevice, 247 UINT32 GpeNumber) 248 { 249 ACPI_STATUS Status = AE_BAD_PARAMETER; 250 ACPI_GPE_EVENT_INFO *GpeEventInfo; 251 ACPI_CPU_FLAGS Flags; 252 253 254 ACPI_FUNCTION_TRACE (AcpiEnableGpe); 255 256 257 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 258 259 /* 260 * Ensure that we have a valid GPE number and that there is some way 261 * of handling the GPE (handler or a GPE method). In other words, we 262 * won't allow a valid GPE to be enabled if there is no way to handle it. 263 */ 264 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 265 if (GpeEventInfo) 266 { 267 if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) != 268 ACPI_GPE_DISPATCH_NONE) 269 { 270 Status = AcpiEvAddGpeReference (GpeEventInfo); 271 if (ACPI_SUCCESS (Status) && 272 ACPI_GPE_IS_POLLING_NEEDED (GpeEventInfo)) 273 { 274 /* Poll edge-triggered GPEs to handle existing events */ 275 276 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 277 (void) AcpiEvDetectGpe ( 278 GpeDevice, GpeEventInfo, GpeNumber); 279 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 280 } 281 } 282 else 283 { 284 Status = AE_NO_HANDLER; 285 } 286 } 287 288 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 289 return_ACPI_STATUS (Status); 290 } 291 292 ACPI_EXPORT_SYMBOL (AcpiEnableGpe) 293 294 295 /******************************************************************************* 296 * 297 * FUNCTION: AcpiDisableGpe 298 * 299 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 300 * GpeNumber - GPE level within the GPE block 301 * 302 * RETURN: Status 303 * 304 * DESCRIPTION: Remove a reference to a GPE. When the last reference is 305 * removed, only then is the GPE disabled (for runtime GPEs), or 306 * the GPE mask bit disabled (for wake GPEs) 307 * 308 ******************************************************************************/ 309 310 ACPI_STATUS 311 AcpiDisableGpe ( 312 ACPI_HANDLE GpeDevice, 313 UINT32 GpeNumber) 314 { 315 ACPI_STATUS Status = AE_BAD_PARAMETER; 316 ACPI_GPE_EVENT_INFO *GpeEventInfo; 317 ACPI_CPU_FLAGS Flags; 318 319 320 ACPI_FUNCTION_TRACE (AcpiDisableGpe); 321 322 323 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 324 325 /* Ensure that we have a valid GPE number */ 326 327 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 328 if (GpeEventInfo) 329 { 330 Status = AcpiEvRemoveGpeReference (GpeEventInfo); 331 } 332 333 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 334 return_ACPI_STATUS (Status); 335 } 336 337 ACPI_EXPORT_SYMBOL (AcpiDisableGpe) 338 339 340 /******************************************************************************* 341 * 342 * FUNCTION: AcpiSetGpe 343 * 344 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 345 * GpeNumber - GPE level within the GPE block 346 * Action - ACPI_GPE_ENABLE or ACPI_GPE_DISABLE 347 * 348 * RETURN: Status 349 * 350 * DESCRIPTION: Enable or disable an individual GPE. This function bypasses 351 * the reference count mechanism used in the AcpiEnableGpe(), 352 * AcpiDisableGpe() interfaces. 353 * This API is typically used by the GPE raw handler mode driver 354 * to switch between the polling mode and the interrupt mode after 355 * the driver has enabled the GPE. 356 * The APIs should be invoked in this order: 357 * AcpiEnableGpe() <- Ensure the reference count > 0 358 * AcpiSetGpe(ACPI_GPE_DISABLE) <- Enter polling mode 359 * AcpiSetGpe(ACPI_GPE_ENABLE) <- Leave polling mode 360 * AcpiDisableGpe() <- Decrease the reference count 361 * 362 * Note: If a GPE is shared by 2 silicon components, then both the drivers 363 * should support GPE polling mode or disabling the GPE for long period 364 * for one driver may break the other. So use it with care since all 365 * firmware _Lxx/_Exx handlers currently rely on the GPE interrupt mode. 366 * 367 ******************************************************************************/ 368 369 ACPI_STATUS 370 AcpiSetGpe ( 371 ACPI_HANDLE GpeDevice, 372 UINT32 GpeNumber, 373 UINT8 Action) 374 { 375 ACPI_GPE_EVENT_INFO *GpeEventInfo; 376 ACPI_STATUS Status; 377 ACPI_CPU_FLAGS Flags; 378 379 380 ACPI_FUNCTION_TRACE (AcpiSetGpe); 381 382 383 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 384 385 /* Ensure that we have a valid GPE number */ 386 387 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 388 if (!GpeEventInfo) 389 { 390 Status = AE_BAD_PARAMETER; 391 goto UnlockAndExit; 392 } 393 394 /* Perform the action */ 395 396 switch (Action) 397 { 398 case ACPI_GPE_ENABLE: 399 400 Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_ENABLE); 401 GpeEventInfo->DisableForDispatch = FALSE; 402 break; 403 404 case ACPI_GPE_DISABLE: 405 406 Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE); 407 GpeEventInfo->DisableForDispatch = TRUE; 408 break; 409 410 default: 411 412 Status = AE_BAD_PARAMETER; 413 break; 414 } 415 416 UnlockAndExit: 417 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 418 return_ACPI_STATUS (Status); 419 } 420 421 ACPI_EXPORT_SYMBOL (AcpiSetGpe) 422 423 424 /******************************************************************************* 425 * 426 * FUNCTION: AcpiMaskGpe 427 * 428 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 429 * GpeNumber - GPE level within the GPE block 430 * IsMasked - Whether the GPE is masked or not 431 * 432 * RETURN: Status 433 * 434 * DESCRIPTION: Unconditionally mask/unmask the an individual GPE, ex., to 435 * prevent a GPE flooding. 436 * 437 ******************************************************************************/ 438 439 ACPI_STATUS 440 AcpiMaskGpe ( 441 ACPI_HANDLE GpeDevice, 442 UINT32 GpeNumber, 443 BOOLEAN IsMasked) 444 { 445 ACPI_GPE_EVENT_INFO *GpeEventInfo; 446 ACPI_STATUS Status; 447 ACPI_CPU_FLAGS Flags; 448 449 450 ACPI_FUNCTION_TRACE (AcpiMaskGpe); 451 452 453 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 454 455 /* Ensure that we have a valid GPE number */ 456 457 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 458 if (!GpeEventInfo) 459 { 460 Status = AE_BAD_PARAMETER; 461 goto UnlockAndExit; 462 } 463 464 Status = AcpiEvMaskGpe (GpeEventInfo, IsMasked); 465 466 UnlockAndExit: 467 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 468 return_ACPI_STATUS (Status); 469 } 470 471 ACPI_EXPORT_SYMBOL (AcpiMaskGpe) 472 473 474 /******************************************************************************* 475 * 476 * FUNCTION: AcpiMarkGpeForWake 477 * 478 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 479 * GpeNumber - GPE level within the GPE block 480 * 481 * RETURN: Status 482 * 483 * DESCRIPTION: Mark a GPE as having the ability to wake the system. Simply 484 * sets the ACPI_GPE_CAN_WAKE flag. 485 * 486 * Some potential callers of AcpiSetupGpeForWake may know in advance that 487 * there won't be any notify handlers installed for device wake notifications 488 * from the given GPE (one example is a button GPE in Linux). For these cases, 489 * AcpiMarkGpeForWake should be used instead of AcpiSetupGpeForWake. 490 * This will set the ACPI_GPE_CAN_WAKE flag for the GPE without trying to 491 * setup implicit wake notification for it (since there's no handler method). 492 * 493 ******************************************************************************/ 494 495 ACPI_STATUS 496 AcpiMarkGpeForWake ( 497 ACPI_HANDLE GpeDevice, 498 UINT32 GpeNumber) 499 { 500 ACPI_GPE_EVENT_INFO *GpeEventInfo; 501 ACPI_STATUS Status = AE_BAD_PARAMETER; 502 ACPI_CPU_FLAGS Flags; 503 504 505 ACPI_FUNCTION_TRACE (AcpiMarkGpeForWake); 506 507 508 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 509 510 /* Ensure that we have a valid GPE number */ 511 512 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 513 if (GpeEventInfo) 514 { 515 /* Mark the GPE as a possible wake event */ 516 517 GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE; 518 Status = AE_OK; 519 } 520 521 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 522 return_ACPI_STATUS (Status); 523 } 524 525 ACPI_EXPORT_SYMBOL (AcpiMarkGpeForWake) 526 527 528 /******************************************************************************* 529 * 530 * FUNCTION: AcpiSetupGpeForWake 531 * 532 * PARAMETERS: WakeDevice - Device associated with the GPE (via _PRW) 533 * GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 534 * GpeNumber - GPE level within the GPE block 535 * 536 * RETURN: Status 537 * 538 * DESCRIPTION: Mark a GPE as having the ability to wake the system. This 539 * interface is intended to be used as the host executes the 540 * _PRW methods (Power Resources for Wake) in the system tables. 541 * Each _PRW appears under a Device Object (The WakeDevice), and 542 * contains the info for the wake GPE associated with the 543 * WakeDevice. 544 * 545 ******************************************************************************/ 546 547 ACPI_STATUS 548 AcpiSetupGpeForWake ( 549 ACPI_HANDLE WakeDevice, 550 ACPI_HANDLE GpeDevice, 551 UINT32 GpeNumber) 552 { 553 ACPI_STATUS Status; 554 ACPI_GPE_EVENT_INFO *GpeEventInfo; 555 ACPI_NAMESPACE_NODE *DeviceNode; 556 ACPI_GPE_NOTIFY_INFO *Notify; 557 ACPI_GPE_NOTIFY_INFO *NewNotify; 558 ACPI_CPU_FLAGS Flags; 559 560 561 ACPI_FUNCTION_TRACE (AcpiSetupGpeForWake); 562 563 564 /* Parameter Validation */ 565 566 if (!WakeDevice) 567 { 568 /* 569 * By forcing WakeDevice to be valid, we automatically enable the 570 * implicit notify feature on all hosts. 571 */ 572 return_ACPI_STATUS (AE_BAD_PARAMETER); 573 } 574 575 /* Handle root object case */ 576 577 if (WakeDevice == ACPI_ROOT_OBJECT) 578 { 579 DeviceNode = AcpiGbl_RootNode; 580 } 581 else 582 { 583 DeviceNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, WakeDevice); 584 } 585 586 /* Validate WakeDevice is of type Device */ 587 588 if (DeviceNode->Type != ACPI_TYPE_DEVICE) 589 { 590 return_ACPI_STATUS (AE_BAD_PARAMETER); 591 } 592 593 /* 594 * Allocate a new notify object up front, in case it is needed. 595 * Memory allocation while holding a spinlock is a big no-no 596 * on some hosts. 597 */ 598 NewNotify = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_NOTIFY_INFO)); 599 if (!NewNotify) 600 { 601 return_ACPI_STATUS (AE_NO_MEMORY); 602 } 603 604 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 605 606 /* Ensure that we have a valid GPE number */ 607 608 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 609 if (!GpeEventInfo) 610 { 611 Status = AE_BAD_PARAMETER; 612 goto UnlockAndExit; 613 } 614 615 /* 616 * If there is no method or handler for this GPE, then the 617 * WakeDevice will be notified whenever this GPE fires. This is 618 * known as an "implicit notify". Note: The GPE is assumed to be 619 * level-triggered (for windows compatibility). 620 */ 621 if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) == 622 ACPI_GPE_DISPATCH_NONE) 623 { 624 /* 625 * This is the first device for implicit notify on this GPE. 626 * Just set the flags here, and enter the NOTIFY block below. 627 */ 628 GpeEventInfo->Flags = 629 (ACPI_GPE_DISPATCH_NOTIFY | ACPI_GPE_LEVEL_TRIGGERED); 630 } 631 else if (GpeEventInfo->Flags & ACPI_GPE_AUTO_ENABLED) 632 { 633 /* 634 * A reference to this GPE has been added during the GPE block 635 * initialization, so drop it now to prevent the GPE from being 636 * permanently enabled and clear its ACPI_GPE_AUTO_ENABLED flag. 637 */ 638 (void) AcpiEvRemoveGpeReference (GpeEventInfo); 639 GpeEventInfo->Flags &= ~~ACPI_GPE_AUTO_ENABLED; 640 } 641 642 /* 643 * If we already have an implicit notify on this GPE, add 644 * this device to the notify list. 645 */ 646 if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) == 647 ACPI_GPE_DISPATCH_NOTIFY) 648 { 649 /* Ensure that the device is not already in the list */ 650 651 Notify = GpeEventInfo->Dispatch.NotifyList; 652 while (Notify) 653 { 654 if (Notify->DeviceNode == DeviceNode) 655 { 656 Status = AE_ALREADY_EXISTS; 657 goto UnlockAndExit; 658 } 659 Notify = Notify->Next; 660 } 661 662 /* Add this device to the notify list for this GPE */ 663 664 NewNotify->DeviceNode = DeviceNode; 665 NewNotify->Next = GpeEventInfo->Dispatch.NotifyList; 666 GpeEventInfo->Dispatch.NotifyList = NewNotify; 667 NewNotify = NULL; 668 } 669 670 /* Mark the GPE as a possible wake event */ 671 672 GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE; 673 Status = AE_OK; 674 675 676 UnlockAndExit: 677 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 678 679 /* Delete the notify object if it was not used above */ 680 681 if (NewNotify) 682 { 683 ACPI_FREE (NewNotify); 684 } 685 return_ACPI_STATUS (Status); 686 } 687 688 ACPI_EXPORT_SYMBOL (AcpiSetupGpeForWake) 689 690 691 /******************************************************************************* 692 * 693 * FUNCTION: AcpiSetGpeWakeMask 694 * 695 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 696 * GpeNumber - GPE level within the GPE block 697 * Action - Enable or Disable 698 * 699 * RETURN: Status 700 * 701 * DESCRIPTION: Set or clear the GPE's wakeup enable mask bit. The GPE must 702 * already be marked as a WAKE GPE. 703 * 704 ******************************************************************************/ 705 706 ACPI_STATUS 707 AcpiSetGpeWakeMask ( 708 ACPI_HANDLE GpeDevice, 709 UINT32 GpeNumber, 710 UINT8 Action) 711 { 712 ACPI_STATUS Status = AE_OK; 713 ACPI_GPE_EVENT_INFO *GpeEventInfo; 714 ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; 715 ACPI_CPU_FLAGS Flags; 716 UINT32 RegisterBit; 717 718 719 ACPI_FUNCTION_TRACE (AcpiSetGpeWakeMask); 720 721 722 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 723 724 /* 725 * Ensure that we have a valid GPE number and that this GPE is in 726 * fact a wake GPE 727 */ 728 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 729 if (!GpeEventInfo) 730 { 731 Status = AE_BAD_PARAMETER; 732 goto UnlockAndExit; 733 } 734 735 if (!(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE)) 736 { 737 Status = AE_TYPE; 738 goto UnlockAndExit; 739 } 740 741 GpeRegisterInfo = GpeEventInfo->RegisterInfo; 742 if (!GpeRegisterInfo) 743 { 744 Status = AE_NOT_EXIST; 745 goto UnlockAndExit; 746 } 747 748 RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo); 749 750 /* Perform the action */ 751 752 switch (Action) 753 { 754 case ACPI_GPE_ENABLE: 755 756 ACPI_SET_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit); 757 break; 758 759 case ACPI_GPE_DISABLE: 760 761 ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit); 762 break; 763 764 default: 765 766 ACPI_ERROR ((AE_INFO, "%u, Invalid action", Action)); 767 Status = AE_BAD_PARAMETER; 768 break; 769 } 770 771 UnlockAndExit: 772 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 773 return_ACPI_STATUS (Status); 774 } 775 776 ACPI_EXPORT_SYMBOL (AcpiSetGpeWakeMask) 777 778 779 /******************************************************************************* 780 * 781 * FUNCTION: AcpiClearGpe 782 * 783 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 784 * GpeNumber - GPE level within the GPE block 785 * 786 * RETURN: Status 787 * 788 * DESCRIPTION: Clear an ACPI event (general purpose) 789 * 790 ******************************************************************************/ 791 792 ACPI_STATUS 793 AcpiClearGpe ( 794 ACPI_HANDLE GpeDevice, 795 UINT32 GpeNumber) 796 { 797 ACPI_STATUS Status = AE_OK; 798 ACPI_GPE_EVENT_INFO *GpeEventInfo; 799 ACPI_CPU_FLAGS Flags; 800 801 802 ACPI_FUNCTION_TRACE (AcpiClearGpe); 803 804 805 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 806 807 /* Ensure that we have a valid GPE number */ 808 809 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 810 if (!GpeEventInfo) 811 { 812 Status = AE_BAD_PARAMETER; 813 goto UnlockAndExit; 814 } 815 816 Status = AcpiHwClearGpe (GpeEventInfo); 817 818 UnlockAndExit: 819 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 820 return_ACPI_STATUS (Status); 821 } 822 823 ACPI_EXPORT_SYMBOL (AcpiClearGpe) 824 825 826 /******************************************************************************* 827 * 828 * FUNCTION: AcpiGetGpeStatus 829 * 830 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 831 * GpeNumber - GPE level within the GPE block 832 * EventStatus - Where the current status of the event 833 * will be returned 834 * 835 * RETURN: Status 836 * 837 * DESCRIPTION: Get the current status of a GPE (signalled/not_signalled) 838 * 839 ******************************************************************************/ 840 841 ACPI_STATUS 842 AcpiGetGpeStatus ( 843 ACPI_HANDLE GpeDevice, 844 UINT32 GpeNumber, 845 ACPI_EVENT_STATUS *EventStatus) 846 { 847 ACPI_STATUS Status = AE_OK; 848 ACPI_GPE_EVENT_INFO *GpeEventInfo; 849 ACPI_CPU_FLAGS Flags; 850 851 852 ACPI_FUNCTION_TRACE (AcpiGetGpeStatus); 853 854 855 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 856 857 /* Ensure that we have a valid GPE number */ 858 859 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 860 if (!GpeEventInfo) 861 { 862 Status = AE_BAD_PARAMETER; 863 goto UnlockAndExit; 864 } 865 866 /* Obtain status on the requested GPE number */ 867 868 Status = AcpiHwGetGpeStatus (GpeEventInfo, EventStatus); 869 870 UnlockAndExit: 871 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 872 return_ACPI_STATUS (Status); 873 } 874 875 ACPI_EXPORT_SYMBOL (AcpiGetGpeStatus) 876 877 878 /******************************************************************************* 879 * 880 * FUNCTION: AcpiFinishGpe 881 * 882 * PARAMETERS: GpeDevice - Namespace node for the GPE Block 883 * (NULL for FADT defined GPEs) 884 * GpeNumber - GPE level within the GPE block 885 * 886 * RETURN: Status 887 * 888 * DESCRIPTION: Clear and conditionally reenable a GPE. This completes the GPE 889 * processing. Intended for use by asynchronous host-installed 890 * GPE handlers. The GPE is only reenabled if the EnableForRun bit 891 * is set in the GPE info. 892 * 893 ******************************************************************************/ 894 895 ACPI_STATUS 896 AcpiFinishGpe ( 897 ACPI_HANDLE GpeDevice, 898 UINT32 GpeNumber) 899 { 900 ACPI_GPE_EVENT_INFO *GpeEventInfo; 901 ACPI_STATUS Status; 902 ACPI_CPU_FLAGS Flags; 903 904 905 ACPI_FUNCTION_TRACE (AcpiFinishGpe); 906 907 908 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 909 910 /* Ensure that we have a valid GPE number */ 911 912 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 913 if (!GpeEventInfo) 914 { 915 Status = AE_BAD_PARAMETER; 916 goto UnlockAndExit; 917 } 918 919 Status = AcpiEvFinishGpe (GpeEventInfo); 920 921 UnlockAndExit: 922 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 923 return_ACPI_STATUS (Status); 924 } 925 926 ACPI_EXPORT_SYMBOL (AcpiFinishGpe) 927 928 929 /****************************************************************************** 930 * 931 * FUNCTION: AcpiDisableAllGpes 932 * 933 * PARAMETERS: None 934 * 935 * RETURN: Status 936 * 937 * DESCRIPTION: Disable and clear all GPEs in all GPE blocks 938 * 939 ******************************************************************************/ 940 941 ACPI_STATUS 942 AcpiDisableAllGpes ( 943 void) 944 { 945 ACPI_STATUS Status; 946 947 948 ACPI_FUNCTION_TRACE (AcpiDisableAllGpes); 949 950 951 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 952 if (ACPI_FAILURE (Status)) 953 { 954 return_ACPI_STATUS (Status); 955 } 956 957 Status = AcpiHwDisableAllGpes (); 958 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 959 960 return_ACPI_STATUS (Status); 961 } 962 963 ACPI_EXPORT_SYMBOL (AcpiDisableAllGpes) 964 965 966 /****************************************************************************** 967 * 968 * FUNCTION: AcpiEnableAllRuntimeGpes 969 * 970 * PARAMETERS: None 971 * 972 * RETURN: Status 973 * 974 * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks 975 * 976 ******************************************************************************/ 977 978 ACPI_STATUS 979 AcpiEnableAllRuntimeGpes ( 980 void) 981 { 982 ACPI_STATUS Status; 983 984 985 ACPI_FUNCTION_TRACE (AcpiEnableAllRuntimeGpes); 986 987 988 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 989 if (ACPI_FAILURE (Status)) 990 { 991 return_ACPI_STATUS (Status); 992 } 993 994 Status = AcpiHwEnableAllRuntimeGpes (); 995 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 996 997 return_ACPI_STATUS (Status); 998 } 999 1000 ACPI_EXPORT_SYMBOL (AcpiEnableAllRuntimeGpes) 1001 1002 1003 /****************************************************************************** 1004 * 1005 * FUNCTION: AcpiEnableAllWakeupGpes 1006 * 1007 * PARAMETERS: None 1008 * 1009 * RETURN: Status 1010 * 1011 * DESCRIPTION: Enable all "wakeup" GPEs and disable all of the other GPEs, in 1012 * all GPE blocks. 1013 * 1014 ******************************************************************************/ 1015 1016 ACPI_STATUS 1017 AcpiEnableAllWakeupGpes ( 1018 void) 1019 { 1020 ACPI_STATUS Status; 1021 1022 1023 ACPI_FUNCTION_TRACE (AcpiEnableAllWakeupGpes); 1024 1025 1026 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 1027 if (ACPI_FAILURE (Status)) 1028 { 1029 return_ACPI_STATUS (Status); 1030 } 1031 1032 Status = AcpiHwEnableAllWakeupGpes (); 1033 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 1034 1035 return_ACPI_STATUS (Status); 1036 } 1037 1038 ACPI_EXPORT_SYMBOL (AcpiEnableAllWakeupGpes) 1039 1040 1041 /******************************************************************************* 1042 * 1043 * FUNCTION: AcpiInstallGpeBlock 1044 * 1045 * PARAMETERS: GpeDevice - Handle to the parent GPE Block Device 1046 * GpeBlockAddress - Address and SpaceID 1047 * RegisterCount - Number of GPE register pairs in the block 1048 * InterruptNumber - H/W interrupt for the block 1049 * 1050 * RETURN: Status 1051 * 1052 * DESCRIPTION: Create and Install a block of GPE registers. The GPEs are not 1053 * enabled here. 1054 * 1055 ******************************************************************************/ 1056 1057 ACPI_STATUS 1058 AcpiInstallGpeBlock ( 1059 ACPI_HANDLE GpeDevice, 1060 ACPI_GENERIC_ADDRESS *GpeBlockAddress, 1061 UINT32 RegisterCount, 1062 UINT32 InterruptNumber) 1063 { 1064 ACPI_STATUS Status; 1065 ACPI_OPERAND_OBJECT *ObjDesc; 1066 ACPI_NAMESPACE_NODE *Node; 1067 ACPI_GPE_BLOCK_INFO *GpeBlock; 1068 1069 1070 ACPI_FUNCTION_TRACE (AcpiInstallGpeBlock); 1071 1072 1073 if ((!GpeDevice) || 1074 (!GpeBlockAddress) || 1075 (!RegisterCount)) 1076 { 1077 return_ACPI_STATUS (AE_BAD_PARAMETER); 1078 } 1079 1080 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 1081 if (ACPI_FAILURE (Status)) 1082 { 1083 return_ACPI_STATUS (Status); 1084 } 1085 1086 Node = AcpiNsValidateHandle (GpeDevice); 1087 if (!Node) 1088 { 1089 Status = AE_BAD_PARAMETER; 1090 goto UnlockAndExit; 1091 } 1092 1093 /* Validate the parent device */ 1094 1095 if (Node->Type != ACPI_TYPE_DEVICE) 1096 { 1097 Status = AE_TYPE; 1098 goto UnlockAndExit; 1099 } 1100 1101 if (Node->Object) 1102 { 1103 Status = AE_ALREADY_EXISTS; 1104 goto UnlockAndExit; 1105 } 1106 1107 /* 1108 * For user-installed GPE Block Devices, the GpeBlockBaseNumber 1109 * is always zero 1110 */ 1111 Status = AcpiEvCreateGpeBlock (Node, GpeBlockAddress->Address, 1112 GpeBlockAddress->SpaceId, RegisterCount, 1113 0, InterruptNumber, &GpeBlock); 1114 if (ACPI_FAILURE (Status)) 1115 { 1116 goto UnlockAndExit; 1117 } 1118 1119 /* Install block in the DeviceObject attached to the node */ 1120 1121 ObjDesc = AcpiNsGetAttachedObject (Node); 1122 if (!ObjDesc) 1123 { 1124 /* 1125 * No object, create a new one (Device nodes do not always have 1126 * an attached object) 1127 */ 1128 ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_DEVICE); 1129 if (!ObjDesc) 1130 { 1131 Status = AE_NO_MEMORY; 1132 goto UnlockAndExit; 1133 } 1134 1135 Status = AcpiNsAttachObject (Node, ObjDesc, ACPI_TYPE_DEVICE); 1136 1137 /* Remove local reference to the object */ 1138 1139 AcpiUtRemoveReference (ObjDesc); 1140 if (ACPI_FAILURE (Status)) 1141 { 1142 goto UnlockAndExit; 1143 } 1144 } 1145 1146 /* Now install the GPE block in the DeviceObject */ 1147 1148 ObjDesc->Device.GpeBlock = GpeBlock; 1149 1150 1151 UnlockAndExit: 1152 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 1153 return_ACPI_STATUS (Status); 1154 } 1155 1156 ACPI_EXPORT_SYMBOL (AcpiInstallGpeBlock) 1157 1158 1159 /******************************************************************************* 1160 * 1161 * FUNCTION: AcpiRemoveGpeBlock 1162 * 1163 * PARAMETERS: GpeDevice - Handle to the parent GPE Block Device 1164 * 1165 * RETURN: Status 1166 * 1167 * DESCRIPTION: Remove a previously installed block of GPE registers 1168 * 1169 ******************************************************************************/ 1170 1171 ACPI_STATUS 1172 AcpiRemoveGpeBlock ( 1173 ACPI_HANDLE GpeDevice) 1174 { 1175 ACPI_OPERAND_OBJECT *ObjDesc; 1176 ACPI_STATUS Status; 1177 ACPI_NAMESPACE_NODE *Node; 1178 1179 1180 ACPI_FUNCTION_TRACE (AcpiRemoveGpeBlock); 1181 1182 1183 if (!GpeDevice) 1184 { 1185 return_ACPI_STATUS (AE_BAD_PARAMETER); 1186 } 1187 1188 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 1189 if (ACPI_FAILURE (Status)) 1190 { 1191 return_ACPI_STATUS (Status); 1192 } 1193 1194 Node = AcpiNsValidateHandle (GpeDevice); 1195 if (!Node) 1196 { 1197 Status = AE_BAD_PARAMETER; 1198 goto UnlockAndExit; 1199 } 1200 1201 /* Validate the parent device */ 1202 1203 if (Node->Type != ACPI_TYPE_DEVICE) 1204 { 1205 Status = AE_TYPE; 1206 goto UnlockAndExit; 1207 } 1208 1209 /* Get the DeviceObject attached to the node */ 1210 1211 ObjDesc = AcpiNsGetAttachedObject (Node); 1212 if (!ObjDesc || 1213 !ObjDesc->Device.GpeBlock) 1214 { 1215 return_ACPI_STATUS (AE_NULL_OBJECT); 1216 } 1217 1218 /* Delete the GPE block (but not the DeviceObject) */ 1219 1220 Status = AcpiEvDeleteGpeBlock (ObjDesc->Device.GpeBlock); 1221 if (ACPI_SUCCESS (Status)) 1222 { 1223 ObjDesc->Device.GpeBlock = NULL; 1224 } 1225 1226 UnlockAndExit: 1227 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 1228 return_ACPI_STATUS (Status); 1229 } 1230 1231 ACPI_EXPORT_SYMBOL (AcpiRemoveGpeBlock) 1232 1233 1234 /******************************************************************************* 1235 * 1236 * FUNCTION: AcpiGetGpeDevice 1237 * 1238 * PARAMETERS: Index - System GPE index (0-CurrentGpeCount) 1239 * GpeDevice - Where the parent GPE Device is returned 1240 * 1241 * RETURN: Status 1242 * 1243 * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL 1244 * gpe device indicates that the gpe number is contained in one of 1245 * the FADT-defined gpe blocks. Otherwise, the GPE block device. 1246 * 1247 ******************************************************************************/ 1248 1249 ACPI_STATUS 1250 AcpiGetGpeDevice ( 1251 UINT32 Index, 1252 ACPI_HANDLE *GpeDevice) 1253 { 1254 ACPI_GPE_DEVICE_INFO Info; 1255 ACPI_STATUS Status; 1256 1257 1258 ACPI_FUNCTION_TRACE (AcpiGetGpeDevice); 1259 1260 1261 if (!GpeDevice) 1262 { 1263 return_ACPI_STATUS (AE_BAD_PARAMETER); 1264 } 1265 1266 if (Index >= AcpiCurrentGpeCount) 1267 { 1268 return_ACPI_STATUS (AE_NOT_EXIST); 1269 } 1270 1271 /* Setup and walk the GPE list */ 1272 1273 Info.Index = Index; 1274 Info.Status = AE_NOT_EXIST; 1275 Info.GpeDevice = NULL; 1276 Info.NextBlockBaseIndex = 0; 1277 1278 Status = AcpiEvWalkGpeList (AcpiEvGetGpeDevice, &Info); 1279 if (ACPI_FAILURE (Status)) 1280 { 1281 return_ACPI_STATUS (Status); 1282 } 1283 1284 *GpeDevice = ACPI_CAST_PTR (ACPI_HANDLE, Info.GpeDevice); 1285 return_ACPI_STATUS (Info.Status); 1286 } 1287 1288 ACPI_EXPORT_SYMBOL (AcpiGetGpeDevice) 1289 1290 #endif /* !ACPI_REDUCED_HARDWARE */ 1291