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