xref: /illumos-gate/usr/src/common/acpica/events/evxfgpe.c (revision 8119dad84d6416f13557b0ba8e2aaf9064cbcfd3)
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 - 2018, 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);
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:    AcpiFinishGpe
881  *
882  * PARAMETERS:  GpeDevice           - Namespace node for the GPE Block
883  *                                    (NULL for FADT defined GPEs)
884  *              GpeNumber           - GPE level within the GPE block
885  *
886  * RETURN:      Status
887  *
888  * DESCRIPTION: Clear and conditionally reenable a GPE. This completes the GPE
889  *              processing. Intended for use by asynchronous host-installed
890  *              GPE handlers. The GPE is only reenabled if the EnableForRun bit
891  *              is set in the GPE info.
892  *
893  ******************************************************************************/
894 
895 ACPI_STATUS
896 AcpiFinishGpe (
897     ACPI_HANDLE             GpeDevice,
898     UINT32                  GpeNumber)
899 {
900     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
901     ACPI_STATUS             Status;
902     ACPI_CPU_FLAGS          Flags;
903 
904 
905     ACPI_FUNCTION_TRACE (AcpiFinishGpe);
906 
907 
908     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
909 
910     /* Ensure that we have a valid GPE number */
911 
912     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
913     if (!GpeEventInfo)
914     {
915         Status = AE_BAD_PARAMETER;
916         goto UnlockAndExit;
917     }
918 
919     Status = AcpiEvFinishGpe (GpeEventInfo);
920 
921 UnlockAndExit:
922     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
923     return_ACPI_STATUS (Status);
924 }
925 
926 ACPI_EXPORT_SYMBOL (AcpiFinishGpe)
927 
928 
929 /******************************************************************************
930  *
931  * FUNCTION:    AcpiDisableAllGpes
932  *
933  * PARAMETERS:  None
934  *
935  * RETURN:      Status
936  *
937  * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
938  *
939  ******************************************************************************/
940 
941 ACPI_STATUS
942 AcpiDisableAllGpes (
943     void)
944 {
945     ACPI_STATUS             Status;
946 
947 
948     ACPI_FUNCTION_TRACE (AcpiDisableAllGpes);
949 
950 
951     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
952     if (ACPI_FAILURE (Status))
953     {
954         return_ACPI_STATUS (Status);
955     }
956 
957     Status = AcpiHwDisableAllGpes ();
958     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
959 
960     return_ACPI_STATUS (Status);
961 }
962 
963 ACPI_EXPORT_SYMBOL (AcpiDisableAllGpes)
964 
965 
966 /******************************************************************************
967  *
968  * FUNCTION:    AcpiEnableAllRuntimeGpes
969  *
970  * PARAMETERS:  None
971  *
972  * RETURN:      Status
973  *
974  * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
975  *
976  ******************************************************************************/
977 
978 ACPI_STATUS
979 AcpiEnableAllRuntimeGpes (
980     void)
981 {
982     ACPI_STATUS             Status;
983 
984 
985     ACPI_FUNCTION_TRACE (AcpiEnableAllRuntimeGpes);
986 
987 
988     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
989     if (ACPI_FAILURE (Status))
990     {
991         return_ACPI_STATUS (Status);
992     }
993 
994     Status = AcpiHwEnableAllRuntimeGpes ();
995     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
996 
997     return_ACPI_STATUS (Status);
998 }
999 
1000 ACPI_EXPORT_SYMBOL (AcpiEnableAllRuntimeGpes)
1001 
1002 
1003 /******************************************************************************
1004  *
1005  * FUNCTION:    AcpiEnableAllWakeupGpes
1006  *
1007  * PARAMETERS:  None
1008  *
1009  * RETURN:      Status
1010  *
1011  * DESCRIPTION: Enable all "wakeup" GPEs and disable all of the other GPEs, in
1012  *              all GPE blocks.
1013  *
1014  ******************************************************************************/
1015 
1016 ACPI_STATUS
1017 AcpiEnableAllWakeupGpes (
1018     void)
1019 {
1020     ACPI_STATUS             Status;
1021 
1022 
1023     ACPI_FUNCTION_TRACE (AcpiEnableAllWakeupGpes);
1024 
1025 
1026     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
1027     if (ACPI_FAILURE (Status))
1028     {
1029         return_ACPI_STATUS (Status);
1030     }
1031 
1032     Status = AcpiHwEnableAllWakeupGpes ();
1033     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
1034 
1035     return_ACPI_STATUS (Status);
1036 }
1037 
1038 ACPI_EXPORT_SYMBOL (AcpiEnableAllWakeupGpes)
1039 
1040 
1041 /*******************************************************************************
1042  *
1043  * FUNCTION:    AcpiInstallGpeBlock
1044  *
1045  * PARAMETERS:  GpeDevice           - Handle to the parent GPE Block Device
1046  *              GpeBlockAddress     - Address and SpaceID
1047  *              RegisterCount       - Number of GPE register pairs in the block
1048  *              InterruptNumber     - H/W interrupt for the block
1049  *
1050  * RETURN:      Status
1051  *
1052  * DESCRIPTION: Create and Install a block of GPE registers. The GPEs are not
1053  *              enabled here.
1054  *
1055  ******************************************************************************/
1056 
1057 ACPI_STATUS
1058 AcpiInstallGpeBlock (
1059     ACPI_HANDLE             GpeDevice,
1060     ACPI_GENERIC_ADDRESS    *GpeBlockAddress,
1061     UINT32                  RegisterCount,
1062     UINT32                  InterruptNumber)
1063 {
1064     ACPI_STATUS             Status;
1065     ACPI_OPERAND_OBJECT     *ObjDesc;
1066     ACPI_NAMESPACE_NODE     *Node;
1067     ACPI_GPE_BLOCK_INFO     *GpeBlock;
1068 
1069 
1070     ACPI_FUNCTION_TRACE (AcpiInstallGpeBlock);
1071 
1072 
1073     if ((!GpeDevice)       ||
1074         (!GpeBlockAddress) ||
1075         (!RegisterCount))
1076     {
1077         return_ACPI_STATUS (AE_BAD_PARAMETER);
1078     }
1079 
1080     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
1081     if (ACPI_FAILURE (Status))
1082     {
1083         return_ACPI_STATUS (Status);
1084     }
1085 
1086     Node = AcpiNsValidateHandle (GpeDevice);
1087     if (!Node)
1088     {
1089         Status = AE_BAD_PARAMETER;
1090         goto UnlockAndExit;
1091     }
1092 
1093     /* Validate the parent device */
1094 
1095     if (Node->Type != ACPI_TYPE_DEVICE)
1096     {
1097         Status = AE_TYPE;
1098         goto UnlockAndExit;
1099     }
1100 
1101     if (Node->Object)
1102     {
1103         Status = AE_ALREADY_EXISTS;
1104         goto UnlockAndExit;
1105     }
1106 
1107     /*
1108      * For user-installed GPE Block Devices, the GpeBlockBaseNumber
1109      * is always zero
1110      */
1111     Status = AcpiEvCreateGpeBlock (Node, GpeBlockAddress->Address,
1112         GpeBlockAddress->SpaceId, RegisterCount,
1113         0, InterruptNumber, &GpeBlock);
1114     if (ACPI_FAILURE (Status))
1115     {
1116         goto UnlockAndExit;
1117     }
1118 
1119     /* Install block in the DeviceObject attached to the node */
1120 
1121     ObjDesc = AcpiNsGetAttachedObject (Node);
1122     if (!ObjDesc)
1123     {
1124         /*
1125          * No object, create a new one (Device nodes do not always have
1126          * an attached object)
1127          */
1128         ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_DEVICE);
1129         if (!ObjDesc)
1130         {
1131             Status = AE_NO_MEMORY;
1132             goto UnlockAndExit;
1133         }
1134 
1135         Status = AcpiNsAttachObject (Node, ObjDesc, ACPI_TYPE_DEVICE);
1136 
1137         /* Remove local reference to the object */
1138 
1139         AcpiUtRemoveReference (ObjDesc);
1140         if (ACPI_FAILURE (Status))
1141         {
1142             goto UnlockAndExit;
1143         }
1144     }
1145 
1146     /* Now install the GPE block in the DeviceObject */
1147 
1148     ObjDesc->Device.GpeBlock = GpeBlock;
1149 
1150 
1151 UnlockAndExit:
1152     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
1153     return_ACPI_STATUS (Status);
1154 }
1155 
1156 ACPI_EXPORT_SYMBOL (AcpiInstallGpeBlock)
1157 
1158 
1159 /*******************************************************************************
1160  *
1161  * FUNCTION:    AcpiRemoveGpeBlock
1162  *
1163  * PARAMETERS:  GpeDevice           - Handle to the parent GPE Block Device
1164  *
1165  * RETURN:      Status
1166  *
1167  * DESCRIPTION: Remove a previously installed block of GPE registers
1168  *
1169  ******************************************************************************/
1170 
1171 ACPI_STATUS
1172 AcpiRemoveGpeBlock (
1173     ACPI_HANDLE             GpeDevice)
1174 {
1175     ACPI_OPERAND_OBJECT     *ObjDesc;
1176     ACPI_STATUS             Status;
1177     ACPI_NAMESPACE_NODE     *Node;
1178 
1179 
1180     ACPI_FUNCTION_TRACE (AcpiRemoveGpeBlock);
1181 
1182 
1183     if (!GpeDevice)
1184     {
1185         return_ACPI_STATUS (AE_BAD_PARAMETER);
1186     }
1187 
1188     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
1189     if (ACPI_FAILURE (Status))
1190     {
1191         return_ACPI_STATUS (Status);
1192     }
1193 
1194     Node = AcpiNsValidateHandle (GpeDevice);
1195     if (!Node)
1196     {
1197         Status = AE_BAD_PARAMETER;
1198         goto UnlockAndExit;
1199     }
1200 
1201     /* Validate the parent device */
1202 
1203     if (Node->Type != ACPI_TYPE_DEVICE)
1204     {
1205         Status = AE_TYPE;
1206         goto UnlockAndExit;
1207     }
1208 
1209     /* Get the DeviceObject attached to the node */
1210 
1211     ObjDesc = AcpiNsGetAttachedObject (Node);
1212     if (!ObjDesc ||
1213         !ObjDesc->Device.GpeBlock)
1214     {
1215         return_ACPI_STATUS (AE_NULL_OBJECT);
1216     }
1217 
1218     /* Delete the GPE block (but not the DeviceObject) */
1219 
1220     Status = AcpiEvDeleteGpeBlock (ObjDesc->Device.GpeBlock);
1221     if (ACPI_SUCCESS (Status))
1222     {
1223         ObjDesc->Device.GpeBlock = NULL;
1224     }
1225 
1226 UnlockAndExit:
1227     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
1228     return_ACPI_STATUS (Status);
1229 }
1230 
1231 ACPI_EXPORT_SYMBOL (AcpiRemoveGpeBlock)
1232 
1233 
1234 /*******************************************************************************
1235  *
1236  * FUNCTION:    AcpiGetGpeDevice
1237  *
1238  * PARAMETERS:  Index               - System GPE index (0-CurrentGpeCount)
1239  *              GpeDevice           - Where the parent GPE Device is returned
1240  *
1241  * RETURN:      Status
1242  *
1243  * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL
1244  *              gpe device indicates that the gpe number is contained in one of
1245  *              the FADT-defined gpe blocks. Otherwise, the GPE block device.
1246  *
1247  ******************************************************************************/
1248 
1249 ACPI_STATUS
1250 AcpiGetGpeDevice (
1251     UINT32                  Index,
1252     ACPI_HANDLE             *GpeDevice)
1253 {
1254     ACPI_GPE_DEVICE_INFO    Info;
1255     ACPI_STATUS             Status;
1256 
1257 
1258     ACPI_FUNCTION_TRACE (AcpiGetGpeDevice);
1259 
1260 
1261     if (!GpeDevice)
1262     {
1263         return_ACPI_STATUS (AE_BAD_PARAMETER);
1264     }
1265 
1266     if (Index >= AcpiCurrentGpeCount)
1267     {
1268         return_ACPI_STATUS (AE_NOT_EXIST);
1269     }
1270 
1271     /* Setup and walk the GPE list */
1272 
1273     Info.Index = Index;
1274     Info.Status = AE_NOT_EXIST;
1275     Info.GpeDevice = NULL;
1276     Info.NextBlockBaseIndex = 0;
1277 
1278     Status = AcpiEvWalkGpeList (AcpiEvGetGpeDevice, &Info);
1279     if (ACPI_FAILURE (Status))
1280     {
1281         return_ACPI_STATUS (Status);
1282     }
1283 
1284     *GpeDevice = ACPI_CAST_PTR (ACPI_HANDLE, Info.GpeDevice);
1285     return_ACPI_STATUS (Info.Status);
1286 }
1287 
1288 ACPI_EXPORT_SYMBOL (AcpiGetGpeDevice)
1289 
1290 #endif /* !ACPI_REDUCED_HARDWARE */
1291