xref: /freebsd/sys/contrib/dev/acpica/components/events/evgpe.c (revision 5dae51da3da0cc94d17bd67b308fad304ebec7e0)
1 /******************************************************************************
2  *
3  * Module Name: evgpe - General Purpose Event handling and dispatch
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2016, 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 <contrib/dev/acpica/include/acpi.h>
45 #include <contrib/dev/acpica/include/accommon.h>
46 #include <contrib/dev/acpica/include/acevents.h>
47 #include <contrib/dev/acpica/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: Clear a GPE of stale events and enable it.
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_STATUS             Status;
438     ACPI_GPE_BLOCK_INFO     *GpeBlock;
439     ACPI_NAMESPACE_NODE     *GpeDevice;
440     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
441     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
442     UINT32                  GpeNumber;
443     ACPI_GPE_HANDLER_INFO   *GpeHandlerInfo;
444     UINT32                  IntStatus = ACPI_INTERRUPT_NOT_HANDLED;
445     UINT8                   EnabledStatusByte;
446     UINT32                  StatusReg;
447     UINT32                  EnableReg;
448     ACPI_CPU_FLAGS          Flags;
449     UINT32                  i;
450     UINT32                  j;
451 
452 
453     ACPI_FUNCTION_NAME (EvGpeDetect);
454 
455     /* Check for the case where there are no GPEs */
456 
457     if (!GpeXruptList)
458     {
459         return (IntStatus);
460     }
461 
462     /*
463      * We need to obtain the GPE lock for both the data structs and registers
464      * Note: Not necessary to obtain the hardware lock, since the GPE
465      * registers are owned by the GpeLock.
466      */
467     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
468 
469     /* Examine all GPE blocks attached to this interrupt level */
470 
471     GpeBlock = GpeXruptList->GpeBlockListHead;
472     while (GpeBlock)
473     {
474         GpeDevice = GpeBlock->Node;
475 
476         /*
477          * Read all of the 8-bit GPE status and enable registers in this GPE
478          * block, saving all of them. Find all currently active GP events.
479          */
480         for (i = 0; i < GpeBlock->RegisterCount; i++)
481         {
482             /* Get the next status/enable pair */
483 
484             GpeRegisterInfo = &GpeBlock->RegisterInfo[i];
485 
486             /*
487              * Optimization: If there are no GPEs enabled within this
488              * register, we can safely ignore the entire register.
489              */
490             if (!(GpeRegisterInfo->EnableForRun |
491                   GpeRegisterInfo->EnableForWake))
492             {
493                 ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
494                     "Ignore disabled registers for GPE %02X-%02X: "
495                     "RunEnable=%02X, WakeEnable=%02X\n",
496                     GpeRegisterInfo->BaseGpeNumber,
497                     GpeRegisterInfo->BaseGpeNumber + (ACPI_GPE_REGISTER_WIDTH - 1),
498                     GpeRegisterInfo->EnableForRun,
499                     GpeRegisterInfo->EnableForWake));
500                 continue;
501             }
502 
503             /* Read the Status Register */
504 
505             Status = AcpiHwRead (&StatusReg, &GpeRegisterInfo->StatusAddress);
506             if (ACPI_FAILURE (Status))
507             {
508                 goto UnlockAndExit;
509             }
510 
511             /* Read the Enable Register */
512 
513             Status = AcpiHwRead (&EnableReg, &GpeRegisterInfo->EnableAddress);
514             if (ACPI_FAILURE (Status))
515             {
516                 goto UnlockAndExit;
517             }
518 
519             ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
520                 "Read registers for GPE %02X-%02X: Status=%02X, Enable=%02X, "
521                 "RunEnable=%02X, WakeEnable=%02X\n",
522                 GpeRegisterInfo->BaseGpeNumber,
523                 GpeRegisterInfo->BaseGpeNumber + (ACPI_GPE_REGISTER_WIDTH - 1),
524                 StatusReg, EnableReg,
525                 GpeRegisterInfo->EnableForRun,
526                 GpeRegisterInfo->EnableForWake));
527 
528             /* Check if there is anything active at all in this register */
529 
530             EnabledStatusByte = (UINT8) (StatusReg & EnableReg);
531             if (!EnabledStatusByte)
532             {
533                 /* No active GPEs in this register, move on */
534 
535                 continue;
536             }
537 
538             /* Now look at the individual GPEs in this byte register */
539 
540             for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++)
541             {
542                 /* Examine one GPE bit */
543 
544                 GpeEventInfo = &GpeBlock->EventInfo[((ACPI_SIZE) i *
545                     ACPI_GPE_REGISTER_WIDTH) + j];
546                 GpeNumber = j + GpeRegisterInfo->BaseGpeNumber;
547 
548                 if (EnabledStatusByte & (1 << j))
549                 {
550                     /* Invoke global event handler if present */
551 
552                     AcpiGpeCount++;
553                     if (AcpiGbl_GlobalEventHandler)
554                     {
555                         AcpiGbl_GlobalEventHandler (ACPI_EVENT_TYPE_GPE,
556                             GpeDevice, GpeNumber,
557                             AcpiGbl_GlobalEventHandlerContext);
558                     }
559 
560                     /* Found an active GPE */
561 
562                     if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) ==
563                         ACPI_GPE_DISPATCH_RAW_HANDLER)
564                     {
565                         /* Dispatch the event to a raw handler */
566 
567                         GpeHandlerInfo = GpeEventInfo->Dispatch.Handler;
568 
569                         /*
570                          * There is no protection around the namespace node
571                          * and the GPE handler to ensure a safe destruction
572                          * because:
573                          * 1. The namespace node is expected to always
574                          *    exist after loading a table.
575                          * 2. The GPE handler is expected to be flushed by
576                          *    AcpiOsWaitEventsComplete() before the
577                          *    destruction.
578                          */
579                         AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
580                         IntStatus |= GpeHandlerInfo->Address (
581                             GpeDevice, GpeNumber, GpeHandlerInfo->Context);
582                         Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
583                     }
584                     else
585                     {
586                         /*
587                          * Dispatch the event to a standard handler or
588                          * method.
589                          */
590                         IntStatus |= AcpiEvGpeDispatch (GpeDevice,
591                             GpeEventInfo, GpeNumber);
592                     }
593                 }
594             }
595         }
596 
597         GpeBlock = GpeBlock->Next;
598     }
599 
600 UnlockAndExit:
601 
602     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
603     return (IntStatus);
604 }
605 
606 
607 /*******************************************************************************
608  *
609  * FUNCTION:    AcpiEvAsynchExecuteGpeMethod
610  *
611  * PARAMETERS:  Context (GpeEventInfo) - Info for this GPE
612  *
613  * RETURN:      None
614  *
615  * DESCRIPTION: Perform the actual execution of a GPE control method. This
616  *              function is called from an invocation of AcpiOsExecute and
617  *              therefore does NOT execute at interrupt level - so that
618  *              the control method itself is not executed in the context of
619  *              an interrupt handler.
620  *
621  ******************************************************************************/
622 
623 static void ACPI_SYSTEM_XFACE
624 AcpiEvAsynchExecuteGpeMethod (
625     void                    *Context)
626 {
627     ACPI_GPE_EVENT_INFO     *GpeEventInfo = Context;
628     ACPI_STATUS             Status = AE_OK;
629     ACPI_EVALUATE_INFO      *Info;
630     ACPI_GPE_NOTIFY_INFO    *Notify;
631 
632 
633     ACPI_FUNCTION_TRACE (EvAsynchExecuteGpeMethod);
634 
635 
636     /* Do the correct dispatch - normal method or implicit notify */
637 
638     switch (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags))
639     {
640     case ACPI_GPE_DISPATCH_NOTIFY:
641         /*
642          * Implicit notify.
643          * Dispatch a DEVICE_WAKE notify to the appropriate handler.
644          * NOTE: the request is queued for execution after this method
645          * completes. The notify handlers are NOT invoked synchronously
646          * from this thread -- because handlers may in turn run other
647          * control methods.
648          *
649          * June 2012: Expand implicit notify mechanism to support
650          * notifies on multiple device objects.
651          */
652         Notify = GpeEventInfo->Dispatch.NotifyList;
653         while (ACPI_SUCCESS (Status) && Notify)
654         {
655             Status = AcpiEvQueueNotifyRequest (
656                 Notify->DeviceNode, ACPI_NOTIFY_DEVICE_WAKE);
657 
658             Notify = Notify->Next;
659         }
660         break;
661 
662     case ACPI_GPE_DISPATCH_METHOD:
663 
664         /* Allocate the evaluation information block */
665 
666         Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
667         if (!Info)
668         {
669             Status = AE_NO_MEMORY;
670         }
671         else
672         {
673             /*
674              * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the
675              * _Lxx/_Exx control method that corresponds to this GPE
676              */
677             Info->PrefixNode = GpeEventInfo->Dispatch.MethodNode;
678             Info->Flags = ACPI_IGNORE_RETURN_VALUE;
679 
680             Status = AcpiNsEvaluate (Info);
681             ACPI_FREE (Info);
682         }
683 
684         if (ACPI_FAILURE (Status))
685         {
686             ACPI_EXCEPTION ((AE_INFO, Status,
687                 "while evaluating GPE method [%4.4s]",
688                 AcpiUtGetNodeName (GpeEventInfo->Dispatch.MethodNode)));
689         }
690         break;
691 
692     default:
693 
694         goto ErrorExit; /* Should never happen */
695     }
696 
697     /* Defer enabling of GPE until all notify handlers are done */
698 
699     Status = AcpiOsExecute (OSL_NOTIFY_HANDLER,
700         AcpiEvAsynchEnableGpe, GpeEventInfo);
701     if (ACPI_SUCCESS (Status))
702     {
703         return_VOID;
704     }
705 
706 ErrorExit:
707     AcpiEvAsynchEnableGpe (GpeEventInfo);
708     return_VOID;
709 }
710 
711 
712 /*******************************************************************************
713  *
714  * FUNCTION:    AcpiEvAsynchEnableGpe
715  *
716  * PARAMETERS:  Context (GpeEventInfo) - Info for this GPE
717  *              Callback from AcpiOsExecute
718  *
719  * RETURN:      None
720  *
721  * DESCRIPTION: Asynchronous clear/enable for GPE. This allows the GPE to
722  *              complete (i.e., finish execution of Notify)
723  *
724  ******************************************************************************/
725 
726 static void ACPI_SYSTEM_XFACE
727 AcpiEvAsynchEnableGpe (
728     void                    *Context)
729 {
730     ACPI_GPE_EVENT_INFO     *GpeEventInfo = Context;
731     ACPI_CPU_FLAGS          Flags;
732 
733 
734     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
735     (void) AcpiEvFinishGpe (GpeEventInfo);
736     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
737 
738     return;
739 }
740 
741 
742 /*******************************************************************************
743  *
744  * FUNCTION:    AcpiEvFinishGpe
745  *
746  * PARAMETERS:  GpeEventInfo        - Info for this GPE
747  *
748  * RETURN:      Status
749  *
750  * DESCRIPTION: Clear/Enable a GPE. Common code that is used after execution
751  *              of a GPE method or a synchronous or asynchronous GPE handler.
752  *
753  ******************************************************************************/
754 
755 ACPI_STATUS
756 AcpiEvFinishGpe (
757     ACPI_GPE_EVENT_INFO     *GpeEventInfo)
758 {
759     ACPI_STATUS             Status;
760 
761 
762     if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
763             ACPI_GPE_LEVEL_TRIGGERED)
764     {
765         /*
766          * GPE is level-triggered, we clear the GPE status bit after
767          * handling the event.
768          */
769         Status = AcpiHwClearGpe (GpeEventInfo);
770         if (ACPI_FAILURE (Status))
771         {
772             return (Status);
773         }
774     }
775 
776     /*
777      * Enable this GPE, conditionally. This means that the GPE will
778      * only be physically enabled if the EnableMask bit is set
779      * in the EventInfo.
780      */
781     (void) AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_CONDITIONAL_ENABLE);
782     GpeEventInfo->DisableForDispatch = FALSE;
783     return (AE_OK);
784 }
785 
786 
787 /*******************************************************************************
788  *
789  * FUNCTION:    AcpiEvGpeDispatch
790  *
791  * PARAMETERS:  GpeDevice           - Device node. NULL for GPE0/GPE1
792  *              GpeEventInfo        - Info for this GPE
793  *              GpeNumber           - Number relative to the parent GPE block
794  *
795  * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
796  *
797  * DESCRIPTION: Dispatch a General Purpose Event to either a function (e.g. EC)
798  *              or method (e.g. _Lxx/_Exx) handler.
799  *
800  *              This function executes at interrupt level.
801  *
802  ******************************************************************************/
803 
804 UINT32
805 AcpiEvGpeDispatch (
806     ACPI_NAMESPACE_NODE     *GpeDevice,
807     ACPI_GPE_EVENT_INFO     *GpeEventInfo,
808     UINT32                  GpeNumber)
809 {
810     ACPI_STATUS             Status;
811     UINT32                  ReturnValue;
812 
813 
814     ACPI_FUNCTION_TRACE (EvGpeDispatch);
815 
816 
817     /*
818      * Always disable the GPE so that it does not keep firing before
819      * any asynchronous activity completes (either from the execution
820      * of a GPE method or an asynchronous GPE handler.)
821      *
822      * If there is no handler or method to run, just disable the
823      * GPE and leave it disabled permanently to prevent further such
824      * pointless events from firing.
825      */
826     Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE);
827     if (ACPI_FAILURE (Status))
828     {
829         ACPI_EXCEPTION ((AE_INFO, Status,
830             "Unable to disable GPE %02X", GpeNumber));
831         return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
832     }
833 
834     /*
835      * If edge-triggered, clear the GPE status bit now. Note that
836      * level-triggered events are cleared after the GPE is serviced.
837      */
838     if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
839             ACPI_GPE_EDGE_TRIGGERED)
840     {
841         Status = AcpiHwClearGpe (GpeEventInfo);
842         if (ACPI_FAILURE (Status))
843         {
844             ACPI_EXCEPTION ((AE_INFO, Status,
845                 "Unable to clear GPE %02X", GpeNumber));
846             (void) AcpiHwLowSetGpe (
847                 GpeEventInfo, ACPI_GPE_CONDITIONAL_ENABLE);
848             return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
849         }
850     }
851 
852     GpeEventInfo->DisableForDispatch = TRUE;
853 
854     /*
855      * Dispatch the GPE to either an installed handler or the control
856      * method associated with this GPE (_Lxx or _Exx). If a handler
857      * exists, we invoke it and do not attempt to run the method.
858      * If there is neither a handler nor a method, leave the GPE
859      * disabled.
860      */
861     switch (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags))
862     {
863     case ACPI_GPE_DISPATCH_HANDLER:
864 
865         /* Invoke the installed handler (at interrupt level) */
866 
867         ReturnValue = GpeEventInfo->Dispatch.Handler->Address (
868             GpeDevice, GpeNumber,
869             GpeEventInfo->Dispatch.Handler->Context);
870 
871         /* If requested, clear (if level-triggered) and reenable the GPE */
872 
873         if (ReturnValue & ACPI_REENABLE_GPE)
874         {
875             (void) AcpiEvFinishGpe (GpeEventInfo);
876         }
877         break;
878 
879     case ACPI_GPE_DISPATCH_METHOD:
880     case ACPI_GPE_DISPATCH_NOTIFY:
881         /*
882          * Execute the method associated with the GPE
883          * NOTE: Level-triggered GPEs are cleared after the method completes.
884          */
885         Status = AcpiOsExecute (OSL_GPE_HANDLER,
886             AcpiEvAsynchExecuteGpeMethod, GpeEventInfo);
887         if (ACPI_FAILURE (Status))
888         {
889             ACPI_EXCEPTION ((AE_INFO, Status,
890                 "Unable to queue handler for GPE %02X - event disabled",
891                 GpeNumber));
892         }
893         break;
894 
895     default:
896         /*
897          * No handler or method to run!
898          * 03/2010: This case should no longer be possible. We will not allow
899          * a GPE to be enabled if it has no handler or method.
900          */
901         ACPI_ERROR ((AE_INFO,
902             "No handler or method for GPE %02X, disabling event",
903             GpeNumber));
904         break;
905     }
906 
907     return_UINT32 (ACPI_INTERRUPT_HANDLED);
908 }
909 
910 #endif /* !ACPI_REDUCED_HARDWARE */
911