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