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