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