xref: /reactos/drivers/bus/acpi/acpica/events/evxfgpe.c (revision 9393fc32)
1 /******************************************************************************
2  *
3  * Module Name: evxfgpe - External Interfaces for General Purpose Events (GPEs)
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2021, 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 MERCHANTABILITY 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 #define EXPORT_ACPI_INTERFACES
45 
46 #include "acpi.h"
47 #include "accommon.h"
48 #include "acevents.h"
49 #include "acnamesp.h"
50 
51 #define _COMPONENT          ACPI_EVENTS
52         ACPI_MODULE_NAME    ("evxfgpe")
53 
54 
55 #if (!ACPI_REDUCED_HARDWARE) /* Entire module */
56 /*******************************************************************************
57  *
58  * FUNCTION:    AcpiUpdateAllGpes
59  *
60  * PARAMETERS:  None
61  *
62  * RETURN:      Status
63  *
64  * DESCRIPTION: Complete GPE initialization and enable all GPEs that have
65  *              associated _Lxx or _Exx methods and are not pointed to by any
66  *              device _PRW methods (this indicates that these GPEs are
67  *              generally intended for system or device wakeup. Such GPEs
68  *              have to be enabled directly when the devices whose _PRW
69  *              methods point to them are set up for wakeup signaling.)
70  *
71  * NOTE: Should be called after any GPEs are added to the system. Primarily,
72  * after the system _PRW methods have been run, but also after a GPE Block
73  * Device has been added or if any new GPE methods have been added via a
74  * dynamic table load.
75  *
76  ******************************************************************************/
77 
78 ACPI_STATUS
79 AcpiUpdateAllGpes (
80     void)
81 {
82     ACPI_STATUS             Status;
83     BOOLEAN                 IsPollingNeeded = FALSE;
84 
85 
86     ACPI_FUNCTION_TRACE (AcpiUpdateAllGpes);
87 
88 
89     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
90     if (ACPI_FAILURE (Status))
91     {
92         return_ACPI_STATUS (Status);
93     }
94 
95     if (AcpiGbl_AllGpesInitialized)
96     {
97         goto UnlockAndExit;
98     }
99 
100     Status = AcpiEvWalkGpeList (AcpiEvInitializeGpeBlock,
101         &IsPollingNeeded);
102     if (ACPI_SUCCESS (Status))
103     {
104         AcpiGbl_AllGpesInitialized = TRUE;
105     }
106 
107 UnlockAndExit:
108     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
109 
110     if (IsPollingNeeded && AcpiGbl_AllGpesInitialized)
111     {
112         /* Poll GPEs to handle already triggered events */
113 
114         AcpiEvGpeDetect (AcpiGbl_GpeXruptListHead);
115     }
116     return_ACPI_STATUS (Status);
117 }
118 
119 ACPI_EXPORT_SYMBOL (AcpiUpdateAllGpes)
120 
121 
122 /*******************************************************************************
123  *
124  * FUNCTION:    AcpiEnableGpe
125  *
126  * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
127  *              GpeNumber           - GPE level within the GPE block
128  *
129  * RETURN:      Status
130  *
131  * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is
132  *              hardware-enabled.
133  *
134  ******************************************************************************/
135 
136 ACPI_STATUS
137 AcpiEnableGpe (
138     ACPI_HANDLE             GpeDevice,
139     UINT32                  GpeNumber)
140 {
141     ACPI_STATUS             Status = AE_BAD_PARAMETER;
142     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
143     ACPI_CPU_FLAGS          Flags;
144 
145 
146     ACPI_FUNCTION_TRACE (AcpiEnableGpe);
147 
148 
149     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
150 
151     /*
152      * Ensure that we have a valid GPE number and that there is some way
153      * of handling the GPE (handler or a GPE method). In other words, we
154      * won't allow a valid GPE to be enabled if there is no way to handle it.
155      */
156     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
157     if (GpeEventInfo)
158     {
159         if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) !=
160             ACPI_GPE_DISPATCH_NONE)
161         {
162             Status = AcpiEvAddGpeReference (GpeEventInfo, TRUE);
163             if (ACPI_SUCCESS (Status) &&
164                 ACPI_GPE_IS_POLLING_NEEDED (GpeEventInfo))
165             {
166                 /* Poll edge-triggered GPEs to handle existing events */
167 
168                 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
169                 (void) AcpiEvDetectGpe (
170                     GpeDevice, GpeEventInfo, GpeNumber);
171                 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
172             }
173         }
174         else
175         {
176             Status = AE_NO_HANDLER;
177         }
178     }
179 
180     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
181     return_ACPI_STATUS (Status);
182 }
183 
184 ACPI_EXPORT_SYMBOL (AcpiEnableGpe)
185 
186 
187 /*******************************************************************************
188  *
189  * FUNCTION:    AcpiDisableGpe
190  *
191  * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
192  *              GpeNumber           - GPE level within the GPE block
193  *
194  * RETURN:      Status
195  *
196  * DESCRIPTION: Remove a reference to a GPE. When the last reference is
197  *              removed, only then is the GPE disabled (for runtime GPEs), or
198  *              the GPE mask bit disabled (for wake GPEs)
199  *
200  ******************************************************************************/
201 
202 ACPI_STATUS
203 AcpiDisableGpe (
204     ACPI_HANDLE             GpeDevice,
205     UINT32                  GpeNumber)
206 {
207     ACPI_STATUS             Status = AE_BAD_PARAMETER;
208     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
209     ACPI_CPU_FLAGS          Flags;
210 
211 
212     ACPI_FUNCTION_TRACE (AcpiDisableGpe);
213 
214 
215     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
216 
217     /* Ensure that we have a valid GPE number */
218 
219     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
220     if (GpeEventInfo)
221     {
222         Status = AcpiEvRemoveGpeReference (GpeEventInfo);
223     }
224 
225     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
226     return_ACPI_STATUS (Status);
227 }
228 
229 ACPI_EXPORT_SYMBOL (AcpiDisableGpe)
230 
231 
232 /*******************************************************************************
233  *
234  * FUNCTION:    AcpiSetGpe
235  *
236  * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
237  *              GpeNumber           - GPE level within the GPE block
238  *              Action              - ACPI_GPE_ENABLE or ACPI_GPE_DISABLE
239  *
240  * RETURN:      Status
241  *
242  * DESCRIPTION: Enable or disable an individual GPE. This function bypasses
243  *              the reference count mechanism used in the AcpiEnableGpe(),
244  *              AcpiDisableGpe() interfaces.
245  *              This API is typically used by the GPE raw handler mode driver
246  *              to switch between the polling mode and the interrupt mode after
247  *              the driver has enabled the GPE.
248  *              The APIs should be invoked in this order:
249  *               AcpiEnableGpe()              <- Ensure the reference count > 0
250  *               AcpiSetGpe(ACPI_GPE_DISABLE) <- Enter polling mode
251  *               AcpiSetGpe(ACPI_GPE_ENABLE)  <- Leave polling mode
252  *               AcpiDisableGpe()             <- Decrease the reference count
253  *
254  * Note: If a GPE is shared by 2 silicon components, then both the drivers
255  *       should support GPE polling mode or disabling the GPE for long period
256  *       for one driver may break the other. So use it with care since all
257  *       firmware _Lxx/_Exx handlers currently rely on the GPE interrupt mode.
258  *
259  ******************************************************************************/
260 
261 ACPI_STATUS
262 AcpiSetGpe (
263     ACPI_HANDLE             GpeDevice,
264     UINT32                  GpeNumber,
265     UINT8                   Action)
266 {
267     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
268     ACPI_STATUS             Status;
269     ACPI_CPU_FLAGS          Flags;
270 
271 
272     ACPI_FUNCTION_TRACE (AcpiSetGpe);
273 
274 
275     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
276 
277     /* Ensure that we have a valid GPE number */
278 
279     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
280     if (!GpeEventInfo)
281     {
282         Status = AE_BAD_PARAMETER;
283         goto UnlockAndExit;
284     }
285 
286     /* Perform the action */
287 
288     switch (Action)
289     {
290     case ACPI_GPE_ENABLE:
291 
292         Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_ENABLE);
293         GpeEventInfo->DisableForDispatch = FALSE;
294         break;
295 
296     case ACPI_GPE_DISABLE:
297 
298         Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE);
299         GpeEventInfo->DisableForDispatch = TRUE;
300         break;
301 
302     default:
303 
304         Status = AE_BAD_PARAMETER;
305         break;
306     }
307 
308 UnlockAndExit:
309     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
310     return_ACPI_STATUS (Status);
311 }
312 
313 ACPI_EXPORT_SYMBOL (AcpiSetGpe)
314 
315 
316 /*******************************************************************************
317  *
318  * FUNCTION:    AcpiMaskGpe
319  *
320  * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
321  *              GpeNumber           - GPE level within the GPE block
322  *              IsMasked            - Whether the GPE is masked or not
323  *
324  * RETURN:      Status
325  *
326  * DESCRIPTION: Unconditionally mask/unmask the an individual GPE, ex., to
327  *              prevent a GPE flooding.
328  *
329  ******************************************************************************/
330 
331 ACPI_STATUS
332 AcpiMaskGpe (
333     ACPI_HANDLE             GpeDevice,
334     UINT32                  GpeNumber,
335     BOOLEAN                 IsMasked)
336 {
337     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
338     ACPI_STATUS             Status;
339     ACPI_CPU_FLAGS          Flags;
340 
341 
342     ACPI_FUNCTION_TRACE (AcpiMaskGpe);
343 
344 
345     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
346 
347     /* Ensure that we have a valid GPE number */
348 
349     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
350     if (!GpeEventInfo)
351     {
352         Status = AE_BAD_PARAMETER;
353         goto UnlockAndExit;
354     }
355 
356     Status = AcpiEvMaskGpe (GpeEventInfo, IsMasked);
357 
358 UnlockAndExit:
359     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
360     return_ACPI_STATUS (Status);
361 }
362 
363 ACPI_EXPORT_SYMBOL (AcpiMaskGpe)
364 
365 
366 /*******************************************************************************
367  *
368  * FUNCTION:    AcpiMarkGpeForWake
369  *
370  * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
371  *              GpeNumber           - GPE level within the GPE block
372  *
373  * RETURN:      Status
374  *
375  * DESCRIPTION: Mark a GPE as having the ability to wake the system. Simply
376  *              sets the ACPI_GPE_CAN_WAKE flag.
377  *
378  * Some potential callers of AcpiSetupGpeForWake may know in advance that
379  * there won't be any notify handlers installed for device wake notifications
380  * from the given GPE (one example is a button GPE in Linux). For these cases,
381  * AcpiMarkGpeForWake should be used instead of AcpiSetupGpeForWake.
382  * This will set the ACPI_GPE_CAN_WAKE flag for the GPE without trying to
383  * setup implicit wake notification for it (since there's no handler method).
384  *
385  ******************************************************************************/
386 
387 ACPI_STATUS
388 AcpiMarkGpeForWake (
389     ACPI_HANDLE             GpeDevice,
390     UINT32                  GpeNumber)
391 {
392     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
393     ACPI_STATUS             Status = AE_BAD_PARAMETER;
394     ACPI_CPU_FLAGS          Flags;
395 
396 
397     ACPI_FUNCTION_TRACE (AcpiMarkGpeForWake);
398 
399 
400     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
401 
402     /* Ensure that we have a valid GPE number */
403 
404     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
405     if (GpeEventInfo)
406     {
407         /* Mark the GPE as a possible wake event */
408 
409         GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE;
410         Status = AE_OK;
411     }
412 
413     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
414     return_ACPI_STATUS (Status);
415 }
416 
417 ACPI_EXPORT_SYMBOL (AcpiMarkGpeForWake)
418 
419 
420 /*******************************************************************************
421  *
422  * FUNCTION:    AcpiSetupGpeForWake
423  *
424  * PARAMETERS:  WakeDevice          - Device associated with the GPE (via _PRW)
425  *              GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
426  *              GpeNumber           - GPE level within the GPE block
427  *
428  * RETURN:      Status
429  *
430  * DESCRIPTION: Mark a GPE as having the ability to wake the system. This
431  *              interface is intended to be used as the host executes the
432  *              _PRW methods (Power Resources for Wake) in the system tables.
433  *              Each _PRW appears under a Device Object (The WakeDevice), and
434  *              contains the info for the wake GPE associated with the
435  *              WakeDevice.
436  *
437  ******************************************************************************/
438 
439 ACPI_STATUS
440 AcpiSetupGpeForWake (
441     ACPI_HANDLE             WakeDevice,
442     ACPI_HANDLE             GpeDevice,
443     UINT32                  GpeNumber)
444 {
445     ACPI_STATUS             Status;
446     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
447     ACPI_NAMESPACE_NODE     *DeviceNode;
448     ACPI_GPE_NOTIFY_INFO    *Notify;
449     ACPI_GPE_NOTIFY_INFO    *NewNotify;
450     ACPI_CPU_FLAGS          Flags;
451 
452 
453     ACPI_FUNCTION_TRACE (AcpiSetupGpeForWake);
454 
455 
456     /* Parameter Validation */
457 
458     if (!WakeDevice)
459     {
460         /*
461          * By forcing WakeDevice to be valid, we automatically enable the
462          * implicit notify feature on all hosts.
463          */
464         return_ACPI_STATUS (AE_BAD_PARAMETER);
465     }
466 
467     /* Handle root object case */
468 
469     if (WakeDevice == ACPI_ROOT_OBJECT)
470     {
471         DeviceNode = AcpiGbl_RootNode;
472     }
473     else
474     {
475         DeviceNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, WakeDevice);
476     }
477 
478     /* Validate WakeDevice is of type Device */
479 
480     if (DeviceNode->Type != ACPI_TYPE_DEVICE)
481     {
482         return_ACPI_STATUS (AE_BAD_PARAMETER);
483     }
484 
485     /*
486      * Allocate a new notify object up front, in case it is needed.
487      * Memory allocation while holding a spinlock is a big no-no
488      * on some hosts.
489      */
490     NewNotify = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_NOTIFY_INFO));
491     if (!NewNotify)
492     {
493         return_ACPI_STATUS (AE_NO_MEMORY);
494     }
495 
496     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
497 
498     /* Ensure that we have a valid GPE number */
499 
500     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
501     if (!GpeEventInfo)
502     {
503         Status = AE_BAD_PARAMETER;
504         goto UnlockAndExit;
505     }
506 
507     /*
508      * If there is no method or handler for this GPE, then the
509      * WakeDevice will be notified whenever this GPE fires. This is
510      * known as an "implicit notify". Note: The GPE is assumed to be
511      * level-triggered (for windows compatibility).
512      */
513     if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) ==
514         ACPI_GPE_DISPATCH_NONE)
515     {
516         /*
517          * This is the first device for implicit notify on this GPE.
518          * Just set the flags here, and enter the NOTIFY block below.
519          */
520         GpeEventInfo->Flags =
521             (ACPI_GPE_DISPATCH_NOTIFY | ACPI_GPE_LEVEL_TRIGGERED);
522     }
523     else if (GpeEventInfo->Flags & ACPI_GPE_AUTO_ENABLED)
524     {
525         /*
526          * A reference to this GPE has been added during the GPE block
527          * initialization, so drop it now to prevent the GPE from being
528          * permanently enabled and clear its ACPI_GPE_AUTO_ENABLED flag.
529          */
530         (void) AcpiEvRemoveGpeReference (GpeEventInfo);
531         GpeEventInfo->Flags &= ~~ACPI_GPE_AUTO_ENABLED;
532     }
533 
534     /*
535      * If we already have an implicit notify on this GPE, add
536      * this device to the notify list.
537      */
538     if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) ==
539         ACPI_GPE_DISPATCH_NOTIFY)
540     {
541         /* Ensure that the device is not already in the list */
542 
543         Notify = GpeEventInfo->Dispatch.NotifyList;
544         while (Notify)
545         {
546             if (Notify->DeviceNode == DeviceNode)
547             {
548                 Status = AE_ALREADY_EXISTS;
549                 goto UnlockAndExit;
550             }
551             Notify = Notify->Next;
552         }
553 
554         /* Add this device to the notify list for this GPE */
555 
556         NewNotify->DeviceNode = DeviceNode;
557         NewNotify->Next = GpeEventInfo->Dispatch.NotifyList;
558         GpeEventInfo->Dispatch.NotifyList = NewNotify;
559         NewNotify = NULL;
560     }
561 
562     /* Mark the GPE as a possible wake event */
563 
564     GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE;
565     Status = AE_OK;
566 
567 
568 UnlockAndExit:
569     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
570 
571     /* Delete the notify object if it was not used above */
572 
573     if (NewNotify)
574     {
575         ACPI_FREE (NewNotify);
576     }
577     return_ACPI_STATUS (Status);
578 }
579 
580 ACPI_EXPORT_SYMBOL (AcpiSetupGpeForWake)
581 
582 
583 /*******************************************************************************
584  *
585  * FUNCTION:    AcpiSetGpeWakeMask
586  *
587  * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
588  *              GpeNumber           - GPE level within the GPE block
589  *              Action              - Enable or Disable
590  *
591  * RETURN:      Status
592  *
593  * DESCRIPTION: Set or clear the GPE's wakeup enable mask bit. The GPE must
594  *              already be marked as a WAKE GPE.
595  *
596  ******************************************************************************/
597 
598 ACPI_STATUS
599 AcpiSetGpeWakeMask (
600     ACPI_HANDLE             GpeDevice,
601     UINT32                  GpeNumber,
602     UINT8                   Action)
603 {
604     ACPI_STATUS             Status = AE_OK;
605     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
606     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
607     ACPI_CPU_FLAGS          Flags;
608     UINT32                  RegisterBit;
609 
610 
611     ACPI_FUNCTION_TRACE (AcpiSetGpeWakeMask);
612 
613 
614     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
615 
616     /*
617      * Ensure that we have a valid GPE number and that this GPE is in
618      * fact a wake GPE
619      */
620     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
621     if (!GpeEventInfo)
622     {
623         Status = AE_BAD_PARAMETER;
624         goto UnlockAndExit;
625     }
626 
627     if (!(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE))
628     {
629         Status = AE_TYPE;
630         goto UnlockAndExit;
631     }
632 
633     GpeRegisterInfo = GpeEventInfo->RegisterInfo;
634     if (!GpeRegisterInfo)
635     {
636         Status = AE_NOT_EXIST;
637         goto UnlockAndExit;
638     }
639 
640     RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo);
641 
642     /* Perform the action */
643 
644     switch (Action)
645     {
646     case ACPI_GPE_ENABLE:
647 
648         ACPI_SET_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit);
649         break;
650 
651     case ACPI_GPE_DISABLE:
652 
653         ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit);
654         break;
655 
656     default:
657 
658         ACPI_ERROR ((AE_INFO, "%u, Invalid action", Action));
659         Status = AE_BAD_PARAMETER;
660         break;
661     }
662 
663 UnlockAndExit:
664     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
665     return_ACPI_STATUS (Status);
666 }
667 
668 ACPI_EXPORT_SYMBOL (AcpiSetGpeWakeMask)
669 
670 
671 /*******************************************************************************
672  *
673  * FUNCTION:    AcpiClearGpe
674  *
675  * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
676  *              GpeNumber           - GPE level within the GPE block
677  *
678  * RETURN:      Status
679  *
680  * DESCRIPTION: Clear an ACPI event (general purpose)
681  *
682  ******************************************************************************/
683 
684 ACPI_STATUS
685 AcpiClearGpe (
686     ACPI_HANDLE             GpeDevice,
687     UINT32                  GpeNumber)
688 {
689     ACPI_STATUS             Status = AE_OK;
690     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
691     ACPI_CPU_FLAGS          Flags;
692 
693 
694     ACPI_FUNCTION_TRACE (AcpiClearGpe);
695 
696 
697     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
698 
699     /* Ensure that we have a valid GPE number */
700 
701     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
702     if (!GpeEventInfo)
703     {
704         Status = AE_BAD_PARAMETER;
705         goto UnlockAndExit;
706     }
707 
708     Status = AcpiHwClearGpe (GpeEventInfo);
709 
710 UnlockAndExit:
711     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
712     return_ACPI_STATUS (Status);
713 }
714 
715 ACPI_EXPORT_SYMBOL (AcpiClearGpe)
716 
717 
718 /*******************************************************************************
719  *
720  * FUNCTION:    AcpiGetGpeStatus
721  *
722  * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
723  *              GpeNumber           - GPE level within the GPE block
724  *              EventStatus         - Where the current status of the event
725  *                                    will be returned
726  *
727  * RETURN:      Status
728  *
729  * DESCRIPTION: Get the current status of a GPE (signalled/not_signalled)
730  *
731  ******************************************************************************/
732 
733 ACPI_STATUS
734 AcpiGetGpeStatus (
735     ACPI_HANDLE             GpeDevice,
736     UINT32                  GpeNumber,
737     ACPI_EVENT_STATUS       *EventStatus)
738 {
739     ACPI_STATUS             Status = AE_OK;
740     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
741     ACPI_CPU_FLAGS          Flags;
742 
743 
744     ACPI_FUNCTION_TRACE (AcpiGetGpeStatus);
745 
746 
747     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
748 
749     /* Ensure that we have a valid GPE number */
750 
751     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
752     if (!GpeEventInfo)
753     {
754         Status = AE_BAD_PARAMETER;
755         goto UnlockAndExit;
756     }
757 
758     /* Obtain status on the requested GPE number */
759 
760     Status = AcpiHwGetGpeStatus (GpeEventInfo, EventStatus);
761 
762 UnlockAndExit:
763     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
764     return_ACPI_STATUS (Status);
765 }
766 
767 ACPI_EXPORT_SYMBOL (AcpiGetGpeStatus)
768 
769 
770 /*******************************************************************************
771  *
772  * FUNCTION:    AcpiDispatchGpe
773  *
774  * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
775  *              GpeNumber           - GPE level within the GPE block
776  *
777  * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
778  *
779  * DESCRIPTION: Detect and dispatch a General Purpose Event to either a function
780  *              (e.g. EC) or method (e.g. _Lxx/_Exx) handler.
781  *
782  ******************************************************************************/
783 
784 UINT32
785 AcpiDispatchGpe(
786     ACPI_HANDLE             GpeDevice,
787     UINT32                  GpeNumber)
788 {
789     ACPI_FUNCTION_TRACE(acpi_dispatch_gpe);
790 
791     return (AcpiEvDetectGpe (GpeDevice, NULL, GpeNumber));
792 }
793 
794 ACPI_EXPORT_SYMBOL (AcpiDispatchGpe)
795 
796 
797 /*******************************************************************************
798  *
799  * FUNCTION:    AcpiFinishGpe
800  *
801  * PARAMETERS:  GpeDevice           - Namespace node for the GPE Block
802  *                                    (NULL for FADT defined GPEs)
803  *              GpeNumber           - GPE level within the GPE block
804  *
805  * RETURN:      Status
806  *
807  * DESCRIPTION: Clear and conditionally re-enable a GPE. This completes the GPE
808  *              processing. Intended for use by asynchronous host-installed
809  *              GPE handlers. The GPE is only re-enabled if the EnableForRun bit
810  *              is set in the GPE info.
811  *
812  ******************************************************************************/
813 
814 ACPI_STATUS
815 AcpiFinishGpe (
816     ACPI_HANDLE             GpeDevice,
817     UINT32                  GpeNumber)
818 {
819     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
820     ACPI_STATUS             Status;
821     ACPI_CPU_FLAGS          Flags;
822 
823 
824     ACPI_FUNCTION_TRACE (AcpiFinishGpe);
825 
826 
827     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
828 
829     /* Ensure that we have a valid GPE number */
830 
831     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
832     if (!GpeEventInfo)
833     {
834         Status = AE_BAD_PARAMETER;
835         goto UnlockAndExit;
836     }
837 
838     Status = AcpiEvFinishGpe (GpeEventInfo);
839 
840 UnlockAndExit:
841     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
842     return_ACPI_STATUS (Status);
843 }
844 
845 ACPI_EXPORT_SYMBOL (AcpiFinishGpe)
846 
847 
848 /******************************************************************************
849  *
850  * FUNCTION:    AcpiDisableAllGpes
851  *
852  * PARAMETERS:  None
853  *
854  * RETURN:      Status
855  *
856  * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
857  *
858  ******************************************************************************/
859 
860 ACPI_STATUS
861 AcpiDisableAllGpes (
862     void)
863 {
864     ACPI_STATUS             Status;
865 
866 
867     ACPI_FUNCTION_TRACE (AcpiDisableAllGpes);
868 
869 
870     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
871     if (ACPI_FAILURE (Status))
872     {
873         return_ACPI_STATUS (Status);
874     }
875 
876     Status = AcpiHwDisableAllGpes ();
877     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
878 
879     return_ACPI_STATUS (Status);
880 }
881 
882 ACPI_EXPORT_SYMBOL (AcpiDisableAllGpes)
883 
884 
885 /******************************************************************************
886  *
887  * FUNCTION:    AcpiEnableAllRuntimeGpes
888  *
889  * PARAMETERS:  None
890  *
891  * RETURN:      Status
892  *
893  * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
894  *
895  ******************************************************************************/
896 
897 ACPI_STATUS
898 AcpiEnableAllRuntimeGpes (
899     void)
900 {
901     ACPI_STATUS             Status;
902 
903 
904     ACPI_FUNCTION_TRACE (AcpiEnableAllRuntimeGpes);
905 
906 
907     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
908     if (ACPI_FAILURE (Status))
909     {
910         return_ACPI_STATUS (Status);
911     }
912 
913     Status = AcpiHwEnableAllRuntimeGpes ();
914     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
915 
916     return_ACPI_STATUS (Status);
917 }
918 
919 ACPI_EXPORT_SYMBOL (AcpiEnableAllRuntimeGpes)
920 
921 
922 /******************************************************************************
923  *
924  * FUNCTION:    AcpiEnableAllWakeupGpes
925  *
926  * PARAMETERS:  None
927  *
928  * RETURN:      Status
929  *
930  * DESCRIPTION: Enable all "wakeup" GPEs and disable all of the other GPEs, in
931  *              all GPE blocks.
932  *
933  ******************************************************************************/
934 
935 ACPI_STATUS
936 AcpiEnableAllWakeupGpes (
937     void)
938 {
939     ACPI_STATUS             Status;
940 
941 
942     ACPI_FUNCTION_TRACE (AcpiEnableAllWakeupGpes);
943 
944 
945     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
946     if (ACPI_FAILURE (Status))
947     {
948         return_ACPI_STATUS (Status);
949     }
950 
951     Status = AcpiHwEnableAllWakeupGpes ();
952     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
953 
954     return_ACPI_STATUS (Status);
955 }
956 
957 ACPI_EXPORT_SYMBOL (AcpiEnableAllWakeupGpes)
958 
959 
960 /******************************************************************************
961  *
962  * FUNCTION:    AcpiAnyGpeStatusSet
963  *
964  * PARAMETERS:  None
965  *
966  * RETURN:      Whether or not the status bit is set for any GPE
967  *
968  * DESCRIPTION: Check the status bits of all enabled GPEs and return TRUE if any
969  *              of them is set or FALSE otherwise.
970  *
971  ******************************************************************************/
972 
973 UINT32
974 AcpiAnyGpeStatusSet (
975     void)
976 {
977     ACPI_STATUS                Status;
978     UINT8                      Ret;
979 
980 
981     ACPI_FUNCTION_TRACE (AcpiAnyGpeStatusSet);
982 
983     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
984     if (ACPI_FAILURE (Status))
985     {
986         return (FALSE);
987     }
988 
989     Ret = AcpiHwCheckAllGpes ();
990     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
991 
992     return (Ret);
993 }
994 
995 ACPI_EXPORT_SYMBOL(AcpiAnyGpeStatusSet)
996 
997 
998 /*******************************************************************************
999  *
1000  * FUNCTION:    AcpiInstallGpeBlock
1001  *
1002  * PARAMETERS:  GpeDevice           - Handle to the parent GPE Block Device
1003  *              GpeBlockAddress     - Address and SpaceID
1004  *              RegisterCount       - Number of GPE register pairs in the block
1005  *              InterruptNumber     - H/W interrupt for the block
1006  *
1007  * RETURN:      Status
1008  *
1009  * DESCRIPTION: Create and Install a block of GPE registers. The GPEs are not
1010  *              enabled here.
1011  *
1012  ******************************************************************************/
1013 
1014 ACPI_STATUS
1015 AcpiInstallGpeBlock (
1016     ACPI_HANDLE             GpeDevice,
1017     ACPI_GENERIC_ADDRESS    *GpeBlockAddress,
1018     UINT32                  RegisterCount,
1019     UINT32                  InterruptNumber)
1020 {
1021     ACPI_STATUS             Status;
1022     ACPI_OPERAND_OBJECT     *ObjDesc;
1023     ACPI_NAMESPACE_NODE     *Node;
1024     ACPI_GPE_BLOCK_INFO     *GpeBlock;
1025 
1026 
1027     ACPI_FUNCTION_TRACE (AcpiInstallGpeBlock);
1028 
1029 
1030     if ((!GpeDevice)       ||
1031         (!GpeBlockAddress) ||
1032         (!RegisterCount))
1033     {
1034         return_ACPI_STATUS (AE_BAD_PARAMETER);
1035     }
1036 
1037     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
1038     if (ACPI_FAILURE (Status))
1039     {
1040         return_ACPI_STATUS (Status);
1041     }
1042 
1043     Node = AcpiNsValidateHandle (GpeDevice);
1044     if (!Node)
1045     {
1046         Status = AE_BAD_PARAMETER;
1047         goto UnlockAndExit;
1048     }
1049 
1050     /* Validate the parent device */
1051 
1052     if (Node->Type != ACPI_TYPE_DEVICE)
1053     {
1054         Status = AE_TYPE;
1055         goto UnlockAndExit;
1056     }
1057 
1058     if (Node->Object)
1059     {
1060         Status = AE_ALREADY_EXISTS;
1061         goto UnlockAndExit;
1062     }
1063 
1064     /*
1065      * For user-installed GPE Block Devices, the GpeBlockBaseNumber
1066      * is always zero
1067      */
1068     Status = AcpiEvCreateGpeBlock (Node, GpeBlockAddress->Address,
1069         GpeBlockAddress->SpaceId, RegisterCount,
1070         0, InterruptNumber, &GpeBlock);
1071     if (ACPI_FAILURE (Status))
1072     {
1073         goto UnlockAndExit;
1074     }
1075 
1076     /* Install block in the DeviceObject attached to the node */
1077 
1078     ObjDesc = AcpiNsGetAttachedObject (Node);
1079     if (!ObjDesc)
1080     {
1081         /*
1082          * No object, create a new one (Device nodes do not always have
1083          * an attached object)
1084          */
1085         ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_DEVICE);
1086         if (!ObjDesc)
1087         {
1088             Status = AE_NO_MEMORY;
1089             goto UnlockAndExit;
1090         }
1091 
1092         Status = AcpiNsAttachObject (Node, ObjDesc, ACPI_TYPE_DEVICE);
1093 
1094         /* Remove local reference to the object */
1095 
1096         AcpiUtRemoveReference (ObjDesc);
1097         if (ACPI_FAILURE (Status))
1098         {
1099             goto UnlockAndExit;
1100         }
1101     }
1102 
1103     /* Now install the GPE block in the DeviceObject */
1104 
1105     ObjDesc->Device.GpeBlock = GpeBlock;
1106 
1107 
1108 UnlockAndExit:
1109     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
1110     return_ACPI_STATUS (Status);
1111 }
1112 
1113 ACPI_EXPORT_SYMBOL (AcpiInstallGpeBlock)
1114 
1115 
1116 /*******************************************************************************
1117  *
1118  * FUNCTION:    AcpiRemoveGpeBlock
1119  *
1120  * PARAMETERS:  GpeDevice           - Handle to the parent GPE Block Device
1121  *
1122  * RETURN:      Status
1123  *
1124  * DESCRIPTION: Remove a previously installed block of GPE registers
1125  *
1126  ******************************************************************************/
1127 
1128 ACPI_STATUS
1129 AcpiRemoveGpeBlock (
1130     ACPI_HANDLE             GpeDevice)
1131 {
1132     ACPI_OPERAND_OBJECT     *ObjDesc;
1133     ACPI_STATUS             Status;
1134     ACPI_NAMESPACE_NODE     *Node;
1135 
1136 
1137     ACPI_FUNCTION_TRACE (AcpiRemoveGpeBlock);
1138 
1139 
1140     if (!GpeDevice)
1141     {
1142         return_ACPI_STATUS (AE_BAD_PARAMETER);
1143     }
1144 
1145     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
1146     if (ACPI_FAILURE (Status))
1147     {
1148         return_ACPI_STATUS (Status);
1149     }
1150 
1151     Node = AcpiNsValidateHandle (GpeDevice);
1152     if (!Node)
1153     {
1154         Status = AE_BAD_PARAMETER;
1155         goto UnlockAndExit;
1156     }
1157 
1158     /* Validate the parent device */
1159 
1160     if (Node->Type != ACPI_TYPE_DEVICE)
1161     {
1162         Status = AE_TYPE;
1163         goto UnlockAndExit;
1164     }
1165 
1166     /* Get the DeviceObject attached to the node */
1167 
1168     ObjDesc = AcpiNsGetAttachedObject (Node);
1169     if (!ObjDesc ||
1170         !ObjDesc->Device.GpeBlock)
1171     {
1172         return_ACPI_STATUS (AE_NULL_OBJECT);
1173     }
1174 
1175     /* Delete the GPE block (but not the DeviceObject) */
1176 
1177     Status = AcpiEvDeleteGpeBlock (ObjDesc->Device.GpeBlock);
1178     if (ACPI_SUCCESS (Status))
1179     {
1180         ObjDesc->Device.GpeBlock = NULL;
1181     }
1182 
1183 UnlockAndExit:
1184     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
1185     return_ACPI_STATUS (Status);
1186 }
1187 
1188 ACPI_EXPORT_SYMBOL (AcpiRemoveGpeBlock)
1189 
1190 
1191 /*******************************************************************************
1192  *
1193  * FUNCTION:    AcpiGetGpeDevice
1194  *
1195  * PARAMETERS:  Index               - System GPE index (0-CurrentGpeCount)
1196  *              GpeDevice           - Where the parent GPE Device is returned
1197  *
1198  * RETURN:      Status
1199  *
1200  * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL
1201  *              gpe device indicates that the gpe number is contained in one of
1202  *              the FADT-defined gpe blocks. Otherwise, the GPE block device.
1203  *
1204  ******************************************************************************/
1205 
1206 ACPI_STATUS
1207 AcpiGetGpeDevice (
1208     UINT32                  Index,
1209     ACPI_HANDLE             *GpeDevice)
1210 {
1211     ACPI_GPE_DEVICE_INFO    Info;
1212     ACPI_STATUS             Status;
1213 
1214 
1215     ACPI_FUNCTION_TRACE (AcpiGetGpeDevice);
1216 
1217 
1218     if (!GpeDevice)
1219     {
1220         return_ACPI_STATUS (AE_BAD_PARAMETER);
1221     }
1222 
1223     if (Index >= AcpiCurrentGpeCount)
1224     {
1225         return_ACPI_STATUS (AE_NOT_EXIST);
1226     }
1227 
1228     /* Setup and walk the GPE list */
1229 
1230     Info.Index = Index;
1231     Info.Status = AE_NOT_EXIST;
1232     Info.GpeDevice = NULL;
1233     Info.NextBlockBaseIndex = 0;
1234 
1235     Status = AcpiEvWalkGpeList (AcpiEvGetGpeDevice, &Info);
1236     if (ACPI_FAILURE (Status))
1237     {
1238         return_ACPI_STATUS (Status);
1239     }
1240 
1241     *GpeDevice = ACPI_CAST_PTR (ACPI_HANDLE, Info.GpeDevice);
1242     return_ACPI_STATUS (Info.Status);
1243 }
1244 
1245 ACPI_EXPORT_SYMBOL (AcpiGetGpeDevice)
1246 
1247 #endif /* !ACPI_REDUCED_HARDWARE */
1248