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