1/******************************************************************************
2 *
3 * Module Name: evgpe - General Purpose Event handling and dispatch
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2015, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions, and the following disclaimer,
16 *    without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 *    substantially similar to the "NO WARRANTY" disclaimer below
19 *    ("Disclaimer") and any redistribution must be conditioned upon
20 *    including a substantially similar Disclaimer requirement for further
21 *    binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 *    of any contributors may be used to endorse or promote products derived
24 *    from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44#include <contrib/dev/acpica/include/acpi.h>
45#include <contrib/dev/acpica/include/accommon.h>
46#include <contrib/dev/acpica/include/acevents.h>
47#include <contrib/dev/acpica/include/acnamesp.h>
48
49#define _COMPONENT          ACPI_EVENTS
50        ACPI_MODULE_NAME    ("evgpe")
51
52#if (!ACPI_REDUCED_HARDWARE) /* Entire module */
53
54/* Local prototypes */
55
56static void ACPI_SYSTEM_XFACE
57AcpiEvAsynchExecuteGpeMethod (
58    void                    *Context);
59
60static void ACPI_SYSTEM_XFACE
61AcpiEvAsynchEnableGpe (
62    void                    *Context);
63
64
65/*******************************************************************************
66 *
67 * FUNCTION:    AcpiEvUpdateGpeEnableMask
68 *
69 * PARAMETERS:  GpeEventInfo            - GPE to update
70 *
71 * RETURN:      Status
72 *
73 * DESCRIPTION: Updates GPE register enable mask based upon whether there are
74 *              runtime references to this GPE
75 *
76 ******************************************************************************/
77
78ACPI_STATUS
79AcpiEvUpdateGpeEnableMask (
80    ACPI_GPE_EVENT_INFO     *GpeEventInfo)
81{
82    ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
83    UINT32                  RegisterBit;
84
85
86    ACPI_FUNCTION_TRACE (EvUpdateGpeEnableMask);
87
88
89    GpeRegisterInfo = GpeEventInfo->RegisterInfo;
90    if (!GpeRegisterInfo)
91    {
92        return_ACPI_STATUS (AE_NOT_EXIST);
93    }
94
95    RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo);
96
97    /* Clear the run bit up front */
98
99    ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForRun, RegisterBit);
100
101    /* Set the mask bit only if there are references to this GPE */
102
103    if (GpeEventInfo->RuntimeCount)
104    {
105        ACPI_SET_BIT (GpeRegisterInfo->EnableForRun, (UINT8) RegisterBit);
106    }
107
108    return_ACPI_STATUS (AE_OK);
109}
110
111
112/*******************************************************************************
113 *
114 * FUNCTION:    AcpiEvEnableGpe
115 *
116 * PARAMETERS:  GpeEventInfo            - GPE to enable
117 *
118 * RETURN:      Status
119 *
120 * DESCRIPTION: Clear a GPE of stale events and enable it.
121 *
122 ******************************************************************************/
123
124ACPI_STATUS
125AcpiEvEnableGpe (
126    ACPI_GPE_EVENT_INFO     *GpeEventInfo)
127{
128    ACPI_STATUS             Status;
129
130
131    ACPI_FUNCTION_TRACE (EvEnableGpe);
132
133
134    /* Clear the GPE (of stale events) */
135
136    Status = AcpiHwClearGpe (GpeEventInfo);
137    if (ACPI_FAILURE (Status))
138    {
139        return_ACPI_STATUS (Status);
140    }
141
142    /* Enable the requested GPE */
143
144    Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_ENABLE_SAVE);
145    return_ACPI_STATUS (Status);
146}
147
148
149/*******************************************************************************
150 *
151 * FUNCTION:    AcpiEvAddGpeReference
152 *
153 * PARAMETERS:  GpeEventInfo            - Add a reference to this GPE
154 *
155 * RETURN:      Status
156 *
157 * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is
158 *              hardware-enabled.
159 *
160 ******************************************************************************/
161
162ACPI_STATUS
163AcpiEvAddGpeReference (
164    ACPI_GPE_EVENT_INFO     *GpeEventInfo)
165{
166    ACPI_STATUS             Status = AE_OK;
167
168
169    ACPI_FUNCTION_TRACE (EvAddGpeReference);
170
171
172    if (GpeEventInfo->RuntimeCount == ACPI_UINT8_MAX)
173    {
174        return_ACPI_STATUS (AE_LIMIT);
175    }
176
177    GpeEventInfo->RuntimeCount++;
178    if (GpeEventInfo->RuntimeCount == 1)
179    {
180        /* Enable on first reference */
181
182        Status = AcpiEvUpdateGpeEnableMask (GpeEventInfo);
183        if (ACPI_SUCCESS (Status))
184        {
185            Status = AcpiEvEnableGpe (GpeEventInfo);
186        }
187
188        if (ACPI_FAILURE (Status))
189        {
190            GpeEventInfo->RuntimeCount--;
191        }
192    }
193
194    return_ACPI_STATUS (Status);
195}
196
197
198/*******************************************************************************
199 *
200 * FUNCTION:    AcpiEvRemoveGpeReference
201 *
202 * PARAMETERS:  GpeEventInfo            - Remove a reference to this GPE
203 *
204 * RETURN:      Status
205 *
206 * DESCRIPTION: Remove a reference to a GPE. When the last reference is
207 *              removed, the GPE is hardware-disabled.
208 *
209 ******************************************************************************/
210
211ACPI_STATUS
212AcpiEvRemoveGpeReference (
213    ACPI_GPE_EVENT_INFO     *GpeEventInfo)
214{
215    ACPI_STATUS             Status = AE_OK;
216
217
218    ACPI_FUNCTION_TRACE (EvRemoveGpeReference);
219
220
221    if (!GpeEventInfo->RuntimeCount)
222    {
223        return_ACPI_STATUS (AE_LIMIT);
224    }
225
226    GpeEventInfo->RuntimeCount--;
227    if (!GpeEventInfo->RuntimeCount)
228    {
229        /* Disable on last reference */
230
231        Status = AcpiEvUpdateGpeEnableMask (GpeEventInfo);
232        if (ACPI_SUCCESS (Status))
233        {
234            Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE_SAVE);
235        }
236
237        if (ACPI_FAILURE (Status))
238        {
239            GpeEventInfo->RuntimeCount++;
240        }
241    }
242
243    return_ACPI_STATUS (Status);
244}
245
246
247/*******************************************************************************
248 *
249 * FUNCTION:    AcpiEvLowGetGpeInfo
250 *
251 * PARAMETERS:  GpeNumber           - Raw GPE number
252 *              GpeBlock            - A GPE info block
253 *
254 * RETURN:      A GPE EventInfo struct. NULL if not a valid GPE (The GpeNumber
255 *              is not within the specified GPE block)
256 *
257 * DESCRIPTION: Returns the EventInfo struct associated with this GPE. This is
258 *              the low-level implementation of EvGetGpeEventInfo.
259 *
260 ******************************************************************************/
261
262ACPI_GPE_EVENT_INFO *
263AcpiEvLowGetGpeInfo (
264    UINT32                  GpeNumber,
265    ACPI_GPE_BLOCK_INFO     *GpeBlock)
266{
267    UINT32                  GpeIndex;
268
269
270    /*
271     * Validate that the GpeNumber is within the specified GpeBlock.
272     * (Two steps)
273     */
274    if (!GpeBlock ||
275        (GpeNumber < GpeBlock->BlockBaseNumber))
276    {
277        return (NULL);
278    }
279
280    GpeIndex = GpeNumber - GpeBlock->BlockBaseNumber;
281    if (GpeIndex >= GpeBlock->GpeCount)
282    {
283        return (NULL);
284    }
285
286    return (&GpeBlock->EventInfo[GpeIndex]);
287}
288
289
290/*******************************************************************************
291 *
292 * FUNCTION:    AcpiEvGetGpeEventInfo
293 *
294 * PARAMETERS:  GpeDevice           - Device node. NULL for GPE0/GPE1
295 *              GpeNumber           - Raw GPE number
296 *
297 * RETURN:      A GPE EventInfo struct. NULL if not a valid GPE
298 *
299 * DESCRIPTION: Returns the EventInfo struct associated with this GPE.
300 *              Validates the GpeBlock and the GpeNumber
301 *
302 *              Should be called only when the GPE lists are semaphore locked
303 *              and not subject to change.
304 *
305 ******************************************************************************/
306
307ACPI_GPE_EVENT_INFO *
308AcpiEvGetGpeEventInfo (
309    ACPI_HANDLE             GpeDevice,
310    UINT32                  GpeNumber)
311{
312    ACPI_OPERAND_OBJECT     *ObjDesc;
313    ACPI_GPE_EVENT_INFO     *GpeInfo;
314    UINT32                  i;
315
316
317    ACPI_FUNCTION_ENTRY ();
318
319
320    /* A NULL GpeDevice means use the FADT-defined GPE block(s) */
321
322    if (!GpeDevice)
323    {
324        /* Examine GPE Block 0 and 1 (These blocks are permanent) */
325
326        for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++)
327        {
328            GpeInfo = AcpiEvLowGetGpeInfo (GpeNumber,
329                        AcpiGbl_GpeFadtBlocks[i]);
330            if (GpeInfo)
331            {
332                return (GpeInfo);
333            }
334        }
335
336        /* The GpeNumber was not in the range of either FADT GPE block */
337
338        return (NULL);
339    }
340
341    /* A Non-NULL GpeDevice means this is a GPE Block Device */
342
343    ObjDesc = AcpiNsGetAttachedObject ((ACPI_NAMESPACE_NODE *) GpeDevice);
344    if (!ObjDesc ||
345        !ObjDesc->Device.GpeBlock)
346    {
347        return (NULL);
348    }
349
350    return (AcpiEvLowGetGpeInfo (GpeNumber, ObjDesc->Device.GpeBlock));
351}
352
353
354/*******************************************************************************
355 *
356 * FUNCTION:    AcpiEvGpeDetect
357 *
358 * PARAMETERS:  GpeXruptList        - Interrupt block for this interrupt.
359 *                                    Can have multiple GPE blocks attached.
360 *
361 * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
362 *
363 * DESCRIPTION: Detect if any GP events have occurred. This function is
364 *              executed at interrupt level.
365 *
366 ******************************************************************************/
367
368UINT32
369AcpiEvGpeDetect (
370    ACPI_GPE_XRUPT_INFO     *GpeXruptList)
371{
372    ACPI_STATUS             Status;
373    ACPI_GPE_BLOCK_INFO     *GpeBlock;
374    ACPI_NAMESPACE_NODE     *GpeDevice;
375    ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
376    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
377    UINT32                  GpeNumber;
378    ACPI_GPE_HANDLER_INFO   *GpeHandlerInfo;
379    UINT32                  IntStatus = ACPI_INTERRUPT_NOT_HANDLED;
380    UINT8                   EnabledStatusByte;
381    UINT32                  StatusReg;
382    UINT32                  EnableReg;
383    ACPI_CPU_FLAGS          Flags;
384    UINT32                  i;
385    UINT32                  j;
386
387
388    ACPI_FUNCTION_NAME (EvGpeDetect);
389
390    /* Check for the case where there are no GPEs */
391
392    if (!GpeXruptList)
393    {
394        return (IntStatus);
395    }
396
397    /*
398     * We need to obtain the GPE lock for both the data structs and registers
399     * Note: Not necessary to obtain the hardware lock, since the GPE
400     * registers are owned by the GpeLock.
401     */
402    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
403
404    /* Examine all GPE blocks attached to this interrupt level */
405
406    GpeBlock = GpeXruptList->GpeBlockListHead;
407    while (GpeBlock)
408    {
409        GpeDevice = GpeBlock->Node;
410
411        /*
412         * Read all of the 8-bit GPE status and enable registers in this GPE
413         * block, saving all of them. Find all currently active GP events.
414         */
415        for (i = 0; i < GpeBlock->RegisterCount; i++)
416        {
417            /* Get the next status/enable pair */
418
419            GpeRegisterInfo = &GpeBlock->RegisterInfo[i];
420
421            /*
422             * Optimization: If there are no GPEs enabled within this
423             * register, we can safely ignore the entire register.
424             */
425            if (!(GpeRegisterInfo->EnableForRun |
426                  GpeRegisterInfo->EnableForWake))
427            {
428                ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
429                    "Ignore disabled registers for GPE %02X-%02X: "
430                    "RunEnable=%02X, WakeEnable=%02X\n",
431                    GpeRegisterInfo->BaseGpeNumber,
432                    GpeRegisterInfo->BaseGpeNumber + (ACPI_GPE_REGISTER_WIDTH - 1),
433                    GpeRegisterInfo->EnableForRun,
434                    GpeRegisterInfo->EnableForWake));
435                continue;
436            }
437
438            /* Read the Status Register */
439
440            Status = AcpiHwRead (&StatusReg, &GpeRegisterInfo->StatusAddress);
441            if (ACPI_FAILURE (Status))
442            {
443                goto UnlockAndExit;
444            }
445
446            /* Read the Enable Register */
447
448            Status = AcpiHwRead (&EnableReg, &GpeRegisterInfo->EnableAddress);
449            if (ACPI_FAILURE (Status))
450            {
451                goto UnlockAndExit;
452            }
453
454            ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
455                "Read registers for GPE %02X-%02X: Status=%02X, Enable=%02X, "
456                "RunEnable=%02X, WakeEnable=%02X\n",
457                GpeRegisterInfo->BaseGpeNumber,
458                GpeRegisterInfo->BaseGpeNumber + (ACPI_GPE_REGISTER_WIDTH - 1),
459                StatusReg, EnableReg,
460                GpeRegisterInfo->EnableForRun,
461                GpeRegisterInfo->EnableForWake));
462
463            /* Check if there is anything active at all in this register */
464
465            EnabledStatusByte = (UINT8) (StatusReg & EnableReg);
466            if (!EnabledStatusByte)
467            {
468                /* No active GPEs in this register, move on */
469
470                continue;
471            }
472
473            /* Now look at the individual GPEs in this byte register */
474
475            for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++)
476            {
477                /* Examine one GPE bit */
478
479                GpeEventInfo = &GpeBlock->EventInfo[((ACPI_SIZE) i *
480                    ACPI_GPE_REGISTER_WIDTH) + j];
481                GpeNumber = j + GpeRegisterInfo->BaseGpeNumber;
482
483                if (EnabledStatusByte & (1 << j))
484                {
485                    /* Invoke global event handler if present */
486
487                    AcpiGpeCount++;
488                    if (AcpiGbl_GlobalEventHandler)
489                    {
490                        AcpiGbl_GlobalEventHandler (ACPI_EVENT_TYPE_GPE,
491                            GpeDevice, GpeNumber,
492                            AcpiGbl_GlobalEventHandlerContext);
493                    }
494
495                    /* Found an active GPE */
496
497                    if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) ==
498                        ACPI_GPE_DISPATCH_RAW_HANDLER)
499                    {
500                        /* Dispatch the event to a raw handler */
501
502                        GpeHandlerInfo = GpeEventInfo->Dispatch.Handler;
503
504                        /*
505                         * There is no protection around the namespace node
506                         * and the GPE handler to ensure a safe destruction
507                         * because:
508                         * 1. The namespace node is expected to always
509                         *    exist after loading a table.
510                         * 2. The GPE handler is expected to be flushed by
511                         *    AcpiOsWaitEventsComplete() before the
512                         *    destruction.
513                         */
514                        AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
515                        IntStatus |= GpeHandlerInfo->Address (
516                            GpeDevice, GpeNumber, GpeHandlerInfo->Context);
517                        Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
518                    }
519                    else
520                    {
521                        /*
522                         * Dispatch the event to a standard handler or
523                         * method.
524                         */
525                        IntStatus |= AcpiEvGpeDispatch (GpeDevice,
526                            GpeEventInfo, GpeNumber);
527                    }
528                }
529            }
530        }
531
532        GpeBlock = GpeBlock->Next;
533    }
534
535UnlockAndExit:
536
537    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
538    return (IntStatus);
539}
540
541
542/*******************************************************************************
543 *
544 * FUNCTION:    AcpiEvAsynchExecuteGpeMethod
545 *
546 * PARAMETERS:  Context (GpeEventInfo) - Info for this GPE
547 *
548 * RETURN:      None
549 *
550 * DESCRIPTION: Perform the actual execution of a GPE control method. This
551 *              function is called from an invocation of AcpiOsExecute and
552 *              therefore does NOT execute at interrupt level - so that
553 *              the control method itself is not executed in the context of
554 *              an interrupt handler.
555 *
556 ******************************************************************************/
557
558static void ACPI_SYSTEM_XFACE
559AcpiEvAsynchExecuteGpeMethod (
560    void                    *Context)
561{
562    ACPI_GPE_EVENT_INFO     *GpeEventInfo = Context;
563    ACPI_STATUS             Status = AE_OK;
564    ACPI_EVALUATE_INFO      *Info;
565    ACPI_GPE_NOTIFY_INFO    *Notify;
566
567
568    ACPI_FUNCTION_TRACE (EvAsynchExecuteGpeMethod);
569
570
571    /* Do the correct dispatch - normal method or implicit notify */
572
573    switch (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags))
574    {
575    case ACPI_GPE_DISPATCH_NOTIFY:
576        /*
577         * Implicit notify.
578         * Dispatch a DEVICE_WAKE notify to the appropriate handler.
579         * NOTE: the request is queued for execution after this method
580         * completes. The notify handlers are NOT invoked synchronously
581         * from this thread -- because handlers may in turn run other
582         * control methods.
583         *
584         * June 2012: Expand implicit notify mechanism to support
585         * notifies on multiple device objects.
586         */
587        Notify = GpeEventInfo->Dispatch.NotifyList;
588        while (ACPI_SUCCESS (Status) && Notify)
589        {
590            Status = AcpiEvQueueNotifyRequest (Notify->DeviceNode,
591                        ACPI_NOTIFY_DEVICE_WAKE);
592
593            Notify = Notify->Next;
594        }
595        break;
596
597    case ACPI_GPE_DISPATCH_METHOD:
598
599        /* Allocate the evaluation information block */
600
601        Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
602        if (!Info)
603        {
604            Status = AE_NO_MEMORY;
605        }
606        else
607        {
608            /*
609             * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the
610             * _Lxx/_Exx control method that corresponds to this GPE
611             */
612            Info->PrefixNode = GpeEventInfo->Dispatch.MethodNode;
613            Info->Flags = ACPI_IGNORE_RETURN_VALUE;
614
615            Status = AcpiNsEvaluate (Info);
616            ACPI_FREE (Info);
617        }
618
619        if (ACPI_FAILURE (Status))
620        {
621            ACPI_EXCEPTION ((AE_INFO, Status,
622                "while evaluating GPE method [%4.4s]",
623                AcpiUtGetNodeName (GpeEventInfo->Dispatch.MethodNode)));
624        }
625        break;
626
627    default:
628
629        goto ErrorExit; /* Should never happen */
630    }
631
632    /* Defer enabling of GPE until all notify handlers are done */
633
634    Status = AcpiOsExecute (OSL_NOTIFY_HANDLER,
635                AcpiEvAsynchEnableGpe, GpeEventInfo);
636    if (ACPI_SUCCESS (Status))
637    {
638        return_VOID;
639    }
640
641ErrorExit:
642    AcpiEvAsynchEnableGpe (GpeEventInfo);
643    return_VOID;
644}
645
646
647/*******************************************************************************
648 *
649 * FUNCTION:    AcpiEvAsynchEnableGpe
650 *
651 * PARAMETERS:  Context (GpeEventInfo) - Info for this GPE
652 *              Callback from AcpiOsExecute
653 *
654 * RETURN:      None
655 *
656 * DESCRIPTION: Asynchronous clear/enable for GPE. This allows the GPE to
657 *              complete (i.e., finish execution of Notify)
658 *
659 ******************************************************************************/
660
661static void ACPI_SYSTEM_XFACE
662AcpiEvAsynchEnableGpe (
663    void                    *Context)
664{
665    ACPI_GPE_EVENT_INFO     *GpeEventInfo = Context;
666    ACPI_CPU_FLAGS          Flags;
667
668
669    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
670    (void) AcpiEvFinishGpe (GpeEventInfo);
671    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
672
673    return;
674}
675
676
677/*******************************************************************************
678 *
679 * FUNCTION:    AcpiEvFinishGpe
680 *
681 * PARAMETERS:  GpeEventInfo        - Info for this GPE
682 *
683 * RETURN:      Status
684 *
685 * DESCRIPTION: Clear/Enable a GPE. Common code that is used after execution
686 *              of a GPE method or a synchronous or asynchronous GPE handler.
687 *
688 ******************************************************************************/
689
690ACPI_STATUS
691AcpiEvFinishGpe (
692    ACPI_GPE_EVENT_INFO     *GpeEventInfo)
693{
694    ACPI_STATUS             Status;
695
696
697    if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
698            ACPI_GPE_LEVEL_TRIGGERED)
699    {
700        /*
701         * GPE is level-triggered, we clear the GPE status bit after
702         * handling the event.
703         */
704        Status = AcpiHwClearGpe (GpeEventInfo);
705        if (ACPI_FAILURE (Status))
706        {
707            return (Status);
708        }
709    }
710
711    /*
712     * Enable this GPE, conditionally. This means that the GPE will
713     * only be physically enabled if the EnableMask bit is set
714     * in the EventInfo.
715     */
716    (void) AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_CONDITIONAL_ENABLE);
717    return (AE_OK);
718}
719
720
721/*******************************************************************************
722 *
723 * FUNCTION:    AcpiEvGpeDispatch
724 *
725 * PARAMETERS:  GpeDevice           - Device node. NULL for GPE0/GPE1
726 *              GpeEventInfo        - Info for this GPE
727 *              GpeNumber           - Number relative to the parent GPE block
728 *
729 * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
730 *
731 * DESCRIPTION: Dispatch a General Purpose Event to either a function (e.g. EC)
732 *              or method (e.g. _Lxx/_Exx) handler.
733 *
734 *              This function executes at interrupt level.
735 *
736 ******************************************************************************/
737
738UINT32
739AcpiEvGpeDispatch (
740    ACPI_NAMESPACE_NODE     *GpeDevice,
741    ACPI_GPE_EVENT_INFO     *GpeEventInfo,
742    UINT32                  GpeNumber)
743{
744    ACPI_STATUS             Status;
745    UINT32                  ReturnValue;
746
747
748    ACPI_FUNCTION_TRACE (EvGpeDispatch);
749
750
751    /*
752     * Always disable the GPE so that it does not keep firing before
753     * any asynchronous activity completes (either from the execution
754     * of a GPE method or an asynchronous GPE handler.)
755     *
756     * If there is no handler or method to run, just disable the
757     * GPE and leave it disabled permanently to prevent further such
758     * pointless events from firing.
759     */
760    Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE);
761    if (ACPI_FAILURE (Status))
762    {
763        ACPI_EXCEPTION ((AE_INFO, Status,
764            "Unable to disable GPE %02X", GpeNumber));
765        return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
766    }
767
768    /*
769     * If edge-triggered, clear the GPE status bit now. Note that
770     * level-triggered events are cleared after the GPE is serviced.
771     */
772    if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
773            ACPI_GPE_EDGE_TRIGGERED)
774    {
775        Status = AcpiHwClearGpe (GpeEventInfo);
776        if (ACPI_FAILURE (Status))
777        {
778            ACPI_EXCEPTION ((AE_INFO, Status,
779                "Unable to clear GPE %02X", GpeNumber));
780            (void) AcpiHwLowSetGpe (GpeEventInfo,
781                    ACPI_GPE_CONDITIONAL_ENABLE);
782            return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
783        }
784    }
785
786    /*
787     * Dispatch the GPE to either an installed handler or the control
788     * method associated with this GPE (_Lxx or _Exx). If a handler
789     * exists, we invoke it and do not attempt to run the method.
790     * If there is neither a handler nor a method, leave the GPE
791     * disabled.
792     */
793    switch (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags))
794    {
795    case ACPI_GPE_DISPATCH_HANDLER:
796
797        /* Invoke the installed handler (at interrupt level) */
798
799        ReturnValue = GpeEventInfo->Dispatch.Handler->Address (
800            GpeDevice, GpeNumber,
801            GpeEventInfo->Dispatch.Handler->Context);
802
803        /* If requested, clear (if level-triggered) and reenable the GPE */
804
805        if (ReturnValue & ACPI_REENABLE_GPE)
806        {
807            (void) AcpiEvFinishGpe (GpeEventInfo);
808        }
809        break;
810
811    case ACPI_GPE_DISPATCH_METHOD:
812    case ACPI_GPE_DISPATCH_NOTIFY:
813        /*
814         * Execute the method associated with the GPE
815         * NOTE: Level-triggered GPEs are cleared after the method completes.
816         */
817        Status = AcpiOsExecute (OSL_GPE_HANDLER,
818                    AcpiEvAsynchExecuteGpeMethod, GpeEventInfo);
819        if (ACPI_FAILURE (Status))
820        {
821            ACPI_EXCEPTION ((AE_INFO, Status,
822                "Unable to queue handler for GPE %02X - event disabled",
823                GpeNumber));
824        }
825        break;
826
827    default:
828        /*
829         * No handler or method to run!
830         * 03/2010: This case should no longer be possible. We will not allow
831         * a GPE to be enabled if it has no handler or method.
832         */
833        ACPI_ERROR ((AE_INFO,
834            "No handler or method for GPE %02X, disabling event",
835            GpeNumber));
836        break;
837    }
838
839    return_UINT32 (ACPI_INTERRUPT_HANDLED);
840}
841
842#endif /* !ACPI_REDUCED_HARDWARE */
843