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