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 - 2020, 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 "acpi.h"
155 #include "accommon.h"
156 #include "acevents.h"
157 #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:    AcpiInstallGpeBlock
1071  *
1072  * PARAMETERS:  GpeDevice           - Handle to the parent GPE Block Device
1073  *              GpeBlockAddress     - Address and SpaceID
1074  *              RegisterCount       - Number of GPE register pairs in the block
1075  *              InterruptNumber     - H/W interrupt for the block
1076  *
1077  * RETURN:      Status
1078  *
1079  * DESCRIPTION: Create and Install a block of GPE registers. The GPEs are not
1080  *              enabled here.
1081  *
1082  ******************************************************************************/
1083 
1084 ACPI_STATUS
1085 AcpiInstallGpeBlock (
1086     ACPI_HANDLE             GpeDevice,
1087     ACPI_GENERIC_ADDRESS    *GpeBlockAddress,
1088     UINT32                  RegisterCount,
1089     UINT32                  InterruptNumber)
1090 {
1091     ACPI_STATUS             Status;
1092     ACPI_OPERAND_OBJECT     *ObjDesc;
1093     ACPI_NAMESPACE_NODE     *Node;
1094     ACPI_GPE_BLOCK_INFO     *GpeBlock;
1095 
1096 
1097     ACPI_FUNCTION_TRACE (AcpiInstallGpeBlock);
1098 
1099 
1100     if ((!GpeDevice)       ||
1101         (!GpeBlockAddress) ||
1102         (!RegisterCount))
1103     {
1104         return_ACPI_STATUS (AE_BAD_PARAMETER);
1105     }
1106 
1107     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
1108     if (ACPI_FAILURE (Status))
1109     {
1110         return_ACPI_STATUS (Status);
1111     }
1112 
1113     Node = AcpiNsValidateHandle (GpeDevice);
1114     if (!Node)
1115     {
1116         Status = AE_BAD_PARAMETER;
1117         goto UnlockAndExit;
1118     }
1119 
1120     /* Validate the parent device */
1121 
1122     if (Node->Type != ACPI_TYPE_DEVICE)
1123     {
1124         Status = AE_TYPE;
1125         goto UnlockAndExit;
1126     }
1127 
1128     if (Node->Object)
1129     {
1130         Status = AE_ALREADY_EXISTS;
1131         goto UnlockAndExit;
1132     }
1133 
1134     /*
1135      * For user-installed GPE Block Devices, the GpeBlockBaseNumber
1136      * is always zero
1137      */
1138     Status = AcpiEvCreateGpeBlock (Node, GpeBlockAddress->Address,
1139         GpeBlockAddress->SpaceId, RegisterCount,
1140         0, InterruptNumber, &GpeBlock);
1141     if (ACPI_FAILURE (Status))
1142     {
1143         goto UnlockAndExit;
1144     }
1145 
1146     /* Install block in the DeviceObject attached to the node */
1147 
1148     ObjDesc = AcpiNsGetAttachedObject (Node);
1149     if (!ObjDesc)
1150     {
1151         /*
1152          * No object, create a new one (Device nodes do not always have
1153          * an attached object)
1154          */
1155         ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_DEVICE);
1156         if (!ObjDesc)
1157         {
1158             Status = AE_NO_MEMORY;
1159             goto UnlockAndExit;
1160         }
1161 
1162         Status = AcpiNsAttachObject (Node, ObjDesc, ACPI_TYPE_DEVICE);
1163 
1164         /* Remove local reference to the object */
1165 
1166         AcpiUtRemoveReference (ObjDesc);
1167         if (ACPI_FAILURE (Status))
1168         {
1169             goto UnlockAndExit;
1170         }
1171     }
1172 
1173     /* Now install the GPE block in the DeviceObject */
1174 
1175     ObjDesc->Device.GpeBlock = GpeBlock;
1176 
1177 
1178 UnlockAndExit:
1179     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
1180     return_ACPI_STATUS (Status);
1181 }
1182 
1183 ACPI_EXPORT_SYMBOL (AcpiInstallGpeBlock)
1184 
1185 
1186 /*******************************************************************************
1187  *
1188  * FUNCTION:    AcpiRemoveGpeBlock
1189  *
1190  * PARAMETERS:  GpeDevice           - Handle to the parent GPE Block Device
1191  *
1192  * RETURN:      Status
1193  *
1194  * DESCRIPTION: Remove a previously installed block of GPE registers
1195  *
1196  ******************************************************************************/
1197 
1198 ACPI_STATUS
1199 AcpiRemoveGpeBlock (
1200     ACPI_HANDLE             GpeDevice)
1201 {
1202     ACPI_OPERAND_OBJECT     *ObjDesc;
1203     ACPI_STATUS             Status;
1204     ACPI_NAMESPACE_NODE     *Node;
1205 
1206 
1207     ACPI_FUNCTION_TRACE (AcpiRemoveGpeBlock);
1208 
1209 
1210     if (!GpeDevice)
1211     {
1212         return_ACPI_STATUS (AE_BAD_PARAMETER);
1213     }
1214 
1215     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
1216     if (ACPI_FAILURE (Status))
1217     {
1218         return_ACPI_STATUS (Status);
1219     }
1220 
1221     Node = AcpiNsValidateHandle (GpeDevice);
1222     if (!Node)
1223     {
1224         Status = AE_BAD_PARAMETER;
1225         goto UnlockAndExit;
1226     }
1227 
1228     /* Validate the parent device */
1229 
1230     if (Node->Type != ACPI_TYPE_DEVICE)
1231     {
1232         Status = AE_TYPE;
1233         goto UnlockAndExit;
1234     }
1235 
1236     /* Get the DeviceObject attached to the node */
1237 
1238     ObjDesc = AcpiNsGetAttachedObject (Node);
1239     if (!ObjDesc ||
1240         !ObjDesc->Device.GpeBlock)
1241     {
1242         return_ACPI_STATUS (AE_NULL_OBJECT);
1243     }
1244 
1245     /* Delete the GPE block (but not the DeviceObject) */
1246 
1247     Status = AcpiEvDeleteGpeBlock (ObjDesc->Device.GpeBlock);
1248     if (ACPI_SUCCESS (Status))
1249     {
1250         ObjDesc->Device.GpeBlock = NULL;
1251     }
1252 
1253 UnlockAndExit:
1254     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
1255     return_ACPI_STATUS (Status);
1256 }
1257 
1258 ACPI_EXPORT_SYMBOL (AcpiRemoveGpeBlock)
1259 
1260 
1261 /*******************************************************************************
1262  *
1263  * FUNCTION:    AcpiGetGpeDevice
1264  *
1265  * PARAMETERS:  Index               - System GPE index (0-CurrentGpeCount)
1266  *              GpeDevice           - Where the parent GPE Device is returned
1267  *
1268  * RETURN:      Status
1269  *
1270  * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL
1271  *              gpe device indicates that the gpe number is contained in one of
1272  *              the FADT-defined gpe blocks. Otherwise, the GPE block device.
1273  *
1274  ******************************************************************************/
1275 
1276 ACPI_STATUS
1277 AcpiGetGpeDevice (
1278     UINT32                  Index,
1279     ACPI_HANDLE             *GpeDevice)
1280 {
1281     ACPI_GPE_DEVICE_INFO    Info;
1282     ACPI_STATUS             Status;
1283 
1284 
1285     ACPI_FUNCTION_TRACE (AcpiGetGpeDevice);
1286 
1287 
1288     if (!GpeDevice)
1289     {
1290         return_ACPI_STATUS (AE_BAD_PARAMETER);
1291     }
1292 
1293     if (Index >= AcpiCurrentGpeCount)
1294     {
1295         return_ACPI_STATUS (AE_NOT_EXIST);
1296     }
1297 
1298     /* Setup and walk the GPE list */
1299 
1300     Info.Index = Index;
1301     Info.Status = AE_NOT_EXIST;
1302     Info.GpeDevice = NULL;
1303     Info.NextBlockBaseIndex = 0;
1304 
1305     Status = AcpiEvWalkGpeList (AcpiEvGetGpeDevice, &Info);
1306     if (ACPI_FAILURE (Status))
1307     {
1308         return_ACPI_STATUS (Status);
1309     }
1310 
1311     *GpeDevice = ACPI_CAST_PTR (ACPI_HANDLE, Info.GpeDevice);
1312     return_ACPI_STATUS (Info.Status);
1313 }
1314 
1315 ACPI_EXPORT_SYMBOL (AcpiGetGpeDevice)
1316 
1317 #endif /* !ACPI_REDUCED_HARDWARE */
1318