Back to home page

Quest Cross Reference

 
 

    


Warning, cross-references for /kernel/drivers/acpica/evgpe.c need to be fixed.

0001 /******************************************************************************
0002  *
0003  * Module Name: evgpe - General Purpose Event handling and dispatch
0004  *
0005  *****************************************************************************/
0006 
0007 /******************************************************************************
0008  *
0009  * 1. Copyright Notice
0010  *
0011  * Some or all of this work - Copyright (c) 1999 - 2009, Intel Corp.
0012  * All rights reserved.
0013  *
0014  * 2. License
0015  *
0016  * 2.1. This is your license from Intel Corp. under its intellectual property
0017  * rights.  You may have additional license terms from the party that provided
0018  * you this software, covering your right to use that party's intellectual
0019  * property rights.
0020  *
0021  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
0022  * copy of the source code appearing in this file ("Covered Code") an
0023  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
0024  * base code distributed originally by Intel ("Original Intel Code") to copy,
0025  * make derivatives, distribute, use and display any portion of the Covered
0026  * Code in any form, with the right to sublicense such rights; and
0027  *
0028  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
0029  * license (with the right to sublicense), under only those claims of Intel
0030  * patents that are infringed by the Original Intel Code, to make, use, sell,
0031  * offer to sell, and import the Covered Code and derivative works thereof
0032  * solely to the minimum extent necessary to exercise the above copyright
0033  * license, and in no event shall the patent license extend to any additions
0034  * to or modifications of the Original Intel Code.  No other license or right
0035  * is granted directly or by implication, estoppel or otherwise;
0036  *
0037  * The above copyright and patent license is granted only if the following
0038  * conditions are met:
0039  *
0040  * 3. Conditions
0041  *
0042  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
0043  * Redistribution of source code of any substantial portion of the Covered
0044  * Code or modification with rights to further distribute source must include
0045  * the above Copyright Notice, the above License, this list of Conditions,
0046  * and the following Disclaimer and Export Compliance provision.  In addition,
0047  * Licensee must cause all Covered Code to which Licensee contributes to
0048  * contain a file documenting the changes Licensee made to create that Covered
0049  * Code and the date of any change.  Licensee must include in that file the
0050  * documentation of any changes made by any predecessor Licensee.  Licensee
0051  * must include a prominent statement that the modification is derived,
0052  * directly or indirectly, from Original Intel Code.
0053  *
0054  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
0055  * Redistribution of source code of any substantial portion of the Covered
0056  * Code or modification without rights to further distribute source must
0057  * include the following Disclaimer and Export Compliance provision in the
0058  * documentation and/or other materials provided with distribution.  In
0059  * addition, Licensee may not authorize further sublicense of source of any
0060  * portion of the Covered Code, and must include terms to the effect that the
0061  * license from Licensee to its licensee is limited to the intellectual
0062  * property embodied in the software Licensee provides to its licensee, and
0063  * not to intellectual property embodied in modifications its licensee may
0064  * make.
0065  *
0066  * 3.3. Redistribution of Executable. Redistribution in executable form of any
0067  * substantial portion of the Covered Code or modification must reproduce the
0068  * above Copyright Notice, and the following Disclaimer and Export Compliance
0069  * provision in the documentation and/or other materials provided with the
0070  * distribution.
0071  *
0072  * 3.4. Intel retains all right, title, and interest in and to the Original
0073  * Intel Code.
0074  *
0075  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
0076  * Intel shall be used in advertising or otherwise to promote the sale, use or
0077  * other dealings in products derived from or relating to the Covered Code
0078  * without prior written authorization from Intel.
0079  *
0080  * 4. Disclaimer and Export Compliance
0081  *
0082  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
0083  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
0084  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
0085  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
0086  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
0087  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
0088  * PARTICULAR PURPOSE.
0089  *
0090  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
0091  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
0092  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
0093  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
0094  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
0095  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
0096  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
0097  * LIMITED REMEDY.
0098  *
0099  * 4.3. Licensee shall not export, either directly or indirectly, any of this
0100  * software or system incorporating such software without first obtaining any
0101  * required license or other approval from the U. S. Department of Commerce or
0102  * any other agency or department of the United States Government.  In the
0103  * event Licensee exports any such software from the United States or
0104  * re-exports any such software from a foreign destination, Licensee shall
0105  * ensure that the distribution and export/re-export of the software is in
0106  * compliance with all laws, regulations, orders, or other restrictions of the
0107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
0108  * any of its subsidiaries will export/re-export any technical data, process,
0109  * software, or service, directly or indirectly, to any country for which the
0110  * United States government or any agency thereof requires an export license,
0111  * other governmental approval, or letter of assurance, without first obtaining
0112  * such license, approval or letter.
0113  *
0114  *****************************************************************************/
0115 
0116 #include "acpi.h"
0117 #include "accommon.h"
0118 #include "acevents.h"
0119 #include "acnamesp.h"
0120 
0121 #define _COMPONENT          ACPI_EVENTS
0122         ACPI_MODULE_NAME    ("evgpe")
0123 
0124 /* Local prototypes */
0125 
0126 static void ACPI_SYSTEM_XFACE
0127 AcpiEvAsynchExecuteGpeMethod (
0128     void                    *Context);
0129 
0130 static void ACPI_SYSTEM_XFACE
0131 AcpiEvAsynchEnableGpe (
0132     void                    *Context);
0133 
0134 
0135 /*******************************************************************************
0136  *
0137  * FUNCTION:    AcpiEvSetGpeType
0138  *
0139  * PARAMETERS:  GpeEventInfo            - GPE to set
0140  *              Type                    - New type
0141  *
0142  * RETURN:      Status
0143  *
0144  * DESCRIPTION: Sets the new type for the GPE (wake, run, or wake/run)
0145  *
0146  ******************************************************************************/
0147 
0148 ACPI_STATUS
0149 AcpiEvSetGpeType (
0150     ACPI_GPE_EVENT_INFO     *GpeEventInfo,
0151     UINT8                   Type)
0152 {
0153     ACPI_STATUS             Status;
0154 
0155 
0156     ACPI_FUNCTION_TRACE (EvSetGpeType);
0157 
0158 
0159     /* Validate type and update register enable masks */
0160 
0161     switch (Type)
0162     {
0163     case ACPI_GPE_TYPE_WAKE:
0164     case ACPI_GPE_TYPE_RUNTIME:
0165     case ACPI_GPE_TYPE_WAKE_RUN:
0166         break;
0167 
0168     default:
0169         return_ACPI_STATUS (AE_BAD_PARAMETER);
0170     }
0171 
0172     /* Disable the GPE if currently enabled */
0173 
0174     Status = AcpiEvDisableGpe (GpeEventInfo);
0175 
0176     /* Clear the type bits and insert the new Type */
0177 
0178     GpeEventInfo->Flags &= ~ACPI_GPE_TYPE_MASK;
0179     GpeEventInfo->Flags |= Type;
0180     return_ACPI_STATUS (Status);
0181 }
0182 
0183 
0184 /*******************************************************************************
0185  *
0186  * FUNCTION:    AcpiEvUpdateGpeEnableMasks
0187  *
0188  * PARAMETERS:  GpeEventInfo            - GPE to update
0189  *              Type                    - What to do: ACPI_GPE_DISABLE or
0190  *                                        ACPI_GPE_ENABLE
0191  *
0192  * RETURN:      Status
0193  *
0194  * DESCRIPTION: Updates GPE register enable masks based on the GPE type
0195  *
0196  ******************************************************************************/
0197 
0198 ACPI_STATUS
0199 AcpiEvUpdateGpeEnableMasks (
0200     ACPI_GPE_EVENT_INFO     *GpeEventInfo,
0201     UINT8                   Type)
0202 {
0203     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
0204     UINT8                   RegisterBit;
0205 
0206 
0207     ACPI_FUNCTION_TRACE (EvUpdateGpeEnableMasks);
0208 
0209 
0210     GpeRegisterInfo = GpeEventInfo->RegisterInfo;
0211     if (!GpeRegisterInfo)
0212     {
0213         return_ACPI_STATUS (AE_NOT_EXIST);
0214     }
0215 
0216     RegisterBit = (UINT8)
0217         (1 << (GpeEventInfo->GpeNumber - GpeRegisterInfo->BaseGpeNumber));
0218 
0219     /* 1) Disable case. Simply clear all enable bits */
0220 
0221     if (Type == ACPI_GPE_DISABLE)
0222     {
0223         ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, RegisterBit);
0224         ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForRun, RegisterBit);
0225         return_ACPI_STATUS (AE_OK);
0226     }
0227 
0228     /* 2) Enable case. Set/Clear the appropriate enable bits */
0229 
0230     switch (GpeEventInfo->Flags & ACPI_GPE_TYPE_MASK)
0231     {
0232     case ACPI_GPE_TYPE_WAKE:
0233         ACPI_SET_BIT   (GpeRegisterInfo->EnableForWake, RegisterBit);
0234         ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForRun, RegisterBit);
0235         break;
0236 
0237     case ACPI_GPE_TYPE_RUNTIME:
0238         ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, RegisterBit);
0239         ACPI_SET_BIT   (GpeRegisterInfo->EnableForRun, RegisterBit);
0240         break;
0241 
0242     case ACPI_GPE_TYPE_WAKE_RUN:
0243         ACPI_SET_BIT   (GpeRegisterInfo->EnableForWake, RegisterBit);
0244         ACPI_SET_BIT   (GpeRegisterInfo->EnableForRun, RegisterBit);
0245         break;
0246 
0247     default:
0248         return_ACPI_STATUS (AE_BAD_PARAMETER);
0249     }
0250 
0251     return_ACPI_STATUS (AE_OK);
0252 }
0253 
0254 
0255 /*******************************************************************************
0256  *
0257  * FUNCTION:    AcpiEvEnableGpe
0258  *
0259  * PARAMETERS:  GpeEventInfo            - GPE to enable
0260  *              WriteToHardware         - Enable now, or just mark data structs
0261  *                                        (WAKE GPEs should be deferred)
0262  *
0263  * RETURN:      Status
0264  *
0265  * DESCRIPTION: Enable a GPE based on the GPE type
0266  *
0267  ******************************************************************************/
0268 
0269 ACPI_STATUS
0270 AcpiEvEnableGpe (
0271     ACPI_GPE_EVENT_INFO     *GpeEventInfo,
0272     BOOLEAN                 WriteToHardware)
0273 {
0274     ACPI_STATUS             Status;
0275 
0276 
0277     ACPI_FUNCTION_TRACE (EvEnableGpe);
0278 
0279 
0280     /* Make sure HW enable masks are updated */
0281 
0282     Status = AcpiEvUpdateGpeEnableMasks (GpeEventInfo, ACPI_GPE_ENABLE);
0283     if (ACPI_FAILURE (Status))
0284     {
0285         return_ACPI_STATUS (Status);
0286     }
0287 
0288     /* Mark wake-enabled or HW enable, or both */
0289 
0290     switch (GpeEventInfo->Flags & ACPI_GPE_TYPE_MASK)
0291     {
0292     case ACPI_GPE_TYPE_WAKE:
0293 
0294         ACPI_SET_BIT (GpeEventInfo->Flags, ACPI_GPE_WAKE_ENABLED);
0295         break;
0296 
0297     case ACPI_GPE_TYPE_WAKE_RUN:
0298 
0299         ACPI_SET_BIT (GpeEventInfo->Flags, ACPI_GPE_WAKE_ENABLED);
0300 
0301         /*lint -fallthrough */
0302 
0303     case ACPI_GPE_TYPE_RUNTIME:
0304 
0305         ACPI_SET_BIT (GpeEventInfo->Flags, ACPI_GPE_RUN_ENABLED);
0306 
0307         if (WriteToHardware)
0308         {
0309             /* Clear the GPE (of stale events), then enable it */
0310 
0311             Status = AcpiHwClearGpe (GpeEventInfo);
0312             if (ACPI_FAILURE (Status))
0313             {
0314                 return_ACPI_STATUS (Status);
0315             }
0316 
0317             /* Enable the requested runtime GPE */
0318 
0319             Status = AcpiHwWriteGpeEnableReg (GpeEventInfo);
0320         }
0321         break;
0322 
0323     default:
0324         return_ACPI_STATUS (AE_BAD_PARAMETER);
0325     }
0326 
0327     return_ACPI_STATUS (AE_OK);
0328 }
0329 
0330 
0331 /*******************************************************************************
0332  *
0333  * FUNCTION:    AcpiEvDisableGpe
0334  *
0335  * PARAMETERS:  GpeEventInfo            - GPE to disable
0336  *
0337  * RETURN:      Status
0338  *
0339  * DESCRIPTION: Disable a GPE based on the GPE type
0340  *
0341  ******************************************************************************/
0342 
0343 ACPI_STATUS
0344 AcpiEvDisableGpe (
0345     ACPI_GPE_EVENT_INFO     *GpeEventInfo)
0346 {
0347     ACPI_STATUS             Status;
0348 
0349 
0350     ACPI_FUNCTION_TRACE (EvDisableGpe);
0351 
0352 
0353     /*
0354      * Note: Always disable the GPE, even if we think that that it is already
0355      * disabled. It is possible that the AML or some other code has enabled
0356      * the GPE behind our back.
0357      */
0358 
0359     /* Make sure HW enable masks are updated */
0360 
0361     Status = AcpiEvUpdateGpeEnableMasks (GpeEventInfo, ACPI_GPE_DISABLE);
0362     if (ACPI_FAILURE (Status))
0363     {
0364         return_ACPI_STATUS (Status);
0365     }
0366 
0367     /* Clear the appropriate enabled flags for this GPE */
0368 
0369     switch (GpeEventInfo->Flags & ACPI_GPE_TYPE_MASK)
0370     {
0371     case ACPI_GPE_TYPE_WAKE:
0372 
0373         ACPI_CLEAR_BIT (GpeEventInfo->Flags, ACPI_GPE_WAKE_ENABLED);
0374         break;
0375 
0376     case ACPI_GPE_TYPE_WAKE_RUN:
0377 
0378         ACPI_CLEAR_BIT (GpeEventInfo->Flags, ACPI_GPE_WAKE_ENABLED);
0379 
0380         /*lint -fallthrough */
0381 
0382     case ACPI_GPE_TYPE_RUNTIME:
0383 
0384         /* Disable the requested runtime GPE */
0385 
0386         ACPI_CLEAR_BIT (GpeEventInfo->Flags, ACPI_GPE_RUN_ENABLED);
0387         break;
0388 
0389     default:
0390         break;
0391     }
0392 
0393     /*
0394      * Always H/W disable this GPE, even if we don't know the GPE type.
0395      * Simply clear the enable bit for this particular GPE, but do not
0396      * write out the current GPE enable mask since this may inadvertently
0397      * enable GPEs too early. An example is a rogue GPE that has arrived
0398      * during ACPICA initialization - possibly because AML or other code
0399      * has enabled the GPE.
0400      */
0401     Status = AcpiHwLowDisableGpe (GpeEventInfo);
0402     return_ACPI_STATUS (Status);
0403 }
0404 
0405 
0406 /*******************************************************************************
0407  *
0408  * FUNCTION:    AcpiEvGetGpeEventInfo
0409  *
0410  * PARAMETERS:  GpeDevice           - Device node. NULL for GPE0/GPE1
0411  *              GpeNumber           - Raw GPE number
0412  *
0413  * RETURN:      A GPE EventInfo struct. NULL if not a valid GPE
0414  *
0415  * DESCRIPTION: Returns the EventInfo struct associated with this GPE.
0416  *              Validates the GpeBlock and the GpeNumber
0417  *
0418  *              Should be called only when the GPE lists are semaphore locked
0419  *              and not subject to change.
0420  *
0421  ******************************************************************************/
0422 
0423 ACPI_GPE_EVENT_INFO *
0424 AcpiEvGetGpeEventInfo (
0425     ACPI_HANDLE             GpeDevice,
0426     UINT32                  GpeNumber)
0427 {
0428     ACPI_OPERAND_OBJECT     *ObjDesc;
0429     ACPI_GPE_BLOCK_INFO     *GpeBlock;
0430     UINT32                  i;
0431 
0432 
0433     ACPI_FUNCTION_ENTRY ();
0434 
0435 
0436     /* A NULL GpeBlock means use the FADT-defined GPE block(s) */
0437 
0438     if (!GpeDevice)
0439     {
0440         /* Examine GPE Block 0 and 1 (These blocks are permanent) */
0441 
0442         for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++)
0443         {
0444             GpeBlock = AcpiGbl_GpeFadtBlocks[i];
0445             if (GpeBlock)
0446             {
0447                 if ((GpeNumber >= GpeBlock->BlockBaseNumber) &&
0448                     (GpeNumber < GpeBlock->BlockBaseNumber +
0449                         (GpeBlock->RegisterCount * 8)))
0450                 {
0451                     return (&GpeBlock->EventInfo[GpeNumber -
0452                         GpeBlock->BlockBaseNumber]);
0453                 }
0454             }
0455         }
0456 
0457         /* The GpeNumber was not in the range of either FADT GPE block */
0458 
0459         return (NULL);
0460     }
0461 
0462     /* A Non-NULL GpeDevice means this is a GPE Block Device */
0463 
0464     ObjDesc = AcpiNsGetAttachedObject ((ACPI_NAMESPACE_NODE *) GpeDevice);
0465     if (!ObjDesc ||
0466         !ObjDesc->Device.GpeBlock)
0467     {
0468         return (NULL);
0469     }
0470 
0471     GpeBlock = ObjDesc->Device.GpeBlock;
0472 
0473     if ((GpeNumber >= GpeBlock->BlockBaseNumber) &&
0474         (GpeNumber < GpeBlock->BlockBaseNumber + (GpeBlock->RegisterCount * 8)))
0475     {
0476         return (&GpeBlock->EventInfo[GpeNumber - GpeBlock->BlockBaseNumber]);
0477     }
0478 
0479     return (NULL);
0480 }
0481 
0482 
0483 /*******************************************************************************
0484  *
0485  * FUNCTION:    AcpiEvGpeDetect
0486  *
0487  * PARAMETERS:  GpeXruptList        - Interrupt block for this interrupt.
0488  *                                    Can have multiple GPE blocks attached.
0489  *
0490  * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
0491  *
0492  * DESCRIPTION: Detect if any GP events have occurred. This function is
0493  *              executed at interrupt level.
0494  *
0495  ******************************************************************************/
0496 
0497 UINT32
0498 AcpiEvGpeDetect (
0499     ACPI_GPE_XRUPT_INFO     *GpeXruptList)
0500 {
0501     ACPI_STATUS             Status;
0502     ACPI_GPE_BLOCK_INFO     *GpeBlock;
0503     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
0504     UINT32                  IntStatus = ACPI_INTERRUPT_NOT_HANDLED;
0505     UINT8                   EnabledStatusByte;
0506     UINT32                  StatusReg;
0507     UINT32                  EnableReg;
0508     ACPI_CPU_FLAGS          Flags;
0509     UINT32                  i;
0510     UINT32                  j;
0511 
0512 
0513     ACPI_FUNCTION_NAME (EvGpeDetect);
0514 
0515     /* Check for the case where there are no GPEs */
0516 
0517     if (!GpeXruptList)
0518     {
0519         return (IntStatus);
0520     }
0521 
0522     /*
0523      * We need to obtain the GPE lock for both the data structs and registers
0524      * Note: Not necessary to obtain the hardware lock, since the GPE
0525      * registers are owned by the GpeLock.
0526      */
0527     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
0528 
0529     /* Examine all GPE blocks attached to this interrupt level */
0530 
0531     GpeBlock = GpeXruptList->GpeBlockListHead;
0532     while (GpeBlock)
0533     {
0534         /*
0535          * Read all of the 8-bit GPE status and enable registers in this GPE
0536          * block, saving all of them. Find all currently active GP events.
0537          */
0538         for (i = 0; i < GpeBlock->RegisterCount; i++)
0539         {
0540             /* Get the next status/enable pair */
0541 
0542             GpeRegisterInfo = &GpeBlock->RegisterInfo[i];
0543 
0544             /* Read the Status Register */
0545 
0546             Status = AcpiHwRead (&StatusReg, &GpeRegisterInfo->StatusAddress);
0547             if (ACPI_FAILURE (Status))
0548             {
0549                 goto UnlockAndExit;
0550             }
0551 
0552             /* Read the Enable Register */
0553 
0554             Status = AcpiHwRead (&EnableReg, &GpeRegisterInfo->EnableAddress);
0555             if (ACPI_FAILURE (Status))
0556             {
0557                 goto UnlockAndExit;
0558             }
0559 
0560             ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
0561                 "Read GPE Register at GPE%X: Status=%02X, Enable=%02X\n",
0562                 GpeRegisterInfo->BaseGpeNumber, StatusReg, EnableReg));
0563 
0564             /* Check if there is anything active at all in this register */
0565 
0566             EnabledStatusByte = (UINT8) (StatusReg & EnableReg);
0567             if (!EnabledStatusByte)
0568             {
0569                 /* No active GPEs in this register, move on */
0570 
0571                 continue;
0572             }
0573 
0574             /* Now look at the individual GPEs in this byte register */
0575 
0576             for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++)
0577             {
0578                 /* Examine one GPE bit */
0579 
0580                 if (EnabledStatusByte & (1 << j))
0581                 {
0582                     /*
0583                      * Found an active GPE. Dispatch the event to a handler
0584                      * or method.
0585                      */
0586                     IntStatus |= AcpiEvGpeDispatch (
0587                         &GpeBlock->EventInfo[((ACPI_SIZE) i *
0588                             ACPI_GPE_REGISTER_WIDTH) + j],
0589                         j + GpeRegisterInfo->BaseGpeNumber);
0590                 }
0591             }
0592         }
0593 
0594         GpeBlock = GpeBlock->Next;
0595     }
0596 
0597 UnlockAndExit:
0598 
0599     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
0600     return (IntStatus);
0601 }
0602 
0603 
0604 /*******************************************************************************
0605  *
0606  * FUNCTION:    AcpiEvAsynchExecuteGpeMethod
0607  *
0608  * PARAMETERS:  Context (GpeEventInfo) - Info for this GPE
0609  *
0610  * RETURN:      None
0611  *
0612  * DESCRIPTION: Perform the actual execution of a GPE control method. This
0613  *              function is called from an invocation of AcpiOsExecute and
0614  *              therefore does NOT execute at interrupt level - so that
0615  *              the control method itself is not executed in the context of
0616  *              an interrupt handler.
0617  *
0618  ******************************************************************************/
0619 
0620 static void ACPI_SYSTEM_XFACE
0621 AcpiEvAsynchExecuteGpeMethod (
0622     void                    *Context)
0623 {
0624     ACPI_GPE_EVENT_INFO     *GpeEventInfo = Context;
0625     ACPI_STATUS             Status;
0626     ACPI_GPE_EVENT_INFO     *LocalGpeEventInfo;
0627     ACPI_EVALUATE_INFO      *Info;
0628 
0629 
0630     ACPI_FUNCTION_TRACE (EvAsynchExecuteGpeMethod);
0631 
0632 
0633     /* Allocate a local GPE block */
0634 
0635     LocalGpeEventInfo = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_EVENT_INFO));
0636     if (!LocalGpeEventInfo)
0637     {
0638         ACPI_EXCEPTION ((AE_INFO, AE_NO_MEMORY,
0639             "while handling a GPE"));
0640         return_VOID;
0641     }
0642 
0643     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
0644     if (ACPI_FAILURE (Status))
0645     {
0646         return_VOID;
0647     }
0648 
0649     /* Must revalidate the GpeNumber/GpeBlock */
0650 
0651     if (!AcpiEvValidGpeEvent (GpeEventInfo))
0652     {
0653         Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
0654         return_VOID;
0655     }
0656 
0657     /* Set the GPE flags for return to enabled state */
0658 
0659     (void) AcpiEvEnableGpe (GpeEventInfo, FALSE);
0660 
0661     /*
0662      * Take a snapshot of the GPE info for this level - we copy the info to
0663      * prevent a race condition with RemoveHandler/RemoveBlock.
0664      */
0665     ACPI_MEMCPY (LocalGpeEventInfo, GpeEventInfo,
0666         sizeof (ACPI_GPE_EVENT_INFO));
0667 
0668     Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
0669     if (ACPI_FAILURE (Status))
0670     {
0671         return_VOID;
0672     }
0673 
0674     /*
0675      * Must check for control method type dispatch one more time to avoid a
0676      * race with EvGpeInstallHandler
0677      */
0678     if ((LocalGpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
0679             ACPI_GPE_DISPATCH_METHOD)
0680     {
0681         /* Allocate the evaluation information block */
0682 
0683         Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
0684         if (!Info)
0685         {
0686             Status = AE_NO_MEMORY;
0687         }
0688         else
0689         {
0690             /*
0691              * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the _Lxx/_Exx
0692              * control method that corresponds to this GPE
0693              */
0694             Info->PrefixNode = LocalGpeEventInfo->Dispatch.MethodNode;
0695             Info->Flags = ACPI_IGNORE_RETURN_VALUE;
0696 
0697             Status = AcpiNsEvaluate (Info);
0698             ACPI_FREE (Info);
0699         }
0700 
0701         if (ACPI_FAILURE (Status))
0702         {
0703             ACPI_EXCEPTION ((AE_INFO, Status,
0704                 "while evaluating GPE method [%4.4s]",
0705                 AcpiUtGetNodeName (LocalGpeEventInfo->Dispatch.MethodNode)));
0706         }
0707     }
0708 
0709     /* Defer enabling of GPE until all notify handlers are done */
0710 
0711     Status = AcpiOsExecute (OSL_NOTIFY_HANDLER,
0712                 AcpiEvAsynchEnableGpe, LocalGpeEventInfo);
0713     if (ACPI_FAILURE (Status))
0714     {
0715         ACPI_FREE (LocalGpeEventInfo);
0716     }
0717     return_VOID;
0718 }
0719 
0720 
0721 /*******************************************************************************
0722  *
0723  * FUNCTION:    AcpiEvAsynchEnableGpe
0724  *
0725  * PARAMETERS:  Context (GpeEventInfo) - Info for this GPE
0726  *
0727  * RETURN:      None
0728  *
0729  * DESCRIPTION: Asynchronous clear/enable for GPE. This allows the GPE to
0730  *              complete (i.e., finish execution of Notify)
0731  *
0732  ******************************************************************************/
0733 
0734 static void ACPI_SYSTEM_XFACE
0735 AcpiEvAsynchEnableGpe (
0736     void                    *Context)
0737 {
0738     ACPI_GPE_EVENT_INFO     *GpeEventInfo = Context;
0739     ACPI_STATUS             Status;
0740 
0741 
0742     if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
0743             ACPI_GPE_LEVEL_TRIGGERED)
0744     {
0745         /*
0746          * GPE is level-triggered, we clear the GPE status bit after handling
0747          * the event.
0748          */
0749         Status = AcpiHwClearGpe (GpeEventInfo);
0750         if (ACPI_FAILURE (Status))
0751         {
0752             goto Exit;
0753         }
0754     }
0755 
0756     /* Enable this GPE */
0757 
0758     (void) AcpiHwWriteGpeEnableReg (GpeEventInfo);
0759 
0760 Exit:
0761     ACPI_FREE (GpeEventInfo);
0762     return;
0763 }
0764 
0765 
0766 /*******************************************************************************
0767  *
0768  * FUNCTION:    AcpiEvGpeDispatch
0769  *
0770  * PARAMETERS:  GpeEventInfo    - Info for this GPE
0771  *              GpeNumber       - Number relative to the parent GPE block
0772  *
0773  * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
0774  *
0775  * DESCRIPTION: Dispatch a General Purpose Event to either a function (e.g. EC)
0776  *              or method (e.g. _Lxx/_Exx) handler.
0777  *
0778  *              This function executes at interrupt level.
0779  *
0780  ******************************************************************************/
0781 
0782 UINT32
0783 AcpiEvGpeDispatch (
0784     ACPI_GPE_EVENT_INFO     *GpeEventInfo,
0785     UINT32                  GpeNumber)
0786 {
0787     ACPI_STATUS             Status;
0788 
0789 
0790     ACPI_FUNCTION_TRACE (EvGpeDispatch);
0791 
0792 
0793     AcpiGpeCount++;
0794 
0795     /*
0796      * If edge-triggered, clear the GPE status bit now. Note that
0797      * level-triggered events are cleared after the GPE is serviced.
0798      */
0799     if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
0800             ACPI_GPE_EDGE_TRIGGERED)
0801     {
0802         Status = AcpiHwClearGpe (GpeEventInfo);
0803         if (ACPI_FAILURE (Status))
0804         {
0805             ACPI_EXCEPTION ((AE_INFO, Status,
0806                 "Unable to clear GPE[%2X]", GpeNumber));
0807             return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
0808         }
0809     }
0810 
0811     /*
0812      * Dispatch the GPE to either an installed handler, or the control method
0813      * associated with this GPE (_Lxx or _Exx). If a handler exists, we invoke
0814      * it and do not attempt to run the method. If there is neither a handler
0815      * nor a method, we disable this GPE to prevent further such pointless
0816      * events from firing.
0817      */
0818     switch (GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK)
0819     {
0820     case ACPI_GPE_DISPATCH_HANDLER:
0821 
0822         /*
0823          * Invoke the installed handler (at interrupt level)
0824          * Ignore return status for now.
0825          * TBD: leave GPE disabled on error?
0826          */
0827         (void) GpeEventInfo->Dispatch.Handler->Address (
0828                         GpeEventInfo->Dispatch.Handler->Context);
0829 
0830         /* It is now safe to clear level-triggered events. */
0831 
0832         if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
0833                 ACPI_GPE_LEVEL_TRIGGERED)
0834         {
0835             Status = AcpiHwClearGpe (GpeEventInfo);
0836             if (ACPI_FAILURE (Status))
0837             {
0838                 ACPI_EXCEPTION ((AE_INFO, Status,
0839                     "Unable to clear GPE[%2X]", GpeNumber));
0840                 return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
0841             }
0842         }
0843         break;
0844 
0845     case ACPI_GPE_DISPATCH_METHOD:
0846 
0847         /*
0848          * Disable the GPE, so it doesn't keep firing before the method has a
0849          * chance to run (it runs asynchronously with interrupts enabled).
0850          */
0851         Status = AcpiEvDisableGpe (GpeEventInfo);
0852         if (ACPI_FAILURE (Status))
0853         {
0854             ACPI_EXCEPTION ((AE_INFO, Status,
0855                 "Unable to disable GPE[%2X]", GpeNumber));
0856             return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
0857         }
0858 
0859         /*
0860          * Execute the method associated with the GPE
0861          * NOTE: Level-triggered GPEs are cleared after the method completes.
0862          */
0863         Status = AcpiOsExecute (OSL_GPE_HANDLER,
0864                     AcpiEvAsynchExecuteGpeMethod, GpeEventInfo);
0865         if (ACPI_FAILURE (Status))
0866         {
0867             ACPI_EXCEPTION ((AE_INFO, Status,
0868                 "Unable to queue handler for GPE[%2X] - event disabled",
0869                 GpeNumber));
0870         }
0871         break;
0872 
0873     default:
0874 
0875         /* No handler or method to run! */
0876 
0877         ACPI_ERROR ((AE_INFO,
0878             "No handler or method for GPE[%2X], disabling event",
0879             GpeNumber));
0880 
0881         /*
0882          * Disable the GPE. The GPE will remain disabled until the ACPICA
0883          * Core Subsystem is restarted, or a handler is installed.
0884          */
0885         Status = AcpiEvDisableGpe (GpeEventInfo);
0886         if (ACPI_FAILURE (Status))
0887         {
0888             ACPI_EXCEPTION ((AE_INFO, Status,
0889                 "Unable to disable GPE[%2X]", GpeNumber));
0890             return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
0891         }
0892         break;
0893     }
0894 
0895     return_UINT32 (ACPI_INTERRUPT_HANDLED);
0896 }
0897