evxfgpe.c revision 316303
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
186ACPI_STATUS
187AcpiUpdateAllGpes (
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
213UnlockAndExit:
214    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
215    return_ACPI_STATUS (Status);
216}
217
218ACPI_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
235ACPI_STATUS
236AcpiEnableGpe (
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
273ACPI_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
291ACPI_STATUS
292AcpiDisableGpe (
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
318ACPI_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
350ACPI_STATUS
351AcpiSetGpe (
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
397UnlockAndExit:
398    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
399    return_ACPI_STATUS (Status);
400}
401
402ACPI_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
420ACPI_STATUS
421AcpiMaskGpe (
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
447UnlockAndExit:
448    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
449    return_ACPI_STATUS (Status);
450}
451
452ACPI_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
476ACPI_STATUS
477AcpiMarkGpeForWake (
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
506ACPI_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
528ACPI_STATUS
529AcpiSetupGpeForWake (
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
647UnlockAndExit:
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
659ACPI_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
677ACPI_STATUS
678AcpiSetGpeWakeMask (
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
742UnlockAndExit:
743    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
744    return_ACPI_STATUS (Status);
745}
746
747ACPI_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
763ACPI_STATUS
764AcpiClearGpe (
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
789UnlockAndExit:
790    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
791    return_ACPI_STATUS (Status);
792}
793
794ACPI_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
812ACPI_STATUS
813AcpiGetGpeStatus (
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
841UnlockAndExit:
842    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
843    return_ACPI_STATUS (Status);
844}
845
846ACPI_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
866ACPI_STATUS
867AcpiFinishGpe (
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
892UnlockAndExit:
893    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
894    return_ACPI_STATUS (Status);
895}
896
897ACPI_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
912ACPI_STATUS
913AcpiDisableAllGpes (
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
934ACPI_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
949ACPI_STATUS
950AcpiEnableAllRuntimeGpes (
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
971ACPI_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
987ACPI_STATUS
988AcpiEnableAllWakeupGpes (
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
1009ACPI_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
1028ACPI_STATUS
1029AcpiInstallGpeBlock (
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
1122UnlockAndExit:
1123    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
1124    return_ACPI_STATUS (Status);
1125}
1126
1127ACPI_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
1142ACPI_STATUS
1143AcpiRemoveGpeBlock (
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
1197UnlockAndExit:
1198    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
1199    return_ACPI_STATUS (Status);
1200}
1201
1202ACPI_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
1220ACPI_STATUS
1221AcpiGetGpeDevice (
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
1259ACPI_EXPORT_SYMBOL (AcpiGetGpeDevice)
1260
1261#endif /* !ACPI_REDUCED_HARDWARE */
1262