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