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