Home | History | Annotate | Line # | Download | only in events
evgpe.c revision 1.1.1.6
      1 /******************************************************************************
      2  *
      3  * Module Name: evgpe - General Purpose Event handling and dispatch
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2015, 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 #include "acpi.h"
     45 #include "accommon.h"
     46 #include "acevents.h"
     47 #include "acnamesp.h"
     48 
     49 #define _COMPONENT          ACPI_EVENTS
     50         ACPI_MODULE_NAME    ("evgpe")
     51 
     52 #if (!ACPI_REDUCED_HARDWARE) /* Entire module */
     53 
     54 /* Local prototypes */
     55 
     56 static void ACPI_SYSTEM_XFACE
     57 AcpiEvAsynchExecuteGpeMethod (
     58     void                    *Context);
     59 
     60 static void ACPI_SYSTEM_XFACE
     61 AcpiEvAsynchEnableGpe (
     62     void                    *Context);
     63 
     64 
     65 /*******************************************************************************
     66  *
     67  * FUNCTION:    AcpiEvUpdateGpeEnableMask
     68  *
     69  * PARAMETERS:  GpeEventInfo            - GPE to update
     70  *
     71  * RETURN:      Status
     72  *
     73  * DESCRIPTION: Updates GPE register enable mask based upon whether there are
     74  *              runtime references to this GPE
     75  *
     76  ******************************************************************************/
     77 
     78 ACPI_STATUS
     79 AcpiEvUpdateGpeEnableMask (
     80     ACPI_GPE_EVENT_INFO     *GpeEventInfo)
     81 {
     82     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
     83     UINT32                  RegisterBit;
     84 
     85 
     86     ACPI_FUNCTION_TRACE (EvUpdateGpeEnableMask);
     87 
     88 
     89     GpeRegisterInfo = GpeEventInfo->RegisterInfo;
     90     if (!GpeRegisterInfo)
     91     {
     92         return_ACPI_STATUS (AE_NOT_EXIST);
     93     }
     94 
     95     RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo);
     96 
     97     /* Clear the run bit up front */
     98 
     99     ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForRun, RegisterBit);
    100 
    101     /* Set the mask bit only if there are references to this GPE */
    102 
    103     if (GpeEventInfo->RuntimeCount)
    104     {
    105         ACPI_SET_BIT (GpeRegisterInfo->EnableForRun, (UINT8) RegisterBit);
    106     }
    107     GpeRegisterInfo->EnableMask = GpeRegisterInfo->EnableForRun;
    108 
    109     return_ACPI_STATUS (AE_OK);
    110 }
    111 
    112 
    113 /*******************************************************************************
    114  *
    115  * FUNCTION:    AcpiEvEnableGpe
    116  *
    117  * PARAMETERS:  GpeEventInfo            - GPE to enable
    118  *
    119  * RETURN:      Status
    120  *
    121  * DESCRIPTION: Clear a GPE of stale events and enable it.
    122  *
    123  ******************************************************************************/
    124 
    125 ACPI_STATUS
    126 AcpiEvEnableGpe (
    127     ACPI_GPE_EVENT_INFO     *GpeEventInfo)
    128 {
    129     ACPI_STATUS             Status;
    130 
    131 
    132     ACPI_FUNCTION_TRACE (EvEnableGpe);
    133 
    134 
    135     /* Clear the GPE (of stale events) */
    136 
    137     Status = AcpiHwClearGpe (GpeEventInfo);
    138     if (ACPI_FAILURE (Status))
    139     {
    140         return_ACPI_STATUS (Status);
    141     }
    142 
    143     /* Enable the requested GPE */
    144 
    145     Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_ENABLE);
    146     return_ACPI_STATUS (Status);
    147 }
    148 
    149 
    150 /*******************************************************************************
    151  *
    152  * FUNCTION:    AcpiEvAddGpeReference
    153  *
    154  * PARAMETERS:  GpeEventInfo            - Add a reference to this GPE
    155  *
    156  * RETURN:      Status
    157  *
    158  * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is
    159  *              hardware-enabled.
    160  *
    161  ******************************************************************************/
    162 
    163 ACPI_STATUS
    164 AcpiEvAddGpeReference (
    165     ACPI_GPE_EVENT_INFO     *GpeEventInfo)
    166 {
    167     ACPI_STATUS             Status = AE_OK;
    168 
    169 
    170     ACPI_FUNCTION_TRACE (EvAddGpeReference);
    171 
    172 
    173     if (GpeEventInfo->RuntimeCount == ACPI_UINT8_MAX)
    174     {
    175         return_ACPI_STATUS (AE_LIMIT);
    176     }
    177 
    178     GpeEventInfo->RuntimeCount++;
    179     if (GpeEventInfo->RuntimeCount == 1)
    180     {
    181         /* Enable on first reference */
    182 
    183         Status = AcpiEvUpdateGpeEnableMask (GpeEventInfo);
    184         if (ACPI_SUCCESS (Status))
    185         {
    186             Status = AcpiEvEnableGpe (GpeEventInfo);
    187         }
    188 
    189         if (ACPI_FAILURE (Status))
    190         {
    191             GpeEventInfo->RuntimeCount--;
    192         }
    193     }
    194 
    195     return_ACPI_STATUS (Status);
    196 }
    197 
    198 
    199 /*******************************************************************************
    200  *
    201  * FUNCTION:    AcpiEvRemoveGpeReference
    202  *
    203  * PARAMETERS:  GpeEventInfo            - Remove a reference to this GPE
    204  *
    205  * RETURN:      Status
    206  *
    207  * DESCRIPTION: Remove a reference to a GPE. When the last reference is
    208  *              removed, the GPE is hardware-disabled.
    209  *
    210  ******************************************************************************/
    211 
    212 ACPI_STATUS
    213 AcpiEvRemoveGpeReference (
    214     ACPI_GPE_EVENT_INFO     *GpeEventInfo)
    215 {
    216     ACPI_STATUS             Status = AE_OK;
    217 
    218 
    219     ACPI_FUNCTION_TRACE (EvRemoveGpeReference);
    220 
    221 
    222     if (!GpeEventInfo->RuntimeCount)
    223     {
    224         return_ACPI_STATUS (AE_LIMIT);
    225     }
    226 
    227     GpeEventInfo->RuntimeCount--;
    228     if (!GpeEventInfo->RuntimeCount)
    229     {
    230         /* Disable on last reference */
    231 
    232         Status = AcpiEvUpdateGpeEnableMask (GpeEventInfo);
    233         if (ACPI_SUCCESS (Status))
    234         {
    235             Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE);
    236         }
    237 
    238         if (ACPI_FAILURE (Status))
    239         {
    240             GpeEventInfo->RuntimeCount++;
    241         }
    242     }
    243 
    244     return_ACPI_STATUS (Status);
    245 }
    246 
    247 
    248 /*******************************************************************************
    249  *
    250  * FUNCTION:    AcpiEvLowGetGpeInfo
    251  *
    252  * PARAMETERS:  GpeNumber           - Raw GPE number
    253  *              GpeBlock            - A GPE info block
    254  *
    255  * RETURN:      A GPE EventInfo struct. NULL if not a valid GPE (The GpeNumber
    256  *              is not within the specified GPE block)
    257  *
    258  * DESCRIPTION: Returns the EventInfo struct associated with this GPE. This is
    259  *              the low-level implementation of EvGetGpeEventInfo.
    260  *
    261  ******************************************************************************/
    262 
    263 ACPI_GPE_EVENT_INFO *
    264 AcpiEvLowGetGpeInfo (
    265     UINT32                  GpeNumber,
    266     ACPI_GPE_BLOCK_INFO     *GpeBlock)
    267 {
    268     UINT32                  GpeIndex;
    269 
    270 
    271     /*
    272      * Validate that the GpeNumber is within the specified GpeBlock.
    273      * (Two steps)
    274      */
    275     if (!GpeBlock ||
    276         (GpeNumber < GpeBlock->BlockBaseNumber))
    277     {
    278         return (NULL);
    279     }
    280 
    281     GpeIndex = GpeNumber - GpeBlock->BlockBaseNumber;
    282     if (GpeIndex >= GpeBlock->GpeCount)
    283     {
    284         return (NULL);
    285     }
    286 
    287     return (&GpeBlock->EventInfo[GpeIndex]);
    288 }
    289 
    290 
    291 /*******************************************************************************
    292  *
    293  * FUNCTION:    AcpiEvGetGpeEventInfo
    294  *
    295  * PARAMETERS:  GpeDevice           - Device node. NULL for GPE0/GPE1
    296  *              GpeNumber           - Raw GPE number
    297  *
    298  * RETURN:      A GPE EventInfo struct. NULL if not a valid GPE
    299  *
    300  * DESCRIPTION: Returns the EventInfo struct associated with this GPE.
    301  *              Validates the GpeBlock and the GpeNumber
    302  *
    303  *              Should be called only when the GPE lists are semaphore locked
    304  *              and not subject to change.
    305  *
    306  ******************************************************************************/
    307 
    308 ACPI_GPE_EVENT_INFO *
    309 AcpiEvGetGpeEventInfo (
    310     ACPI_HANDLE             GpeDevice,
    311     UINT32                  GpeNumber)
    312 {
    313     ACPI_OPERAND_OBJECT     *ObjDesc;
    314     ACPI_GPE_EVENT_INFO     *GpeInfo;
    315     UINT32                  i;
    316 
    317 
    318     ACPI_FUNCTION_ENTRY ();
    319 
    320 
    321     /* A NULL GpeDevice means use the FADT-defined GPE block(s) */
    322 
    323     if (!GpeDevice)
    324     {
    325         /* Examine GPE Block 0 and 1 (These blocks are permanent) */
    326 
    327         for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++)
    328         {
    329             GpeInfo = AcpiEvLowGetGpeInfo (GpeNumber,
    330                         AcpiGbl_GpeFadtBlocks[i]);
    331             if (GpeInfo)
    332             {
    333                 return (GpeInfo);
    334             }
    335         }
    336 
    337         /* The GpeNumber was not in the range of either FADT GPE block */
    338 
    339         return (NULL);
    340     }
    341 
    342     /* A Non-NULL GpeDevice means this is a GPE Block Device */
    343 
    344     ObjDesc = AcpiNsGetAttachedObject ((ACPI_NAMESPACE_NODE *) GpeDevice);
    345     if (!ObjDesc ||
    346         !ObjDesc->Device.GpeBlock)
    347     {
    348         return (NULL);
    349     }
    350 
    351     return (AcpiEvLowGetGpeInfo (GpeNumber, ObjDesc->Device.GpeBlock));
    352 }
    353 
    354 
    355 /*******************************************************************************
    356  *
    357  * FUNCTION:    AcpiEvGpeDetect
    358  *
    359  * PARAMETERS:  GpeXruptList        - Interrupt block for this interrupt.
    360  *                                    Can have multiple GPE blocks attached.
    361  *
    362  * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
    363  *
    364  * DESCRIPTION: Detect if any GP events have occurred. This function is
    365  *              executed at interrupt level.
    366  *
    367  ******************************************************************************/
    368 
    369 UINT32
    370 AcpiEvGpeDetect (
    371     ACPI_GPE_XRUPT_INFO     *GpeXruptList)
    372 {
    373     ACPI_STATUS             Status;
    374     ACPI_GPE_BLOCK_INFO     *GpeBlock;
    375     ACPI_NAMESPACE_NODE     *GpeDevice;
    376     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
    377     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
    378     UINT32                  GpeNumber;
    379     ACPI_GPE_HANDLER_INFO   *GpeHandlerInfo;
    380     UINT32                  IntStatus = ACPI_INTERRUPT_NOT_HANDLED;
    381     UINT8                   EnabledStatusByte;
    382     UINT32                  StatusReg;
    383     UINT32                  EnableReg;
    384     ACPI_CPU_FLAGS          Flags;
    385     UINT32                  i;
    386     UINT32                  j;
    387 
    388 
    389     ACPI_FUNCTION_NAME (EvGpeDetect);
    390 
    391     /* Check for the case where there are no GPEs */
    392 
    393     if (!GpeXruptList)
    394     {
    395         return (IntStatus);
    396     }
    397 
    398     /*
    399      * We need to obtain the GPE lock for both the data structs and registers
    400      * Note: Not necessary to obtain the hardware lock, since the GPE
    401      * registers are owned by the GpeLock.
    402      */
    403     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
    404 
    405     /* Examine all GPE blocks attached to this interrupt level */
    406 
    407     GpeBlock = GpeXruptList->GpeBlockListHead;
    408     while (GpeBlock)
    409     {
    410         GpeDevice = GpeBlock->Node;
    411 
    412         /*
    413          * Read all of the 8-bit GPE status and enable registers in this GPE
    414          * block, saving all of them. Find all currently active GP events.
    415          */
    416         for (i = 0; i < GpeBlock->RegisterCount; i++)
    417         {
    418             /* Get the next status/enable pair */
    419 
    420             GpeRegisterInfo = &GpeBlock->RegisterInfo[i];
    421 
    422             /*
    423              * Optimization: If there are no GPEs enabled within this
    424              * register, we can safely ignore the entire register.
    425              */
    426             if (!(GpeRegisterInfo->EnableForRun |
    427                   GpeRegisterInfo->EnableForWake))
    428             {
    429                 ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
    430                     "Ignore disabled registers for GPE %02X-%02X: "
    431                     "RunEnable=%02X, WakeEnable=%02X\n",
    432                     GpeRegisterInfo->BaseGpeNumber,
    433                     GpeRegisterInfo->BaseGpeNumber + (ACPI_GPE_REGISTER_WIDTH - 1),
    434                     GpeRegisterInfo->EnableForRun,
    435                     GpeRegisterInfo->EnableForWake));
    436                 continue;
    437             }
    438 
    439             /* Read the Status Register */
    440 
    441             Status = AcpiHwRead (&StatusReg, &GpeRegisterInfo->StatusAddress);
    442             if (ACPI_FAILURE (Status))
    443             {
    444                 goto UnlockAndExit;
    445             }
    446 
    447             /* Read the Enable Register */
    448 
    449             Status = AcpiHwRead (&EnableReg, &GpeRegisterInfo->EnableAddress);
    450             if (ACPI_FAILURE (Status))
    451             {
    452                 goto UnlockAndExit;
    453             }
    454 
    455             ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
    456                 "Read registers for GPE %02X-%02X: Status=%02X, Enable=%02X, "
    457                 "RunEnable=%02X, WakeEnable=%02X\n",
    458                 GpeRegisterInfo->BaseGpeNumber,
    459                 GpeRegisterInfo->BaseGpeNumber + (ACPI_GPE_REGISTER_WIDTH - 1),
    460                 StatusReg, EnableReg,
    461                 GpeRegisterInfo->EnableForRun,
    462                 GpeRegisterInfo->EnableForWake));
    463 
    464             /* Check if there is anything active at all in this register */
    465 
    466             EnabledStatusByte = (UINT8) (StatusReg & EnableReg);
    467             if (!EnabledStatusByte)
    468             {
    469                 /* No active GPEs in this register, move on */
    470 
    471                 continue;
    472             }
    473 
    474             /* Now look at the individual GPEs in this byte register */
    475 
    476             for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++)
    477             {
    478                 /* Examine one GPE bit */
    479 
    480                 GpeEventInfo = &GpeBlock->EventInfo[((ACPI_SIZE) i *
    481                     ACPI_GPE_REGISTER_WIDTH) + j];
    482                 GpeNumber = j + GpeRegisterInfo->BaseGpeNumber;
    483 
    484                 if (EnabledStatusByte & (1 << j))
    485                 {
    486                     /* Invoke global event handler if present */
    487 
    488                     AcpiGpeCount++;
    489                     if (AcpiGbl_GlobalEventHandler)
    490                     {
    491                         AcpiGbl_GlobalEventHandler (ACPI_EVENT_TYPE_GPE,
    492                             GpeDevice, GpeNumber,
    493                             AcpiGbl_GlobalEventHandlerContext);
    494                     }
    495 
    496                     /* Found an active GPE */
    497 
    498                     if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) ==
    499                         ACPI_GPE_DISPATCH_RAW_HANDLER)
    500                     {
    501                         /* Dispatch the event to a raw handler */
    502 
    503                         GpeHandlerInfo = GpeEventInfo->Dispatch.Handler;
    504 
    505                         /*
    506                          * There is no protection around the namespace node
    507                          * and the GPE handler to ensure a safe destruction
    508                          * because:
    509                          * 1. The namespace node is expected to always
    510                          *    exist after loading a table.
    511                          * 2. The GPE handler is expected to be flushed by
    512                          *    AcpiOsWaitEventsComplete() before the
    513                          *    destruction.
    514                          */
    515                         AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
    516                         IntStatus |= GpeHandlerInfo->Address (
    517                             GpeDevice, GpeNumber, GpeHandlerInfo->Context);
    518                         Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
    519                     }
    520                     else
    521                     {
    522                         /*
    523                          * Dispatch the event to a standard handler or
    524                          * method.
    525                          */
    526                         IntStatus |= AcpiEvGpeDispatch (GpeDevice,
    527                             GpeEventInfo, GpeNumber);
    528                     }
    529                 }
    530             }
    531         }
    532 
    533         GpeBlock = GpeBlock->Next;
    534     }
    535 
    536 UnlockAndExit:
    537 
    538     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
    539     return (IntStatus);
    540 }
    541 
    542 
    543 /*******************************************************************************
    544  *
    545  * FUNCTION:    AcpiEvAsynchExecuteGpeMethod
    546  *
    547  * PARAMETERS:  Context (GpeEventInfo) - Info for this GPE
    548  *
    549  * RETURN:      None
    550  *
    551  * DESCRIPTION: Perform the actual execution of a GPE control method. This
    552  *              function is called from an invocation of AcpiOsExecute and
    553  *              therefore does NOT execute at interrupt level - so that
    554  *              the control method itself is not executed in the context of
    555  *              an interrupt handler.
    556  *
    557  ******************************************************************************/
    558 
    559 static void ACPI_SYSTEM_XFACE
    560 AcpiEvAsynchExecuteGpeMethod (
    561     void                    *Context)
    562 {
    563     ACPI_GPE_EVENT_INFO     *GpeEventInfo = Context;
    564     ACPI_STATUS             Status = AE_OK;
    565     ACPI_EVALUATE_INFO      *Info;
    566     ACPI_GPE_NOTIFY_INFO    *Notify;
    567 
    568 
    569     ACPI_FUNCTION_TRACE (EvAsynchExecuteGpeMethod);
    570 
    571 
    572     /* Do the correct dispatch - normal method or implicit notify */
    573 
    574     switch (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags))
    575     {
    576     case ACPI_GPE_DISPATCH_NOTIFY:
    577         /*
    578          * Implicit notify.
    579          * Dispatch a DEVICE_WAKE notify to the appropriate handler.
    580          * NOTE: the request is queued for execution after this method
    581          * completes. The notify handlers are NOT invoked synchronously
    582          * from this thread -- because handlers may in turn run other
    583          * control methods.
    584          *
    585          * June 2012: Expand implicit notify mechanism to support
    586          * notifies on multiple device objects.
    587          */
    588         Notify = GpeEventInfo->Dispatch.NotifyList;
    589         while (ACPI_SUCCESS (Status) && Notify)
    590         {
    591             Status = AcpiEvQueueNotifyRequest (Notify->DeviceNode,
    592                         ACPI_NOTIFY_DEVICE_WAKE);
    593 
    594             Notify = Notify->Next;
    595         }
    596         break;
    597 
    598     case ACPI_GPE_DISPATCH_METHOD:
    599 
    600         /* Allocate the evaluation information block */
    601 
    602         Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
    603         if (!Info)
    604         {
    605             Status = AE_NO_MEMORY;
    606         }
    607         else
    608         {
    609             /*
    610              * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the
    611              * _Lxx/_Exx control method that corresponds to this GPE
    612              */
    613             Info->PrefixNode = GpeEventInfo->Dispatch.MethodNode;
    614             Info->Flags = ACPI_IGNORE_RETURN_VALUE;
    615 
    616             Status = AcpiNsEvaluate (Info);
    617             ACPI_FREE (Info);
    618         }
    619 
    620         if (ACPI_FAILURE (Status))
    621         {
    622             ACPI_EXCEPTION ((AE_INFO, Status,
    623                 "while evaluating GPE method [%4.4s]",
    624                 AcpiUtGetNodeName (GpeEventInfo->Dispatch.MethodNode)));
    625         }
    626         break;
    627 
    628     default:
    629 
    630         goto ErrorExit; /* Should never happen */
    631     }
    632 
    633     /* Defer enabling of GPE until all notify handlers are done */
    634 
    635     Status = AcpiOsExecute (OSL_NOTIFY_HANDLER,
    636                 AcpiEvAsynchEnableGpe, GpeEventInfo);
    637     if (ACPI_SUCCESS (Status))
    638     {
    639         return_VOID;
    640     }
    641 
    642 ErrorExit:
    643     AcpiEvAsynchEnableGpe (GpeEventInfo);
    644     return_VOID;
    645 }
    646 
    647 
    648 /*******************************************************************************
    649  *
    650  * FUNCTION:    AcpiEvAsynchEnableGpe
    651  *
    652  * PARAMETERS:  Context (GpeEventInfo) - Info for this GPE
    653  *              Callback from AcpiOsExecute
    654  *
    655  * RETURN:      None
    656  *
    657  * DESCRIPTION: Asynchronous clear/enable for GPE. This allows the GPE to
    658  *              complete (i.e., finish execution of Notify)
    659  *
    660  ******************************************************************************/
    661 
    662 static void ACPI_SYSTEM_XFACE
    663 AcpiEvAsynchEnableGpe (
    664     void                    *Context)
    665 {
    666     ACPI_GPE_EVENT_INFO     *GpeEventInfo = Context;
    667     ACPI_CPU_FLAGS          Flags;
    668 
    669 
    670     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
    671     (void) AcpiEvFinishGpe (GpeEventInfo);
    672     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
    673 
    674     return;
    675 }
    676 
    677 
    678 /*******************************************************************************
    679  *
    680  * FUNCTION:    AcpiEvFinishGpe
    681  *
    682  * PARAMETERS:  GpeEventInfo        - Info for this GPE
    683  *
    684  * RETURN:      Status
    685  *
    686  * DESCRIPTION: Clear/Enable a GPE. Common code that is used after execution
    687  *              of a GPE method or a synchronous or asynchronous GPE handler.
    688  *
    689  ******************************************************************************/
    690 
    691 ACPI_STATUS
    692 AcpiEvFinishGpe (
    693     ACPI_GPE_EVENT_INFO     *GpeEventInfo)
    694 {
    695     ACPI_STATUS             Status;
    696 
    697 
    698     if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
    699             ACPI_GPE_LEVEL_TRIGGERED)
    700     {
    701         /*
    702          * GPE is level-triggered, we clear the GPE status bit after
    703          * handling the event.
    704          */
    705         Status = AcpiHwClearGpe (GpeEventInfo);
    706         if (ACPI_FAILURE (Status))
    707         {
    708             return (Status);
    709         }
    710     }
    711 
    712     /*
    713      * Enable this GPE, conditionally. This means that the GPE will
    714      * only be physically enabled if the EnableMask bit is set
    715      * in the EventInfo.
    716      */
    717     (void) AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_CONDITIONAL_ENABLE);
    718     return (AE_OK);
    719 }
    720 
    721 
    722 /*******************************************************************************
    723  *
    724  * FUNCTION:    AcpiEvGpeDispatch
    725  *
    726  * PARAMETERS:  GpeDevice           - Device node. NULL for GPE0/GPE1
    727  *              GpeEventInfo        - Info for this GPE
    728  *              GpeNumber           - Number relative to the parent GPE block
    729  *
    730  * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
    731  *
    732  * DESCRIPTION: Dispatch a General Purpose Event to either a function (e.g. EC)
    733  *              or method (e.g. _Lxx/_Exx) handler.
    734  *
    735  *              This function executes at interrupt level.
    736  *
    737  ******************************************************************************/
    738 
    739 UINT32
    740 AcpiEvGpeDispatch (
    741     ACPI_NAMESPACE_NODE     *GpeDevice,
    742     ACPI_GPE_EVENT_INFO     *GpeEventInfo,
    743     UINT32                  GpeNumber)
    744 {
    745     ACPI_STATUS             Status;
    746     UINT32                  ReturnValue;
    747 
    748 
    749     ACPI_FUNCTION_TRACE (EvGpeDispatch);
    750 
    751 
    752     /*
    753      * Always disable the GPE so that it does not keep firing before
    754      * any asynchronous activity completes (either from the execution
    755      * of a GPE method or an asynchronous GPE handler.)
    756      *
    757      * If there is no handler or method to run, just disable the
    758      * GPE and leave it disabled permanently to prevent further such
    759      * pointless events from firing.
    760      */
    761     Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE);
    762     if (ACPI_FAILURE (Status))
    763     {
    764         ACPI_EXCEPTION ((AE_INFO, Status,
    765             "Unable to disable GPE %02X", GpeNumber));
    766         return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
    767     }
    768 
    769     /*
    770      * If edge-triggered, clear the GPE status bit now. Note that
    771      * level-triggered events are cleared after the GPE is serviced.
    772      */
    773     if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
    774             ACPI_GPE_EDGE_TRIGGERED)
    775     {
    776         Status = AcpiHwClearGpe (GpeEventInfo);
    777         if (ACPI_FAILURE (Status))
    778         {
    779             ACPI_EXCEPTION ((AE_INFO, Status,
    780                 "Unable to clear GPE %02X", GpeNumber));
    781             (void) AcpiHwLowSetGpe (GpeEventInfo,
    782                     ACPI_GPE_CONDITIONAL_ENABLE);
    783             return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
    784         }
    785     }
    786 
    787     /*
    788      * Dispatch the GPE to either an installed handler or the control
    789      * method associated with this GPE (_Lxx or _Exx). If a handler
    790      * exists, we invoke it and do not attempt to run the method.
    791      * If there is neither a handler nor a method, leave the GPE
    792      * disabled.
    793      */
    794     switch (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags))
    795     {
    796     case ACPI_GPE_DISPATCH_HANDLER:
    797 
    798         /* Invoke the installed handler (at interrupt level) */
    799 
    800         ReturnValue = GpeEventInfo->Dispatch.Handler->Address (
    801             GpeDevice, GpeNumber,
    802             GpeEventInfo->Dispatch.Handler->Context);
    803 
    804         /* If requested, clear (if level-triggered) and reenable the GPE */
    805 
    806         if (ReturnValue & ACPI_REENABLE_GPE)
    807         {
    808             (void) AcpiEvFinishGpe (GpeEventInfo);
    809         }
    810         break;
    811 
    812     case ACPI_GPE_DISPATCH_METHOD:
    813     case ACPI_GPE_DISPATCH_NOTIFY:
    814         /*
    815          * Execute the method associated with the GPE
    816          * NOTE: Level-triggered GPEs are cleared after the method completes.
    817          */
    818         Status = AcpiOsExecute (OSL_GPE_HANDLER,
    819                     AcpiEvAsynchExecuteGpeMethod, GpeEventInfo);
    820         if (ACPI_FAILURE (Status))
    821         {
    822             ACPI_EXCEPTION ((AE_INFO, Status,
    823                 "Unable to queue handler for GPE %02X - event disabled",
    824                 GpeNumber));
    825         }
    826         break;
    827 
    828     default:
    829         /*
    830          * No handler or method to run!
    831          * 03/2010: This case should no longer be possible. We will not allow
    832          * a GPE to be enabled if it has no handler or method.
    833          */
    834         ACPI_ERROR ((AE_INFO,
    835             "No handler or method for GPE %02X, disabling event",
    836             GpeNumber));
    837         break;
    838     }
    839 
    840     return_UINT32 (ACPI_INTERRUPT_HANDLED);
    841 }
    842 
    843 #endif /* !ACPI_REDUCED_HARDWARE */
    844