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