evxfgpe.c revision 306536
1234285Sdim/******************************************************************************
2234285Sdim *
3234285Sdim * Module Name: evxfgpe - External Interfaces for General Purpose Events (GPEs)
4234285Sdim *
5234285Sdim *****************************************************************************/
6234285Sdim
7234285Sdim/*
8234285Sdim * Copyright (C) 2000 - 2016, Intel Corp.
9234285Sdim * All rights reserved.
10234285Sdim *
11234285Sdim * Redistribution and use in source and binary forms, with or without
12234285Sdim * modification, are permitted provided that the following conditions
13234285Sdim * are met:
14234285Sdim * 1. Redistributions of source code must retain the above copyright
15234285Sdim *    notice, this list of conditions, and the following disclaimer,
16234285Sdim *    without modification.
17243830Sdim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18263508Sdim *    substantially similar to the "NO WARRANTY" disclaimer below
19234285Sdim *    ("Disclaimer") and any redistribution must be conditioned upon
20249423Sdim *    including a substantially similar Disclaimer requirement for further
21234285Sdim *    binary redistribution.
22249423Sdim * 3. Neither the names of the above-listed copyright holders nor the names
23249423Sdim *    of any contributors may be used to endorse or promote products derived
24234285Sdim *    from this software without specific prior written permission.
25234285Sdim *
26234285Sdim * Alternatively, this software may be distributed under the terms of the
27234285Sdim * GNU General Public License ("GPL") version 2 as published by the Free
28234285Sdim * Software Foundation.
29251662Sdim *
30251662Sdim * NO WARRANTY
31234285Sdim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32251662Sdim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33251662Sdim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34251662Sdim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35243830Sdim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36249423Sdim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37251662Sdim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38251662Sdim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39249423Sdim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40251662Sdim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41234285Sdim * POSSIBILITY OF SUCH DAMAGES.
42234285Sdim */
43234285Sdim
44234285Sdim#define EXPORT_ACPI_INTERFACES
45234285Sdim
46234285Sdim#include <contrib/dev/acpica/include/acpi.h>
47234285Sdim#include <contrib/dev/acpica/include/accommon.h>
48234285Sdim#include <contrib/dev/acpica/include/acevents.h>
49234285Sdim#include <contrib/dev/acpica/include/acnamesp.h>
50234285Sdim
51234285Sdim#define _COMPONENT          ACPI_EVENTS
52234285Sdim        ACPI_MODULE_NAME    ("evxfgpe")
53234285Sdim
54243830Sdim
55243830Sdim#if (!ACPI_REDUCED_HARDWARE) /* Entire module */
56243830Sdim/*******************************************************************************
57234285Sdim *
58243830Sdim * FUNCTION:    AcpiUpdateAllGpes
59243830Sdim *
60243830Sdim * PARAMETERS:  None
61243830Sdim *
62234285Sdim * RETURN:      Status
63234285Sdim *
64234285Sdim * DESCRIPTION: Complete GPE initialization and enable all GPEs that have
65234285Sdim *              associated _Lxx or _Exx methods and are not pointed to by any
66234285Sdim *              device _PRW methods (this indicates that these GPEs are
67234285Sdim *              generally intended for system or device wakeup. Such GPEs
68234285Sdim *              have to be enabled directly when the devices whose _PRW
69234285Sdim *              methods point to them are set up for wakeup signaling.)
70234285Sdim *
71234285Sdim * NOTE: Should be called after any GPEs are added to the system. Primarily,
72234285Sdim * after the system _PRW methods have been run, but also after a GPE Block
73234285Sdim * Device has been added or if any new GPE methods have been added via a
74243830Sdim * dynamic table load.
75239462Sdim *
76239462Sdim ******************************************************************************/
77234285Sdim
78234285SdimACPI_STATUS
79234285SdimAcpiUpdateAllGpes (
80249423Sdim    void)
81249423Sdim{
82263508Sdim    ACPI_STATUS             Status;
83234285Sdim
84234285Sdim
85234285Sdim    ACPI_FUNCTION_TRACE (AcpiUpdateAllGpes);
86234285Sdim
87234285Sdim
88249423Sdim    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
89249423Sdim    if (ACPI_FAILURE (Status))
90249423Sdim    {
91249423Sdim        return_ACPI_STATUS (Status);
92249423Sdim    }
93249423Sdim
94249423Sdim    if (AcpiGbl_AllGpesInitialized)
95249423Sdim    {
96234285Sdim        goto UnlockAndExit;
97234285Sdim    }
98234285Sdim
99234285Sdim    Status = AcpiEvWalkGpeList (AcpiEvInitializeGpeBlock, NULL);
100234285Sdim    if (ACPI_SUCCESS (Status))
101234285Sdim    {
102234285Sdim        AcpiGbl_AllGpesInitialized = TRUE;
103234285Sdim    }
104243830Sdim
105263508SdimUnlockAndExit:
106263508Sdim    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
107263508Sdim    return_ACPI_STATUS (Status);
108263508Sdim}
109263508Sdim
110263508SdimACPI_EXPORT_SYMBOL (AcpiUpdateAllGpes)
111263508Sdim
112243830Sdim
113243830Sdim/*******************************************************************************
114234285Sdim *
115234285Sdim * FUNCTION:    AcpiEnableGpe
116234285Sdim *
117234285Sdim * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
118234285Sdim *              GpeNumber           - GPE level within the GPE block
119263508Sdim *
120263508Sdim * RETURN:      Status
121263508Sdim *
122263508Sdim * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is
123263508Sdim *              hardware-enabled.
124234285Sdim *
125234285Sdim ******************************************************************************/
126234285Sdim
127234285SdimACPI_STATUS
128234285SdimAcpiEnableGpe (
129234285Sdim    ACPI_HANDLE             GpeDevice,
130234285Sdim    UINT32                  GpeNumber)
131234285Sdim{
132234285Sdim    ACPI_STATUS             Status = AE_BAD_PARAMETER;
133234285Sdim    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
134234285Sdim    ACPI_CPU_FLAGS          Flags;
135234285Sdim
136234285Sdim
137263508Sdim    ACPI_FUNCTION_TRACE (AcpiEnableGpe);
138251662Sdim
139249423Sdim
140251662Sdim    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
141251662Sdim
142249423Sdim    /*
143251662Sdim     * Ensure that we have a valid GPE number and that there is some way
144249423Sdim     * of handling the GPE (handler or a GPE method). In other words, we
145251662Sdim     * won't allow a valid GPE to be enabled if there is no way to handle it.
146249423Sdim     */
147251662Sdim    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
148251662Sdim    if (GpeEventInfo)
149249423Sdim    {
150234285Sdim        if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) !=
151234285Sdim            ACPI_GPE_DISPATCH_NONE)
152234285Sdim        {
153234285Sdim            Status = AcpiEvAddGpeReference (GpeEventInfo);
154251662Sdim        }
155251662Sdim        else
156251662Sdim        {
157234285Sdim            Status = AE_NO_HANDLER;
158234285Sdim        }
159234285Sdim    }
160234285Sdim
161251662Sdim    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
162251662Sdim    return_ACPI_STATUS (Status);
163251662Sdim}
164251662Sdim
165251662SdimACPI_EXPORT_SYMBOL (AcpiEnableGpe)
166234285Sdim
167234285Sdim
168234285Sdim/*******************************************************************************
169263508Sdim *
170263508Sdim * FUNCTION:    AcpiDisableGpe
171263508Sdim *
172263508Sdim * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
173263508Sdim *              GpeNumber           - GPE level within the GPE block
174249423Sdim *
175249423Sdim * RETURN:      Status
176263508Sdim *
177263508Sdim * DESCRIPTION: Remove a reference to a GPE. When the last reference is
178263508Sdim *              removed, only then is the GPE disabled (for runtime GPEs), or
179263508Sdim *              the GPE mask bit disabled (for wake GPEs)
180263508Sdim *
181234285Sdim ******************************************************************************/
182234285Sdim
183234285SdimACPI_STATUS
184251662SdimAcpiDisableGpe (
185251662Sdim    ACPI_HANDLE             GpeDevice,
186234285Sdim    UINT32                  GpeNumber)
187251662Sdim{
188249423Sdim    ACPI_STATUS             Status = AE_BAD_PARAMETER;
189239462Sdim    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
190234285Sdim    ACPI_CPU_FLAGS          Flags;
191251662Sdim
192234285Sdim
193234285Sdim    ACPI_FUNCTION_TRACE (AcpiDisableGpe);
194251662Sdim
195234285Sdim
196239462Sdim    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
197251662Sdim
198251662Sdim    /* Ensure that we have a valid GPE number */
199251662Sdim
200249423Sdim    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
201251662Sdim    if (GpeEventInfo)
202239462Sdim    {
203234285Sdim        Status = AcpiEvRemoveGpeReference (GpeEventInfo);
204234285Sdim    }
205
206    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
207    return_ACPI_STATUS (Status);
208}
209
210ACPI_EXPORT_SYMBOL (AcpiDisableGpe)
211
212
213/*******************************************************************************
214 *
215 * FUNCTION:    AcpiSetGpe
216 *
217 * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
218 *              GpeNumber           - GPE level within the GPE block
219 *              Action              - ACPI_GPE_ENABLE or ACPI_GPE_DISABLE
220 *
221 * RETURN:      Status
222 *
223 * DESCRIPTION: Enable or disable an individual GPE. This function bypasses
224 *              the reference count mechanism used in the AcpiEnableGpe(),
225 *              AcpiDisableGpe() interfaces.
226 *              This API is typically used by the GPE raw handler mode driver
227 *              to switch between the polling mode and the interrupt mode after
228 *              the driver has enabled the GPE.
229 *              The APIs should be invoked in this order:
230 *               AcpiEnableGpe()              <- Ensure the reference count > 0
231 *               AcpiSetGpe(ACPI_GPE_DISABLE) <- Enter polling mode
232 *               AcpiSetGpe(ACPI_GPE_ENABLE)  <- Leave polling mode
233 *               AcpiDisableGpe()             <- Decrease the reference count
234 *
235 * Note: If a GPE is shared by 2 silicon components, then both the drivers
236 *       should support GPE polling mode or disabling the GPE for long period
237 *       for one driver may break the other. So use it with care since all
238 *       firmware _Lxx/_Exx handlers currently rely on the GPE interrupt mode.
239 *
240 ******************************************************************************/
241
242ACPI_STATUS
243AcpiSetGpe (
244    ACPI_HANDLE             GpeDevice,
245    UINT32                  GpeNumber,
246    UINT8                   Action)
247{
248    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
249    ACPI_STATUS             Status;
250    ACPI_CPU_FLAGS          Flags;
251
252
253    ACPI_FUNCTION_TRACE (AcpiSetGpe);
254
255
256    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
257
258    /* Ensure that we have a valid GPE number */
259
260    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
261    if (!GpeEventInfo)
262    {
263        Status = AE_BAD_PARAMETER;
264        goto UnlockAndExit;
265    }
266
267    /* Perform the action */
268
269    switch (Action)
270    {
271    case ACPI_GPE_ENABLE:
272
273        Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_ENABLE);
274        break;
275
276    case ACPI_GPE_DISABLE:
277
278        Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE);
279        break;
280
281    default:
282
283        Status = AE_BAD_PARAMETER;
284        break;
285    }
286
287UnlockAndExit:
288    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
289    return_ACPI_STATUS (Status);
290}
291
292ACPI_EXPORT_SYMBOL (AcpiSetGpe)
293
294
295/*******************************************************************************
296 *
297 * FUNCTION:    AcpiMarkGpeForWake
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: Mark a GPE as having the ability to wake the system. Simply
305 *              sets the ACPI_GPE_CAN_WAKE flag.
306 *
307 * Some potential callers of AcpiSetupGpeForWake may know in advance that
308 * there won't be any notify handlers installed for device wake notifications
309 * from the given GPE (one example is a button GPE in Linux). For these cases,
310 * AcpiMarkGpeForWake should be used instead of AcpiSetupGpeForWake.
311 * This will set the ACPI_GPE_CAN_WAKE flag for the GPE without trying to
312 * setup implicit wake notification for it (since there's no handler method).
313 *
314 ******************************************************************************/
315
316ACPI_STATUS
317AcpiMarkGpeForWake (
318    ACPI_HANDLE             GpeDevice,
319    UINT32                  GpeNumber)
320{
321    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
322    ACPI_STATUS             Status = AE_BAD_PARAMETER;
323    ACPI_CPU_FLAGS          Flags;
324
325
326    ACPI_FUNCTION_TRACE (AcpiMarkGpeForWake);
327
328
329    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
330
331    /* Ensure that we have a valid GPE number */
332
333    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
334    if (GpeEventInfo)
335    {
336        /* Mark the GPE as a possible wake event */
337
338        GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE;
339        Status = AE_OK;
340    }
341
342    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
343    return_ACPI_STATUS (Status);
344}
345
346ACPI_EXPORT_SYMBOL (AcpiMarkGpeForWake)
347
348
349/*******************************************************************************
350 *
351 * FUNCTION:    AcpiSetupGpeForWake
352 *
353 * PARAMETERS:  WakeDevice          - Device associated with the GPE (via _PRW)
354 *              GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
355 *              GpeNumber           - GPE level within the GPE block
356 *
357 * RETURN:      Status
358 *
359 * DESCRIPTION: Mark a GPE as having the ability to wake the system. This
360 *              interface is intended to be used as the host executes the
361 *              _PRW methods (Power Resources for Wake) in the system tables.
362 *              Each _PRW appears under a Device Object (The WakeDevice), and
363 *              contains the info for the wake GPE associated with the
364 *              WakeDevice.
365 *
366 ******************************************************************************/
367
368ACPI_STATUS
369AcpiSetupGpeForWake (
370    ACPI_HANDLE             WakeDevice,
371    ACPI_HANDLE             GpeDevice,
372    UINT32                  GpeNumber)
373{
374    ACPI_STATUS             Status;
375    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
376    ACPI_NAMESPACE_NODE     *DeviceNode;
377    ACPI_GPE_NOTIFY_INFO    *Notify;
378    ACPI_GPE_NOTIFY_INFO    *NewNotify;
379    ACPI_CPU_FLAGS          Flags;
380
381
382    ACPI_FUNCTION_TRACE (AcpiSetupGpeForWake);
383
384
385    /* Parameter Validation */
386
387    if (!WakeDevice)
388    {
389        /*
390         * By forcing WakeDevice to be valid, we automatically enable the
391         * implicit notify feature on all hosts.
392         */
393        return_ACPI_STATUS (AE_BAD_PARAMETER);
394    }
395
396    /* Handle root object case */
397
398    if (WakeDevice == ACPI_ROOT_OBJECT)
399    {
400        DeviceNode = AcpiGbl_RootNode;
401    }
402    else
403    {
404        DeviceNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, WakeDevice);
405    }
406
407    /* Validate WakeDevice is of type Device */
408
409    if (DeviceNode->Type != ACPI_TYPE_DEVICE)
410    {
411        return_ACPI_STATUS (AE_BAD_PARAMETER);
412    }
413
414    /*
415     * Allocate a new notify object up front, in case it is needed.
416     * Memory allocation while holding a spinlock is a big no-no
417     * on some hosts.
418     */
419    NewNotify = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_NOTIFY_INFO));
420    if (!NewNotify)
421    {
422        return_ACPI_STATUS (AE_NO_MEMORY);
423    }
424
425    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
426
427    /* Ensure that we have a valid GPE number */
428
429    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
430    if (!GpeEventInfo)
431    {
432        Status = AE_BAD_PARAMETER;
433        goto UnlockAndExit;
434    }
435
436    /*
437     * If there is no method or handler for this GPE, then the
438     * WakeDevice will be notified whenever this GPE fires. This is
439     * known as an "implicit notify". Note: The GPE is assumed to be
440     * level-triggered (for windows compatibility).
441     */
442    if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) ==
443        ACPI_GPE_DISPATCH_NONE)
444    {
445        /*
446         * This is the first device for implicit notify on this GPE.
447         * Just set the flags here, and enter the NOTIFY block below.
448         */
449        GpeEventInfo->Flags =
450            (ACPI_GPE_DISPATCH_NOTIFY | ACPI_GPE_LEVEL_TRIGGERED);
451    }
452
453    /*
454     * If we already have an implicit notify on this GPE, add
455     * this device to the notify list.
456     */
457    if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) ==
458        ACPI_GPE_DISPATCH_NOTIFY)
459    {
460        /* Ensure that the device is not already in the list */
461
462        Notify = GpeEventInfo->Dispatch.NotifyList;
463        while (Notify)
464        {
465            if (Notify->DeviceNode == DeviceNode)
466            {
467                Status = AE_ALREADY_EXISTS;
468                goto UnlockAndExit;
469            }
470            Notify = Notify->Next;
471        }
472
473        /* Add this device to the notify list for this GPE */
474
475        NewNotify->DeviceNode = DeviceNode;
476        NewNotify->Next = GpeEventInfo->Dispatch.NotifyList;
477        GpeEventInfo->Dispatch.NotifyList = NewNotify;
478        NewNotify = NULL;
479    }
480
481    /* Mark the GPE as a possible wake event */
482
483    GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE;
484    Status = AE_OK;
485
486
487UnlockAndExit:
488    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
489
490    /* Delete the notify object if it was not used above */
491
492    if (NewNotify)
493    {
494        ACPI_FREE (NewNotify);
495    }
496    return_ACPI_STATUS (Status);
497}
498
499ACPI_EXPORT_SYMBOL (AcpiSetupGpeForWake)
500
501
502/*******************************************************************************
503 *
504 * FUNCTION:    AcpiSetGpeWakeMask
505 *
506 * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
507 *              GpeNumber           - GPE level within the GPE block
508 *              Action              - Enable or Disable
509 *
510 * RETURN:      Status
511 *
512 * DESCRIPTION: Set or clear the GPE's wakeup enable mask bit. The GPE must
513 *              already be marked as a WAKE GPE.
514 *
515 ******************************************************************************/
516
517ACPI_STATUS
518AcpiSetGpeWakeMask (
519    ACPI_HANDLE             GpeDevice,
520    UINT32                  GpeNumber,
521    UINT8                   Action)
522{
523    ACPI_STATUS             Status = AE_OK;
524    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
525    ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
526    ACPI_CPU_FLAGS          Flags;
527    UINT32                  RegisterBit;
528
529
530    ACPI_FUNCTION_TRACE (AcpiSetGpeWakeMask);
531
532
533    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
534
535    /*
536     * Ensure that we have a valid GPE number and that this GPE is in
537     * fact a wake GPE
538     */
539    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
540    if (!GpeEventInfo)
541    {
542        Status = AE_BAD_PARAMETER;
543        goto UnlockAndExit;
544    }
545
546    if (!(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE))
547    {
548        Status = AE_TYPE;
549        goto UnlockAndExit;
550    }
551
552    GpeRegisterInfo = GpeEventInfo->RegisterInfo;
553    if (!GpeRegisterInfo)
554    {
555        Status = AE_NOT_EXIST;
556        goto UnlockAndExit;
557    }
558
559    RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo);
560
561    /* Perform the action */
562
563    switch (Action)
564    {
565    case ACPI_GPE_ENABLE:
566
567        ACPI_SET_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit);
568        break;
569
570    case ACPI_GPE_DISABLE:
571
572        ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit);
573        break;
574
575    default:
576
577        ACPI_ERROR ((AE_INFO, "%u, Invalid action", Action));
578        Status = AE_BAD_PARAMETER;
579        break;
580    }
581
582UnlockAndExit:
583    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
584    return_ACPI_STATUS (Status);
585}
586
587ACPI_EXPORT_SYMBOL (AcpiSetGpeWakeMask)
588
589
590/*******************************************************************************
591 *
592 * FUNCTION:    AcpiClearGpe
593 *
594 * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
595 *              GpeNumber           - GPE level within the GPE block
596 *
597 * RETURN:      Status
598 *
599 * DESCRIPTION: Clear an ACPI event (general purpose)
600 *
601 ******************************************************************************/
602
603ACPI_STATUS
604AcpiClearGpe (
605    ACPI_HANDLE             GpeDevice,
606    UINT32                  GpeNumber)
607{
608    ACPI_STATUS             Status = AE_OK;
609    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
610    ACPI_CPU_FLAGS          Flags;
611
612
613    ACPI_FUNCTION_TRACE (AcpiClearGpe);
614
615
616    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
617
618    /* Ensure that we have a valid GPE number */
619
620    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
621    if (!GpeEventInfo)
622    {
623        Status = AE_BAD_PARAMETER;
624        goto UnlockAndExit;
625    }
626
627    Status = AcpiHwClearGpe (GpeEventInfo);
628
629UnlockAndExit:
630    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
631    return_ACPI_STATUS (Status);
632}
633
634ACPI_EXPORT_SYMBOL (AcpiClearGpe)
635
636
637/*******************************************************************************
638 *
639 * FUNCTION:    AcpiGetGpeStatus
640 *
641 * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
642 *              GpeNumber           - GPE level within the GPE block
643 *              EventStatus         - Where the current status of the event
644 *                                    will be returned
645 *
646 * RETURN:      Status
647 *
648 * DESCRIPTION: Get the current status of a GPE (signalled/not_signalled)
649 *
650 ******************************************************************************/
651
652ACPI_STATUS
653AcpiGetGpeStatus (
654    ACPI_HANDLE             GpeDevice,
655    UINT32                  GpeNumber,
656    ACPI_EVENT_STATUS       *EventStatus)
657{
658    ACPI_STATUS             Status = AE_OK;
659    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
660    ACPI_CPU_FLAGS          Flags;
661
662
663    ACPI_FUNCTION_TRACE (AcpiGetGpeStatus);
664
665
666    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
667
668    /* Ensure that we have a valid GPE number */
669
670    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
671    if (!GpeEventInfo)
672    {
673        Status = AE_BAD_PARAMETER;
674        goto UnlockAndExit;
675    }
676
677    /* Obtain status on the requested GPE number */
678
679    Status = AcpiHwGetGpeStatus (GpeEventInfo, EventStatus);
680
681UnlockAndExit:
682    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
683    return_ACPI_STATUS (Status);
684}
685
686ACPI_EXPORT_SYMBOL (AcpiGetGpeStatus)
687
688
689/*******************************************************************************
690 *
691 * FUNCTION:    AcpiFinishGpe
692 *
693 * PARAMETERS:  GpeDevice           - Namespace node for the GPE Block
694 *                                    (NULL for FADT defined GPEs)
695 *              GpeNumber           - GPE level within the GPE block
696 *
697 * RETURN:      Status
698 *
699 * DESCRIPTION: Clear and conditionally reenable a GPE. This completes the GPE
700 *              processing. Intended for use by asynchronous host-installed
701 *              GPE handlers. The GPE is only reenabled if the EnableForRun bit
702 *              is set in the GPE info.
703 *
704 ******************************************************************************/
705
706ACPI_STATUS
707AcpiFinishGpe (
708    ACPI_HANDLE             GpeDevice,
709    UINT32                  GpeNumber)
710{
711    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
712    ACPI_STATUS             Status;
713    ACPI_CPU_FLAGS          Flags;
714
715
716    ACPI_FUNCTION_TRACE (AcpiFinishGpe);
717
718
719    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
720
721    /* Ensure that we have a valid GPE number */
722
723    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
724    if (!GpeEventInfo)
725    {
726        Status = AE_BAD_PARAMETER;
727        goto UnlockAndExit;
728    }
729
730    Status = AcpiEvFinishGpe (GpeEventInfo);
731
732UnlockAndExit:
733    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
734    return_ACPI_STATUS (Status);
735}
736
737ACPI_EXPORT_SYMBOL (AcpiFinishGpe)
738
739
740/******************************************************************************
741 *
742 * FUNCTION:    AcpiDisableAllGpes
743 *
744 * PARAMETERS:  None
745 *
746 * RETURN:      Status
747 *
748 * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
749 *
750 ******************************************************************************/
751
752ACPI_STATUS
753AcpiDisableAllGpes (
754    void)
755{
756    ACPI_STATUS             Status;
757
758
759    ACPI_FUNCTION_TRACE (AcpiDisableAllGpes);
760
761
762    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
763    if (ACPI_FAILURE (Status))
764    {
765        return_ACPI_STATUS (Status);
766    }
767
768    Status = AcpiHwDisableAllGpes ();
769    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
770
771    return_ACPI_STATUS (Status);
772}
773
774ACPI_EXPORT_SYMBOL (AcpiDisableAllGpes)
775
776
777/******************************************************************************
778 *
779 * FUNCTION:    AcpiEnableAllRuntimeGpes
780 *
781 * PARAMETERS:  None
782 *
783 * RETURN:      Status
784 *
785 * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
786 *
787 ******************************************************************************/
788
789ACPI_STATUS
790AcpiEnableAllRuntimeGpes (
791    void)
792{
793    ACPI_STATUS             Status;
794
795
796    ACPI_FUNCTION_TRACE (AcpiEnableAllRuntimeGpes);
797
798
799    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
800    if (ACPI_FAILURE (Status))
801    {
802        return_ACPI_STATUS (Status);
803    }
804
805    Status = AcpiHwEnableAllRuntimeGpes ();
806    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
807
808    return_ACPI_STATUS (Status);
809}
810
811ACPI_EXPORT_SYMBOL (AcpiEnableAllRuntimeGpes)
812
813
814/******************************************************************************
815 *
816 * FUNCTION:    AcpiEnableAllWakeupGpes
817 *
818 * PARAMETERS:  None
819 *
820 * RETURN:      Status
821 *
822 * DESCRIPTION: Enable all "wakeup" GPEs and disable all of the other GPEs, in
823 *              all GPE blocks.
824 *
825 ******************************************************************************/
826
827ACPI_STATUS
828AcpiEnableAllWakeupGpes (
829    void)
830{
831    ACPI_STATUS             Status;
832
833
834    ACPI_FUNCTION_TRACE (AcpiEnableAllWakeupGpes);
835
836
837    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
838    if (ACPI_FAILURE (Status))
839    {
840        return_ACPI_STATUS (Status);
841    }
842
843    Status = AcpiHwEnableAllWakeupGpes ();
844    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
845
846    return_ACPI_STATUS (Status);
847}
848
849ACPI_EXPORT_SYMBOL (AcpiEnableAllWakeupGpes)
850
851
852/*******************************************************************************
853 *
854 * FUNCTION:    AcpiInstallGpeBlock
855 *
856 * PARAMETERS:  GpeDevice           - Handle to the parent GPE Block Device
857 *              GpeBlockAddress     - Address and SpaceID
858 *              RegisterCount       - Number of GPE register pairs in the block
859 *              InterruptNumber     - H/W interrupt for the block
860 *
861 * RETURN:      Status
862 *
863 * DESCRIPTION: Create and Install a block of GPE registers. The GPEs are not
864 *              enabled here.
865 *
866 ******************************************************************************/
867
868ACPI_STATUS
869AcpiInstallGpeBlock (
870    ACPI_HANDLE             GpeDevice,
871    ACPI_GENERIC_ADDRESS    *GpeBlockAddress,
872    UINT32                  RegisterCount,
873    UINT32                  InterruptNumber)
874{
875    ACPI_STATUS             Status;
876    ACPI_OPERAND_OBJECT     *ObjDesc;
877    ACPI_NAMESPACE_NODE     *Node;
878    ACPI_GPE_BLOCK_INFO     *GpeBlock;
879
880
881    ACPI_FUNCTION_TRACE (AcpiInstallGpeBlock);
882
883
884    if ((!GpeDevice)       ||
885        (!GpeBlockAddress) ||
886        (!RegisterCount))
887    {
888        return_ACPI_STATUS (AE_BAD_PARAMETER);
889    }
890
891    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
892    if (ACPI_FAILURE (Status))
893    {
894        return_ACPI_STATUS (Status);
895    }
896
897    Node = AcpiNsValidateHandle (GpeDevice);
898    if (!Node)
899    {
900        Status = AE_BAD_PARAMETER;
901        goto UnlockAndExit;
902    }
903
904    /* Validate the parent device */
905
906    if (Node->Type != ACPI_TYPE_DEVICE)
907    {
908        Status = AE_TYPE;
909        goto UnlockAndExit;
910    }
911
912    if (Node->Object)
913    {
914        Status = AE_ALREADY_EXISTS;
915        goto UnlockAndExit;
916    }
917
918    /*
919     * For user-installed GPE Block Devices, the GpeBlockBaseNumber
920     * is always zero
921     */
922    Status = AcpiEvCreateGpeBlock (Node, GpeBlockAddress->Address,
923        GpeBlockAddress->SpaceId, RegisterCount,
924        0, InterruptNumber, &GpeBlock);
925    if (ACPI_FAILURE (Status))
926    {
927        goto UnlockAndExit;
928    }
929
930    /* Install block in the DeviceObject attached to the node */
931
932    ObjDesc = AcpiNsGetAttachedObject (Node);
933    if (!ObjDesc)
934    {
935        /*
936         * No object, create a new one (Device nodes do not always have
937         * an attached object)
938         */
939        ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_DEVICE);
940        if (!ObjDesc)
941        {
942            Status = AE_NO_MEMORY;
943            goto UnlockAndExit;
944        }
945
946        Status = AcpiNsAttachObject (Node, ObjDesc, ACPI_TYPE_DEVICE);
947
948        /* Remove local reference to the object */
949
950        AcpiUtRemoveReference (ObjDesc);
951        if (ACPI_FAILURE (Status))
952        {
953            goto UnlockAndExit;
954        }
955    }
956
957    /* Now install the GPE block in the DeviceObject */
958
959    ObjDesc->Device.GpeBlock = GpeBlock;
960
961
962UnlockAndExit:
963    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
964    return_ACPI_STATUS (Status);
965}
966
967ACPI_EXPORT_SYMBOL (AcpiInstallGpeBlock)
968
969
970/*******************************************************************************
971 *
972 * FUNCTION:    AcpiRemoveGpeBlock
973 *
974 * PARAMETERS:  GpeDevice           - Handle to the parent GPE Block Device
975 *
976 * RETURN:      Status
977 *
978 * DESCRIPTION: Remove a previously installed block of GPE registers
979 *
980 ******************************************************************************/
981
982ACPI_STATUS
983AcpiRemoveGpeBlock (
984    ACPI_HANDLE             GpeDevice)
985{
986    ACPI_OPERAND_OBJECT     *ObjDesc;
987    ACPI_STATUS             Status;
988    ACPI_NAMESPACE_NODE     *Node;
989
990
991    ACPI_FUNCTION_TRACE (AcpiRemoveGpeBlock);
992
993
994    if (!GpeDevice)
995    {
996        return_ACPI_STATUS (AE_BAD_PARAMETER);
997    }
998
999    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
1000    if (ACPI_FAILURE (Status))
1001    {
1002        return_ACPI_STATUS (Status);
1003    }
1004
1005    Node = AcpiNsValidateHandle (GpeDevice);
1006    if (!Node)
1007    {
1008        Status = AE_BAD_PARAMETER;
1009        goto UnlockAndExit;
1010    }
1011
1012    /* Validate the parent device */
1013
1014    if (Node->Type != ACPI_TYPE_DEVICE)
1015    {
1016        Status = AE_TYPE;
1017        goto UnlockAndExit;
1018    }
1019
1020    /* Get the DeviceObject attached to the node */
1021
1022    ObjDesc = AcpiNsGetAttachedObject (Node);
1023    if (!ObjDesc ||
1024        !ObjDesc->Device.GpeBlock)
1025    {
1026        return_ACPI_STATUS (AE_NULL_OBJECT);
1027    }
1028
1029    /* Delete the GPE block (but not the DeviceObject) */
1030
1031    Status = AcpiEvDeleteGpeBlock (ObjDesc->Device.GpeBlock);
1032    if (ACPI_SUCCESS (Status))
1033    {
1034        ObjDesc->Device.GpeBlock = NULL;
1035    }
1036
1037UnlockAndExit:
1038    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
1039    return_ACPI_STATUS (Status);
1040}
1041
1042ACPI_EXPORT_SYMBOL (AcpiRemoveGpeBlock)
1043
1044
1045/*******************************************************************************
1046 *
1047 * FUNCTION:    AcpiGetGpeDevice
1048 *
1049 * PARAMETERS:  Index               - System GPE index (0-CurrentGpeCount)
1050 *              GpeDevice           - Where the parent GPE Device is returned
1051 *
1052 * RETURN:      Status
1053 *
1054 * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL
1055 *              gpe device indicates that the gpe number is contained in one of
1056 *              the FADT-defined gpe blocks. Otherwise, the GPE block device.
1057 *
1058 ******************************************************************************/
1059
1060ACPI_STATUS
1061AcpiGetGpeDevice (
1062    UINT32                  Index,
1063    ACPI_HANDLE             *GpeDevice)
1064{
1065    ACPI_GPE_DEVICE_INFO    Info;
1066    ACPI_STATUS             Status;
1067
1068
1069    ACPI_FUNCTION_TRACE (AcpiGetGpeDevice);
1070
1071
1072    if (!GpeDevice)
1073    {
1074        return_ACPI_STATUS (AE_BAD_PARAMETER);
1075    }
1076
1077    if (Index >= AcpiCurrentGpeCount)
1078    {
1079        return_ACPI_STATUS (AE_NOT_EXIST);
1080    }
1081
1082    /* Setup and walk the GPE list */
1083
1084    Info.Index = Index;
1085    Info.Status = AE_NOT_EXIST;
1086    Info.GpeDevice = NULL;
1087    Info.NextBlockBaseIndex = 0;
1088
1089    Status = AcpiEvWalkGpeList (AcpiEvGetGpeDevice, &Info);
1090    if (ACPI_FAILURE (Status))
1091    {
1092        return_ACPI_STATUS (Status);
1093    }
1094
1095    *GpeDevice = ACPI_CAST_PTR (ACPI_HANDLE, Info.GpeDevice);
1096    return_ACPI_STATUS (Info.Status);
1097}
1098
1099ACPI_EXPORT_SYMBOL (AcpiGetGpeDevice)
1100
1101#endif /* !ACPI_REDUCED_HARDWARE */
1102