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