Home | History | Annotate | Line # | Download | only in events
      1 /******************************************************************************
      2  *
      3  * Module Name: evgpe - General Purpose Event handling and dispatch
      4  *
      5  *****************************************************************************/
      6 
      7 /******************************************************************************
      8  *
      9  * 1. Copyright Notice
     10  *
     11  * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
     12  * All rights reserved.
     13  *
     14  * 2. License
     15  *
     16  * 2.1. This is your license from Intel Corp. under its intellectual property
     17  * rights. You may have additional license terms from the party that provided
     18  * you this software, covering your right to use that party's intellectual
     19  * property rights.
     20  *
     21  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
     22  * copy of the source code appearing in this file ("Covered Code") an
     23  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
     24  * base code distributed originally by Intel ("Original Intel Code") to copy,
     25  * make derivatives, distribute, use and display any portion of the Covered
     26  * Code in any form, with the right to sublicense such rights; and
     27  *
     28  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
     29  * license (with the right to sublicense), under only those claims of Intel
     30  * patents that are infringed by the Original Intel Code, to make, use, sell,
     31  * offer to sell, and import the Covered Code and derivative works thereof
     32  * solely to the minimum extent necessary to exercise the above copyright
     33  * license, and in no event shall the patent license extend to any additions
     34  * to or modifications of the Original Intel Code. No other license or right
     35  * is granted directly or by implication, estoppel or otherwise;
     36  *
     37  * The above copyright and patent license is granted only if the following
     38  * conditions are met:
     39  *
     40  * 3. Conditions
     41  *
     42  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
     43  * Redistribution of source code of any substantial portion of the Covered
     44  * Code or modification with rights to further distribute source must include
     45  * the above Copyright Notice, the above License, this list of Conditions,
     46  * and the following Disclaimer and Export Compliance provision. In addition,
     47  * Licensee must cause all Covered Code to which Licensee contributes to
     48  * contain a file documenting the changes Licensee made to create that Covered
     49  * Code and the date of any change. Licensee must include in that file the
     50  * documentation of any changes made by any predecessor Licensee. Licensee
     51  * must include a prominent statement that the modification is derived,
     52  * directly or indirectly, from Original Intel Code.
     53  *
     54  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
     55  * Redistribution of source code of any substantial portion of the Covered
     56  * Code or modification without rights to further distribute source must
     57  * include the following Disclaimer and Export Compliance provision in the
     58  * documentation and/or other materials provided with distribution. In
     59  * addition, Licensee may not authorize further sublicense of source of any
     60  * portion of the Covered Code, and must include terms to the effect that the
     61  * license from Licensee to its licensee is limited to the intellectual
     62  * property embodied in the software Licensee provides to its licensee, and
     63  * not to intellectual property embodied in modifications its licensee may
     64  * make.
     65  *
     66  * 3.3. Redistribution of Executable. Redistribution in executable form of any
     67  * substantial portion of the Covered Code or modification must reproduce the
     68  * above Copyright Notice, and the following Disclaimer and Export Compliance
     69  * provision in the documentation and/or other materials provided with the
     70  * distribution.
     71  *
     72  * 3.4. Intel retains all right, title, and interest in and to the Original
     73  * Intel Code.
     74  *
     75  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
     76  * Intel shall be used in advertising or otherwise to promote the sale, use or
     77  * other dealings in products derived from or relating to the Covered Code
     78  * without prior written authorization from Intel.
     79  *
     80  * 4. Disclaimer and Export Compliance
     81  *
     82  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
     83  * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
     84  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
     85  * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
     86  * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
     87  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
     88  * PARTICULAR PURPOSE.
     89  *
     90  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
     91  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
     92  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
     93  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
     94  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
     95  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
     96  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
     97  * LIMITED REMEDY.
     98  *
     99  * 4.3. Licensee shall not export, either directly or indirectly, any of this
    100  * software or system incorporating such software without first obtaining any
    101  * required license or other approval from the U. S. Department of Commerce or
    102  * any other agency or department of the United States Government. In the
    103  * event Licensee exports any such software from the United States or
    104  * re-exports any such software from a foreign destination, Licensee shall
    105  * ensure that the distribution and export/re-export of the software is in
    106  * compliance with all laws, regulations, orders, or other restrictions of the
    107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
    108  * any of its subsidiaries will export/re-export any technical data, process,
    109  * software, or service, directly or indirectly, to any country for which the
    110  * United States government or any agency thereof requires an export license,
    111  * other governmental approval, or letter of assurance, without first obtaining
    112  * such license, approval or letter.
    113  *
    114  *****************************************************************************
    115  *
    116  * Alternatively, you may choose to be licensed under the terms of the
    117  * following license:
    118  *
    119  * Redistribution and use in source and binary forms, with or without
    120  * modification, are permitted provided that the following conditions
    121  * are met:
    122  * 1. Redistributions of source code must retain the above copyright
    123  *    notice, this list of conditions, and the following disclaimer,
    124  *    without modification.
    125  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
    126  *    substantially similar to the "NO WARRANTY" disclaimer below
    127  *    ("Disclaimer") and any redistribution must be conditioned upon
    128  *    including a substantially similar Disclaimer requirement for further
    129  *    binary redistribution.
    130  * 3. Neither the names of the above-listed copyright holders nor the names
    131  *    of any contributors may be used to endorse or promote products derived
    132  *    from this software without specific prior written permission.
    133  *
    134  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    135  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    136  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    137  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    138  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    139  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    140  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    141  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    142  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    143  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    144  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    145  *
    146  * Alternatively, you may choose to be licensed under the terms of the
    147  * GNU General Public License ("GPL") version 2 as published by the Free
    148  * Software Foundation.
    149  *
    150  *****************************************************************************/
    151 
    152 #include "acpi.h"
    153 #include "accommon.h"
    154 #include "acevents.h"
    155 #include "acnamesp.h"
    156 
    157 #define _COMPONENT          ACPI_EVENTS
    158         ACPI_MODULE_NAME    ("evgpe")
    159 
    160 #if (!ACPI_REDUCED_HARDWARE) /* Entire module */
    161 
    162 /* Local prototypes */
    163 
    164 static void ACPI_SYSTEM_XFACE
    165 AcpiEvAsynchExecuteGpeMethod (
    166     void                    *Context);
    167 
    168 static void ACPI_SYSTEM_XFACE
    169 AcpiEvAsynchEnableGpe (
    170     void                    *Context);
    171 
    172 
    173 /*******************************************************************************
    174  *
    175  * FUNCTION:    AcpiEvUpdateGpeEnableMask
    176  *
    177  * PARAMETERS:  GpeEventInfo            - GPE to update
    178  *
    179  * RETURN:      Status
    180  *
    181  * DESCRIPTION: Updates GPE register enable mask based upon whether there are
    182  *              runtime references to this GPE
    183  *
    184  ******************************************************************************/
    185 
    186 ACPI_STATUS
    187 AcpiEvUpdateGpeEnableMask (
    188     ACPI_GPE_EVENT_INFO     *GpeEventInfo)
    189 {
    190     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
    191     UINT32                  RegisterBit;
    192 
    193 
    194     ACPI_FUNCTION_TRACE (EvUpdateGpeEnableMask);
    195 
    196 
    197     GpeRegisterInfo = GpeEventInfo->RegisterInfo;
    198     if (!GpeRegisterInfo)
    199     {
    200         return_ACPI_STATUS (AE_NOT_EXIST);
    201     }
    202 
    203     RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo);
    204 
    205     /* Clear the run bit up front */
    206 
    207     ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForRun, RegisterBit);
    208 
    209     /* Set the mask bit only if there are references to this GPE */
    210 
    211     if (GpeEventInfo->RuntimeCount)
    212     {
    213         ACPI_SET_BIT (GpeRegisterInfo->EnableForRun, (UINT8) RegisterBit);
    214     }
    215 
    216     GpeRegisterInfo->EnableMask = GpeRegisterInfo->EnableForRun;
    217     return_ACPI_STATUS (AE_OK);
    218 }
    219 
    220 
    221 /*******************************************************************************
    222  *
    223  * FUNCTION:    AcpiEvEnableGpe
    224  *
    225  * PARAMETERS:  GpeEventInfo            - GPE to enable
    226  *
    227  * RETURN:      Status
    228  *
    229  * DESCRIPTION: Enable a GPE.
    230  *
    231  ******************************************************************************/
    232 
    233 ACPI_STATUS
    234 AcpiEvEnableGpe (
    235     ACPI_GPE_EVENT_INFO     *GpeEventInfo)
    236 {
    237     ACPI_STATUS             Status;
    238 
    239 
    240     ACPI_FUNCTION_TRACE (EvEnableGpe);
    241 
    242 
    243     /* Enable the requested GPE */
    244 
    245     Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_ENABLE);
    246     return_ACPI_STATUS (Status);
    247 }
    248 
    249 
    250 /*******************************************************************************
    251  *
    252  * FUNCTION:    AcpiEvMaskGpe
    253  *
    254  * PARAMETERS:  GpeEventInfo            - GPE to be blocked/unblocked
    255  *              IsMasked                - Whether the GPE is masked or not
    256  *
    257  * RETURN:      Status
    258  *
    259  * DESCRIPTION: Unconditionally mask/unmask a GPE during runtime.
    260  *
    261  ******************************************************************************/
    262 
    263 ACPI_STATUS
    264 AcpiEvMaskGpe (
    265     ACPI_GPE_EVENT_INFO     *GpeEventInfo,
    266     BOOLEAN                 IsMasked)
    267 {
    268     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
    269     UINT32                  RegisterBit;
    270 
    271 
    272     ACPI_FUNCTION_TRACE (EvMaskGpe);
    273 
    274 
    275     GpeRegisterInfo = GpeEventInfo->RegisterInfo;
    276     if (!GpeRegisterInfo)
    277     {
    278         return_ACPI_STATUS (AE_NOT_EXIST);
    279     }
    280 
    281     RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo);
    282 
    283     /* Perform the action */
    284 
    285     if (IsMasked)
    286     {
    287         if (RegisterBit & GpeRegisterInfo->MaskForRun)
    288         {
    289             return_ACPI_STATUS (AE_BAD_PARAMETER);
    290         }
    291 
    292         (void) AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE);
    293         ACPI_SET_BIT (GpeRegisterInfo->MaskForRun, (UINT8) RegisterBit);
    294     }
    295     else
    296     {
    297         if (!(RegisterBit & GpeRegisterInfo->MaskForRun))
    298         {
    299             return_ACPI_STATUS (AE_BAD_PARAMETER);
    300         }
    301 
    302         ACPI_CLEAR_BIT (GpeRegisterInfo->MaskForRun, (UINT8) RegisterBit);
    303         if (GpeEventInfo->RuntimeCount &&
    304             !GpeEventInfo->DisableForDispatch)
    305         {
    306             (void) AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_ENABLE);
    307         }
    308     }
    309 
    310     return_ACPI_STATUS (AE_OK);
    311 }
    312 
    313 
    314 /*******************************************************************************
    315  *
    316  * FUNCTION:    AcpiEvAddGpeReference
    317  *
    318  * PARAMETERS:  GpeEventInfo            - Add a reference to this GPE
    319  *              ClearOnEnable           - Clear GPE status before enabling it
    320  *
    321  * RETURN:      Status
    322  *
    323  * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is
    324  *              hardware-enabled.
    325  *
    326  ******************************************************************************/
    327 
    328 ACPI_STATUS
    329 AcpiEvAddGpeReference (
    330     ACPI_GPE_EVENT_INFO     *GpeEventInfo,
    331     BOOLEAN                 ClearOnEnable)
    332 {
    333     ACPI_STATUS             Status = AE_OK;
    334 
    335 
    336     ACPI_FUNCTION_TRACE (EvAddGpeReference);
    337 
    338 
    339     if (GpeEventInfo->RuntimeCount == ACPI_UINT8_MAX)
    340     {
    341         return_ACPI_STATUS (AE_LIMIT);
    342     }
    343 
    344     GpeEventInfo->RuntimeCount++;
    345     if (GpeEventInfo->RuntimeCount == 1)
    346     {
    347         /* Enable on first reference */
    348 
    349         if (ClearOnEnable)
    350         {
    351             (void) AcpiHwClearGpe (GpeEventInfo);
    352         }
    353 
    354         Status = AcpiEvUpdateGpeEnableMask (GpeEventInfo);
    355         if (ACPI_SUCCESS (Status))
    356         {
    357             Status = AcpiEvEnableGpe (GpeEventInfo);
    358         }
    359 
    360         if (ACPI_FAILURE (Status))
    361         {
    362             GpeEventInfo->RuntimeCount--;
    363         }
    364     }
    365 
    366     return_ACPI_STATUS (Status);
    367 }
    368 
    369 
    370 /*******************************************************************************
    371  *
    372  * FUNCTION:    AcpiEvRemoveGpeReference
    373  *
    374  * PARAMETERS:  GpeEventInfo            - Remove a reference to this GPE
    375  *
    376  * RETURN:      Status
    377  *
    378  * DESCRIPTION: Remove a reference to a GPE. When the last reference is
    379  *              removed, the GPE is hardware-disabled.
    380  *
    381  ******************************************************************************/
    382 
    383 ACPI_STATUS
    384 AcpiEvRemoveGpeReference (
    385     ACPI_GPE_EVENT_INFO     *GpeEventInfo)
    386 {
    387     ACPI_STATUS             Status = AE_OK;
    388 
    389 
    390     ACPI_FUNCTION_TRACE (EvRemoveGpeReference);
    391 
    392 
    393     if (!GpeEventInfo->RuntimeCount)
    394     {
    395         return_ACPI_STATUS (AE_LIMIT);
    396     }
    397 
    398     GpeEventInfo->RuntimeCount--;
    399     if (!GpeEventInfo->RuntimeCount)
    400     {
    401         /* Disable on last reference */
    402 
    403         Status = AcpiEvUpdateGpeEnableMask (GpeEventInfo);
    404         if (ACPI_SUCCESS (Status))
    405         {
    406             Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE);
    407         }
    408 
    409         if (ACPI_FAILURE (Status))
    410         {
    411             GpeEventInfo->RuntimeCount++;
    412         }
    413     }
    414 
    415     return_ACPI_STATUS (Status);
    416 }
    417 
    418 
    419 /*******************************************************************************
    420  *
    421  * FUNCTION:    AcpiEvLowGetGpeInfo
    422  *
    423  * PARAMETERS:  GpeNumber           - Raw GPE number
    424  *              GpeBlock            - A GPE info block
    425  *
    426  * RETURN:      A GPE EventInfo struct. NULL if not a valid GPE (The GpeNumber
    427  *              is not within the specified GPE block)
    428  *
    429  * DESCRIPTION: Returns the EventInfo struct associated with this GPE. This is
    430  *              the low-level implementation of EvGetGpeEventInfo.
    431  *
    432  ******************************************************************************/
    433 
    434 ACPI_GPE_EVENT_INFO *
    435 AcpiEvLowGetGpeInfo (
    436     UINT32                  GpeNumber,
    437     ACPI_GPE_BLOCK_INFO     *GpeBlock)
    438 {
    439     UINT32                  GpeIndex;
    440 
    441 
    442     /*
    443      * Validate that the GpeNumber is within the specified GpeBlock.
    444      * (Two steps)
    445      */
    446     if (!GpeBlock ||
    447         (GpeNumber < GpeBlock->BlockBaseNumber))
    448     {
    449         return (NULL);
    450     }
    451 
    452     GpeIndex = GpeNumber - GpeBlock->BlockBaseNumber;
    453     if (GpeIndex >= GpeBlock->GpeCount)
    454     {
    455         return (NULL);
    456     }
    457 
    458     return (&GpeBlock->EventInfo[GpeIndex]);
    459 }
    460 
    461 
    462 /*******************************************************************************
    463  *
    464  * FUNCTION:    AcpiEvGetGpeEventInfo
    465  *
    466  * PARAMETERS:  GpeDevice           - Device node. NULL for GPE0/GPE1
    467  *              GpeNumber           - Raw GPE number
    468  *
    469  * RETURN:      A GPE EventInfo struct. NULL if not a valid GPE
    470  *
    471  * DESCRIPTION: Returns the EventInfo struct associated with this GPE.
    472  *              Validates the GpeBlock and the GpeNumber
    473  *
    474  *              Should be called only when the GPE lists are semaphore locked
    475  *              and not subject to change.
    476  *
    477  ******************************************************************************/
    478 
    479 ACPI_GPE_EVENT_INFO *
    480 AcpiEvGetGpeEventInfo (
    481     ACPI_HANDLE             GpeDevice,
    482     UINT32                  GpeNumber)
    483 {
    484     ACPI_OPERAND_OBJECT     *ObjDesc;
    485     ACPI_GPE_EVENT_INFO     *GpeInfo;
    486     UINT32                  i;
    487 
    488 
    489     ACPI_FUNCTION_ENTRY ();
    490 
    491 
    492     /* A NULL GpeDevice means use the FADT-defined GPE block(s) */
    493 
    494     if (!GpeDevice)
    495     {
    496         /* Examine GPE Block 0 and 1 (These blocks are permanent) */
    497 
    498         for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++)
    499         {
    500             GpeInfo = AcpiEvLowGetGpeInfo (GpeNumber,
    501                 AcpiGbl_GpeFadtBlocks[i]);
    502             if (GpeInfo)
    503             {
    504                 return (GpeInfo);
    505             }
    506         }
    507 
    508         /* The GpeNumber was not in the range of either FADT GPE block */
    509 
    510         return (NULL);
    511     }
    512 
    513     /* A Non-NULL GpeDevice means this is a GPE Block Device */
    514 
    515     ObjDesc = AcpiNsGetAttachedObject ((ACPI_NAMESPACE_NODE *) GpeDevice);
    516     if (!ObjDesc ||
    517         !ObjDesc->Device.GpeBlock)
    518     {
    519         return (NULL);
    520     }
    521 
    522     return (AcpiEvLowGetGpeInfo (GpeNumber, ObjDesc->Device.GpeBlock));
    523 }
    524 
    525 
    526 /*******************************************************************************
    527  *
    528  * FUNCTION:    AcpiEvGpeDetect
    529  *
    530  * PARAMETERS:  GpeXruptList        - Interrupt block for this interrupt.
    531  *                                    Can have multiple GPE blocks attached.
    532  *
    533  * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
    534  *
    535  * DESCRIPTION: Detect if any GP events have occurred. This function is
    536  *              executed at interrupt level.
    537  *
    538  ******************************************************************************/
    539 
    540 UINT32
    541 AcpiEvGpeDetect (
    542     ACPI_GPE_XRUPT_INFO     *GpeXruptList)
    543 {
    544     ACPI_GPE_BLOCK_INFO     *GpeBlock;
    545     ACPI_NAMESPACE_NODE     *GpeDevice;
    546     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
    547     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
    548     UINT32                  GpeNumber;
    549     UINT32                  IntStatus = ACPI_INTERRUPT_NOT_HANDLED;
    550     ACPI_CPU_FLAGS          Flags;
    551     UINT32                  i;
    552     UINT32                  j;
    553 
    554 
    555     ACPI_FUNCTION_NAME (EvGpeDetect);
    556 
    557     /* Check for the case where there are no GPEs */
    558 
    559     if (!GpeXruptList)
    560     {
    561         return (IntStatus);
    562     }
    563 
    564     /*
    565      * We need to obtain the GPE lock for both the data structs and registers
    566      * Note: Not necessary to obtain the hardware lock, since the GPE
    567      * registers are owned by the GpeLock.
    568      */
    569     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
    570 
    571     /* Examine all GPE blocks attached to this interrupt level */
    572 
    573     GpeBlock = GpeXruptList->GpeBlockListHead;
    574     while (GpeBlock)
    575     {
    576         GpeDevice = GpeBlock->Node;
    577 
    578         /*
    579          * Read all of the 8-bit GPE status and enable registers in this GPE
    580          * block, saving all of them. Find all currently active GP events.
    581          */
    582         for (i = 0; i < GpeBlock->RegisterCount; i++)
    583         {
    584             /* Get the next status/enable pair */
    585 
    586             GpeRegisterInfo = &GpeBlock->RegisterInfo[i];
    587 
    588             /*
    589              * Optimization: If there are no GPEs enabled within this
    590              * register, we can safely ignore the entire register.
    591              */
    592             if (!(GpeRegisterInfo->EnableForRun |
    593                   GpeRegisterInfo->EnableForWake))
    594             {
    595                 ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
    596                     "Ignore disabled registers for GPE %02X-%02X: "
    597                     "RunEnable=%02X, WakeEnable=%02X\n",
    598                     GpeRegisterInfo->BaseGpeNumber,
    599                     GpeRegisterInfo->BaseGpeNumber + (ACPI_GPE_REGISTER_WIDTH - 1),
    600                     GpeRegisterInfo->EnableForRun,
    601                     GpeRegisterInfo->EnableForWake));
    602                 continue;
    603             }
    604 
    605             /* Now look at the individual GPEs in this byte register */
    606 
    607             for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++)
    608             {
    609                 /* Detect and dispatch one GPE bit */
    610 
    611                 GpeEventInfo = &GpeBlock->EventInfo[((ACPI_SIZE) i *
    612                     ACPI_GPE_REGISTER_WIDTH) + j];
    613                 GpeNumber = j + GpeRegisterInfo->BaseGpeNumber;
    614                 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
    615                 IntStatus |= AcpiEvDetectGpe (
    616                     GpeDevice, GpeEventInfo, GpeNumber);
    617                 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
    618             }
    619         }
    620 
    621         GpeBlock = GpeBlock->Next;
    622     }
    623 
    624     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
    625     return (IntStatus);
    626 }
    627 
    628 
    629 /*******************************************************************************
    630  *
    631  * FUNCTION:    AcpiEvAsynchExecuteGpeMethod
    632  *
    633  * PARAMETERS:  Context (GpeEventInfo) - Info for this GPE
    634  *
    635  * RETURN:      None
    636  *
    637  * DESCRIPTION: Perform the actual execution of a GPE control method. This
    638  *              function is called from an invocation of AcpiOsExecute and
    639  *              therefore does NOT execute at interrupt level - so that
    640  *              the control method itself is not executed in the context of
    641  *              an interrupt handler.
    642  *
    643  ******************************************************************************/
    644 
    645 static void ACPI_SYSTEM_XFACE
    646 AcpiEvAsynchExecuteGpeMethod (
    647     void                    *Context)
    648 {
    649     ACPI_GPE_EVENT_INFO     *GpeEventInfo = Context;
    650     ACPI_STATUS             Status = AE_OK;
    651     ACPI_EVALUATE_INFO      *Info;
    652     ACPI_GPE_NOTIFY_INFO    *Notify;
    653 
    654 
    655     ACPI_FUNCTION_TRACE (EvAsynchExecuteGpeMethod);
    656 
    657 
    658     /* Do the correct dispatch - normal method or implicit notify */
    659 
    660     switch (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags))
    661     {
    662     case ACPI_GPE_DISPATCH_NOTIFY:
    663         /*
    664          * Implicit notify.
    665          * Dispatch a DEVICE_WAKE notify to the appropriate handler.
    666          * NOTE: the request is queued for execution after this method
    667          * completes. The notify handlers are NOT invoked synchronously
    668          * from this thread -- because handlers may in turn run other
    669          * control methods.
    670          *
    671          * June 2012: Expand implicit notify mechanism to support
    672          * notifies on multiple device objects.
    673          */
    674         Notify = GpeEventInfo->Dispatch.NotifyList;
    675         while (ACPI_SUCCESS (Status) && Notify)
    676         {
    677             Status = AcpiEvQueueNotifyRequest (
    678                 Notify->DeviceNode, ACPI_NOTIFY_DEVICE_WAKE);
    679 
    680             Notify = Notify->Next;
    681         }
    682         break;
    683 
    684     case ACPI_GPE_DISPATCH_METHOD:
    685 
    686         /* Allocate the evaluation information block */
    687 
    688         Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
    689         if (!Info)
    690         {
    691             Status = AE_NO_MEMORY;
    692         }
    693         else
    694         {
    695             /*
    696              * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the
    697              * _Lxx/_Exx control method that corresponds to this GPE
    698              */
    699             Info->PrefixNode = GpeEventInfo->Dispatch.MethodNode;
    700             Info->Flags = ACPI_IGNORE_RETURN_VALUE;
    701 
    702             Status = AcpiNsEvaluate (Info);
    703             ACPI_FREE (Info);
    704         }
    705 
    706         if (ACPI_FAILURE (Status))
    707         {
    708             ACPI_EXCEPTION ((AE_INFO, Status,
    709                 "while evaluating GPE method [%4.4s]",
    710                 AcpiUtGetNodeName (GpeEventInfo->Dispatch.MethodNode)));
    711         }
    712         break;
    713 
    714     default:
    715 
    716         goto ErrorExit; /* Should never happen */
    717     }
    718 
    719     /* Defer enabling of GPE until all notify handlers are done */
    720 
    721     Status = AcpiOsExecute (OSL_NOTIFY_HANDLER,
    722         AcpiEvAsynchEnableGpe, GpeEventInfo);
    723     if (ACPI_SUCCESS (Status))
    724     {
    725         return_VOID;
    726     }
    727 
    728 ErrorExit:
    729     AcpiEvAsynchEnableGpe (GpeEventInfo);
    730     return_VOID;
    731 }
    732 
    733 
    734 /*******************************************************************************
    735  *
    736  * FUNCTION:    AcpiEvAsynchEnableGpe
    737  *
    738  * PARAMETERS:  Context (GpeEventInfo) - Info for this GPE
    739  *              Callback from AcpiOsExecute
    740  *
    741  * RETURN:      None
    742  *
    743  * DESCRIPTION: Asynchronous clear/enable for GPE. This allows the GPE to
    744  *              complete (i.e., finish execution of Notify)
    745  *
    746  ******************************************************************************/
    747 
    748 static void ACPI_SYSTEM_XFACE
    749 AcpiEvAsynchEnableGpe (
    750     void                    *Context)
    751 {
    752     ACPI_GPE_EVENT_INFO     *GpeEventInfo = Context;
    753     ACPI_CPU_FLAGS          Flags;
    754 
    755 
    756     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
    757     (void) AcpiEvFinishGpe (GpeEventInfo);
    758     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
    759 
    760     return;
    761 }
    762 
    763 
    764 /*******************************************************************************
    765  *
    766  * FUNCTION:    AcpiEvFinishGpe
    767  *
    768  * PARAMETERS:  GpeEventInfo        - Info for this GPE
    769  *
    770  * RETURN:      Status
    771  *
    772  * DESCRIPTION: Clear/Enable a GPE. Common code that is used after execution
    773  *              of a GPE method or a synchronous or asynchronous GPE handler.
    774  *
    775  ******************************************************************************/
    776 
    777 ACPI_STATUS
    778 AcpiEvFinishGpe (
    779     ACPI_GPE_EVENT_INFO     *GpeEventInfo)
    780 {
    781     ACPI_STATUS             Status;
    782 
    783 
    784     if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
    785             ACPI_GPE_LEVEL_TRIGGERED)
    786     {
    787         /*
    788          * GPE is level-triggered, we clear the GPE status bit after
    789          * handling the event.
    790          */
    791         Status = AcpiHwClearGpe (GpeEventInfo);
    792         if (ACPI_FAILURE (Status))
    793         {
    794             return (Status);
    795         }
    796     }
    797 
    798     /*
    799      * Enable this GPE, conditionally. This means that the GPE will
    800      * only be physically enabled if the EnableMask bit is set
    801      * in the EventInfo.
    802      */
    803     (void) AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_CONDITIONAL_ENABLE);
    804     GpeEventInfo->DisableForDispatch = FALSE;
    805     return (AE_OK);
    806 }
    807 
    808 
    809 /*******************************************************************************
    810  *
    811  * FUNCTION:    AcpiEvDetectGpe
    812  *
    813  * PARAMETERS:  GpeDevice           - Device node. NULL for GPE0/GPE1
    814  *              GpeEventInfo        - Info for this GPE
    815  *              GpeNumber           - Number relative to the parent GPE block
    816  *
    817  * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
    818  *
    819  * DESCRIPTION: Detect and dispatch a General Purpose Event to either a function
    820  *              (e.g. EC) or method (e.g. _Lxx/_Exx) handler.
    821  * NOTE:        GPE is W1C, so it is possible to handle a single GPE from both
    822  *              task and irq context in parallel as long as the process to
    823  *              detect and mask the GPE is atomic.
    824  *              However the atomicity of ACPI_GPE_DISPATCH_RAW_HANDLER is
    825  *              dependent on the raw handler itself.
    826  *
    827  ******************************************************************************/
    828 
    829 UINT32
    830 AcpiEvDetectGpe (
    831     ACPI_NAMESPACE_NODE     *GpeDevice,
    832     ACPI_GPE_EVENT_INFO     *GpeEventInfo,
    833     UINT32                  GpeNumber)
    834 {
    835     UINT32                  IntStatus = ACPI_INTERRUPT_NOT_HANDLED;
    836     UINT8                   EnabledStatusByte;
    837     UINT64                  StatusReg;
    838     UINT64                  EnableReg;
    839     UINT32                  RegisterBit;
    840     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
    841     ACPI_GPE_HANDLER_INFO   *GpeHandlerInfo;
    842     ACPI_CPU_FLAGS          Flags;
    843     ACPI_STATUS             Status;
    844 
    845 
    846     ACPI_FUNCTION_TRACE (EvGpeDetect);
    847 
    848 
    849     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
    850 
    851     if (!GpeEventInfo)
    852     {
    853         GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
    854         if (!GpeEventInfo)
    855         {
    856             goto ErrorExit;
    857         }
    858     }
    859 
    860     /* Get the info block for the entire GPE register */
    861 
    862     GpeRegisterInfo = GpeEventInfo->RegisterInfo;
    863 
    864     /* Get the register bitmask for this GPE */
    865 
    866     RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo);
    867 
    868     /* GPE currently enabled (enable bit == 1)? */
    869 
    870     Status = AcpiHwRead (&EnableReg, &GpeRegisterInfo->EnableAddress);
    871     if (ACPI_FAILURE (Status))
    872     {
    873         goto ErrorExit;
    874     }
    875 
    876     /* GPE currently active (status bit == 1)? */
    877 
    878     Status = AcpiHwRead (&StatusReg, &GpeRegisterInfo->StatusAddress);
    879     if (ACPI_FAILURE (Status))
    880     {
    881         goto ErrorExit;
    882     }
    883 
    884     /* Check if there is anything active at all in this GPE */
    885 
    886     ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
    887         "Read registers for GPE %02X: Status=%02X, Enable=%02X, "
    888         "RunEnable=%02X, WakeEnable=%02X\n",
    889         GpeNumber,
    890         (UINT32) (StatusReg & RegisterBit),
    891         (UINT32) (EnableReg & RegisterBit),
    892         GpeRegisterInfo->EnableForRun,
    893         GpeRegisterInfo->EnableForWake));
    894 
    895     EnabledStatusByte = (UINT8) (StatusReg & EnableReg);
    896     if (!(EnabledStatusByte & RegisterBit))
    897     {
    898         goto ErrorExit;
    899     }
    900 
    901     /* Invoke global event handler if present */
    902 
    903     AcpiGpeCount++;
    904     if (AcpiGbl_GlobalEventHandler)
    905     {
    906         AcpiGbl_GlobalEventHandler (ACPI_EVENT_TYPE_GPE,
    907             GpeDevice, GpeNumber,
    908             AcpiGbl_GlobalEventHandlerContext);
    909     }
    910 
    911     /* Found an active GPE */
    912 
    913     if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) ==
    914         ACPI_GPE_DISPATCH_RAW_HANDLER)
    915     {
    916         /* Dispatch the event to a raw handler */
    917 
    918         GpeHandlerInfo = GpeEventInfo->Dispatch.Handler;
    919 
    920         /*
    921          * There is no protection around the namespace node
    922          * and the GPE handler to ensure a safe destruction
    923          * because:
    924          * 1. The namespace node is expected to always
    925          *    exist after loading a table.
    926          * 2. The GPE handler is expected to be flushed by
    927          *    AcpiOsWaitEventsComplete() before the
    928          *    destruction.
    929          */
    930         AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
    931         IntStatus |= GpeHandlerInfo->Address (
    932             GpeDevice, GpeNumber, GpeHandlerInfo->Context);
    933         Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
    934     }
    935     else
    936     {
    937         /* Dispatch the event to a standard handler or method. */
    938 
    939         IntStatus |= AcpiEvGpeDispatch (GpeDevice,
    940             GpeEventInfo, GpeNumber);
    941     }
    942 
    943 ErrorExit:
    944     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
    945     return (IntStatus);
    946 }
    947 
    948 
    949 /*******************************************************************************
    950  *
    951  * FUNCTION:    AcpiEvGpeDispatch
    952  *
    953  * PARAMETERS:  GpeDevice           - Device node. NULL for GPE0/GPE1
    954  *              GpeEventInfo        - Info for this GPE
    955  *              GpeNumber           - Number relative to the parent GPE block
    956  *
    957  * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
    958  *
    959  * DESCRIPTION: Dispatch a General Purpose Event to either a function (e.g. EC)
    960  *              or method (e.g. _Lxx/_Exx) handler.
    961  *
    962  ******************************************************************************/
    963 
    964 UINT32
    965 AcpiEvGpeDispatch (
    966     ACPI_NAMESPACE_NODE     *GpeDevice,
    967     ACPI_GPE_EVENT_INFO     *GpeEventInfo,
    968     UINT32                  GpeNumber)
    969 {
    970     ACPI_STATUS             Status;
    971     UINT32                  ReturnValue;
    972 
    973 
    974     ACPI_FUNCTION_TRACE (EvGpeDispatch);
    975 
    976 
    977     /*
    978      * Always disable the GPE so that it does not keep firing before
    979      * any asynchronous activity completes (either from the execution
    980      * of a GPE method or an asynchronous GPE handler.)
    981      *
    982      * If there is no handler or method to run, just disable the
    983      * GPE and leave it disabled permanently to prevent further such
    984      * pointless events from firing.
    985      */
    986     Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE);
    987     if (ACPI_FAILURE (Status))
    988     {
    989         ACPI_EXCEPTION ((AE_INFO, Status,
    990             "Unable to disable GPE %02X", GpeNumber));
    991         return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
    992     }
    993 
    994     /*
    995      * If edge-triggered, clear the GPE status bit now. Note that
    996      * level-triggered events are cleared after the GPE is serviced.
    997      */
    998     if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
    999             ACPI_GPE_EDGE_TRIGGERED)
   1000     {
   1001         Status = AcpiHwClearGpe (GpeEventInfo);
   1002         if (ACPI_FAILURE (Status))
   1003         {
   1004             ACPI_EXCEPTION ((AE_INFO, Status,
   1005                 "Unable to clear GPE %02X", GpeNumber));
   1006             (void) AcpiHwLowSetGpe (
   1007                 GpeEventInfo, ACPI_GPE_CONDITIONAL_ENABLE);
   1008             return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
   1009         }
   1010     }
   1011 
   1012     GpeEventInfo->DisableForDispatch = TRUE;
   1013 
   1014     /*
   1015      * Dispatch the GPE to either an installed handler or the control
   1016      * method associated with this GPE (_Lxx or _Exx). If a handler
   1017      * exists, we invoke it and do not attempt to run the method.
   1018      * If there is neither a handler nor a method, leave the GPE
   1019      * disabled.
   1020      */
   1021     switch (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags))
   1022     {
   1023     case ACPI_GPE_DISPATCH_HANDLER:
   1024 
   1025         /* Invoke the installed handler (at interrupt level) */
   1026 
   1027         ReturnValue = GpeEventInfo->Dispatch.Handler->Address (
   1028             GpeDevice, GpeNumber,
   1029             GpeEventInfo->Dispatch.Handler->Context);
   1030 
   1031         /* If requested, clear (if level-triggered) and re-enable the GPE */
   1032 
   1033         if (ReturnValue & ACPI_REENABLE_GPE)
   1034         {
   1035             (void) AcpiEvFinishGpe (GpeEventInfo);
   1036         }
   1037         break;
   1038 
   1039     case ACPI_GPE_DISPATCH_METHOD:
   1040     case ACPI_GPE_DISPATCH_NOTIFY:
   1041         /*
   1042          * Execute the method associated with the GPE
   1043          * NOTE: Level-triggered GPEs are cleared after the method completes.
   1044          */
   1045         Status = AcpiOsExecute (OSL_GPE_HANDLER,
   1046             AcpiEvAsynchExecuteGpeMethod, GpeEventInfo);
   1047         if (ACPI_FAILURE (Status))
   1048         {
   1049             ACPI_EXCEPTION ((AE_INFO, Status,
   1050                 "Unable to queue handler for GPE %02X - event disabled",
   1051                 GpeNumber));
   1052         }
   1053         break;
   1054 
   1055     default:
   1056         /*
   1057          * No handler or method to run!
   1058          * 03/2010: This case should no longer be possible. We will not allow
   1059          * a GPE to be enabled if it has no handler or method.
   1060          */
   1061         ACPI_ERROR ((AE_INFO,
   1062             "No handler or method for GPE %02X, disabling event",
   1063             GpeNumber));
   1064         break;
   1065     }
   1066 
   1067     return_UINT32 (ACPI_INTERRUPT_HANDLED);
   1068 }
   1069 
   1070 #endif /* !ACPI_REDUCED_HARDWARE */
   1071