xref: /freebsd/sys/contrib/dev/acpica/components/events/evxfgpe.c (revision 2e3507c25e42292b45a5482e116d278f5515d04d)
1 /******************************************************************************
2  *
3  * Module Name: evxfgpe - External Interfaces for General Purpose Events (GPEs)
4  *
5  *****************************************************************************/
6 
7 /******************************************************************************
8  *
9  * 1. Copyright Notice
10  *
11  * Some or all of this work - Copyright (c) 1999 - 2022, Intel Corp.
12  * All rights reserved.
13  *
14  * 2. License
15  *
16  * 2.1. This is your license from Intel Corp. under its intellectual property
17  * rights. You may have additional license terms from the party that provided
18  * you this software, covering your right to use that party's intellectual
19  * property rights.
20  *
21  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22  * copy of the source code appearing in this file ("Covered Code") an
23  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24  * base code distributed originally by Intel ("Original Intel Code") to copy,
25  * make derivatives, distribute, use and display any portion of the Covered
26  * Code in any form, with the right to sublicense such rights; and
27  *
28  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29  * license (with the right to sublicense), under only those claims of Intel
30  * patents that are infringed by the Original Intel Code, to make, use, sell,
31  * offer to sell, and import the Covered Code and derivative works thereof
32  * solely to the minimum extent necessary to exercise the above copyright
33  * license, and in no event shall the patent license extend to any additions
34  * to or modifications of the Original Intel Code. No other license or right
35  * is granted directly or by implication, estoppel or otherwise;
36  *
37  * The above copyright and patent license is granted only if the following
38  * conditions are met:
39  *
40  * 3. Conditions
41  *
42  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43  * Redistribution of source code of any substantial portion of the Covered
44  * Code or modification with rights to further distribute source must include
45  * the above Copyright Notice, the above License, this list of Conditions,
46  * and the following Disclaimer and Export Compliance provision. In addition,
47  * Licensee must cause all Covered Code to which Licensee contributes to
48  * contain a file documenting the changes Licensee made to create that Covered
49  * Code and the date of any change. Licensee must include in that file the
50  * documentation of any changes made by any predecessor Licensee. Licensee
51  * must include a prominent statement that the modification is derived,
52  * directly or indirectly, from Original Intel Code.
53  *
54  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55  * Redistribution of source code of any substantial portion of the Covered
56  * Code or modification without rights to further distribute source must
57  * include the following Disclaimer and Export Compliance provision in the
58  * documentation and/or other materials provided with distribution. In
59  * addition, Licensee may not authorize further sublicense of source of any
60  * portion of the Covered Code, and must include terms to the effect that the
61  * license from Licensee to its licensee is limited to the intellectual
62  * property embodied in the software Licensee provides to its licensee, and
63  * not to intellectual property embodied in modifications its licensee may
64  * make.
65  *
66  * 3.3. Redistribution of Executable. Redistribution in executable form of any
67  * substantial portion of the Covered Code or modification must reproduce the
68  * above Copyright Notice, and the following Disclaimer and Export Compliance
69  * provision in the documentation and/or other materials provided with the
70  * distribution.
71  *
72  * 3.4. Intel retains all right, title, and interest in and to the Original
73  * Intel Code.
74  *
75  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76  * Intel shall be used in advertising or otherwise to promote the sale, use or
77  * other dealings in products derived from or relating to the Covered Code
78  * without prior written authorization from Intel.
79  *
80  * 4. Disclaimer and Export Compliance
81  *
82  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83  * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
85  * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
86  * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
87  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88  * PARTICULAR PURPOSE.
89  *
90  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
96  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97  * LIMITED REMEDY.
98  *
99  * 4.3. Licensee shall not export, either directly or indirectly, any of this
100  * software or system incorporating such software without first obtaining any
101  * required license or other approval from the U. S. Department of Commerce or
102  * any other agency or department of the United States Government. In the
103  * event Licensee exports any such software from the United States or
104  * re-exports any such software from a foreign destination, Licensee shall
105  * ensure that the distribution and export/re-export of the software is in
106  * compliance with all laws, regulations, orders, or other restrictions of the
107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108  * any of its subsidiaries will export/re-export any technical data, process,
109  * software, or service, directly or indirectly, to any country for which the
110  * United States government or any agency thereof requires an export license,
111  * other governmental approval, or letter of assurance, without first obtaining
112  * such license, approval or letter.
113  *
114  *****************************************************************************
115  *
116  * Alternatively, you may choose to be licensed under the terms of the
117  * following license:
118  *
119  * Redistribution and use in source and binary forms, with or without
120  * modification, are permitted provided that the following conditions
121  * are met:
122  * 1. Redistributions of source code must retain the above copyright
123  *    notice, this list of conditions, and the following disclaimer,
124  *    without modification.
125  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
126  *    substantially similar to the "NO WARRANTY" disclaimer below
127  *    ("Disclaimer") and any redistribution must be conditioned upon
128  *    including a substantially similar Disclaimer requirement for further
129  *    binary redistribution.
130  * 3. Neither the names of the above-listed copyright holders nor the names
131  *    of any contributors may be used to endorse or promote products derived
132  *    from this software without specific prior written permission.
133  *
134  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
135  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
136  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
137  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
138  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
139  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
140  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
141  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
142  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
143  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
144  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
145  *
146  * Alternatively, you may choose to be licensed under the terms of the
147  * GNU General Public License ("GPL") version 2 as published by the Free
148  * Software Foundation.
149  *
150  *****************************************************************************/
151 
152 #define EXPORT_ACPI_INTERFACES
153 
154 #include <contrib/dev/acpica/include/acpi.h>
155 #include <contrib/dev/acpica/include/accommon.h>
156 #include <contrib/dev/acpica/include/acevents.h>
157 #include <contrib/dev/acpica/include/acnamesp.h>
158 
159 #define _COMPONENT          ACPI_EVENTS
160         ACPI_MODULE_NAME    ("evxfgpe")
161 
162 
163 #if (!ACPI_REDUCED_HARDWARE) /* Entire module */
164 /*******************************************************************************
165  *
166  * FUNCTION:    AcpiUpdateAllGpes
167  *
168  * PARAMETERS:  None
169  *
170  * RETURN:      Status
171  *
172  * DESCRIPTION: Complete GPE initialization and enable all GPEs that have
173  *              associated _Lxx or _Exx methods and are not pointed to by any
174  *              device _PRW methods (this indicates that these GPEs are
175  *              generally intended for system or device wakeup. Such GPEs
176  *              have to be enabled directly when the devices whose _PRW
177  *              methods point to them are set up for wakeup signaling.)
178  *
179  * NOTE: Should be called after any GPEs are added to the system. Primarily,
180  * after the system _PRW methods have been run, but also after a GPE Block
181  * Device has been added or if any new GPE methods have been added via a
182  * dynamic table load.
183  *
184  ******************************************************************************/
185 
186 ACPI_STATUS
187 AcpiUpdateAllGpes (
188     void)
189 {
190     ACPI_STATUS             Status;
191     BOOLEAN                 IsPollingNeeded = FALSE;
192 
193 
194     ACPI_FUNCTION_TRACE (AcpiUpdateAllGpes);
195 
196 
197     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
198     if (ACPI_FAILURE (Status))
199     {
200         return_ACPI_STATUS (Status);
201     }
202 
203     if (AcpiGbl_AllGpesInitialized)
204     {
205         goto UnlockAndExit;
206     }
207 
208     Status = AcpiEvWalkGpeList (AcpiEvInitializeGpeBlock,
209         &IsPollingNeeded);
210     if (ACPI_SUCCESS (Status))
211     {
212         AcpiGbl_AllGpesInitialized = TRUE;
213     }
214 
215 UnlockAndExit:
216     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
217 
218     if (IsPollingNeeded && AcpiGbl_AllGpesInitialized)
219     {
220         /* Poll GPEs to handle already triggered events */
221 
222         AcpiEvGpeDetect (AcpiGbl_GpeXruptListHead);
223     }
224     return_ACPI_STATUS (Status);
225 }
226 
227 ACPI_EXPORT_SYMBOL (AcpiUpdateAllGpes)
228 
229 
230 /*******************************************************************************
231  *
232  * FUNCTION:    AcpiEnableGpe
233  *
234  * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
235  *              GpeNumber           - GPE level within the GPE block
236  *
237  * RETURN:      Status
238  *
239  * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is
240  *              hardware-enabled.
241  *
242  ******************************************************************************/
243 
244 ACPI_STATUS
245 AcpiEnableGpe (
246     ACPI_HANDLE             GpeDevice,
247     UINT32                  GpeNumber)
248 {
249     ACPI_STATUS             Status = AE_BAD_PARAMETER;
250     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
251     ACPI_CPU_FLAGS          Flags;
252 
253 
254     ACPI_FUNCTION_TRACE (AcpiEnableGpe);
255 
256 
257     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
258 
259     /*
260      * Ensure that we have a valid GPE number and that there is some way
261      * of handling the GPE (handler or a GPE method). In other words, we
262      * won't allow a valid GPE to be enabled if there is no way to handle it.
263      */
264     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
265     if (GpeEventInfo)
266     {
267         if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) !=
268             ACPI_GPE_DISPATCH_NONE)
269         {
270             Status = AcpiEvAddGpeReference (GpeEventInfo, TRUE);
271             if (ACPI_SUCCESS (Status) &&
272                 ACPI_GPE_IS_POLLING_NEEDED (GpeEventInfo))
273             {
274                 /* Poll edge-triggered GPEs to handle existing events */
275 
276                 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
277                 (void) AcpiEvDetectGpe (
278                     GpeDevice, GpeEventInfo, GpeNumber);
279                 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
280             }
281         }
282         else
283         {
284             Status = AE_NO_HANDLER;
285         }
286     }
287 
288     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
289     return_ACPI_STATUS (Status);
290 }
291 
292 ACPI_EXPORT_SYMBOL (AcpiEnableGpe)
293 
294 
295 /*******************************************************************************
296  *
297  * FUNCTION:    AcpiDisableGpe
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: Remove a reference to a GPE. When the last reference is
305  *              removed, only then is the GPE disabled (for runtime GPEs), or
306  *              the GPE mask bit disabled (for wake GPEs)
307  *
308  ******************************************************************************/
309 
310 ACPI_STATUS
311 AcpiDisableGpe (
312     ACPI_HANDLE             GpeDevice,
313     UINT32                  GpeNumber)
314 {
315     ACPI_STATUS             Status = AE_BAD_PARAMETER;
316     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
317     ACPI_CPU_FLAGS          Flags;
318 
319 
320     ACPI_FUNCTION_TRACE (AcpiDisableGpe);
321 
322 
323     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
324 
325     /* Ensure that we have a valid GPE number */
326 
327     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
328     if (GpeEventInfo)
329     {
330         Status = AcpiEvRemoveGpeReference (GpeEventInfo);
331     }
332 
333     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
334     return_ACPI_STATUS (Status);
335 }
336 
337 ACPI_EXPORT_SYMBOL (AcpiDisableGpe)
338 
339 
340 /*******************************************************************************
341  *
342  * FUNCTION:    AcpiSetGpe
343  *
344  * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
345  *              GpeNumber           - GPE level within the GPE block
346  *              Action              - ACPI_GPE_ENABLE or ACPI_GPE_DISABLE
347  *
348  * RETURN:      Status
349  *
350  * DESCRIPTION: Enable or disable an individual GPE. This function bypasses
351  *              the reference count mechanism used in the AcpiEnableGpe(),
352  *              AcpiDisableGpe() interfaces.
353  *              This API is typically used by the GPE raw handler mode driver
354  *              to switch between the polling mode and the interrupt mode after
355  *              the driver has enabled the GPE.
356  *              The APIs should be invoked in this order:
357  *               AcpiEnableGpe()              <- Ensure the reference count > 0
358  *               AcpiSetGpe(ACPI_GPE_DISABLE) <- Enter polling mode
359  *               AcpiSetGpe(ACPI_GPE_ENABLE)  <- Leave polling mode
360  *               AcpiDisableGpe()             <- Decrease the reference count
361  *
362  * Note: If a GPE is shared by 2 silicon components, then both the drivers
363  *       should support GPE polling mode or disabling the GPE for long period
364  *       for one driver may break the other. So use it with care since all
365  *       firmware _Lxx/_Exx handlers currently rely on the GPE interrupt mode.
366  *
367  ******************************************************************************/
368 
369 ACPI_STATUS
370 AcpiSetGpe (
371     ACPI_HANDLE             GpeDevice,
372     UINT32                  GpeNumber,
373     UINT8                   Action)
374 {
375     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
376     ACPI_STATUS             Status;
377     ACPI_CPU_FLAGS          Flags;
378 
379 
380     ACPI_FUNCTION_TRACE (AcpiSetGpe);
381 
382 
383     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
384 
385     /* Ensure that we have a valid GPE number */
386 
387     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
388     if (!GpeEventInfo)
389     {
390         Status = AE_BAD_PARAMETER;
391         goto UnlockAndExit;
392     }
393 
394     /* Perform the action */
395 
396     switch (Action)
397     {
398     case ACPI_GPE_ENABLE:
399 
400         Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_ENABLE);
401         GpeEventInfo->DisableForDispatch = FALSE;
402         break;
403 
404     case ACPI_GPE_DISABLE:
405 
406         Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE);
407         GpeEventInfo->DisableForDispatch = TRUE;
408         break;
409 
410     default:
411 
412         Status = AE_BAD_PARAMETER;
413         break;
414     }
415 
416 UnlockAndExit:
417     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
418     return_ACPI_STATUS (Status);
419 }
420 
421 ACPI_EXPORT_SYMBOL (AcpiSetGpe)
422 
423 
424 /*******************************************************************************
425  *
426  * FUNCTION:    AcpiMaskGpe
427  *
428  * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
429  *              GpeNumber           - GPE level within the GPE block
430  *              IsMasked            - Whether the GPE is masked or not
431  *
432  * RETURN:      Status
433  *
434  * DESCRIPTION: Unconditionally mask/unmask the an individual GPE, ex., to
435  *              prevent a GPE flooding.
436  *
437  ******************************************************************************/
438 
439 ACPI_STATUS
440 AcpiMaskGpe (
441     ACPI_HANDLE             GpeDevice,
442     UINT32                  GpeNumber,
443     BOOLEAN                 IsMasked)
444 {
445     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
446     ACPI_STATUS             Status;
447     ACPI_CPU_FLAGS          Flags;
448 
449 
450     ACPI_FUNCTION_TRACE (AcpiMaskGpe);
451 
452 
453     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
454 
455     /* Ensure that we have a valid GPE number */
456 
457     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
458     if (!GpeEventInfo)
459     {
460         Status = AE_BAD_PARAMETER;
461         goto UnlockAndExit;
462     }
463 
464     Status = AcpiEvMaskGpe (GpeEventInfo, IsMasked);
465 
466 UnlockAndExit:
467     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
468     return_ACPI_STATUS (Status);
469 }
470 
471 ACPI_EXPORT_SYMBOL (AcpiMaskGpe)
472 
473 
474 /*******************************************************************************
475  *
476  * FUNCTION:    AcpiMarkGpeForWake
477  *
478  * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
479  *              GpeNumber           - GPE level within the GPE block
480  *
481  * RETURN:      Status
482  *
483  * DESCRIPTION: Mark a GPE as having the ability to wake the system. Simply
484  *              sets the ACPI_GPE_CAN_WAKE flag.
485  *
486  * Some potential callers of AcpiSetupGpeForWake may know in advance that
487  * there won't be any notify handlers installed for device wake notifications
488  * from the given GPE (one example is a button GPE in Linux). For these cases,
489  * AcpiMarkGpeForWake should be used instead of AcpiSetupGpeForWake.
490  * This will set the ACPI_GPE_CAN_WAKE flag for the GPE without trying to
491  * setup implicit wake notification for it (since there's no handler method).
492  *
493  ******************************************************************************/
494 
495 ACPI_STATUS
496 AcpiMarkGpeForWake (
497     ACPI_HANDLE             GpeDevice,
498     UINT32                  GpeNumber)
499 {
500     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
501     ACPI_STATUS             Status = AE_BAD_PARAMETER;
502     ACPI_CPU_FLAGS          Flags;
503 
504 
505     ACPI_FUNCTION_TRACE (AcpiMarkGpeForWake);
506 
507 
508     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
509 
510     /* Ensure that we have a valid GPE number */
511 
512     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
513     if (GpeEventInfo)
514     {
515         /* Mark the GPE as a possible wake event */
516 
517         GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE;
518         Status = AE_OK;
519     }
520 
521     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
522     return_ACPI_STATUS (Status);
523 }
524 
525 ACPI_EXPORT_SYMBOL (AcpiMarkGpeForWake)
526 
527 
528 /*******************************************************************************
529  *
530  * FUNCTION:    AcpiSetupGpeForWake
531  *
532  * PARAMETERS:  WakeDevice          - Device associated with the GPE (via _PRW)
533  *              GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
534  *              GpeNumber           - GPE level within the GPE block
535  *
536  * RETURN:      Status
537  *
538  * DESCRIPTION: Mark a GPE as having the ability to wake the system. This
539  *              interface is intended to be used as the host executes the
540  *              _PRW methods (Power Resources for Wake) in the system tables.
541  *              Each _PRW appears under a Device Object (The WakeDevice), and
542  *              contains the info for the wake GPE associated with the
543  *              WakeDevice.
544  *
545  ******************************************************************************/
546 
547 ACPI_STATUS
548 AcpiSetupGpeForWake (
549     ACPI_HANDLE             WakeDevice,
550     ACPI_HANDLE             GpeDevice,
551     UINT32                  GpeNumber)
552 {
553     ACPI_STATUS             Status;
554     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
555     ACPI_NAMESPACE_NODE     *DeviceNode;
556     ACPI_GPE_NOTIFY_INFO    *Notify;
557     ACPI_GPE_NOTIFY_INFO    *NewNotify;
558     ACPI_CPU_FLAGS          Flags;
559 
560 
561     ACPI_FUNCTION_TRACE (AcpiSetupGpeForWake);
562 
563 
564     /* Parameter Validation */
565 
566     if (!WakeDevice)
567     {
568         /*
569          * By forcing WakeDevice to be valid, we automatically enable the
570          * implicit notify feature on all hosts.
571          */
572         return_ACPI_STATUS (AE_BAD_PARAMETER);
573     }
574 
575     /* Handle root object case */
576 
577     if (WakeDevice == ACPI_ROOT_OBJECT)
578     {
579         DeviceNode = AcpiGbl_RootNode;
580     }
581     else
582     {
583         DeviceNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, WakeDevice);
584     }
585 
586     /* Validate WakeDevice is of type Device */
587 
588     if (DeviceNode->Type != ACPI_TYPE_DEVICE)
589     {
590         return_ACPI_STATUS (AE_BAD_PARAMETER);
591     }
592 
593     /*
594      * Allocate a new notify object up front, in case it is needed.
595      * Memory allocation while holding a spinlock is a big no-no
596      * on some hosts.
597      */
598     NewNotify = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_NOTIFY_INFO));
599     if (!NewNotify)
600     {
601         return_ACPI_STATUS (AE_NO_MEMORY);
602     }
603 
604     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
605 
606     /* Ensure that we have a valid GPE number */
607 
608     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
609     if (!GpeEventInfo)
610     {
611         Status = AE_BAD_PARAMETER;
612         goto UnlockAndExit;
613     }
614 
615     /*
616      * If there is no method or handler for this GPE, then the
617      * WakeDevice will be notified whenever this GPE fires. This is
618      * known as an "implicit notify". Note: The GPE is assumed to be
619      * level-triggered (for windows compatibility).
620      */
621     if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) ==
622         ACPI_GPE_DISPATCH_NONE)
623     {
624         /*
625          * This is the first device for implicit notify on this GPE.
626          * Just set the flags here, and enter the NOTIFY block below.
627          */
628         GpeEventInfo->Flags =
629             (ACPI_GPE_DISPATCH_NOTIFY | ACPI_GPE_LEVEL_TRIGGERED);
630     }
631     else if (GpeEventInfo->Flags & ACPI_GPE_AUTO_ENABLED)
632     {
633         /*
634          * A reference to this GPE has been added during the GPE block
635          * initialization, so drop it now to prevent the GPE from being
636          * permanently enabled and clear its ACPI_GPE_AUTO_ENABLED flag.
637          */
638         (void) AcpiEvRemoveGpeReference (GpeEventInfo);
639         GpeEventInfo->Flags &= ~~ACPI_GPE_AUTO_ENABLED;
640     }
641 
642     /*
643      * If we already have an implicit notify on this GPE, add
644      * this device to the notify list.
645      */
646     if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) ==
647         ACPI_GPE_DISPATCH_NOTIFY)
648     {
649         /* Ensure that the device is not already in the list */
650 
651         Notify = GpeEventInfo->Dispatch.NotifyList;
652         while (Notify)
653         {
654             if (Notify->DeviceNode == DeviceNode)
655             {
656                 Status = AE_ALREADY_EXISTS;
657                 goto UnlockAndExit;
658             }
659             Notify = Notify->Next;
660         }
661 
662         /* Add this device to the notify list for this GPE */
663 
664         NewNotify->DeviceNode = DeviceNode;
665         NewNotify->Next = GpeEventInfo->Dispatch.NotifyList;
666         GpeEventInfo->Dispatch.NotifyList = NewNotify;
667         NewNotify = NULL;
668     }
669 
670     /* Mark the GPE as a possible wake event */
671 
672     GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE;
673     Status = AE_OK;
674 
675 
676 UnlockAndExit:
677     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
678 
679     /* Delete the notify object if it was not used above */
680 
681     if (NewNotify)
682     {
683         ACPI_FREE (NewNotify);
684     }
685     return_ACPI_STATUS (Status);
686 }
687 
688 ACPI_EXPORT_SYMBOL (AcpiSetupGpeForWake)
689 
690 
691 /*******************************************************************************
692  *
693  * FUNCTION:    AcpiSetGpeWakeMask
694  *
695  * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
696  *              GpeNumber           - GPE level within the GPE block
697  *              Action              - Enable or Disable
698  *
699  * RETURN:      Status
700  *
701  * DESCRIPTION: Set or clear the GPE's wakeup enable mask bit. The GPE must
702  *              already be marked as a WAKE GPE.
703  *
704  ******************************************************************************/
705 
706 ACPI_STATUS
707 AcpiSetGpeWakeMask (
708     ACPI_HANDLE             GpeDevice,
709     UINT32                  GpeNumber,
710     UINT8                   Action)
711 {
712     ACPI_STATUS             Status = AE_OK;
713     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
714     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
715     ACPI_CPU_FLAGS          Flags;
716     UINT32                  RegisterBit;
717 
718 
719     ACPI_FUNCTION_TRACE (AcpiSetGpeWakeMask);
720 
721 
722     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
723 
724     /*
725      * Ensure that we have a valid GPE number and that this GPE is in
726      * fact a wake GPE
727      */
728     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
729     if (!GpeEventInfo)
730     {
731         Status = AE_BAD_PARAMETER;
732         goto UnlockAndExit;
733     }
734 
735     if (!(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE))
736     {
737         Status = AE_TYPE;
738         goto UnlockAndExit;
739     }
740 
741     GpeRegisterInfo = GpeEventInfo->RegisterInfo;
742     if (!GpeRegisterInfo)
743     {
744         Status = AE_NOT_EXIST;
745         goto UnlockAndExit;
746     }
747 
748     RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo);
749 
750     /* Perform the action */
751 
752     switch (Action)
753     {
754     case ACPI_GPE_ENABLE:
755 
756         ACPI_SET_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit);
757         break;
758 
759     case ACPI_GPE_DISABLE:
760 
761         ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit);
762         break;
763 
764     default:
765 
766         ACPI_ERROR ((AE_INFO, "%u, Invalid action", Action));
767         Status = AE_BAD_PARAMETER;
768         break;
769     }
770 
771 UnlockAndExit:
772     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
773     return_ACPI_STATUS (Status);
774 }
775 
776 ACPI_EXPORT_SYMBOL (AcpiSetGpeWakeMask)
777 
778 
779 /*******************************************************************************
780  *
781  * FUNCTION:    AcpiClearGpe
782  *
783  * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
784  *              GpeNumber           - GPE level within the GPE block
785  *
786  * RETURN:      Status
787  *
788  * DESCRIPTION: Clear an ACPI event (general purpose)
789  *
790  ******************************************************************************/
791 
792 ACPI_STATUS
793 AcpiClearGpe (
794     ACPI_HANDLE             GpeDevice,
795     UINT32                  GpeNumber)
796 {
797     ACPI_STATUS             Status = AE_OK;
798     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
799     ACPI_CPU_FLAGS          Flags;
800 
801 
802     ACPI_FUNCTION_TRACE (AcpiClearGpe);
803 
804 
805     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
806 
807     /* Ensure that we have a valid GPE number */
808 
809     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
810     if (!GpeEventInfo)
811     {
812         Status = AE_BAD_PARAMETER;
813         goto UnlockAndExit;
814     }
815 
816     Status = AcpiHwClearGpe (GpeEventInfo);
817 
818 UnlockAndExit:
819     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
820     return_ACPI_STATUS (Status);
821 }
822 
823 ACPI_EXPORT_SYMBOL (AcpiClearGpe)
824 
825 
826 /*******************************************************************************
827  *
828  * FUNCTION:    AcpiGetGpeStatus
829  *
830  * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
831  *              GpeNumber           - GPE level within the GPE block
832  *              EventStatus         - Where the current status of the event
833  *                                    will be returned
834  *
835  * RETURN:      Status
836  *
837  * DESCRIPTION: Get the current status of a GPE (signalled/not_signalled)
838  *
839  ******************************************************************************/
840 
841 ACPI_STATUS
842 AcpiGetGpeStatus (
843     ACPI_HANDLE             GpeDevice,
844     UINT32                  GpeNumber,
845     ACPI_EVENT_STATUS       *EventStatus)
846 {
847     ACPI_STATUS             Status = AE_OK;
848     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
849     ACPI_CPU_FLAGS          Flags;
850 
851 
852     ACPI_FUNCTION_TRACE (AcpiGetGpeStatus);
853 
854 
855     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
856 
857     /* Ensure that we have a valid GPE number */
858 
859     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
860     if (!GpeEventInfo)
861     {
862         Status = AE_BAD_PARAMETER;
863         goto UnlockAndExit;
864     }
865 
866     /* Obtain status on the requested GPE number */
867 
868     Status = AcpiHwGetGpeStatus (GpeEventInfo, EventStatus);
869 
870 UnlockAndExit:
871     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
872     return_ACPI_STATUS (Status);
873 }
874 
875 ACPI_EXPORT_SYMBOL (AcpiGetGpeStatus)
876 
877 
878 /*******************************************************************************
879  *
880  * FUNCTION:    AcpiDispatchGpe
881  *
882  * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
883  *              GpeNumber           - GPE level within the GPE block
884  *
885  * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
886  *
887  * DESCRIPTION: Detect and dispatch a General Purpose Event to either a function
888  *              (e.g. EC) or method (e.g. _Lxx/_Exx) handler.
889  *
890  ******************************************************************************/
891 
892 UINT32
893 AcpiDispatchGpe(
894     ACPI_HANDLE             GpeDevice,
895     UINT32                  GpeNumber)
896 {
897     ACPI_FUNCTION_TRACE(acpi_dispatch_gpe);
898 
899     return (AcpiEvDetectGpe (GpeDevice, NULL, GpeNumber));
900 }
901 
902 ACPI_EXPORT_SYMBOL (AcpiDispatchGpe)
903 
904 
905 /*******************************************************************************
906  *
907  * FUNCTION:    AcpiFinishGpe
908  *
909  * PARAMETERS:  GpeDevice           - Namespace node for the GPE Block
910  *                                    (NULL for FADT defined GPEs)
911  *              GpeNumber           - GPE level within the GPE block
912  *
913  * RETURN:      Status
914  *
915  * DESCRIPTION: Clear and conditionally re-enable a GPE. This completes the GPE
916  *              processing. Intended for use by asynchronous host-installed
917  *              GPE handlers. The GPE is only re-enabled if the EnableForRun bit
918  *              is set in the GPE info.
919  *
920  ******************************************************************************/
921 
922 ACPI_STATUS
923 AcpiFinishGpe (
924     ACPI_HANDLE             GpeDevice,
925     UINT32                  GpeNumber)
926 {
927     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
928     ACPI_STATUS             Status;
929     ACPI_CPU_FLAGS          Flags;
930 
931 
932     ACPI_FUNCTION_TRACE (AcpiFinishGpe);
933 
934 
935     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
936 
937     /* Ensure that we have a valid GPE number */
938 
939     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
940     if (!GpeEventInfo)
941     {
942         Status = AE_BAD_PARAMETER;
943         goto UnlockAndExit;
944     }
945 
946     Status = AcpiEvFinishGpe (GpeEventInfo);
947 
948 UnlockAndExit:
949     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
950     return_ACPI_STATUS (Status);
951 }
952 
953 ACPI_EXPORT_SYMBOL (AcpiFinishGpe)
954 
955 
956 /******************************************************************************
957  *
958  * FUNCTION:    AcpiDisableAllGpes
959  *
960  * PARAMETERS:  None
961  *
962  * RETURN:      Status
963  *
964  * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
965  *
966  ******************************************************************************/
967 
968 ACPI_STATUS
969 AcpiDisableAllGpes (
970     void)
971 {
972     ACPI_STATUS             Status;
973 
974 
975     ACPI_FUNCTION_TRACE (AcpiDisableAllGpes);
976 
977 
978     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
979     if (ACPI_FAILURE (Status))
980     {
981         return_ACPI_STATUS (Status);
982     }
983 
984     Status = AcpiHwDisableAllGpes ();
985     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
986 
987     return_ACPI_STATUS (Status);
988 }
989 
990 ACPI_EXPORT_SYMBOL (AcpiDisableAllGpes)
991 
992 
993 /******************************************************************************
994  *
995  * FUNCTION:    AcpiEnableAllRuntimeGpes
996  *
997  * PARAMETERS:  None
998  *
999  * RETURN:      Status
1000  *
1001  * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
1002  *
1003  ******************************************************************************/
1004 
1005 ACPI_STATUS
1006 AcpiEnableAllRuntimeGpes (
1007     void)
1008 {
1009     ACPI_STATUS             Status;
1010 
1011 
1012     ACPI_FUNCTION_TRACE (AcpiEnableAllRuntimeGpes);
1013 
1014 
1015     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
1016     if (ACPI_FAILURE (Status))
1017     {
1018         return_ACPI_STATUS (Status);
1019     }
1020 
1021     Status = AcpiHwEnableAllRuntimeGpes ();
1022     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
1023 
1024     return_ACPI_STATUS (Status);
1025 }
1026 
1027 ACPI_EXPORT_SYMBOL (AcpiEnableAllRuntimeGpes)
1028 
1029 
1030 /******************************************************************************
1031  *
1032  * FUNCTION:    AcpiEnableAllWakeupGpes
1033  *
1034  * PARAMETERS:  None
1035  *
1036  * RETURN:      Status
1037  *
1038  * DESCRIPTION: Enable all "wakeup" GPEs and disable all of the other GPEs, in
1039  *              all GPE blocks.
1040  *
1041  ******************************************************************************/
1042 
1043 ACPI_STATUS
1044 AcpiEnableAllWakeupGpes (
1045     void)
1046 {
1047     ACPI_STATUS             Status;
1048 
1049 
1050     ACPI_FUNCTION_TRACE (AcpiEnableAllWakeupGpes);
1051 
1052 
1053     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
1054     if (ACPI_FAILURE (Status))
1055     {
1056         return_ACPI_STATUS (Status);
1057     }
1058 
1059     Status = AcpiHwEnableAllWakeupGpes ();
1060     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
1061 
1062     return_ACPI_STATUS (Status);
1063 }
1064 
1065 ACPI_EXPORT_SYMBOL (AcpiEnableAllWakeupGpes)
1066 
1067 
1068 /******************************************************************************
1069  *
1070  * FUNCTION:    AcpiAnyGpeStatusSet
1071  *
1072  * PARAMETERS:  None
1073  *
1074  * RETURN:      Whether or not the status bit is set for any GPE
1075  *
1076  * DESCRIPTION: Check the status bits of all enabled GPEs and return TRUE if any
1077  *              of them is set or FALSE otherwise.
1078  *
1079  ******************************************************************************/
1080 
1081 UINT32
1082 AcpiAnyGpeStatusSet (
1083     void)
1084 {
1085     ACPI_STATUS                Status;
1086     UINT8                      Ret;
1087 
1088 
1089     ACPI_FUNCTION_TRACE (AcpiAnyGpeStatusSet);
1090 
1091     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
1092     if (ACPI_FAILURE (Status))
1093     {
1094         return (FALSE);
1095     }
1096 
1097     Ret = AcpiHwCheckAllGpes ();
1098     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
1099 
1100     return (Ret);
1101 }
1102 
1103 ACPI_EXPORT_SYMBOL(AcpiAnyGpeStatusSet)
1104 
1105 
1106 /*******************************************************************************
1107  *
1108  * FUNCTION:    AcpiInstallGpeBlock
1109  *
1110  * PARAMETERS:  GpeDevice           - Handle to the parent GPE Block Device
1111  *              GpeBlockAddress     - Address and SpaceID
1112  *              RegisterCount       - Number of GPE register pairs in the block
1113  *              InterruptNumber     - H/W interrupt for the block
1114  *
1115  * RETURN:      Status
1116  *
1117  * DESCRIPTION: Create and Install a block of GPE registers. The GPEs are not
1118  *              enabled here.
1119  *
1120  ******************************************************************************/
1121 
1122 ACPI_STATUS
1123 AcpiInstallGpeBlock (
1124     ACPI_HANDLE             GpeDevice,
1125     ACPI_GENERIC_ADDRESS    *GpeBlockAddress,
1126     UINT32                  RegisterCount,
1127     UINT32                  InterruptNumber)
1128 {
1129     ACPI_STATUS             Status;
1130     ACPI_OPERAND_OBJECT     *ObjDesc;
1131     ACPI_NAMESPACE_NODE     *Node;
1132     ACPI_GPE_BLOCK_INFO     *GpeBlock;
1133 
1134 
1135     ACPI_FUNCTION_TRACE (AcpiInstallGpeBlock);
1136 
1137 
1138     if ((!GpeDevice)       ||
1139         (!GpeBlockAddress) ||
1140         (!RegisterCount))
1141     {
1142         return_ACPI_STATUS (AE_BAD_PARAMETER);
1143     }
1144 
1145     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
1146     if (ACPI_FAILURE (Status))
1147     {
1148         return_ACPI_STATUS (Status);
1149     }
1150 
1151     Node = AcpiNsValidateHandle (GpeDevice);
1152     if (!Node)
1153     {
1154         Status = AE_BAD_PARAMETER;
1155         goto UnlockAndExit;
1156     }
1157 
1158     /* Validate the parent device */
1159 
1160     if (Node->Type != ACPI_TYPE_DEVICE)
1161     {
1162         Status = AE_TYPE;
1163         goto UnlockAndExit;
1164     }
1165 
1166     if (Node->Object)
1167     {
1168         Status = AE_ALREADY_EXISTS;
1169         goto UnlockAndExit;
1170     }
1171 
1172     /*
1173      * For user-installed GPE Block Devices, the GpeBlockBaseNumber
1174      * is always zero
1175      */
1176     Status = AcpiEvCreateGpeBlock (Node, GpeBlockAddress->Address,
1177         GpeBlockAddress->SpaceId, RegisterCount,
1178         0, InterruptNumber, &GpeBlock);
1179     if (ACPI_FAILURE (Status))
1180     {
1181         goto UnlockAndExit;
1182     }
1183 
1184     /* Install block in the DeviceObject attached to the node */
1185 
1186     ObjDesc = AcpiNsGetAttachedObject (Node);
1187     if (!ObjDesc)
1188     {
1189         /*
1190          * No object, create a new one (Device nodes do not always have
1191          * an attached object)
1192          */
1193         ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_DEVICE);
1194         if (!ObjDesc)
1195         {
1196             Status = AE_NO_MEMORY;
1197             goto UnlockAndExit;
1198         }
1199 
1200         Status = AcpiNsAttachObject (Node, ObjDesc, ACPI_TYPE_DEVICE);
1201 
1202         /* Remove local reference to the object */
1203 
1204         AcpiUtRemoveReference (ObjDesc);
1205         if (ACPI_FAILURE (Status))
1206         {
1207             goto UnlockAndExit;
1208         }
1209     }
1210 
1211     /* Now install the GPE block in the DeviceObject */
1212 
1213     ObjDesc->Device.GpeBlock = GpeBlock;
1214 
1215 
1216 UnlockAndExit:
1217     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
1218     return_ACPI_STATUS (Status);
1219 }
1220 
1221 ACPI_EXPORT_SYMBOL (AcpiInstallGpeBlock)
1222 
1223 
1224 /*******************************************************************************
1225  *
1226  * FUNCTION:    AcpiRemoveGpeBlock
1227  *
1228  * PARAMETERS:  GpeDevice           - Handle to the parent GPE Block Device
1229  *
1230  * RETURN:      Status
1231  *
1232  * DESCRIPTION: Remove a previously installed block of GPE registers
1233  *
1234  ******************************************************************************/
1235 
1236 ACPI_STATUS
1237 AcpiRemoveGpeBlock (
1238     ACPI_HANDLE             GpeDevice)
1239 {
1240     ACPI_OPERAND_OBJECT     *ObjDesc;
1241     ACPI_STATUS             Status;
1242     ACPI_NAMESPACE_NODE     *Node;
1243 
1244 
1245     ACPI_FUNCTION_TRACE (AcpiRemoveGpeBlock);
1246 
1247 
1248     if (!GpeDevice)
1249     {
1250         return_ACPI_STATUS (AE_BAD_PARAMETER);
1251     }
1252 
1253     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
1254     if (ACPI_FAILURE (Status))
1255     {
1256         return_ACPI_STATUS (Status);
1257     }
1258 
1259     Node = AcpiNsValidateHandle (GpeDevice);
1260     if (!Node)
1261     {
1262         Status = AE_BAD_PARAMETER;
1263         goto UnlockAndExit;
1264     }
1265 
1266     /* Validate the parent device */
1267 
1268     if (Node->Type != ACPI_TYPE_DEVICE)
1269     {
1270         Status = AE_TYPE;
1271         goto UnlockAndExit;
1272     }
1273 
1274     /* Get the DeviceObject attached to the node */
1275 
1276     ObjDesc = AcpiNsGetAttachedObject (Node);
1277     if (!ObjDesc ||
1278         !ObjDesc->Device.GpeBlock)
1279     {
1280         return_ACPI_STATUS (AE_NULL_OBJECT);
1281     }
1282 
1283     /* Delete the GPE block (but not the DeviceObject) */
1284 
1285     Status = AcpiEvDeleteGpeBlock (ObjDesc->Device.GpeBlock);
1286     if (ACPI_SUCCESS (Status))
1287     {
1288         ObjDesc->Device.GpeBlock = NULL;
1289     }
1290 
1291 UnlockAndExit:
1292     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
1293     return_ACPI_STATUS (Status);
1294 }
1295 
1296 ACPI_EXPORT_SYMBOL (AcpiRemoveGpeBlock)
1297 
1298 
1299 /*******************************************************************************
1300  *
1301  * FUNCTION:    AcpiGetGpeDevice
1302  *
1303  * PARAMETERS:  Index               - System GPE index (0-CurrentGpeCount)
1304  *              GpeDevice           - Where the parent GPE Device is returned
1305  *
1306  * RETURN:      Status
1307  *
1308  * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL
1309  *              gpe device indicates that the gpe number is contained in one of
1310  *              the FADT-defined gpe blocks. Otherwise, the GPE block device.
1311  *
1312  ******************************************************************************/
1313 
1314 ACPI_STATUS
1315 AcpiGetGpeDevice (
1316     UINT32                  Index,
1317     ACPI_HANDLE             *GpeDevice)
1318 {
1319     ACPI_GPE_DEVICE_INFO    Info;
1320     ACPI_STATUS             Status;
1321 
1322 
1323     ACPI_FUNCTION_TRACE (AcpiGetGpeDevice);
1324 
1325 
1326     if (!GpeDevice)
1327     {
1328         return_ACPI_STATUS (AE_BAD_PARAMETER);
1329     }
1330 
1331     if (Index >= AcpiCurrentGpeCount)
1332     {
1333         return_ACPI_STATUS (AE_NOT_EXIST);
1334     }
1335 
1336     /* Setup and walk the GPE list */
1337 
1338     Info.Index = Index;
1339     Info.Status = AE_NOT_EXIST;
1340     Info.GpeDevice = NULL;
1341     Info.NextBlockBaseIndex = 0;
1342 
1343     Status = AcpiEvWalkGpeList (AcpiEvGetGpeDevice, &Info);
1344     if (ACPI_FAILURE (Status))
1345     {
1346         return_ACPI_STATUS (Status);
1347     }
1348 
1349     *GpeDevice = ACPI_CAST_PTR (ACPI_HANDLE, Info.GpeDevice);
1350     return_ACPI_STATUS (Info.Status);
1351 }
1352 
1353 ACPI_EXPORT_SYMBOL (AcpiGetGpeDevice)
1354 
1355 #endif /* !ACPI_REDUCED_HARDWARE */
1356