Home | History | Annotate | Line # | Download | only in events
evxfgpe.c revision 1.1.1.9
      1 /******************************************************************************
      2  *
      3  * Module Name: evxfgpe - External Interfaces for General Purpose Events (GPEs)
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2018, 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 #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);
    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:    AcpiFinishGpe
    773  *
    774  * PARAMETERS:  GpeDevice           - Namespace node for the GPE Block
    775  *                                    (NULL for FADT defined GPEs)
    776  *              GpeNumber           - GPE level within the GPE block
    777  *
    778  * RETURN:      Status
    779  *
    780  * DESCRIPTION: Clear and conditionally reenable a GPE. This completes the GPE
    781  *              processing. Intended for use by asynchronous host-installed
    782  *              GPE handlers. The GPE is only reenabled if the EnableForRun bit
    783  *              is set in the GPE info.
    784  *
    785  ******************************************************************************/
    786 
    787 ACPI_STATUS
    788 AcpiFinishGpe (
    789     ACPI_HANDLE             GpeDevice,
    790     UINT32                  GpeNumber)
    791 {
    792     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
    793     ACPI_STATUS             Status;
    794     ACPI_CPU_FLAGS          Flags;
    795 
    796 
    797     ACPI_FUNCTION_TRACE (AcpiFinishGpe);
    798 
    799 
    800     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
    801 
    802     /* Ensure that we have a valid GPE number */
    803 
    804     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
    805     if (!GpeEventInfo)
    806     {
    807         Status = AE_BAD_PARAMETER;
    808         goto UnlockAndExit;
    809     }
    810 
    811     Status = AcpiEvFinishGpe (GpeEventInfo);
    812 
    813 UnlockAndExit:
    814     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
    815     return_ACPI_STATUS (Status);
    816 }
    817 
    818 ACPI_EXPORT_SYMBOL (AcpiFinishGpe)
    819 
    820 
    821 /******************************************************************************
    822  *
    823  * FUNCTION:    AcpiDisableAllGpes
    824  *
    825  * PARAMETERS:  None
    826  *
    827  * RETURN:      Status
    828  *
    829  * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
    830  *
    831  ******************************************************************************/
    832 
    833 ACPI_STATUS
    834 AcpiDisableAllGpes (
    835     void)
    836 {
    837     ACPI_STATUS             Status;
    838 
    839 
    840     ACPI_FUNCTION_TRACE (AcpiDisableAllGpes);
    841 
    842 
    843     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
    844     if (ACPI_FAILURE (Status))
    845     {
    846         return_ACPI_STATUS (Status);
    847     }
    848 
    849     Status = AcpiHwDisableAllGpes ();
    850     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
    851 
    852     return_ACPI_STATUS (Status);
    853 }
    854 
    855 ACPI_EXPORT_SYMBOL (AcpiDisableAllGpes)
    856 
    857 
    858 /******************************************************************************
    859  *
    860  * FUNCTION:    AcpiEnableAllRuntimeGpes
    861  *
    862  * PARAMETERS:  None
    863  *
    864  * RETURN:      Status
    865  *
    866  * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
    867  *
    868  ******************************************************************************/
    869 
    870 ACPI_STATUS
    871 AcpiEnableAllRuntimeGpes (
    872     void)
    873 {
    874     ACPI_STATUS             Status;
    875 
    876 
    877     ACPI_FUNCTION_TRACE (AcpiEnableAllRuntimeGpes);
    878 
    879 
    880     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
    881     if (ACPI_FAILURE (Status))
    882     {
    883         return_ACPI_STATUS (Status);
    884     }
    885 
    886     Status = AcpiHwEnableAllRuntimeGpes ();
    887     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
    888 
    889     return_ACPI_STATUS (Status);
    890 }
    891 
    892 ACPI_EXPORT_SYMBOL (AcpiEnableAllRuntimeGpes)
    893 
    894 
    895 /******************************************************************************
    896  *
    897  * FUNCTION:    AcpiEnableAllWakeupGpes
    898  *
    899  * PARAMETERS:  None
    900  *
    901  * RETURN:      Status
    902  *
    903  * DESCRIPTION: Enable all "wakeup" GPEs and disable all of the other GPEs, in
    904  *              all GPE blocks.
    905  *
    906  ******************************************************************************/
    907 
    908 ACPI_STATUS
    909 AcpiEnableAllWakeupGpes (
    910     void)
    911 {
    912     ACPI_STATUS             Status;
    913 
    914 
    915     ACPI_FUNCTION_TRACE (AcpiEnableAllWakeupGpes);
    916 
    917 
    918     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
    919     if (ACPI_FAILURE (Status))
    920     {
    921         return_ACPI_STATUS (Status);
    922     }
    923 
    924     Status = AcpiHwEnableAllWakeupGpes ();
    925     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
    926 
    927     return_ACPI_STATUS (Status);
    928 }
    929 
    930 ACPI_EXPORT_SYMBOL (AcpiEnableAllWakeupGpes)
    931 
    932 
    933 /*******************************************************************************
    934  *
    935  * FUNCTION:    AcpiInstallGpeBlock
    936  *
    937  * PARAMETERS:  GpeDevice           - Handle to the parent GPE Block Device
    938  *              GpeBlockAddress     - Address and SpaceID
    939  *              RegisterCount       - Number of GPE register pairs in the block
    940  *              InterruptNumber     - H/W interrupt for the block
    941  *
    942  * RETURN:      Status
    943  *
    944  * DESCRIPTION: Create and Install a block of GPE registers. The GPEs are not
    945  *              enabled here.
    946  *
    947  ******************************************************************************/
    948 
    949 ACPI_STATUS
    950 AcpiInstallGpeBlock (
    951     ACPI_HANDLE             GpeDevice,
    952     ACPI_GENERIC_ADDRESS    *GpeBlockAddress,
    953     UINT32                  RegisterCount,
    954     UINT32                  InterruptNumber)
    955 {
    956     ACPI_STATUS             Status;
    957     ACPI_OPERAND_OBJECT     *ObjDesc;
    958     ACPI_NAMESPACE_NODE     *Node;
    959     ACPI_GPE_BLOCK_INFO     *GpeBlock;
    960 
    961 
    962     ACPI_FUNCTION_TRACE (AcpiInstallGpeBlock);
    963 
    964 
    965     if ((!GpeDevice)       ||
    966         (!GpeBlockAddress) ||
    967         (!RegisterCount))
    968     {
    969         return_ACPI_STATUS (AE_BAD_PARAMETER);
    970     }
    971 
    972     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
    973     if (ACPI_FAILURE (Status))
    974     {
    975         return_ACPI_STATUS (Status);
    976     }
    977 
    978     Node = AcpiNsValidateHandle (GpeDevice);
    979     if (!Node)
    980     {
    981         Status = AE_BAD_PARAMETER;
    982         goto UnlockAndExit;
    983     }
    984 
    985     /* Validate the parent device */
    986 
    987     if (Node->Type != ACPI_TYPE_DEVICE)
    988     {
    989         Status = AE_TYPE;
    990         goto UnlockAndExit;
    991     }
    992 
    993     if (Node->Object)
    994     {
    995         Status = AE_ALREADY_EXISTS;
    996         goto UnlockAndExit;
    997     }
    998 
    999     /*
   1000      * For user-installed GPE Block Devices, the GpeBlockBaseNumber
   1001      * is always zero
   1002      */
   1003     Status = AcpiEvCreateGpeBlock (Node, GpeBlockAddress->Address,
   1004         GpeBlockAddress->SpaceId, RegisterCount,
   1005         0, InterruptNumber, &GpeBlock);
   1006     if (ACPI_FAILURE (Status))
   1007     {
   1008         goto UnlockAndExit;
   1009     }
   1010 
   1011     /* Install block in the DeviceObject attached to the node */
   1012 
   1013     ObjDesc = AcpiNsGetAttachedObject (Node);
   1014     if (!ObjDesc)
   1015     {
   1016         /*
   1017          * No object, create a new one (Device nodes do not always have
   1018          * an attached object)
   1019          */
   1020         ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_DEVICE);
   1021         if (!ObjDesc)
   1022         {
   1023             Status = AE_NO_MEMORY;
   1024             goto UnlockAndExit;
   1025         }
   1026 
   1027         Status = AcpiNsAttachObject (Node, ObjDesc, ACPI_TYPE_DEVICE);
   1028 
   1029         /* Remove local reference to the object */
   1030 
   1031         AcpiUtRemoveReference (ObjDesc);
   1032         if (ACPI_FAILURE (Status))
   1033         {
   1034             goto UnlockAndExit;
   1035         }
   1036     }
   1037 
   1038     /* Now install the GPE block in the DeviceObject */
   1039 
   1040     ObjDesc->Device.GpeBlock = GpeBlock;
   1041 
   1042 
   1043 UnlockAndExit:
   1044     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
   1045     return_ACPI_STATUS (Status);
   1046 }
   1047 
   1048 ACPI_EXPORT_SYMBOL (AcpiInstallGpeBlock)
   1049 
   1050 
   1051 /*******************************************************************************
   1052  *
   1053  * FUNCTION:    AcpiRemoveGpeBlock
   1054  *
   1055  * PARAMETERS:  GpeDevice           - Handle to the parent GPE Block Device
   1056  *
   1057  * RETURN:      Status
   1058  *
   1059  * DESCRIPTION: Remove a previously installed block of GPE registers
   1060  *
   1061  ******************************************************************************/
   1062 
   1063 ACPI_STATUS
   1064 AcpiRemoveGpeBlock (
   1065     ACPI_HANDLE             GpeDevice)
   1066 {
   1067     ACPI_OPERAND_OBJECT     *ObjDesc;
   1068     ACPI_STATUS             Status;
   1069     ACPI_NAMESPACE_NODE     *Node;
   1070 
   1071 
   1072     ACPI_FUNCTION_TRACE (AcpiRemoveGpeBlock);
   1073 
   1074 
   1075     if (!GpeDevice)
   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     /* Get the DeviceObject attached to the node */
   1102 
   1103     ObjDesc = AcpiNsGetAttachedObject (Node);
   1104     if (!ObjDesc ||
   1105         !ObjDesc->Device.GpeBlock)
   1106     {
   1107         return_ACPI_STATUS (AE_NULL_OBJECT);
   1108     }
   1109 
   1110     /* Delete the GPE block (but not the DeviceObject) */
   1111 
   1112     Status = AcpiEvDeleteGpeBlock (ObjDesc->Device.GpeBlock);
   1113     if (ACPI_SUCCESS (Status))
   1114     {
   1115         ObjDesc->Device.GpeBlock = NULL;
   1116     }
   1117 
   1118 UnlockAndExit:
   1119     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
   1120     return_ACPI_STATUS (Status);
   1121 }
   1122 
   1123 ACPI_EXPORT_SYMBOL (AcpiRemoveGpeBlock)
   1124 
   1125 
   1126 /*******************************************************************************
   1127  *
   1128  * FUNCTION:    AcpiGetGpeDevice
   1129  *
   1130  * PARAMETERS:  Index               - System GPE index (0-CurrentGpeCount)
   1131  *              GpeDevice           - Where the parent GPE Device is returned
   1132  *
   1133  * RETURN:      Status
   1134  *
   1135  * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL
   1136  *              gpe device indicates that the gpe number is contained in one of
   1137  *              the FADT-defined gpe blocks. Otherwise, the GPE block device.
   1138  *
   1139  ******************************************************************************/
   1140 
   1141 ACPI_STATUS
   1142 AcpiGetGpeDevice (
   1143     UINT32                  Index,
   1144     ACPI_HANDLE             *GpeDevice)
   1145 {
   1146     ACPI_GPE_DEVICE_INFO    Info;
   1147     ACPI_STATUS             Status;
   1148 
   1149 
   1150     ACPI_FUNCTION_TRACE (AcpiGetGpeDevice);
   1151 
   1152 
   1153     if (!GpeDevice)
   1154     {
   1155         return_ACPI_STATUS (AE_BAD_PARAMETER);
   1156     }
   1157 
   1158     if (Index >= AcpiCurrentGpeCount)
   1159     {
   1160         return_ACPI_STATUS (AE_NOT_EXIST);
   1161     }
   1162 
   1163     /* Setup and walk the GPE list */
   1164 
   1165     Info.Index = Index;
   1166     Info.Status = AE_NOT_EXIST;
   1167     Info.GpeDevice = NULL;
   1168     Info.NextBlockBaseIndex = 0;
   1169 
   1170     Status = AcpiEvWalkGpeList (AcpiEvGetGpeDevice, &Info);
   1171     if (ACPI_FAILURE (Status))
   1172     {
   1173         return_ACPI_STATUS (Status);
   1174     }
   1175 
   1176     *GpeDevice = ACPI_CAST_PTR (ACPI_HANDLE, Info.GpeDevice);
   1177     return_ACPI_STATUS (Info.Status);
   1178 }
   1179 
   1180 ACPI_EXPORT_SYMBOL (AcpiGetGpeDevice)
   1181 
   1182 #endif /* !ACPI_REDUCED_HARDWARE */
   1183