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