xref: /freebsd/sys/contrib/dev/acpica/components/events/evgpe.c (revision af23369a6deaaeb612ab266eb88b8bb8d560c322)
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 - 2022, 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 
164 static void ACPI_SYSTEM_XFACE
165 AcpiEvAsynchExecuteGpeMethod (
166     void                    *Context);
167 
168 static void ACPI_SYSTEM_XFACE
169 AcpiEvAsynchEnableGpe (
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 
186 ACPI_STATUS
187 AcpiEvUpdateGpeEnableMask (
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: Enable a GPE.
230  *
231  ******************************************************************************/
232 
233 ACPI_STATUS
234 AcpiEvEnableGpe (
235     ACPI_GPE_EVENT_INFO     *GpeEventInfo)
236 {
237     ACPI_STATUS             Status;
238 
239 
240     ACPI_FUNCTION_TRACE (EvEnableGpe);
241 
242 
243     /* Enable the requested GPE */
244 
245     Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_ENABLE);
246     return_ACPI_STATUS (Status);
247 }
248 
249 
250 /*******************************************************************************
251  *
252  * FUNCTION:    AcpiEvMaskGpe
253  *
254  * PARAMETERS:  GpeEventInfo            - GPE to be blocked/unblocked
255  *              IsMasked                - Whether the GPE is masked or not
256  *
257  * RETURN:      Status
258  *
259  * DESCRIPTION: Unconditionally mask/unmask a GPE during runtime.
260  *
261  ******************************************************************************/
262 
263 ACPI_STATUS
264 AcpiEvMaskGpe (
265     ACPI_GPE_EVENT_INFO     *GpeEventInfo,
266     BOOLEAN                 IsMasked)
267 {
268     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
269     UINT32                  RegisterBit;
270 
271 
272     ACPI_FUNCTION_TRACE (EvMaskGpe);
273 
274 
275     GpeRegisterInfo = GpeEventInfo->RegisterInfo;
276     if (!GpeRegisterInfo)
277     {
278         return_ACPI_STATUS (AE_NOT_EXIST);
279     }
280 
281     RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo);
282 
283     /* Perform the action */
284 
285     if (IsMasked)
286     {
287         if (RegisterBit & GpeRegisterInfo->MaskForRun)
288         {
289             return_ACPI_STATUS (AE_BAD_PARAMETER);
290         }
291 
292         (void) AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE);
293         ACPI_SET_BIT (GpeRegisterInfo->MaskForRun, (UINT8) RegisterBit);
294     }
295     else
296     {
297         if (!(RegisterBit & GpeRegisterInfo->MaskForRun))
298         {
299             return_ACPI_STATUS (AE_BAD_PARAMETER);
300         }
301 
302         ACPI_CLEAR_BIT (GpeRegisterInfo->MaskForRun, (UINT8) RegisterBit);
303         if (GpeEventInfo->RuntimeCount &&
304             !GpeEventInfo->DisableForDispatch)
305         {
306             (void) AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_ENABLE);
307         }
308     }
309 
310     return_ACPI_STATUS (AE_OK);
311 }
312 
313 
314 /*******************************************************************************
315  *
316  * FUNCTION:    AcpiEvAddGpeReference
317  *
318  * PARAMETERS:  GpeEventInfo            - Add a reference to this GPE
319  *              ClearOnEnable           - Clear GPE status before enabling it
320  *
321  * RETURN:      Status
322  *
323  * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is
324  *              hardware-enabled.
325  *
326  ******************************************************************************/
327 
328 ACPI_STATUS
329 AcpiEvAddGpeReference (
330     ACPI_GPE_EVENT_INFO     *GpeEventInfo,
331     BOOLEAN                 ClearOnEnable)
332 {
333     ACPI_STATUS             Status = AE_OK;
334 
335 
336     ACPI_FUNCTION_TRACE (EvAddGpeReference);
337 
338 
339     if (GpeEventInfo->RuntimeCount == ACPI_UINT8_MAX)
340     {
341         return_ACPI_STATUS (AE_LIMIT);
342     }
343 
344     GpeEventInfo->RuntimeCount++;
345     if (GpeEventInfo->RuntimeCount == 1)
346     {
347         /* Enable on first reference */
348 
349         if (ClearOnEnable)
350         {
351             (void) AcpiHwClearGpe (GpeEventInfo);
352         }
353 
354         Status = AcpiEvUpdateGpeEnableMask (GpeEventInfo);
355         if (ACPI_SUCCESS (Status))
356         {
357             Status = AcpiEvEnableGpe (GpeEventInfo);
358         }
359 
360         if (ACPI_FAILURE (Status))
361         {
362             GpeEventInfo->RuntimeCount--;
363         }
364     }
365 
366     return_ACPI_STATUS (Status);
367 }
368 
369 
370 /*******************************************************************************
371  *
372  * FUNCTION:    AcpiEvRemoveGpeReference
373  *
374  * PARAMETERS:  GpeEventInfo            - Remove a reference to this GPE
375  *
376  * RETURN:      Status
377  *
378  * DESCRIPTION: Remove a reference to a GPE. When the last reference is
379  *              removed, the GPE is hardware-disabled.
380  *
381  ******************************************************************************/
382 
383 ACPI_STATUS
384 AcpiEvRemoveGpeReference (
385     ACPI_GPE_EVENT_INFO     *GpeEventInfo)
386 {
387     ACPI_STATUS             Status = AE_OK;
388 
389 
390     ACPI_FUNCTION_TRACE (EvRemoveGpeReference);
391 
392 
393     if (!GpeEventInfo->RuntimeCount)
394     {
395         return_ACPI_STATUS (AE_LIMIT);
396     }
397 
398     GpeEventInfo->RuntimeCount--;
399     if (!GpeEventInfo->RuntimeCount)
400     {
401         /* Disable on last reference */
402 
403         Status = AcpiEvUpdateGpeEnableMask (GpeEventInfo);
404         if (ACPI_SUCCESS (Status))
405         {
406             Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE);
407         }
408 
409         if (ACPI_FAILURE (Status))
410         {
411             GpeEventInfo->RuntimeCount++;
412         }
413     }
414 
415     return_ACPI_STATUS (Status);
416 }
417 
418 
419 /*******************************************************************************
420  *
421  * FUNCTION:    AcpiEvLowGetGpeInfo
422  *
423  * PARAMETERS:  GpeNumber           - Raw GPE number
424  *              GpeBlock            - A GPE info block
425  *
426  * RETURN:      A GPE EventInfo struct. NULL if not a valid GPE (The GpeNumber
427  *              is not within the specified GPE block)
428  *
429  * DESCRIPTION: Returns the EventInfo struct associated with this GPE. This is
430  *              the low-level implementation of EvGetGpeEventInfo.
431  *
432  ******************************************************************************/
433 
434 ACPI_GPE_EVENT_INFO *
435 AcpiEvLowGetGpeInfo (
436     UINT32                  GpeNumber,
437     ACPI_GPE_BLOCK_INFO     *GpeBlock)
438 {
439     UINT32                  GpeIndex;
440 
441 
442     /*
443      * Validate that the GpeNumber is within the specified GpeBlock.
444      * (Two steps)
445      */
446     if (!GpeBlock ||
447         (GpeNumber < GpeBlock->BlockBaseNumber))
448     {
449         return (NULL);
450     }
451 
452     GpeIndex = GpeNumber - GpeBlock->BlockBaseNumber;
453     if (GpeIndex >= GpeBlock->GpeCount)
454     {
455         return (NULL);
456     }
457 
458     return (&GpeBlock->EventInfo[GpeIndex]);
459 }
460 
461 
462 /*******************************************************************************
463  *
464  * FUNCTION:    AcpiEvGetGpeEventInfo
465  *
466  * PARAMETERS:  GpeDevice           - Device node. NULL for GPE0/GPE1
467  *              GpeNumber           - Raw GPE number
468  *
469  * RETURN:      A GPE EventInfo struct. NULL if not a valid GPE
470  *
471  * DESCRIPTION: Returns the EventInfo struct associated with this GPE.
472  *              Validates the GpeBlock and the GpeNumber
473  *
474  *              Should be called only when the GPE lists are semaphore locked
475  *              and not subject to change.
476  *
477  ******************************************************************************/
478 
479 ACPI_GPE_EVENT_INFO *
480 AcpiEvGetGpeEventInfo (
481     ACPI_HANDLE             GpeDevice,
482     UINT32                  GpeNumber)
483 {
484     ACPI_OPERAND_OBJECT     *ObjDesc;
485     ACPI_GPE_EVENT_INFO     *GpeInfo;
486     UINT32                  i;
487 
488 
489     ACPI_FUNCTION_ENTRY ();
490 
491 
492     /* A NULL GpeDevice means use the FADT-defined GPE block(s) */
493 
494     if (!GpeDevice)
495     {
496         /* Examine GPE Block 0 and 1 (These blocks are permanent) */
497 
498         for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++)
499         {
500             GpeInfo = AcpiEvLowGetGpeInfo (GpeNumber,
501                 AcpiGbl_GpeFadtBlocks[i]);
502             if (GpeInfo)
503             {
504                 return (GpeInfo);
505             }
506         }
507 
508         /* The GpeNumber was not in the range of either FADT GPE block */
509 
510         return (NULL);
511     }
512 
513     /* A Non-NULL GpeDevice means this is a GPE Block Device */
514 
515     ObjDesc = AcpiNsGetAttachedObject ((ACPI_NAMESPACE_NODE *) GpeDevice);
516     if (!ObjDesc ||
517         !ObjDesc->Device.GpeBlock)
518     {
519         return (NULL);
520     }
521 
522     return (AcpiEvLowGetGpeInfo (GpeNumber, ObjDesc->Device.GpeBlock));
523 }
524 
525 
526 /*******************************************************************************
527  *
528  * FUNCTION:    AcpiEvGpeDetect
529  *
530  * PARAMETERS:  GpeXruptList        - Interrupt block for this interrupt.
531  *                                    Can have multiple GPE blocks attached.
532  *
533  * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
534  *
535  * DESCRIPTION: Detect if any GP events have occurred. This function is
536  *              executed at interrupt level.
537  *
538  ******************************************************************************/
539 
540 UINT32
541 AcpiEvGpeDetect (
542     ACPI_GPE_XRUPT_INFO     *GpeXruptList)
543 {
544     ACPI_GPE_BLOCK_INFO     *GpeBlock;
545     ACPI_NAMESPACE_NODE     *GpeDevice;
546     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
547     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
548     UINT32                  GpeNumber;
549     UINT32                  IntStatus = ACPI_INTERRUPT_NOT_HANDLED;
550     ACPI_CPU_FLAGS          Flags;
551     UINT32                  i;
552     UINT32                  j;
553 
554 
555     ACPI_FUNCTION_NAME (EvGpeDetect);
556 
557     /* Check for the case where there are no GPEs */
558 
559     if (!GpeXruptList)
560     {
561         return (IntStatus);
562     }
563 
564     /*
565      * We need to obtain the GPE lock for both the data structs and registers
566      * Note: Not necessary to obtain the hardware lock, since the GPE
567      * registers are owned by the GpeLock.
568      */
569     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
570 
571     /* Examine all GPE blocks attached to this interrupt level */
572 
573     GpeBlock = GpeXruptList->GpeBlockListHead;
574     while (GpeBlock)
575     {
576         GpeDevice = GpeBlock->Node;
577 
578         /*
579          * Read all of the 8-bit GPE status and enable registers in this GPE
580          * block, saving all of them. Find all currently active GP events.
581          */
582         for (i = 0; i < GpeBlock->RegisterCount; i++)
583         {
584             /* Get the next status/enable pair */
585 
586             GpeRegisterInfo = &GpeBlock->RegisterInfo[i];
587 
588             /*
589              * Optimization: If there are no GPEs enabled within this
590              * register, we can safely ignore the entire register.
591              */
592             if (!(GpeRegisterInfo->EnableForRun |
593                   GpeRegisterInfo->EnableForWake))
594             {
595                 ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
596                     "Ignore disabled registers for GPE %02X-%02X: "
597                     "RunEnable=%02X, WakeEnable=%02X\n",
598                     GpeRegisterInfo->BaseGpeNumber,
599                     GpeRegisterInfo->BaseGpeNumber + (ACPI_GPE_REGISTER_WIDTH - 1),
600                     GpeRegisterInfo->EnableForRun,
601                     GpeRegisterInfo->EnableForWake));
602                 continue;
603             }
604 
605             /* Now look at the individual GPEs in this byte register */
606 
607             for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++)
608             {
609                 /* Detect and dispatch one GPE bit */
610 
611                 GpeEventInfo = &GpeBlock->EventInfo[((ACPI_SIZE) i *
612                     ACPI_GPE_REGISTER_WIDTH) + j];
613                 GpeNumber = j + GpeRegisterInfo->BaseGpeNumber;
614                 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
615                 IntStatus |= AcpiEvDetectGpe (
616                     GpeDevice, GpeEventInfo, GpeNumber);
617                 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
618             }
619         }
620 
621         GpeBlock = GpeBlock->Next;
622     }
623 
624     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
625     return (IntStatus);
626 }
627 
628 
629 /*******************************************************************************
630  *
631  * FUNCTION:    AcpiEvAsynchExecuteGpeMethod
632  *
633  * PARAMETERS:  Context (GpeEventInfo) - Info for this GPE
634  *
635  * RETURN:      None
636  *
637  * DESCRIPTION: Perform the actual execution of a GPE control method. This
638  *              function is called from an invocation of AcpiOsExecute and
639  *              therefore does NOT execute at interrupt level - so that
640  *              the control method itself is not executed in the context of
641  *              an interrupt handler.
642  *
643  ******************************************************************************/
644 
645 static void ACPI_SYSTEM_XFACE
646 AcpiEvAsynchExecuteGpeMethod (
647     void                    *Context)
648 {
649     ACPI_GPE_EVENT_INFO     *GpeEventInfo = Context;
650     ACPI_STATUS             Status = AE_OK;
651     ACPI_EVALUATE_INFO      *Info;
652     ACPI_GPE_NOTIFY_INFO    *Notify;
653 
654 
655     ACPI_FUNCTION_TRACE (EvAsynchExecuteGpeMethod);
656 
657 
658     /* Do the correct dispatch - normal method or implicit notify */
659 
660     switch (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags))
661     {
662     case ACPI_GPE_DISPATCH_NOTIFY:
663         /*
664          * Implicit notify.
665          * Dispatch a DEVICE_WAKE notify to the appropriate handler.
666          * NOTE: the request is queued for execution after this method
667          * completes. The notify handlers are NOT invoked synchronously
668          * from this thread -- because handlers may in turn run other
669          * control methods.
670          *
671          * June 2012: Expand implicit notify mechanism to support
672          * notifies on multiple device objects.
673          */
674         Notify = GpeEventInfo->Dispatch.NotifyList;
675         while (ACPI_SUCCESS (Status) && Notify)
676         {
677             Status = AcpiEvQueueNotifyRequest (
678                 Notify->DeviceNode, ACPI_NOTIFY_DEVICE_WAKE);
679 
680             Notify = Notify->Next;
681         }
682         break;
683 
684     case ACPI_GPE_DISPATCH_METHOD:
685 
686         /* Allocate the evaluation information block */
687 
688         Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
689         if (!Info)
690         {
691             Status = AE_NO_MEMORY;
692         }
693         else
694         {
695             /*
696              * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the
697              * _Lxx/_Exx control method that corresponds to this GPE
698              */
699             Info->PrefixNode = GpeEventInfo->Dispatch.MethodNode;
700             Info->Flags = ACPI_IGNORE_RETURN_VALUE;
701 
702             Status = AcpiNsEvaluate (Info);
703             ACPI_FREE (Info);
704         }
705 
706         if (ACPI_FAILURE (Status))
707         {
708             ACPI_EXCEPTION ((AE_INFO, Status,
709                 "while evaluating GPE method [%4.4s]",
710                 AcpiUtGetNodeName (GpeEventInfo->Dispatch.MethodNode)));
711         }
712         break;
713 
714     default:
715 
716         goto ErrorExit; /* Should never happen */
717     }
718 
719     /* Defer enabling of GPE until all notify handlers are done */
720 
721     Status = AcpiOsExecute (OSL_NOTIFY_HANDLER,
722         AcpiEvAsynchEnableGpe, GpeEventInfo);
723     if (ACPI_SUCCESS (Status))
724     {
725         return_VOID;
726     }
727 
728 ErrorExit:
729     AcpiEvAsynchEnableGpe (GpeEventInfo);
730     return_VOID;
731 }
732 
733 
734 /*******************************************************************************
735  *
736  * FUNCTION:    AcpiEvAsynchEnableGpe
737  *
738  * PARAMETERS:  Context (GpeEventInfo) - Info for this GPE
739  *              Callback from AcpiOsExecute
740  *
741  * RETURN:      None
742  *
743  * DESCRIPTION: Asynchronous clear/enable for GPE. This allows the GPE to
744  *              complete (i.e., finish execution of Notify)
745  *
746  ******************************************************************************/
747 
748 static void ACPI_SYSTEM_XFACE
749 AcpiEvAsynchEnableGpe (
750     void                    *Context)
751 {
752     ACPI_GPE_EVENT_INFO     *GpeEventInfo = Context;
753     ACPI_CPU_FLAGS          Flags;
754 
755 
756     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
757     (void) AcpiEvFinishGpe (GpeEventInfo);
758     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
759 
760     return;
761 }
762 
763 
764 /*******************************************************************************
765  *
766  * FUNCTION:    AcpiEvFinishGpe
767  *
768  * PARAMETERS:  GpeEventInfo        - Info for this GPE
769  *
770  * RETURN:      Status
771  *
772  * DESCRIPTION: Clear/Enable a GPE. Common code that is used after execution
773  *              of a GPE method or a synchronous or asynchronous GPE handler.
774  *
775  ******************************************************************************/
776 
777 ACPI_STATUS
778 AcpiEvFinishGpe (
779     ACPI_GPE_EVENT_INFO     *GpeEventInfo)
780 {
781     ACPI_STATUS             Status;
782 
783 
784     if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
785             ACPI_GPE_LEVEL_TRIGGERED)
786     {
787         /*
788          * GPE is level-triggered, we clear the GPE status bit after
789          * handling the event.
790          */
791         Status = AcpiHwClearGpe (GpeEventInfo);
792         if (ACPI_FAILURE (Status))
793         {
794             return (Status);
795         }
796     }
797 
798     /*
799      * Enable this GPE, conditionally. This means that the GPE will
800      * only be physically enabled if the EnableMask bit is set
801      * in the EventInfo.
802      */
803     (void) AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_CONDITIONAL_ENABLE);
804     GpeEventInfo->DisableForDispatch = FALSE;
805     return (AE_OK);
806 }
807 
808 
809 /*******************************************************************************
810  *
811  * FUNCTION:    AcpiEvDetectGpe
812  *
813  * PARAMETERS:  GpeDevice           - Device node. NULL for GPE0/GPE1
814  *              GpeEventInfo        - Info for this GPE
815  *              GpeNumber           - Number relative to the parent GPE block
816  *
817  * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
818  *
819  * DESCRIPTION: Detect and dispatch a General Purpose Event to either a function
820  *              (e.g. EC) or method (e.g. _Lxx/_Exx) handler.
821  * NOTE:        GPE is W1C, so it is possible to handle a single GPE from both
822  *              task and irq context in parallel as long as the process to
823  *              detect and mask the GPE is atomic.
824  *              However the atomicity of ACPI_GPE_DISPATCH_RAW_HANDLER is
825  *              dependent on the raw handler itself.
826  *
827  ******************************************************************************/
828 
829 UINT32
830 AcpiEvDetectGpe (
831     ACPI_NAMESPACE_NODE     *GpeDevice,
832     ACPI_GPE_EVENT_INFO     *GpeEventInfo,
833     UINT32                  GpeNumber)
834 {
835     UINT32                  IntStatus = ACPI_INTERRUPT_NOT_HANDLED;
836     UINT8                   EnabledStatusByte;
837     UINT64                  StatusReg;
838     UINT64                  EnableReg;
839     UINT32                  RegisterBit;
840     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
841     ACPI_GPE_HANDLER_INFO   *GpeHandlerInfo;
842     ACPI_CPU_FLAGS          Flags;
843     ACPI_STATUS             Status;
844 
845 
846     ACPI_FUNCTION_TRACE (EvGpeDetect);
847 
848 
849     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
850 
851     if (!GpeEventInfo)
852     {
853         GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
854         if (!GpeEventInfo)
855         {
856             goto ErrorExit;
857         }
858     }
859 
860     /* Get the info block for the entire GPE register */
861 
862     GpeRegisterInfo = GpeEventInfo->RegisterInfo;
863 
864     /* Get the register bitmask for this GPE */
865 
866     RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo);
867 
868     /* GPE currently enabled (enable bit == 1)? */
869 
870     Status = AcpiHwRead (&EnableReg, &GpeRegisterInfo->EnableAddress);
871     if (ACPI_FAILURE (Status))
872     {
873         goto ErrorExit;
874     }
875 
876     /* GPE currently active (status bit == 1)? */
877 
878     Status = AcpiHwRead (&StatusReg, &GpeRegisterInfo->StatusAddress);
879     if (ACPI_FAILURE (Status))
880     {
881         goto ErrorExit;
882     }
883 
884     /* Check if there is anything active at all in this GPE */
885 
886     ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
887         "Read registers for GPE %02X: Status=%02X, Enable=%02X, "
888         "RunEnable=%02X, WakeEnable=%02X\n",
889         GpeNumber,
890         (UINT32) (StatusReg & RegisterBit),
891         (UINT32) (EnableReg & RegisterBit),
892         GpeRegisterInfo->EnableForRun,
893         GpeRegisterInfo->EnableForWake));
894 
895     EnabledStatusByte = (UINT8) (StatusReg & EnableReg);
896     if (!(EnabledStatusByte & RegisterBit))
897     {
898         goto ErrorExit;
899     }
900 
901     /* Invoke global event handler if present */
902 
903     AcpiGpeCount++;
904     if (AcpiGbl_GlobalEventHandler)
905     {
906         AcpiGbl_GlobalEventHandler (ACPI_EVENT_TYPE_GPE,
907             GpeDevice, GpeNumber,
908             AcpiGbl_GlobalEventHandlerContext);
909     }
910 
911     /* Found an active GPE */
912 
913     if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) ==
914         ACPI_GPE_DISPATCH_RAW_HANDLER)
915     {
916         /* Dispatch the event to a raw handler */
917 
918         GpeHandlerInfo = GpeEventInfo->Dispatch.Handler;
919 
920         /*
921          * There is no protection around the namespace node
922          * and the GPE handler to ensure a safe destruction
923          * because:
924          * 1. The namespace node is expected to always
925          *    exist after loading a table.
926          * 2. The GPE handler is expected to be flushed by
927          *    AcpiOsWaitEventsComplete() before the
928          *    destruction.
929          */
930         AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
931         IntStatus |= GpeHandlerInfo->Address (
932             GpeDevice, GpeNumber, GpeHandlerInfo->Context);
933         Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
934     }
935     else
936     {
937         /* Dispatch the event to a standard handler or method. */
938 
939         IntStatus |= AcpiEvGpeDispatch (GpeDevice,
940             GpeEventInfo, GpeNumber);
941     }
942 
943 ErrorExit:
944     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
945     return (IntStatus);
946 }
947 
948 
949 /*******************************************************************************
950  *
951  * FUNCTION:    AcpiEvGpeDispatch
952  *
953  * PARAMETERS:  GpeDevice           - Device node. NULL for GPE0/GPE1
954  *              GpeEventInfo        - Info for this GPE
955  *              GpeNumber           - Number relative to the parent GPE block
956  *
957  * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
958  *
959  * DESCRIPTION: Dispatch a General Purpose Event to either a function (e.g. EC)
960  *              or method (e.g. _Lxx/_Exx) handler.
961  *
962  ******************************************************************************/
963 
964 UINT32
965 AcpiEvGpeDispatch (
966     ACPI_NAMESPACE_NODE     *GpeDevice,
967     ACPI_GPE_EVENT_INFO     *GpeEventInfo,
968     UINT32                  GpeNumber)
969 {
970     ACPI_STATUS             Status;
971     UINT32                  ReturnValue;
972 
973 
974     ACPI_FUNCTION_TRACE (EvGpeDispatch);
975 
976 
977     /*
978      * Always disable the GPE so that it does not keep firing before
979      * any asynchronous activity completes (either from the execution
980      * of a GPE method or an asynchronous GPE handler.)
981      *
982      * If there is no handler or method to run, just disable the
983      * GPE and leave it disabled permanently to prevent further such
984      * pointless events from firing.
985      */
986     Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE);
987     if (ACPI_FAILURE (Status))
988     {
989         ACPI_EXCEPTION ((AE_INFO, Status,
990             "Unable to disable GPE %02X", GpeNumber));
991         return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
992     }
993 
994     /*
995      * If edge-triggered, clear the GPE status bit now. Note that
996      * level-triggered events are cleared after the GPE is serviced.
997      */
998     if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
999             ACPI_GPE_EDGE_TRIGGERED)
1000     {
1001         Status = AcpiHwClearGpe (GpeEventInfo);
1002         if (ACPI_FAILURE (Status))
1003         {
1004             ACPI_EXCEPTION ((AE_INFO, Status,
1005                 "Unable to clear GPE %02X", GpeNumber));
1006             (void) AcpiHwLowSetGpe (
1007                 GpeEventInfo, ACPI_GPE_CONDITIONAL_ENABLE);
1008             return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
1009         }
1010     }
1011 
1012     GpeEventInfo->DisableForDispatch = TRUE;
1013 
1014     /*
1015      * Dispatch the GPE to either an installed handler or the control
1016      * method associated with this GPE (_Lxx or _Exx). If a handler
1017      * exists, we invoke it and do not attempt to run the method.
1018      * If there is neither a handler nor a method, leave the GPE
1019      * disabled.
1020      */
1021     switch (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags))
1022     {
1023     case ACPI_GPE_DISPATCH_HANDLER:
1024 
1025         /* Invoke the installed handler (at interrupt level) */
1026 
1027         ReturnValue = GpeEventInfo->Dispatch.Handler->Address (
1028             GpeDevice, GpeNumber,
1029             GpeEventInfo->Dispatch.Handler->Context);
1030 
1031         /* If requested, clear (if level-triggered) and re-enable the GPE */
1032 
1033         if (ReturnValue & ACPI_REENABLE_GPE)
1034         {
1035             (void) AcpiEvFinishGpe (GpeEventInfo);
1036         }
1037         break;
1038 
1039     case ACPI_GPE_DISPATCH_METHOD:
1040     case ACPI_GPE_DISPATCH_NOTIFY:
1041         /*
1042          * Execute the method associated with the GPE
1043          * NOTE: Level-triggered GPEs are cleared after the method completes.
1044          */
1045         Status = AcpiOsExecute (OSL_GPE_HANDLER,
1046             AcpiEvAsynchExecuteGpeMethod, GpeEventInfo);
1047         if (ACPI_FAILURE (Status))
1048         {
1049             ACPI_EXCEPTION ((AE_INFO, Status,
1050                 "Unable to queue handler for GPE %02X - event disabled",
1051                 GpeNumber));
1052         }
1053         break;
1054 
1055     default:
1056         /*
1057          * No handler or method to run!
1058          * 03/2010: This case should no longer be possible. We will not allow
1059          * a GPE to be enabled if it has no handler or method.
1060          */
1061         ACPI_ERROR ((AE_INFO,
1062             "No handler or method for GPE %02X, disabling event",
1063             GpeNumber));
1064         break;
1065     }
1066 
1067     return_UINT32 (ACPI_INTERRUPT_HANDLED);
1068 }
1069 
1070 #endif /* !ACPI_REDUCED_HARDWARE */
1071