evgpe.c revision 197104
1228060Sbapt/******************************************************************************
2228060Sbapt *
3228060Sbapt * Module Name: evgpe - General Purpose Event handling and dispatch
4228060Sbapt *
5228060Sbapt *****************************************************************************/
6228060Sbapt
7228060Sbapt/******************************************************************************
8228060Sbapt *
9228060Sbapt * 1. Copyright Notice
10228060Sbapt *
11228060Sbapt * Some or all of this work - Copyright (c) 1999 - 2009, Intel Corp.
12228060Sbapt * All rights reserved.
13228060Sbapt *
14228060Sbapt * 2. License
15228060Sbapt *
16228060Sbapt * 2.1. This is your license from Intel Corp. under its intellectual property
17228060Sbapt * rights.  You may have additional license terms from the party that provided
18228060Sbapt * you this software, covering your right to use that party's intellectual
19228060Sbapt * property rights.
20228060Sbapt *
21228060Sbapt * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22228060Sbapt * copy of the source code appearing in this file ("Covered Code") an
23228060Sbapt * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24228060Sbapt * base code distributed originally by Intel ("Original Intel Code") to copy,
25228060Sbapt * make derivatives, distribute, use and display any portion of the Covered
26228060Sbapt * Code in any form, with the right to sublicense such rights; and
27228060Sbapt *
28228060Sbapt * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29228060Sbapt * license (with the right to sublicense), under only those claims of Intel
30228060Sbapt * patents that are infringed by the Original Intel Code, to make, use, sell,
31228060Sbapt * offer to sell, and import the Covered Code and derivative works thereof
32228060Sbapt * solely to the minimum extent necessary to exercise the above copyright
33228060Sbapt * license, and in no event shall the patent license extend to any additions
34228060Sbapt * to or modifications of the Original Intel Code.  No other license or right
35228060Sbapt * is granted directly or by implication, estoppel or otherwise;
36228060Sbapt *
37228060Sbapt * The above copyright and patent license is granted only if the following
38228060Sbapt * conditions are met:
39228060Sbapt *
40228060Sbapt * 3. Conditions
41228060Sbapt *
42228060Sbapt * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43228060Sbapt * Redistribution of source code of any substantial portion of the Covered
44228060Sbapt * Code or modification with rights to further distribute source must include
45228060Sbapt * the above Copyright Notice, the above License, this list of Conditions,
46228060Sbapt * and the following Disclaimer and Export Compliance provision.  In addition,
47228060Sbapt * Licensee must cause all Covered Code to which Licensee contributes to
48228060Sbapt * contain a file documenting the changes Licensee made to create that Covered
49228060Sbapt * Code and the date of any change.  Licensee must include in that file the
50228060Sbapt * documentation of any changes made by any predecessor Licensee.  Licensee
51228060Sbapt * must include a prominent statement that the modification is derived,
52228060Sbapt * directly or indirectly, from Original Intel Code.
53228060Sbapt *
54228060Sbapt * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55228060Sbapt * Redistribution of source code of any substantial portion of the Covered
56228060Sbapt * Code or modification without rights to further distribute source must
57228060Sbapt * include the following Disclaimer and Export Compliance provision in the
58228060Sbapt * documentation and/or other materials provided with distribution.  In
59228060Sbapt * addition, Licensee may not authorize further sublicense of source of any
60228060Sbapt * portion of the Covered Code, and must include terms to the effect that the
61228060Sbapt * license from Licensee to its licensee is limited to the intellectual
62228060Sbapt * property embodied in the software Licensee provides to its licensee, and
63228060Sbapt * not to intellectual property embodied in modifications its licensee may
64228060Sbapt * make.
65228060Sbapt *
66228060Sbapt * 3.3. Redistribution of Executable. Redistribution in executable form of any
67228060Sbapt * substantial portion of the Covered Code or modification must reproduce the
68228060Sbapt * above Copyright Notice, and the following Disclaimer and Export Compliance
69 * provision in the documentation and/or other materials provided with the
70 * distribution.
71 *
72 * 3.4. Intel retains all right, title, and interest in and to the Original
73 * Intel Code.
74 *
75 * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76 * Intel shall be used in advertising or otherwise to promote the sale, use or
77 * other dealings in products derived from or relating to the Covered Code
78 * without prior written authorization from Intel.
79 *
80 * 4. Disclaimer and Export Compliance
81 *
82 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83 * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
85 * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
86 * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
87 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88 * PARTICULAR PURPOSE.
89 *
90 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
96 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97 * LIMITED REMEDY.
98 *
99 * 4.3. Licensee shall not export, either directly or indirectly, any of this
100 * software or system incorporating such software without first obtaining any
101 * required license or other approval from the U. S. Department of Commerce or
102 * any other agency or department of the United States Government.  In the
103 * event Licensee exports any such software from the United States or
104 * re-exports any such software from a foreign destination, Licensee shall
105 * ensure that the distribution and export/re-export of the software is in
106 * compliance with all laws, regulations, orders, or other restrictions of the
107 * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108 * any of its subsidiaries will export/re-export any technical data, process,
109 * software, or service, directly or indirectly, to any country for which the
110 * United States government or any agency thereof requires an export license,
111 * other governmental approval, or letter of assurance, without first obtaining
112 * such license, approval or letter.
113 *
114 *****************************************************************************/
115
116#include <contrib/dev/acpica/include/acpi.h>
117#include <contrib/dev/acpica/include/accommon.h>
118#include <contrib/dev/acpica/include/acevents.h>
119#include <contrib/dev/acpica/include/acnamesp.h>
120
121#define _COMPONENT          ACPI_EVENTS
122        ACPI_MODULE_NAME    ("evgpe")
123
124/* Local prototypes */
125
126static void ACPI_SYSTEM_XFACE
127AcpiEvAsynchExecuteGpeMethod (
128    void                    *Context);
129
130static void ACPI_SYSTEM_XFACE
131AcpiEvAsynchEnableGpe (
132    void                    *Context);
133
134
135/*******************************************************************************
136 *
137 * FUNCTION:    AcpiEvSetGpeType
138 *
139 * PARAMETERS:  GpeEventInfo            - GPE to set
140 *              Type                    - New type
141 *
142 * RETURN:      Status
143 *
144 * DESCRIPTION: Sets the new type for the GPE (wake, run, or wake/run)
145 *
146 ******************************************************************************/
147
148ACPI_STATUS
149AcpiEvSetGpeType (
150    ACPI_GPE_EVENT_INFO     *GpeEventInfo,
151    UINT8                   Type)
152{
153    ACPI_STATUS             Status;
154
155
156    ACPI_FUNCTION_TRACE (EvSetGpeType);
157
158
159    /* Validate type and update register enable masks */
160
161    switch (Type)
162    {
163    case ACPI_GPE_TYPE_WAKE:
164    case ACPI_GPE_TYPE_RUNTIME:
165    case ACPI_GPE_TYPE_WAKE_RUN:
166        break;
167
168    default:
169        return_ACPI_STATUS (AE_BAD_PARAMETER);
170    }
171
172    /* Disable the GPE if currently enabled */
173
174    Status = AcpiEvDisableGpe (GpeEventInfo);
175
176    /* Clear the type bits and insert the new Type */
177
178    GpeEventInfo->Flags &= ~ACPI_GPE_TYPE_MASK;
179    GpeEventInfo->Flags |= Type;
180    return_ACPI_STATUS (Status);
181}
182
183
184/*******************************************************************************
185 *
186 * FUNCTION:    AcpiEvUpdateGpeEnableMasks
187 *
188 * PARAMETERS:  GpeEventInfo            - GPE to update
189 *              Type                    - What to do: ACPI_GPE_DISABLE or
190 *                                        ACPI_GPE_ENABLE
191 *
192 * RETURN:      Status
193 *
194 * DESCRIPTION: Updates GPE register enable masks based on the GPE type
195 *
196 ******************************************************************************/
197
198ACPI_STATUS
199AcpiEvUpdateGpeEnableMasks (
200    ACPI_GPE_EVENT_INFO     *GpeEventInfo,
201    UINT8                   Type)
202{
203    ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
204    UINT8                   RegisterBit;
205
206
207    ACPI_FUNCTION_TRACE (EvUpdateGpeEnableMasks);
208
209
210    GpeRegisterInfo = GpeEventInfo->RegisterInfo;
211    if (!GpeRegisterInfo)
212    {
213        return_ACPI_STATUS (AE_NOT_EXIST);
214    }
215
216    RegisterBit = (UINT8)
217        (1 << (GpeEventInfo->GpeNumber - GpeRegisterInfo->BaseGpeNumber));
218
219    /* 1) Disable case. Simply clear all enable bits */
220
221    if (Type == ACPI_GPE_DISABLE)
222    {
223        ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, RegisterBit);
224        ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForRun, RegisterBit);
225        return_ACPI_STATUS (AE_OK);
226    }
227
228    /* 2) Enable case. Set/Clear the appropriate enable bits */
229
230    switch (GpeEventInfo->Flags & ACPI_GPE_TYPE_MASK)
231    {
232    case ACPI_GPE_TYPE_WAKE:
233        ACPI_SET_BIT   (GpeRegisterInfo->EnableForWake, RegisterBit);
234        ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForRun, RegisterBit);
235        break;
236
237    case ACPI_GPE_TYPE_RUNTIME:
238        ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, RegisterBit);
239        ACPI_SET_BIT   (GpeRegisterInfo->EnableForRun, RegisterBit);
240        break;
241
242    case ACPI_GPE_TYPE_WAKE_RUN:
243        ACPI_SET_BIT   (GpeRegisterInfo->EnableForWake, RegisterBit);
244        ACPI_SET_BIT   (GpeRegisterInfo->EnableForRun, RegisterBit);
245        break;
246
247    default:
248        return_ACPI_STATUS (AE_BAD_PARAMETER);
249    }
250
251    return_ACPI_STATUS (AE_OK);
252}
253
254
255/*******************************************************************************
256 *
257 * FUNCTION:    AcpiEvEnableGpe
258 *
259 * PARAMETERS:  GpeEventInfo            - GPE to enable
260 *              WriteToHardware         - Enable now, or just mark data structs
261 *                                        (WAKE GPEs should be deferred)
262 *
263 * RETURN:      Status
264 *
265 * DESCRIPTION: Enable a GPE based on the GPE type
266 *
267 ******************************************************************************/
268
269ACPI_STATUS
270AcpiEvEnableGpe (
271    ACPI_GPE_EVENT_INFO     *GpeEventInfo,
272    BOOLEAN                 WriteToHardware)
273{
274    ACPI_STATUS             Status;
275
276
277    ACPI_FUNCTION_TRACE (EvEnableGpe);
278
279
280    /* Make sure HW enable masks are updated */
281
282    Status = AcpiEvUpdateGpeEnableMasks (GpeEventInfo, ACPI_GPE_ENABLE);
283    if (ACPI_FAILURE (Status))
284    {
285        return_ACPI_STATUS (Status);
286    }
287
288    /* Mark wake-enabled or HW enable, or both */
289
290    switch (GpeEventInfo->Flags & ACPI_GPE_TYPE_MASK)
291    {
292    case ACPI_GPE_TYPE_WAKE:
293
294        ACPI_SET_BIT (GpeEventInfo->Flags, ACPI_GPE_WAKE_ENABLED);
295        break;
296
297    case ACPI_GPE_TYPE_WAKE_RUN:
298
299        ACPI_SET_BIT (GpeEventInfo->Flags, ACPI_GPE_WAKE_ENABLED);
300
301        /*lint -fallthrough */
302
303    case ACPI_GPE_TYPE_RUNTIME:
304
305        ACPI_SET_BIT (GpeEventInfo->Flags, ACPI_GPE_RUN_ENABLED);
306
307        if (WriteToHardware)
308        {
309            /* Clear the GPE (of stale events), then enable it */
310
311            Status = AcpiHwClearGpe (GpeEventInfo);
312            if (ACPI_FAILURE (Status))
313            {
314                return_ACPI_STATUS (Status);
315            }
316
317            /* Enable the requested runtime GPE */
318
319            Status = AcpiHwWriteGpeEnableReg (GpeEventInfo);
320        }
321        break;
322
323    default:
324        return_ACPI_STATUS (AE_BAD_PARAMETER);
325    }
326
327    return_ACPI_STATUS (AE_OK);
328}
329
330
331/*******************************************************************************
332 *
333 * FUNCTION:    AcpiEvDisableGpe
334 *
335 * PARAMETERS:  GpeEventInfo            - GPE to disable
336 *
337 * RETURN:      Status
338 *
339 * DESCRIPTION: Disable a GPE based on the GPE type
340 *
341 ******************************************************************************/
342
343ACPI_STATUS
344AcpiEvDisableGpe (
345    ACPI_GPE_EVENT_INFO     *GpeEventInfo)
346{
347    ACPI_STATUS             Status;
348
349
350    ACPI_FUNCTION_TRACE (EvDisableGpe);
351
352
353    /*
354     * Note: Always disable the GPE, even if we think that that it is already
355     * disabled. It is possible that the AML or some other code has enabled
356     * the GPE behind our back.
357     */
358
359    /* Make sure HW enable masks are updated */
360
361    Status = AcpiEvUpdateGpeEnableMasks (GpeEventInfo, ACPI_GPE_DISABLE);
362    if (ACPI_FAILURE (Status))
363    {
364        return_ACPI_STATUS (Status);
365    }
366
367    /* Clear the appropriate enabled flags for this GPE */
368
369    switch (GpeEventInfo->Flags & ACPI_GPE_TYPE_MASK)
370    {
371    case ACPI_GPE_TYPE_WAKE:
372
373        ACPI_CLEAR_BIT (GpeEventInfo->Flags, ACPI_GPE_WAKE_ENABLED);
374        break;
375
376    case ACPI_GPE_TYPE_WAKE_RUN:
377
378        ACPI_CLEAR_BIT (GpeEventInfo->Flags, ACPI_GPE_WAKE_ENABLED);
379
380        /*lint -fallthrough */
381
382    case ACPI_GPE_TYPE_RUNTIME:
383
384        /* Disable the requested runtime GPE */
385
386        ACPI_CLEAR_BIT (GpeEventInfo->Flags, ACPI_GPE_RUN_ENABLED);
387        break;
388
389    default:
390        break;
391    }
392
393    /*
394     * Always H/W disable this GPE, even if we don't know the GPE type.
395     * Simply clear the enable bit for this particular GPE, but do not
396     * write out the current GPE enable mask since this may inadvertently
397     * enable GPEs too early. An example is a rogue GPE that has arrived
398     * during ACPICA initialization - possibly because AML or other code
399     * has enabled the GPE.
400     */
401    Status = AcpiHwLowDisableGpe (GpeEventInfo);
402    return_ACPI_STATUS (Status);
403}
404
405
406/*******************************************************************************
407 *
408 * FUNCTION:    AcpiEvGetGpeEventInfo
409 *
410 * PARAMETERS:  GpeDevice           - Device node. NULL for GPE0/GPE1
411 *              GpeNumber           - Raw GPE number
412 *
413 * RETURN:      A GPE EventInfo struct. NULL if not a valid GPE
414 *
415 * DESCRIPTION: Returns the EventInfo struct associated with this GPE.
416 *              Validates the GpeBlock and the GpeNumber
417 *
418 *              Should be called only when the GPE lists are semaphore locked
419 *              and not subject to change.
420 *
421 ******************************************************************************/
422
423ACPI_GPE_EVENT_INFO *
424AcpiEvGetGpeEventInfo (
425    ACPI_HANDLE             GpeDevice,
426    UINT32                  GpeNumber)
427{
428    ACPI_OPERAND_OBJECT     *ObjDesc;
429    ACPI_GPE_BLOCK_INFO     *GpeBlock;
430    UINT32                  i;
431
432
433    ACPI_FUNCTION_ENTRY ();
434
435
436    /* A NULL GpeBlock means use the FADT-defined GPE block(s) */
437
438    if (!GpeDevice)
439    {
440        /* Examine GPE Block 0 and 1 (These blocks are permanent) */
441
442        for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++)
443        {
444            GpeBlock = AcpiGbl_GpeFadtBlocks[i];
445            if (GpeBlock)
446            {
447                if ((GpeNumber >= GpeBlock->BlockBaseNumber) &&
448                    (GpeNumber < GpeBlock->BlockBaseNumber +
449                        (GpeBlock->RegisterCount * 8)))
450                {
451                    return (&GpeBlock->EventInfo[GpeNumber -
452                        GpeBlock->BlockBaseNumber]);
453                }
454            }
455        }
456
457        /* The GpeNumber was not in the range of either FADT GPE block */
458
459        return (NULL);
460    }
461
462    /* A Non-NULL GpeDevice means this is a GPE Block Device */
463
464    ObjDesc = AcpiNsGetAttachedObject ((ACPI_NAMESPACE_NODE *) GpeDevice);
465    if (!ObjDesc ||
466        !ObjDesc->Device.GpeBlock)
467    {
468        return (NULL);
469    }
470
471    GpeBlock = ObjDesc->Device.GpeBlock;
472
473    if ((GpeNumber >= GpeBlock->BlockBaseNumber) &&
474        (GpeNumber < GpeBlock->BlockBaseNumber + (GpeBlock->RegisterCount * 8)))
475    {
476        return (&GpeBlock->EventInfo[GpeNumber - GpeBlock->BlockBaseNumber]);
477    }
478
479    return (NULL);
480}
481
482
483/*******************************************************************************
484 *
485 * FUNCTION:    AcpiEvGpeDetect
486 *
487 * PARAMETERS:  GpeXruptList        - Interrupt block for this interrupt.
488 *                                    Can have multiple GPE blocks attached.
489 *
490 * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
491 *
492 * DESCRIPTION: Detect if any GP events have occurred. This function is
493 *              executed at interrupt level.
494 *
495 ******************************************************************************/
496
497UINT32
498AcpiEvGpeDetect (
499    ACPI_GPE_XRUPT_INFO     *GpeXruptList)
500{
501    ACPI_STATUS             Status;
502    ACPI_GPE_BLOCK_INFO     *GpeBlock;
503    ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
504    UINT32                  IntStatus = ACPI_INTERRUPT_NOT_HANDLED;
505    UINT8                   EnabledStatusByte;
506    UINT32                  StatusReg;
507    UINT32                  EnableReg;
508    ACPI_CPU_FLAGS          Flags;
509    UINT32                  i;
510    UINT32                  j;
511
512
513    ACPI_FUNCTION_NAME (EvGpeDetect);
514
515    /* Check for the case where there are no GPEs */
516
517    if (!GpeXruptList)
518    {
519        return (IntStatus);
520    }
521
522    /*
523     * We need to obtain the GPE lock for both the data structs and registers
524     * Note: Not necessary to obtain the hardware lock, since the GPE
525     * registers are owned by the GpeLock.
526     */
527    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
528
529    /* Examine all GPE blocks attached to this interrupt level */
530
531    GpeBlock = GpeXruptList->GpeBlockListHead;
532    while (GpeBlock)
533    {
534        /*
535         * Read all of the 8-bit GPE status and enable registers in this GPE
536         * block, saving all of them. Find all currently active GP events.
537         */
538        for (i = 0; i < GpeBlock->RegisterCount; i++)
539        {
540            /* Get the next status/enable pair */
541
542            GpeRegisterInfo = &GpeBlock->RegisterInfo[i];
543
544            /* Read the Status Register */
545
546            Status = AcpiHwRead (&StatusReg, &GpeRegisterInfo->StatusAddress);
547            if (ACPI_FAILURE (Status))
548            {
549                goto UnlockAndExit;
550            }
551
552            /* Read the Enable Register */
553
554            Status = AcpiHwRead (&EnableReg, &GpeRegisterInfo->EnableAddress);
555            if (ACPI_FAILURE (Status))
556            {
557                goto UnlockAndExit;
558            }
559
560            ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
561                "Read GPE Register at GPE%X: Status=%02X, Enable=%02X\n",
562                GpeRegisterInfo->BaseGpeNumber, StatusReg, EnableReg));
563
564            /* Check if there is anything active at all in this register */
565
566            EnabledStatusByte = (UINT8) (StatusReg & EnableReg);
567            if (!EnabledStatusByte)
568            {
569                /* No active GPEs in this register, move on */
570
571                continue;
572            }
573
574            /* Now look at the individual GPEs in this byte register */
575
576            for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++)
577            {
578                /* Examine one GPE bit */
579
580                if (EnabledStatusByte & (1 << j))
581                {
582                    /*
583                     * Found an active GPE. Dispatch the event to a handler
584                     * or method.
585                     */
586                    IntStatus |= AcpiEvGpeDispatch (
587                        &GpeBlock->EventInfo[((ACPI_SIZE) i *
588                            ACPI_GPE_REGISTER_WIDTH) + j],
589                        j + GpeRegisterInfo->BaseGpeNumber);
590                }
591            }
592        }
593
594        GpeBlock = GpeBlock->Next;
595    }
596
597UnlockAndExit:
598
599    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
600    return (IntStatus);
601}
602
603
604/*******************************************************************************
605 *
606 * FUNCTION:    AcpiEvAsynchExecuteGpeMethod
607 *
608 * PARAMETERS:  Context (GpeEventInfo) - Info for this GPE
609 *
610 * RETURN:      None
611 *
612 * DESCRIPTION: Perform the actual execution of a GPE control method. This
613 *              function is called from an invocation of AcpiOsExecute and
614 *              therefore does NOT execute at interrupt level - so that
615 *              the control method itself is not executed in the context of
616 *              an interrupt handler.
617 *
618 ******************************************************************************/
619
620static void ACPI_SYSTEM_XFACE
621AcpiEvAsynchExecuteGpeMethod (
622    void                    *Context)
623{
624    ACPI_GPE_EVENT_INFO     *GpeEventInfo = Context;
625    ACPI_STATUS             Status;
626    ACPI_GPE_EVENT_INFO     *LocalGpeEventInfo;
627    ACPI_EVALUATE_INFO      *Info;
628
629
630    ACPI_FUNCTION_TRACE (EvAsynchExecuteGpeMethod);
631
632
633    /* Allocate a local GPE block */
634
635    LocalGpeEventInfo = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_EVENT_INFO));
636    if (!LocalGpeEventInfo)
637    {
638        ACPI_EXCEPTION ((AE_INFO, AE_NO_MEMORY,
639            "while handling a GPE"));
640        return_VOID;
641    }
642
643    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
644    if (ACPI_FAILURE (Status))
645    {
646        return_VOID;
647    }
648
649    /* Must revalidate the GpeNumber/GpeBlock */
650
651    if (!AcpiEvValidGpeEvent (GpeEventInfo))
652    {
653        Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
654        return_VOID;
655    }
656
657    /* Set the GPE flags for return to enabled state */
658
659    (void) AcpiEvEnableGpe (GpeEventInfo, FALSE);
660
661    /*
662     * Take a snapshot of the GPE info for this level - we copy the info to
663     * prevent a race condition with RemoveHandler/RemoveBlock.
664     */
665    ACPI_MEMCPY (LocalGpeEventInfo, GpeEventInfo,
666        sizeof (ACPI_GPE_EVENT_INFO));
667
668    Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
669    if (ACPI_FAILURE (Status))
670    {
671        return_VOID;
672    }
673
674    /*
675     * Must check for control method type dispatch one more time to avoid a
676     * race with EvGpeInstallHandler
677     */
678    if ((LocalGpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
679            ACPI_GPE_DISPATCH_METHOD)
680    {
681        /* Allocate the evaluation information block */
682
683        Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
684        if (!Info)
685        {
686            Status = AE_NO_MEMORY;
687        }
688        else
689        {
690            /*
691             * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the _Lxx/_Exx
692             * control method that corresponds to this GPE
693             */
694            Info->PrefixNode = LocalGpeEventInfo->Dispatch.MethodNode;
695            Info->Flags = ACPI_IGNORE_RETURN_VALUE;
696
697            Status = AcpiNsEvaluate (Info);
698            ACPI_FREE (Info);
699        }
700
701        if (ACPI_FAILURE (Status))
702        {
703            ACPI_EXCEPTION ((AE_INFO, Status,
704                "while evaluating GPE method [%4.4s]",
705                AcpiUtGetNodeName (LocalGpeEventInfo->Dispatch.MethodNode)));
706        }
707    }
708
709    /* Defer enabling of GPE until all notify handlers are done */
710
711    Status = AcpiOsExecute (OSL_NOTIFY_HANDLER,
712                AcpiEvAsynchEnableGpe, LocalGpeEventInfo);
713    if (ACPI_FAILURE (Status))
714    {
715        ACPI_FREE (LocalGpeEventInfo);
716    }
717    return_VOID;
718}
719
720
721/*******************************************************************************
722 *
723 * FUNCTION:    AcpiEvAsynchEnableGpe
724 *
725 * PARAMETERS:  Context (GpeEventInfo) - Info for this GPE
726 *
727 * RETURN:      None
728 *
729 * DESCRIPTION: Asynchronous clear/enable for GPE. This allows the GPE to
730 *              complete (i.e., finish execution of Notify)
731 *
732 ******************************************************************************/
733
734static void ACPI_SYSTEM_XFACE
735AcpiEvAsynchEnableGpe (
736    void                    *Context)
737{
738    ACPI_GPE_EVENT_INFO     *GpeEventInfo = Context;
739    ACPI_STATUS             Status;
740
741
742    if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
743            ACPI_GPE_LEVEL_TRIGGERED)
744    {
745        /*
746         * GPE is level-triggered, we clear the GPE status bit after handling
747         * the event.
748         */
749        Status = AcpiHwClearGpe (GpeEventInfo);
750        if (ACPI_FAILURE (Status))
751        {
752            goto Exit;
753        }
754    }
755
756    /* Enable this GPE */
757
758    (void) AcpiHwWriteGpeEnableReg (GpeEventInfo);
759
760Exit:
761    ACPI_FREE (GpeEventInfo);
762    return;
763}
764
765
766/*******************************************************************************
767 *
768 * FUNCTION:    AcpiEvGpeDispatch
769 *
770 * PARAMETERS:  GpeEventInfo    - Info for this GPE
771 *              GpeNumber       - Number relative to the parent GPE block
772 *
773 * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
774 *
775 * DESCRIPTION: Dispatch a General Purpose Event to either a function (e.g. EC)
776 *              or method (e.g. _Lxx/_Exx) handler.
777 *
778 *              This function executes at interrupt level.
779 *
780 ******************************************************************************/
781
782UINT32
783AcpiEvGpeDispatch (
784    ACPI_GPE_EVENT_INFO     *GpeEventInfo,
785    UINT32                  GpeNumber)
786{
787    ACPI_STATUS             Status;
788
789
790    ACPI_FUNCTION_TRACE (EvGpeDispatch);
791
792
793    AcpiGpeCount++;
794
795    /*
796     * If edge-triggered, clear the GPE status bit now. Note that
797     * level-triggered events are cleared after the GPE is serviced.
798     */
799    if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
800            ACPI_GPE_EDGE_TRIGGERED)
801    {
802        Status = AcpiHwClearGpe (GpeEventInfo);
803        if (ACPI_FAILURE (Status))
804        {
805            ACPI_EXCEPTION ((AE_INFO, Status,
806                "Unable to clear GPE[%2X]", GpeNumber));
807            return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
808        }
809    }
810
811    /*
812     * Dispatch the GPE to either an installed handler, or the control method
813     * associated with this GPE (_Lxx or _Exx). If a handler exists, we invoke
814     * it and do not attempt to run the method. If there is neither a handler
815     * nor a method, we disable this GPE to prevent further such pointless
816     * events from firing.
817     */
818    switch (GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK)
819    {
820    case ACPI_GPE_DISPATCH_HANDLER:
821
822        /*
823         * Invoke the installed handler (at interrupt level)
824         * Ignore return status for now.
825         * TBD: leave GPE disabled on error?
826         */
827        (void) GpeEventInfo->Dispatch.Handler->Address (
828                        GpeEventInfo->Dispatch.Handler->Context);
829
830        /* It is now safe to clear level-triggered events. */
831
832        if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
833                ACPI_GPE_LEVEL_TRIGGERED)
834        {
835            Status = AcpiHwClearGpe (GpeEventInfo);
836            if (ACPI_FAILURE (Status))
837            {
838                ACPI_EXCEPTION ((AE_INFO, Status,
839                    "Unable to clear GPE[%2X]", GpeNumber));
840                return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
841            }
842        }
843        break;
844
845    case ACPI_GPE_DISPATCH_METHOD:
846
847        /*
848         * Disable the GPE, so it doesn't keep firing before the method has a
849         * chance to run (it runs asynchronously with interrupts enabled).
850         */
851        Status = AcpiEvDisableGpe (GpeEventInfo);
852        if (ACPI_FAILURE (Status))
853        {
854            ACPI_EXCEPTION ((AE_INFO, Status,
855                "Unable to disable GPE[%2X]", GpeNumber));
856            return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
857        }
858
859        /*
860         * Execute the method associated with the GPE
861         * NOTE: Level-triggered GPEs are cleared after the method completes.
862         */
863        Status = AcpiOsExecute (OSL_GPE_HANDLER,
864                    AcpiEvAsynchExecuteGpeMethod, GpeEventInfo);
865        if (ACPI_FAILURE (Status))
866        {
867            ACPI_EXCEPTION ((AE_INFO, Status,
868                "Unable to queue handler for GPE[%2X] - event disabled",
869                GpeNumber));
870        }
871        break;
872
873    default:
874
875        /* No handler or method to run! */
876
877        ACPI_ERROR ((AE_INFO,
878            "No handler or method for GPE[%2X], disabling event",
879            GpeNumber));
880
881        /*
882         * Disable the GPE. The GPE will remain disabled until the ACPICA
883         * Core Subsystem is restarted, or a handler is installed.
884         */
885        Status = AcpiEvDisableGpe (GpeEventInfo);
886        if (ACPI_FAILURE (Status))
887        {
888            ACPI_EXCEPTION ((AE_INFO, Status,
889                "Unable to disable GPE[%2X]", GpeNumber));
890            return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
891        }
892        break;
893    }
894
895    return_UINT32 (ACPI_INTERRUPT_HANDLED);
896}
897
898