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