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