evgpe.c revision 206117
1/******************************************************************************
2 *
3 * Module Name: evgpe - General Purpose Event handling and dispatch
4 *
5 *****************************************************************************/
6
7/******************************************************************************
8 *
9 * 1. Copyright Notice
10 *
11 * Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp.
12 * All rights reserved.
13 *
14 * 2. License
15 *
16 * 2.1. This is your license from Intel Corp. under its intellectual property
17 * rights.  You may have additional license terms from the party that provided
18 * you this software, covering your right to use that party's intellectual
19 * property rights.
20 *
21 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22 * copy of the source code appearing in this file ("Covered Code") an
23 * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24 * base code distributed originally by Intel ("Original Intel Code") to copy,
25 * make derivatives, distribute, use and display any portion of the Covered
26 * Code in any form, with the right to sublicense such rights; and
27 *
28 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29 * license (with the right to sublicense), under only those claims of Intel
30 * patents that are infringed by the Original Intel Code, to make, use, sell,
31 * offer to sell, and import the Covered Code and derivative works thereof
32 * solely to the minimum extent necessary to exercise the above copyright
33 * license, and in no event shall the patent license extend to any additions
34 * to or modifications of the Original Intel Code.  No other license or right
35 * is granted directly or by implication, estoppel or otherwise;
36 *
37 * The above copyright and patent license is granted only if the following
38 * conditions are met:
39 *
40 * 3. Conditions
41 *
42 * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43 * Redistribution of source code of any substantial portion of the Covered
44 * Code or modification with rights to further distribute source must include
45 * the above Copyright Notice, the above License, this list of Conditions,
46 * and the following Disclaimer and Export Compliance provision.  In addition,
47 * Licensee must cause all Covered Code to which Licensee contributes to
48 * contain a file documenting the changes Licensee made to create that Covered
49 * Code and the date of any change.  Licensee must include in that file the
50 * documentation of any changes made by any predecessor Licensee.  Licensee
51 * must include a prominent statement that the modification is derived,
52 * directly or indirectly, from Original Intel Code.
53 *
54 * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55 * Redistribution of source code of any substantial portion of the Covered
56 * Code or modification without rights to further distribute source must
57 * include the following Disclaimer and Export Compliance provision in the
58 * documentation and/or other materials provided with distribution.  In
59 * addition, Licensee may not authorize further sublicense of source of any
60 * portion of the Covered Code, and must include terms to the effect that the
61 * license from Licensee to its licensee is limited to the intellectual
62 * property embodied in the software Licensee provides to its licensee, and
63 * not to intellectual property embodied in modifications its licensee may
64 * make.
65 *
66 * 3.3. Redistribution of Executable. Redistribution in executable form of any
67 * substantial portion of the Covered Code or modification must reproduce the
68 * 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:    AcpiEvUpdateGpeEnableMasks
138 *
139 * PARAMETERS:  GpeEventInfo            - GPE to update
140 *
141 * RETURN:      Status
142 *
143 * DESCRIPTION: Updates GPE register enable masks based upon whether there are
144 *              references (either wake or run) to this GPE
145 *
146 ******************************************************************************/
147
148ACPI_STATUS
149AcpiEvUpdateGpeEnableMasks (
150    ACPI_GPE_EVENT_INFO     *GpeEventInfo)
151{
152    ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
153    UINT8                   RegisterBit;
154
155
156    ACPI_FUNCTION_TRACE (EvUpdateGpeEnableMasks);
157
158
159    GpeRegisterInfo = GpeEventInfo->RegisterInfo;
160    if (!GpeRegisterInfo)
161    {
162        return_ACPI_STATUS (AE_NOT_EXIST);
163    }
164
165    RegisterBit = (UINT8)
166        (1 << (GpeEventInfo->GpeNumber - GpeRegisterInfo->BaseGpeNumber));
167
168    /* Clear the wake/run bits up front */
169
170    ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, RegisterBit);
171    ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForRun, RegisterBit);
172
173    /* Set the mask bits only if there are references to this GPE */
174
175    if (GpeEventInfo->RuntimeCount)
176    {
177        ACPI_SET_BIT (GpeRegisterInfo->EnableForRun, RegisterBit);
178    }
179
180    if (GpeEventInfo->WakeupCount)
181    {
182        ACPI_SET_BIT (GpeRegisterInfo->EnableForWake, RegisterBit);
183    }
184
185    return_ACPI_STATUS (AE_OK);
186}
187
188
189/*******************************************************************************
190 *
191 * FUNCTION:    AcpiEvEnableGpe
192 *
193 * PARAMETERS:  GpeEventInfo            - GPE to enable
194 *
195 * RETURN:      Status
196 *
197 * DESCRIPTION: Hardware-enable a GPE. Always enables the GPE, regardless
198 *              of type or number of references.
199 *
200 * Note: The GPE lock should be already acquired when this function is called.
201 *
202 ******************************************************************************/
203
204ACPI_STATUS
205AcpiEvEnableGpe (
206    ACPI_GPE_EVENT_INFO     *GpeEventInfo)
207{
208    ACPI_STATUS             Status;
209
210
211    ACPI_FUNCTION_TRACE (EvEnableGpe);
212
213
214    /*
215     * We will only allow a GPE to be enabled if it has either an
216     * associated method (_Lxx/_Exx) or a handler. Otherwise, the
217     * GPE will be immediately disabled by AcpiEvGpeDispatch the
218     * first time it fires.
219     */
220    if (!(GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK))
221    {
222        return_ACPI_STATUS (AE_NO_HANDLER);
223    }
224
225    /* Ensure the HW enable masks are current */
226
227    Status = AcpiEvUpdateGpeEnableMasks (GpeEventInfo);
228    if (ACPI_FAILURE (Status))
229    {
230        return_ACPI_STATUS (Status);
231    }
232
233    /* Clear the GPE (of stale events) */
234
235    Status = AcpiHwClearGpe (GpeEventInfo);
236    if (ACPI_FAILURE (Status))
237    {
238        return_ACPI_STATUS (Status);
239    }
240
241    /* Enable the requested GPE */
242
243    Status = AcpiHwWriteGpeEnableReg (GpeEventInfo);
244    return_ACPI_STATUS (Status);
245}
246
247
248/*******************************************************************************
249 *
250 * FUNCTION:    AcpiEvDisableGpe
251 *
252 * PARAMETERS:  GpeEventInfo            - GPE to disable
253 *
254 * RETURN:      Status
255 *
256 * DESCRIPTION: Hardware-disable a GPE. Always disables the requested GPE,
257 *              regardless of the type or number of references.
258 *
259 * Note: The GPE lock should be already acquired when this function is called.
260 *
261 ******************************************************************************/
262
263ACPI_STATUS
264AcpiEvDisableGpe (
265    ACPI_GPE_EVENT_INFO     *GpeEventInfo)
266{
267    ACPI_STATUS             Status;
268
269
270    ACPI_FUNCTION_TRACE (EvDisableGpe);
271
272
273    /*
274     * Note: Always disable the GPE, even if we think that that it is already
275     * disabled. It is possible that the AML or some other code has enabled
276     * the GPE behind our back.
277     */
278
279    /* Ensure the HW enable masks are current */
280
281    Status = AcpiEvUpdateGpeEnableMasks (GpeEventInfo);
282    if (ACPI_FAILURE (Status))
283    {
284        return_ACPI_STATUS (Status);
285    }
286
287    /*
288     * Always H/W disable this GPE, even if we don't know the GPE type.
289     * Simply clear the enable bit for this particular GPE, but do not
290     * write out the current GPE enable mask since this may inadvertently
291     * enable GPEs too early. An example is a rogue GPE that has arrived
292     * during ACPICA initialization - possibly because AML or other code
293     * has enabled the GPE.
294     */
295    Status = AcpiHwLowDisableGpe (GpeEventInfo);
296    return_ACPI_STATUS (Status);
297}
298
299
300/*******************************************************************************
301 *
302 * FUNCTION:    AcpiEvLowGetGpeInfo
303 *
304 * PARAMETERS:  GpeNumber           - Raw GPE number
305 *              GpeBlock            - A GPE info block
306 *
307 * RETURN:      A GPE EventInfo struct. NULL if not a valid GPE (The GpeNumber
308 *              is not within the specified GPE block)
309 *
310 * DESCRIPTION: Returns the EventInfo struct associated with this GPE. This is
311 *              the low-level implementation of EvGetGpeEventInfo.
312 *
313 ******************************************************************************/
314
315ACPI_GPE_EVENT_INFO *
316AcpiEvLowGetGpeInfo (
317    UINT32                  GpeNumber,
318    ACPI_GPE_BLOCK_INFO     *GpeBlock)
319{
320    UINT32                  GpeIndex;
321
322
323    /*
324     * Validate that the GpeNumber is within the specified GpeBlock.
325     * (Two steps)
326     */
327    if (!GpeBlock ||
328        (GpeNumber < GpeBlock->BlockBaseNumber))
329    {
330        return (NULL);
331    }
332
333    GpeIndex = GpeNumber - GpeBlock->BlockBaseNumber;
334    if (GpeIndex >= GpeBlock->GpeCount)
335    {
336        return (NULL);
337    }
338
339    return (&GpeBlock->EventInfo[GpeIndex]);
340}
341
342
343/*******************************************************************************
344 *
345 * FUNCTION:    AcpiEvGetGpeEventInfo
346 *
347 * PARAMETERS:  GpeDevice           - Device node. NULL for GPE0/GPE1
348 *              GpeNumber           - Raw GPE number
349 *
350 * RETURN:      A GPE EventInfo struct. NULL if not a valid GPE
351 *
352 * DESCRIPTION: Returns the EventInfo struct associated with this GPE.
353 *              Validates the GpeBlock and the GpeNumber
354 *
355 *              Should be called only when the GPE lists are semaphore locked
356 *              and not subject to change.
357 *
358 ******************************************************************************/
359
360ACPI_GPE_EVENT_INFO *
361AcpiEvGetGpeEventInfo (
362    ACPI_HANDLE             GpeDevice,
363    UINT32                  GpeNumber)
364{
365    ACPI_OPERAND_OBJECT     *ObjDesc;
366    ACPI_GPE_EVENT_INFO     *GpeInfo;
367    UINT32                  i;
368
369
370    ACPI_FUNCTION_ENTRY ();
371
372
373    /* A NULL GpeBlock means use the FADT-defined GPE block(s) */
374
375    if (!GpeDevice)
376    {
377        /* Examine GPE Block 0 and 1 (These blocks are permanent) */
378
379        for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++)
380        {
381            GpeInfo = AcpiEvLowGetGpeInfo (GpeNumber,
382                        AcpiGbl_GpeFadtBlocks[i]);
383            if (GpeInfo)
384            {
385                return (GpeInfo);
386            }
387        }
388
389        /* The GpeNumber was not in the range of either FADT GPE block */
390
391        return (NULL);
392    }
393
394    /* A Non-NULL GpeDevice means this is a GPE Block Device */
395
396    ObjDesc = AcpiNsGetAttachedObject ((ACPI_NAMESPACE_NODE *) GpeDevice);
397    if (!ObjDesc ||
398        !ObjDesc->Device.GpeBlock)
399    {
400        return (NULL);
401    }
402
403    return (AcpiEvLowGetGpeInfo (GpeNumber, ObjDesc->Device.GpeBlock));
404}
405
406
407/*******************************************************************************
408 *
409 * FUNCTION:    AcpiEvGpeDetect
410 *
411 * PARAMETERS:  GpeXruptList        - Interrupt block for this interrupt.
412 *                                    Can have multiple GPE blocks attached.
413 *
414 * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
415 *
416 * DESCRIPTION: Detect if any GP events have occurred. This function is
417 *              executed at interrupt level.
418 *
419 ******************************************************************************/
420
421UINT32
422AcpiEvGpeDetect (
423    ACPI_GPE_XRUPT_INFO     *GpeXruptList)
424{
425    ACPI_STATUS             Status;
426    ACPI_GPE_BLOCK_INFO     *GpeBlock;
427    ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
428    UINT32                  IntStatus = ACPI_INTERRUPT_NOT_HANDLED;
429    UINT8                   EnabledStatusByte;
430    UINT32                  StatusReg;
431    UINT32                  EnableReg;
432    ACPI_CPU_FLAGS          Flags;
433    UINT32                  i;
434    UINT32                  j;
435
436
437    ACPI_FUNCTION_NAME (EvGpeDetect);
438
439    /* Check for the case where there are no GPEs */
440
441    if (!GpeXruptList)
442    {
443        return (IntStatus);
444    }
445
446    /*
447     * We need to obtain the GPE lock for both the data structs and registers
448     * Note: Not necessary to obtain the hardware lock, since the GPE
449     * registers are owned by the GpeLock.
450     */
451    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
452
453    /* Examine all GPE blocks attached to this interrupt level */
454
455    GpeBlock = GpeXruptList->GpeBlockListHead;
456    while (GpeBlock)
457    {
458        /*
459         * Read all of the 8-bit GPE status and enable registers in this GPE
460         * block, saving all of them. Find all currently active GP events.
461         */
462        for (i = 0; i < GpeBlock->RegisterCount; i++)
463        {
464            /* Get the next status/enable pair */
465
466            GpeRegisterInfo = &GpeBlock->RegisterInfo[i];
467
468            /* Read the Status Register */
469
470            Status = AcpiHwRead (&StatusReg, &GpeRegisterInfo->StatusAddress);
471            if (ACPI_FAILURE (Status))
472            {
473                goto UnlockAndExit;
474            }
475
476            /* Read the Enable Register */
477
478            Status = AcpiHwRead (&EnableReg, &GpeRegisterInfo->EnableAddress);
479            if (ACPI_FAILURE (Status))
480            {
481                goto UnlockAndExit;
482            }
483
484            ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
485                "Read GPE Register at GPE%X: Status=%02X, Enable=%02X\n",
486                GpeRegisterInfo->BaseGpeNumber, StatusReg, EnableReg));
487
488            /* Check if there is anything active at all in this register */
489
490            EnabledStatusByte = (UINT8) (StatusReg & EnableReg);
491            if (!EnabledStatusByte)
492            {
493                /* No active GPEs in this register, move on */
494
495                continue;
496            }
497
498            /* Now look at the individual GPEs in this byte register */
499
500            for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++)
501            {
502                /* Examine one GPE bit */
503
504                if (EnabledStatusByte & (1 << j))
505                {
506                    /*
507                     * Found an active GPE. Dispatch the event to a handler
508                     * or method.
509                     */
510                    IntStatus |= AcpiEvGpeDispatch (
511                        &GpeBlock->EventInfo[((ACPI_SIZE) i *
512                            ACPI_GPE_REGISTER_WIDTH) + j],
513                        j + GpeRegisterInfo->BaseGpeNumber);
514                }
515            }
516        }
517
518        GpeBlock = GpeBlock->Next;
519    }
520
521UnlockAndExit:
522
523    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
524    return (IntStatus);
525}
526
527
528/*******************************************************************************
529 *
530 * FUNCTION:    AcpiEvAsynchExecuteGpeMethod
531 *
532 * PARAMETERS:  Context (GpeEventInfo) - Info for this GPE
533 *
534 * RETURN:      None
535 *
536 * DESCRIPTION: Perform the actual execution of a GPE control method. This
537 *              function is called from an invocation of AcpiOsExecute and
538 *              therefore does NOT execute at interrupt level - so that
539 *              the control method itself is not executed in the context of
540 *              an interrupt handler.
541 *
542 ******************************************************************************/
543
544static void ACPI_SYSTEM_XFACE
545AcpiEvAsynchExecuteGpeMethod (
546    void                    *Context)
547{
548    ACPI_GPE_EVENT_INFO     *GpeEventInfo = Context;
549    ACPI_STATUS             Status;
550    ACPI_GPE_EVENT_INFO     *LocalGpeEventInfo;
551    ACPI_EVALUATE_INFO      *Info;
552
553
554    ACPI_FUNCTION_TRACE (EvAsynchExecuteGpeMethod);
555
556
557    /* Allocate a local GPE block */
558
559    LocalGpeEventInfo = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_EVENT_INFO));
560    if (!LocalGpeEventInfo)
561    {
562        ACPI_EXCEPTION ((AE_INFO, AE_NO_MEMORY,
563            "while handling a GPE"));
564        return_VOID;
565    }
566
567    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
568    if (ACPI_FAILURE (Status))
569    {
570        return_VOID;
571    }
572
573    /* Must revalidate the GpeNumber/GpeBlock */
574
575    if (!AcpiEvValidGpeEvent (GpeEventInfo))
576    {
577        Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
578        return_VOID;
579    }
580
581    /* Update the GPE register masks for return to enabled state */
582
583    (void) AcpiEvUpdateGpeEnableMasks (GpeEventInfo);
584
585    /*
586     * Take a snapshot of the GPE info for this level - we copy the info to
587     * prevent a race condition with RemoveHandler/RemoveBlock.
588     */
589    ACPI_MEMCPY (LocalGpeEventInfo, GpeEventInfo,
590        sizeof (ACPI_GPE_EVENT_INFO));
591
592    Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
593    if (ACPI_FAILURE (Status))
594    {
595        return_VOID;
596    }
597
598    /*
599     * Must check for control method type dispatch one more time to avoid a
600     * race with EvGpeInstallHandler
601     */
602    if ((LocalGpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
603            ACPI_GPE_DISPATCH_METHOD)
604    {
605        /* Allocate the evaluation information block */
606
607        Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
608        if (!Info)
609        {
610            Status = AE_NO_MEMORY;
611        }
612        else
613        {
614            /*
615             * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the _Lxx/_Exx
616             * control method that corresponds to this GPE
617             */
618            Info->PrefixNode = LocalGpeEventInfo->Dispatch.MethodNode;
619            Info->Flags = ACPI_IGNORE_RETURN_VALUE;
620
621            Status = AcpiNsEvaluate (Info);
622            ACPI_FREE (Info);
623        }
624
625        if (ACPI_FAILURE (Status))
626        {
627            ACPI_EXCEPTION ((AE_INFO, Status,
628                "while evaluating GPE method [%4.4s]",
629                AcpiUtGetNodeName (LocalGpeEventInfo->Dispatch.MethodNode)));
630        }
631    }
632
633    /* Defer enabling of GPE until all notify handlers are done */
634
635    Status = AcpiOsExecute (OSL_NOTIFY_HANDLER,
636                AcpiEvAsynchEnableGpe, LocalGpeEventInfo);
637    if (ACPI_FAILURE (Status))
638    {
639        ACPI_FREE (LocalGpeEventInfo);
640    }
641    return_VOID;
642}
643
644
645/*******************************************************************************
646 *
647 * FUNCTION:    AcpiEvAsynchEnableGpe
648 *
649 * PARAMETERS:  Context (GpeEventInfo) - Info for this GPE
650 *
651 * RETURN:      None
652 *
653 * DESCRIPTION: Asynchronous clear/enable for GPE. This allows the GPE to
654 *              complete (i.e., finish execution of Notify)
655 *
656 ******************************************************************************/
657
658static void ACPI_SYSTEM_XFACE
659AcpiEvAsynchEnableGpe (
660    void                    *Context)
661{
662    ACPI_GPE_EVENT_INFO     *GpeEventInfo = Context;
663    ACPI_STATUS             Status;
664
665
666    if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
667            ACPI_GPE_LEVEL_TRIGGERED)
668    {
669        /*
670         * GPE is level-triggered, we clear the GPE status bit after handling
671         * the event.
672         */
673        Status = AcpiHwClearGpe (GpeEventInfo);
674        if (ACPI_FAILURE (Status))
675        {
676            goto Exit;
677        }
678    }
679
680    /* Enable this GPE */
681
682    (void) AcpiHwWriteGpeEnableReg (GpeEventInfo);
683
684Exit:
685    ACPI_FREE (GpeEventInfo);
686    return;
687}
688
689
690/*******************************************************************************
691 *
692 * FUNCTION:    AcpiEvGpeDispatch
693 *
694 * PARAMETERS:  GpeEventInfo    - Info for this GPE
695 *              GpeNumber       - Number relative to the parent GPE block
696 *
697 * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
698 *
699 * DESCRIPTION: Dispatch a General Purpose Event to either a function (e.g. EC)
700 *              or method (e.g. _Lxx/_Exx) handler.
701 *
702 *              This function executes at interrupt level.
703 *
704 ******************************************************************************/
705
706UINT32
707AcpiEvGpeDispatch (
708    ACPI_GPE_EVENT_INFO     *GpeEventInfo,
709    UINT32                  GpeNumber)
710{
711    ACPI_STATUS             Status;
712
713
714    ACPI_FUNCTION_TRACE (EvGpeDispatch);
715
716
717    AcpiGpeCount++;
718
719    /*
720     * If edge-triggered, clear the GPE status bit now. Note that
721     * level-triggered events are cleared after the GPE is serviced.
722     */
723    if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
724            ACPI_GPE_EDGE_TRIGGERED)
725    {
726        Status = AcpiHwClearGpe (GpeEventInfo);
727        if (ACPI_FAILURE (Status))
728        {
729            ACPI_EXCEPTION ((AE_INFO, Status,
730                "Unable to clear GPE[0x%2X]", GpeNumber));
731            return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
732        }
733    }
734
735    /*
736     * Dispatch the GPE to either an installed handler, or the control method
737     * associated with this GPE (_Lxx or _Exx). If a handler exists, we invoke
738     * it and do not attempt to run the method. If there is neither a handler
739     * nor a method, we disable this GPE to prevent further such pointless
740     * events from firing.
741     */
742    switch (GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK)
743    {
744    case ACPI_GPE_DISPATCH_HANDLER:
745
746        /*
747         * Invoke the installed handler (at interrupt level)
748         * Ignore return status for now.
749         * TBD: leave GPE disabled on error?
750         */
751        (void) GpeEventInfo->Dispatch.Handler->Address (
752                        GpeEventInfo->Dispatch.Handler->Context);
753
754        /* It is now safe to clear level-triggered events. */
755
756        if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
757                ACPI_GPE_LEVEL_TRIGGERED)
758        {
759            Status = AcpiHwClearGpe (GpeEventInfo);
760            if (ACPI_FAILURE (Status))
761            {
762                ACPI_EXCEPTION ((AE_INFO, Status,
763                    "Unable to clear GPE[0x%2X]", GpeNumber));
764                return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
765            }
766        }
767        break;
768
769    case ACPI_GPE_DISPATCH_METHOD:
770
771        /*
772         * Disable the GPE, so it doesn't keep firing before the method has a
773         * chance to run (it runs asynchronously with interrupts enabled).
774         */
775        Status = AcpiEvDisableGpe (GpeEventInfo);
776        if (ACPI_FAILURE (Status))
777        {
778            ACPI_EXCEPTION ((AE_INFO, Status,
779                "Unable to disable GPE[0x%2X]", GpeNumber));
780            return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
781        }
782
783        /*
784         * Execute the method associated with the GPE
785         * NOTE: Level-triggered GPEs are cleared after the method completes.
786         */
787        Status = AcpiOsExecute (OSL_GPE_HANDLER,
788                    AcpiEvAsynchExecuteGpeMethod, GpeEventInfo);
789        if (ACPI_FAILURE (Status))
790        {
791            ACPI_EXCEPTION ((AE_INFO, Status,
792                "Unable to queue handler for GPE[0x%2X] - event disabled",
793                GpeNumber));
794        }
795        break;
796
797    default:
798
799        /*
800         * No handler or method to run!
801         * 03/2010: This case should no longer be possible. We will not allow
802         * a GPE to be enabled if it has no handler or method.
803         */
804        ACPI_ERROR ((AE_INFO,
805            "No handler or method for GPE[0x%2X], disabling event",
806            GpeNumber));
807
808        /*
809         * Disable the GPE. The GPE will remain disabled a handler
810         * is installed or ACPICA is restarted.
811         */
812        Status = AcpiEvDisableGpe (GpeEventInfo);
813        if (ACPI_FAILURE (Status))
814        {
815            ACPI_EXCEPTION ((AE_INFO, Status,
816                "Unable to disable GPE[0x%2X]", GpeNumber));
817            return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
818        }
819        break;
820    }
821
822    return_UINT32 (ACPI_INTERRUPT_HANDLED);
823}
824
825