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 "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 
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         GpeEventInfo->DisableForDispatch = FALSE;
275         break;
276 
277     case ACPI_GPE_DISABLE:
278 
279         Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE);
280         GpeEventInfo->DisableForDispatch = TRUE;
281         break;
282 
283     default:
284 
285         Status = AE_BAD_PARAMETER;
286         break;
287     }
288 
289 UnlockAndExit:
290     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
291     return_ACPI_STATUS (Status);
292 }
293 
294 ACPI_EXPORT_SYMBOL (AcpiSetGpe)
295 
296 
297 /*******************************************************************************
298  *
299  * FUNCTION:    AcpiMaskGpe
300  *
301  * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
302  *              GpeNumber           - GPE level within the GPE block
303  *              IsMasked            - Whether the GPE is masked or not
304  *
305  * RETURN:      Status
306  *
307  * DESCRIPTION: Unconditionally mask/unmask the an individual GPE, ex., to
308  *              prevent a GPE flooding.
309  *
310  ******************************************************************************/
311 
312 ACPI_STATUS
313 AcpiMaskGpe (
314     ACPI_HANDLE             GpeDevice,
315     UINT32                  GpeNumber,
316     BOOLEAN                 IsMasked)
317 {
318     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
319     ACPI_STATUS             Status;
320     ACPI_CPU_FLAGS          Flags;
321 
322 
323     ACPI_FUNCTION_TRACE (AcpiMaskGpe);
324 
325 
326     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
327 
328     /* Ensure that we have a valid GPE number */
329 
330     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
331     if (!GpeEventInfo)
332     {
333         Status = AE_BAD_PARAMETER;
334         goto UnlockAndExit;
335     }
336 
337     Status = AcpiEvMaskGpe (GpeEventInfo, IsMasked);
338 
339 UnlockAndExit:
340     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
341     return_ACPI_STATUS (Status);
342 }
343 
344 ACPI_EXPORT_SYMBOL (AcpiMaskGpe)
345 
346 
347 /*******************************************************************************
348  *
349  * FUNCTION:    AcpiMarkGpeForWake
350  *
351  * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
352  *              GpeNumber           - GPE level within the GPE block
353  *
354  * RETURN:      Status
355  *
356  * DESCRIPTION: Mark a GPE as having the ability to wake the system. Simply
357  *              sets the ACPI_GPE_CAN_WAKE flag.
358  *
359  * Some potential callers of AcpiSetupGpeForWake may know in advance that
360  * there won't be any notify handlers installed for device wake notifications
361  * from the given GPE (one example is a button GPE in Linux). For these cases,
362  * AcpiMarkGpeForWake should be used instead of AcpiSetupGpeForWake.
363  * This will set the ACPI_GPE_CAN_WAKE flag for the GPE without trying to
364  * setup implicit wake notification for it (since there's no handler method).
365  *
366  ******************************************************************************/
367 
368 ACPI_STATUS
369 AcpiMarkGpeForWake (
370     ACPI_HANDLE             GpeDevice,
371     UINT32                  GpeNumber)
372 {
373     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
374     ACPI_STATUS             Status = AE_BAD_PARAMETER;
375     ACPI_CPU_FLAGS          Flags;
376 
377 
378     ACPI_FUNCTION_TRACE (AcpiMarkGpeForWake);
379 
380 
381     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
382 
383     /* Ensure that we have a valid GPE number */
384 
385     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
386     if (GpeEventInfo)
387     {
388         /* Mark the GPE as a possible wake event */
389 
390         GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE;
391         Status = AE_OK;
392     }
393 
394     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
395     return_ACPI_STATUS (Status);
396 }
397 
398 ACPI_EXPORT_SYMBOL (AcpiMarkGpeForWake)
399 
400 
401 /*******************************************************************************
402  *
403  * FUNCTION:    AcpiSetupGpeForWake
404  *
405  * PARAMETERS:  WakeDevice          - Device associated with the GPE (via _PRW)
406  *              GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
407  *              GpeNumber           - GPE level within the GPE block
408  *
409  * RETURN:      Status
410  *
411  * DESCRIPTION: Mark a GPE as having the ability to wake the system. This
412  *              interface is intended to be used as the host executes the
413  *              _PRW methods (Power Resources for Wake) in the system tables.
414  *              Each _PRW appears under a Device Object (The WakeDevice), and
415  *              contains the info for the wake GPE associated with the
416  *              WakeDevice.
417  *
418  ******************************************************************************/
419 
420 ACPI_STATUS
421 AcpiSetupGpeForWake (
422     ACPI_HANDLE             WakeDevice,
423     ACPI_HANDLE             GpeDevice,
424     UINT32                  GpeNumber)
425 {
426     ACPI_STATUS             Status;
427     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
428     ACPI_NAMESPACE_NODE     *DeviceNode;
429     ACPI_GPE_NOTIFY_INFO    *Notify;
430     ACPI_GPE_NOTIFY_INFO    *NewNotify;
431     ACPI_CPU_FLAGS          Flags;
432 
433 
434     ACPI_FUNCTION_TRACE (AcpiSetupGpeForWake);
435 
436 
437     /* Parameter Validation */
438 
439     if (!WakeDevice)
440     {
441         /*
442          * By forcing WakeDevice to be valid, we automatically enable the
443          * implicit notify feature on all hosts.
444          */
445         return_ACPI_STATUS (AE_BAD_PARAMETER);
446     }
447 
448     /* Handle root object case */
449 
450     if (WakeDevice == ACPI_ROOT_OBJECT)
451     {
452         DeviceNode = AcpiGbl_RootNode;
453     }
454     else
455     {
456         DeviceNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, WakeDevice);
457     }
458 
459     /* Validate WakeDevice is of type Device */
460 
461     if (DeviceNode->Type != ACPI_TYPE_DEVICE)
462     {
463         return_ACPI_STATUS (AE_BAD_PARAMETER);
464     }
465 
466     /*
467      * Allocate a new notify object up front, in case it is needed.
468      * Memory allocation while holding a spinlock is a big no-no
469      * on some hosts.
470      */
471     NewNotify = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_NOTIFY_INFO));
472     if (!NewNotify)
473     {
474         return_ACPI_STATUS (AE_NO_MEMORY);
475     }
476 
477     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
478 
479     /* Ensure that we have a valid GPE number */
480 
481     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
482     if (!GpeEventInfo)
483     {
484         Status = AE_BAD_PARAMETER;
485         goto UnlockAndExit;
486     }
487 
488     /*
489      * If there is no method or handler for this GPE, then the
490      * WakeDevice will be notified whenever this GPE fires. This is
491      * known as an "implicit notify". Note: The GPE is assumed to be
492      * level-triggered (for windows compatibility).
493      */
494     if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) ==
495         ACPI_GPE_DISPATCH_NONE)
496     {
497         /*
498          * This is the first device for implicit notify on this GPE.
499          * Just set the flags here, and enter the NOTIFY block below.
500          */
501         GpeEventInfo->Flags =
502             (ACPI_GPE_DISPATCH_NOTIFY | ACPI_GPE_LEVEL_TRIGGERED);
503     }
504 
505     /*
506      * If we already have an implicit notify on this GPE, add
507      * this device to the notify list.
508      */
509     if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) ==
510         ACPI_GPE_DISPATCH_NOTIFY)
511     {
512         /* Ensure that the device is not already in the list */
513 
514         Notify = GpeEventInfo->Dispatch.NotifyList;
515         while (Notify)
516         {
517             if (Notify->DeviceNode == DeviceNode)
518             {
519                 Status = AE_ALREADY_EXISTS;
520                 goto UnlockAndExit;
521             }
522             Notify = Notify->Next;
523         }
524 
525         /* Add this device to the notify list for this GPE */
526 
527         NewNotify->DeviceNode = DeviceNode;
528         NewNotify->Next = GpeEventInfo->Dispatch.NotifyList;
529         GpeEventInfo->Dispatch.NotifyList = NewNotify;
530         NewNotify = NULL;
531     }
532 
533     /* Mark the GPE as a possible wake event */
534 
535     GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE;
536     Status = AE_OK;
537 
538 
539 UnlockAndExit:
540     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
541 
542     /* Delete the notify object if it was not used above */
543 
544     if (NewNotify)
545     {
546         ACPI_FREE (NewNotify);
547     }
548     return_ACPI_STATUS (Status);
549 }
550 
551 ACPI_EXPORT_SYMBOL (AcpiSetupGpeForWake)
552 
553 
554 /*******************************************************************************
555  *
556  * FUNCTION:    AcpiSetGpeWakeMask
557  *
558  * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
559  *              GpeNumber           - GPE level within the GPE block
560  *              Action              - Enable or Disable
561  *
562  * RETURN:      Status
563  *
564  * DESCRIPTION: Set or clear the GPE's wakeup enable mask bit. The GPE must
565  *              already be marked as a WAKE GPE.
566  *
567  ******************************************************************************/
568 
569 ACPI_STATUS
570 AcpiSetGpeWakeMask (
571     ACPI_HANDLE             GpeDevice,
572     UINT32                  GpeNumber,
573     UINT8                   Action)
574 {
575     ACPI_STATUS             Status = AE_OK;
576     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
577     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
578     ACPI_CPU_FLAGS          Flags;
579     UINT32                  RegisterBit;
580 
581 
582     ACPI_FUNCTION_TRACE (AcpiSetGpeWakeMask);
583 
584 
585     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
586 
587     /*
588      * Ensure that we have a valid GPE number and that this GPE is in
589      * fact a wake GPE
590      */
591     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
592     if (!GpeEventInfo)
593     {
594         Status = AE_BAD_PARAMETER;
595         goto UnlockAndExit;
596     }
597 
598     if (!(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE))
599     {
600         Status = AE_TYPE;
601         goto UnlockAndExit;
602     }
603 
604     GpeRegisterInfo = GpeEventInfo->RegisterInfo;
605     if (!GpeRegisterInfo)
606     {
607         Status = AE_NOT_EXIST;
608         goto UnlockAndExit;
609     }
610 
611     RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo);
612 
613     /* Perform the action */
614 
615     switch (Action)
616     {
617     case ACPI_GPE_ENABLE:
618 
619         ACPI_SET_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit);
620         break;
621 
622     case ACPI_GPE_DISABLE:
623 
624         ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit);
625         break;
626 
627     default:
628 
629         ACPI_ERROR ((AE_INFO, "%u, Invalid action", Action));
630         Status = AE_BAD_PARAMETER;
631         break;
632     }
633 
634 UnlockAndExit:
635     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
636     return_ACPI_STATUS (Status);
637 }
638 
639 ACPI_EXPORT_SYMBOL (AcpiSetGpeWakeMask)
640 
641 
642 /*******************************************************************************
643  *
644  * FUNCTION:    AcpiClearGpe
645  *
646  * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
647  *              GpeNumber           - GPE level within the GPE block
648  *
649  * RETURN:      Status
650  *
651  * DESCRIPTION: Clear an ACPI event (general purpose)
652  *
653  ******************************************************************************/
654 
655 ACPI_STATUS
656 AcpiClearGpe (
657     ACPI_HANDLE             GpeDevice,
658     UINT32                  GpeNumber)
659 {
660     ACPI_STATUS             Status = AE_OK;
661     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
662     ACPI_CPU_FLAGS          Flags;
663 
664 
665     ACPI_FUNCTION_TRACE (AcpiClearGpe);
666 
667 
668     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
669 
670     /* Ensure that we have a valid GPE number */
671 
672     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
673     if (!GpeEventInfo)
674     {
675         Status = AE_BAD_PARAMETER;
676         goto UnlockAndExit;
677     }
678 
679     Status = AcpiHwClearGpe (GpeEventInfo);
680 
681 UnlockAndExit:
682     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
683     return_ACPI_STATUS (Status);
684 }
685 
686 ACPI_EXPORT_SYMBOL (AcpiClearGpe)
687 
688 
689 /*******************************************************************************
690  *
691  * FUNCTION:    AcpiGetGpeStatus
692  *
693  * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
694  *              GpeNumber           - GPE level within the GPE block
695  *              EventStatus         - Where the current status of the event
696  *                                    will be returned
697  *
698  * RETURN:      Status
699  *
700  * DESCRIPTION: Get the current status of a GPE (signalled/not_signalled)
701  *
702  ******************************************************************************/
703 
704 ACPI_STATUS
705 AcpiGetGpeStatus (
706     ACPI_HANDLE             GpeDevice,
707     UINT32                  GpeNumber,
708     ACPI_EVENT_STATUS       *EventStatus)
709 {
710     ACPI_STATUS             Status = AE_OK;
711     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
712     ACPI_CPU_FLAGS          Flags;
713 
714 
715     ACPI_FUNCTION_TRACE (AcpiGetGpeStatus);
716 
717 
718     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
719 
720     /* Ensure that we have a valid GPE number */
721 
722     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
723     if (!GpeEventInfo)
724     {
725         Status = AE_BAD_PARAMETER;
726         goto UnlockAndExit;
727     }
728 
729     /* Obtain status on the requested GPE number */
730 
731     Status = AcpiHwGetGpeStatus (GpeEventInfo, EventStatus);
732 
733 UnlockAndExit:
734     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
735     return_ACPI_STATUS (Status);
736 }
737 
738 ACPI_EXPORT_SYMBOL (AcpiGetGpeStatus)
739 
740 
741 /*******************************************************************************
742  *
743  * FUNCTION:    AcpiFinishGpe
744  *
745  * PARAMETERS:  GpeDevice           - Namespace node for the GPE Block
746  *                                    (NULL for FADT defined GPEs)
747  *              GpeNumber           - GPE level within the GPE block
748  *
749  * RETURN:      Status
750  *
751  * DESCRIPTION: Clear and conditionally reenable a GPE. This completes the GPE
752  *              processing. Intended for use by asynchronous host-installed
753  *              GPE handlers. The GPE is only reenabled if the EnableForRun bit
754  *              is set in the GPE info.
755  *
756  ******************************************************************************/
757 
758 ACPI_STATUS
759 AcpiFinishGpe (
760     ACPI_HANDLE             GpeDevice,
761     UINT32                  GpeNumber)
762 {
763     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
764     ACPI_STATUS             Status;
765     ACPI_CPU_FLAGS          Flags;
766 
767 
768     ACPI_FUNCTION_TRACE (AcpiFinishGpe);
769 
770 
771     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
772 
773     /* Ensure that we have a valid GPE number */
774 
775     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
776     if (!GpeEventInfo)
777     {
778         Status = AE_BAD_PARAMETER;
779         goto UnlockAndExit;
780     }
781 
782     Status = AcpiEvFinishGpe (GpeEventInfo);
783 
784 UnlockAndExit:
785     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
786     return_ACPI_STATUS (Status);
787 }
788 
789 ACPI_EXPORT_SYMBOL (AcpiFinishGpe)
790 
791 
792 /******************************************************************************
793  *
794  * FUNCTION:    AcpiDisableAllGpes
795  *
796  * PARAMETERS:  None
797  *
798  * RETURN:      Status
799  *
800  * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
801  *
802  ******************************************************************************/
803 
804 ACPI_STATUS
805 AcpiDisableAllGpes (
806     void)
807 {
808     ACPI_STATUS             Status;
809 
810 
811     ACPI_FUNCTION_TRACE (AcpiDisableAllGpes);
812 
813 
814     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
815     if (ACPI_FAILURE (Status))
816     {
817         return_ACPI_STATUS (Status);
818     }
819 
820     Status = AcpiHwDisableAllGpes ();
821     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
822 
823     return_ACPI_STATUS (Status);
824 }
825 
826 ACPI_EXPORT_SYMBOL (AcpiDisableAllGpes)
827 
828 
829 /******************************************************************************
830  *
831  * FUNCTION:    AcpiEnableAllRuntimeGpes
832  *
833  * PARAMETERS:  None
834  *
835  * RETURN:      Status
836  *
837  * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
838  *
839  ******************************************************************************/
840 
841 ACPI_STATUS
842 AcpiEnableAllRuntimeGpes (
843     void)
844 {
845     ACPI_STATUS             Status;
846 
847 
848     ACPI_FUNCTION_TRACE (AcpiEnableAllRuntimeGpes);
849 
850 
851     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
852     if (ACPI_FAILURE (Status))
853     {
854         return_ACPI_STATUS (Status);
855     }
856 
857     Status = AcpiHwEnableAllRuntimeGpes ();
858     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
859 
860     return_ACPI_STATUS (Status);
861 }
862 
863 ACPI_EXPORT_SYMBOL (AcpiEnableAllRuntimeGpes)
864 
865 
866 /******************************************************************************
867  *
868  * FUNCTION:    AcpiEnableAllWakeupGpes
869  *
870  * PARAMETERS:  None
871  *
872  * RETURN:      Status
873  *
874  * DESCRIPTION: Enable all "wakeup" GPEs and disable all of the other GPEs, in
875  *              all GPE blocks.
876  *
877  ******************************************************************************/
878 
879 ACPI_STATUS
880 AcpiEnableAllWakeupGpes (
881     void)
882 {
883     ACPI_STATUS             Status;
884 
885 
886     ACPI_FUNCTION_TRACE (AcpiEnableAllWakeupGpes);
887 
888 
889     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
890     if (ACPI_FAILURE (Status))
891     {
892         return_ACPI_STATUS (Status);
893     }
894 
895     Status = AcpiHwEnableAllWakeupGpes ();
896     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
897 
898     return_ACPI_STATUS (Status);
899 }
900 
901 ACPI_EXPORT_SYMBOL (AcpiEnableAllWakeupGpes)
902 
903 
904 /*******************************************************************************
905  *
906  * FUNCTION:    AcpiInstallGpeBlock
907  *
908  * PARAMETERS:  GpeDevice           - Handle to the parent GPE Block Device
909  *              GpeBlockAddress     - Address and SpaceID
910  *              RegisterCount       - Number of GPE register pairs in the block
911  *              InterruptNumber     - H/W interrupt for the block
912  *
913  * RETURN:      Status
914  *
915  * DESCRIPTION: Create and Install a block of GPE registers. The GPEs are not
916  *              enabled here.
917  *
918  ******************************************************************************/
919 
920 ACPI_STATUS
921 AcpiInstallGpeBlock (
922     ACPI_HANDLE             GpeDevice,
923     ACPI_GENERIC_ADDRESS    *GpeBlockAddress,
924     UINT32                  RegisterCount,
925     UINT32                  InterruptNumber)
926 {
927     ACPI_STATUS             Status;
928     ACPI_OPERAND_OBJECT     *ObjDesc;
929     ACPI_NAMESPACE_NODE     *Node;
930     ACPI_GPE_BLOCK_INFO     *GpeBlock;
931 
932 
933     ACPI_FUNCTION_TRACE (AcpiInstallGpeBlock);
934 
935 
936     if ((!GpeDevice)       ||
937         (!GpeBlockAddress) ||
938         (!RegisterCount))
939     {
940         return_ACPI_STATUS (AE_BAD_PARAMETER);
941     }
942 
943     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
944     if (ACPI_FAILURE (Status))
945     {
946         return_ACPI_STATUS (Status);
947     }
948 
949     Node = AcpiNsValidateHandle (GpeDevice);
950     if (!Node)
951     {
952         Status = AE_BAD_PARAMETER;
953         goto UnlockAndExit;
954     }
955 
956     /* Validate the parent device */
957 
958     if (Node->Type != ACPI_TYPE_DEVICE)
959     {
960         Status = AE_TYPE;
961         goto UnlockAndExit;
962     }
963 
964     if (Node->Object)
965     {
966         Status = AE_ALREADY_EXISTS;
967         goto UnlockAndExit;
968     }
969 
970     /*
971      * For user-installed GPE Block Devices, the GpeBlockBaseNumber
972      * is always zero
973      */
974     Status = AcpiEvCreateGpeBlock (Node, GpeBlockAddress->Address,
975         GpeBlockAddress->SpaceId, RegisterCount,
976         0, InterruptNumber, &GpeBlock);
977     if (ACPI_FAILURE (Status))
978     {
979         goto UnlockAndExit;
980     }
981 
982     /* Install block in the DeviceObject attached to the node */
983 
984     ObjDesc = AcpiNsGetAttachedObject (Node);
985     if (!ObjDesc)
986     {
987         /*
988          * No object, create a new one (Device nodes do not always have
989          * an attached object)
990          */
991         ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_DEVICE);
992         if (!ObjDesc)
993         {
994             Status = AE_NO_MEMORY;
995             goto UnlockAndExit;
996         }
997 
998         Status = AcpiNsAttachObject (Node, ObjDesc, ACPI_TYPE_DEVICE);
999 
1000         /* Remove local reference to the object */
1001 
1002         AcpiUtRemoveReference (ObjDesc);
1003         if (ACPI_FAILURE (Status))
1004         {
1005             goto UnlockAndExit;
1006         }
1007     }
1008 
1009     /* Now install the GPE block in the DeviceObject */
1010 
1011     ObjDesc->Device.GpeBlock = GpeBlock;
1012 
1013 
1014 UnlockAndExit:
1015     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
1016     return_ACPI_STATUS (Status);
1017 }
1018 
1019 ACPI_EXPORT_SYMBOL (AcpiInstallGpeBlock)
1020 
1021 
1022 /*******************************************************************************
1023  *
1024  * FUNCTION:    AcpiRemoveGpeBlock
1025  *
1026  * PARAMETERS:  GpeDevice           - Handle to the parent GPE Block Device
1027  *
1028  * RETURN:      Status
1029  *
1030  * DESCRIPTION: Remove a previously installed block of GPE registers
1031  *
1032  ******************************************************************************/
1033 
1034 ACPI_STATUS
1035 AcpiRemoveGpeBlock (
1036     ACPI_HANDLE             GpeDevice)
1037 {
1038     ACPI_OPERAND_OBJECT     *ObjDesc;
1039     ACPI_STATUS             Status;
1040     ACPI_NAMESPACE_NODE     *Node;
1041 
1042 
1043     ACPI_FUNCTION_TRACE (AcpiRemoveGpeBlock);
1044 
1045 
1046     if (!GpeDevice)
1047     {
1048         return_ACPI_STATUS (AE_BAD_PARAMETER);
1049     }
1050 
1051     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
1052     if (ACPI_FAILURE (Status))
1053     {
1054         return_ACPI_STATUS (Status);
1055     }
1056 
1057     Node = AcpiNsValidateHandle (GpeDevice);
1058     if (!Node)
1059     {
1060         Status = AE_BAD_PARAMETER;
1061         goto UnlockAndExit;
1062     }
1063 
1064     /* Validate the parent device */
1065 
1066     if (Node->Type != ACPI_TYPE_DEVICE)
1067     {
1068         Status = AE_TYPE;
1069         goto UnlockAndExit;
1070     }
1071 
1072     /* Get the DeviceObject attached to the node */
1073 
1074     ObjDesc = AcpiNsGetAttachedObject (Node);
1075     if (!ObjDesc ||
1076         !ObjDesc->Device.GpeBlock)
1077     {
1078         return_ACPI_STATUS (AE_NULL_OBJECT);
1079     }
1080 
1081     /* Delete the GPE block (but not the DeviceObject) */
1082 
1083     Status = AcpiEvDeleteGpeBlock (ObjDesc->Device.GpeBlock);
1084     if (ACPI_SUCCESS (Status))
1085     {
1086         ObjDesc->Device.GpeBlock = NULL;
1087     }
1088 
1089 UnlockAndExit:
1090     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
1091     return_ACPI_STATUS (Status);
1092 }
1093 
1094 ACPI_EXPORT_SYMBOL (AcpiRemoveGpeBlock)
1095 
1096 
1097 /*******************************************************************************
1098  *
1099  * FUNCTION:    AcpiGetGpeDevice
1100  *
1101  * PARAMETERS:  Index               - System GPE index (0-CurrentGpeCount)
1102  *              GpeDevice           - Where the parent GPE Device is returned
1103  *
1104  * RETURN:      Status
1105  *
1106  * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL
1107  *              gpe device indicates that the gpe number is contained in one of
1108  *              the FADT-defined gpe blocks. Otherwise, the GPE block device.
1109  *
1110  ******************************************************************************/
1111 
1112 ACPI_STATUS
1113 AcpiGetGpeDevice (
1114     UINT32                  Index,
1115     ACPI_HANDLE             *GpeDevice)
1116 {
1117     ACPI_GPE_DEVICE_INFO    Info;
1118     ACPI_STATUS             Status;
1119 
1120 
1121     ACPI_FUNCTION_TRACE (AcpiGetGpeDevice);
1122 
1123 
1124     if (!GpeDevice)
1125     {
1126         return_ACPI_STATUS (AE_BAD_PARAMETER);
1127     }
1128 
1129     if (Index >= AcpiCurrentGpeCount)
1130     {
1131         return_ACPI_STATUS (AE_NOT_EXIST);
1132     }
1133 
1134     /* Setup and walk the GPE list */
1135 
1136     Info.Index = Index;
1137     Info.Status = AE_NOT_EXIST;
1138     Info.GpeDevice = NULL;
1139     Info.NextBlockBaseIndex = 0;
1140 
1141     Status = AcpiEvWalkGpeList (AcpiEvGetGpeDevice, &Info);
1142     if (ACPI_FAILURE (Status))
1143     {
1144         return_ACPI_STATUS (Status);
1145     }
1146 
1147     *GpeDevice = ACPI_CAST_PTR (ACPI_HANDLE, Info.GpeDevice);
1148     return_ACPI_STATUS (Info.Status);
1149 }
1150 
1151 ACPI_EXPORT_SYMBOL (AcpiGetGpeDevice)
1152 
1153 #endif /* !ACPI_REDUCED_HARDWARE */
1154