1216331Sjkim/******************************************************************************
2216331Sjkim *
3216331Sjkim * Module Name: evxfgpe - External Interfaces for General Purpose Events (GPEs)
4216331Sjkim *
5216331Sjkim *****************************************************************************/
6216331Sjkim
7217365Sjkim/*
8298714Sjkim * Copyright (C) 2000 - 2016, Intel Corp.
9216331Sjkim * All rights reserved.
10216331Sjkim *
11217365Sjkim * Redistribution and use in source and binary forms, with or without
12217365Sjkim * modification, are permitted provided that the following conditions
13217365Sjkim * are met:
14217365Sjkim * 1. Redistributions of source code must retain the above copyright
15217365Sjkim *    notice, this list of conditions, and the following disclaimer,
16217365Sjkim *    without modification.
17217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18217365Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
19217365Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
20217365Sjkim *    including a substantially similar Disclaimer requirement for further
21217365Sjkim *    binary redistribution.
22217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
23217365Sjkim *    of any contributors may be used to endorse or promote products derived
24217365Sjkim *    from this software without specific prior written permission.
25216331Sjkim *
26217365Sjkim * Alternatively, this software may be distributed under the terms of the
27217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
28217365Sjkim * Software Foundation.
29216331Sjkim *
30217365Sjkim * NO WARRANTY
31217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41217365Sjkim * POSSIBILITY OF SUCH DAMAGES.
42217365Sjkim */
43216331Sjkim
44272444Sjkim#define EXPORT_ACPI_INTERFACES
45216331Sjkim
46216471Sjkim#include <contrib/dev/acpica/include/acpi.h>
47216471Sjkim#include <contrib/dev/acpica/include/accommon.h>
48216471Sjkim#include <contrib/dev/acpica/include/acevents.h>
49216471Sjkim#include <contrib/dev/acpica/include/acnamesp.h>
50216331Sjkim
51216331Sjkim#define _COMPONENT          ACPI_EVENTS
52216331Sjkim        ACPI_MODULE_NAME    ("evxfgpe")
53216331Sjkim
54216331Sjkim
55231844Sjkim#if (!ACPI_REDUCED_HARDWARE) /* Entire module */
56216331Sjkim/*******************************************************************************
57216331Sjkim *
58216331Sjkim * FUNCTION:    AcpiUpdateAllGpes
59216331Sjkim *
60216331Sjkim * PARAMETERS:  None
61216331Sjkim *
62216331Sjkim * RETURN:      Status
63216331Sjkim *
64216331Sjkim * DESCRIPTION: Complete GPE initialization and enable all GPEs that have
65216331Sjkim *              associated _Lxx or _Exx methods and are not pointed to by any
66216331Sjkim *              device _PRW methods (this indicates that these GPEs are
67216331Sjkim *              generally intended for system or device wakeup. Such GPEs
68216331Sjkim *              have to be enabled directly when the devices whose _PRW
69216331Sjkim *              methods point to them are set up for wakeup signaling.)
70216331Sjkim *
71216331Sjkim * NOTE: Should be called after any GPEs are added to the system. Primarily,
72216331Sjkim * after the system _PRW methods have been run, but also after a GPE Block
73216331Sjkim * Device has been added or if any new GPE methods have been added via a
74216331Sjkim * dynamic table load.
75216331Sjkim *
76216331Sjkim ******************************************************************************/
77216331Sjkim
78216331SjkimACPI_STATUS
79216331SjkimAcpiUpdateAllGpes (
80216331Sjkim    void)
81216331Sjkim{
82216331Sjkim    ACPI_STATUS             Status;
83216331Sjkim
84216331Sjkim
85238381Sjkim    ACPI_FUNCTION_TRACE (AcpiUpdateAllGpes);
86216331Sjkim
87216331Sjkim
88216331Sjkim    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
89216331Sjkim    if (ACPI_FAILURE (Status))
90216331Sjkim    {
91216331Sjkim        return_ACPI_STATUS (Status);
92216331Sjkim    }
93216331Sjkim
94216331Sjkim    if (AcpiGbl_AllGpesInitialized)
95216331Sjkim    {
96216331Sjkim        goto UnlockAndExit;
97216331Sjkim    }
98216331Sjkim
99216331Sjkim    Status = AcpiEvWalkGpeList (AcpiEvInitializeGpeBlock, NULL);
100216331Sjkim    if (ACPI_SUCCESS (Status))
101216331Sjkim    {
102216331Sjkim        AcpiGbl_AllGpesInitialized = TRUE;
103216331Sjkim    }
104216331Sjkim
105216331SjkimUnlockAndExit:
106216331Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
107216331Sjkim    return_ACPI_STATUS (Status);
108216331Sjkim}
109216331Sjkim
110216331SjkimACPI_EXPORT_SYMBOL (AcpiUpdateAllGpes)
111216331Sjkim
112216331Sjkim
113216331Sjkim/*******************************************************************************
114216331Sjkim *
115216331Sjkim * FUNCTION:    AcpiEnableGpe
116216331Sjkim *
117216331Sjkim * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
118216331Sjkim *              GpeNumber           - GPE level within the GPE block
119216331Sjkim *
120216331Sjkim * RETURN:      Status
121216331Sjkim *
122216331Sjkim * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is
123216331Sjkim *              hardware-enabled.
124216331Sjkim *
125216331Sjkim ******************************************************************************/
126216331Sjkim
127216331SjkimACPI_STATUS
128216331SjkimAcpiEnableGpe (
129216331Sjkim    ACPI_HANDLE             GpeDevice,
130216331Sjkim    UINT32                  GpeNumber)
131216331Sjkim{
132216331Sjkim    ACPI_STATUS             Status = AE_BAD_PARAMETER;
133216331Sjkim    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
134216331Sjkim    ACPI_CPU_FLAGS          Flags;
135216331Sjkim
136216331Sjkim
137216331Sjkim    ACPI_FUNCTION_TRACE (AcpiEnableGpe);
138216331Sjkim
139216331Sjkim
140216331Sjkim    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
141216331Sjkim
142272444Sjkim    /*
143272444Sjkim     * Ensure that we have a valid GPE number and that there is some way
144272444Sjkim     * of handling the GPE (handler or a GPE method). In other words, we
145272444Sjkim     * won't allow a valid GPE to be enabled if there is no way to handle it.
146272444Sjkim     */
147216331Sjkim    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
148216331Sjkim    if (GpeEventInfo)
149216331Sjkim    {
150278970Sjkim        if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) !=
151272444Sjkim            ACPI_GPE_DISPATCH_NONE)
152272444Sjkim        {
153272444Sjkim            Status = AcpiEvAddGpeReference (GpeEventInfo);
154272444Sjkim        }
155272444Sjkim        else
156272444Sjkim        {
157272444Sjkim            Status = AE_NO_HANDLER;
158272444Sjkim        }
159216331Sjkim    }
160216331Sjkim
161216331Sjkim    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
162216331Sjkim    return_ACPI_STATUS (Status);
163216331Sjkim}
164216331Sjkim
165216331SjkimACPI_EXPORT_SYMBOL (AcpiEnableGpe)
166216331Sjkim
167216331Sjkim
168216331Sjkim/*******************************************************************************
169216331Sjkim *
170216331Sjkim * FUNCTION:    AcpiDisableGpe
171216331Sjkim *
172216331Sjkim * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
173216331Sjkim *              GpeNumber           - GPE level within the GPE block
174216331Sjkim *
175216331Sjkim * RETURN:      Status
176216331Sjkim *
177216331Sjkim * DESCRIPTION: Remove a reference to a GPE. When the last reference is
178216331Sjkim *              removed, only then is the GPE disabled (for runtime GPEs), or
179216331Sjkim *              the GPE mask bit disabled (for wake GPEs)
180216331Sjkim *
181216331Sjkim ******************************************************************************/
182216331Sjkim
183216331SjkimACPI_STATUS
184216331SjkimAcpiDisableGpe (
185216331Sjkim    ACPI_HANDLE             GpeDevice,
186216331Sjkim    UINT32                  GpeNumber)
187216331Sjkim{
188216331Sjkim    ACPI_STATUS             Status = AE_BAD_PARAMETER;
189216331Sjkim    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
190216331Sjkim    ACPI_CPU_FLAGS          Flags;
191216331Sjkim
192216331Sjkim
193216331Sjkim    ACPI_FUNCTION_TRACE (AcpiDisableGpe);
194216331Sjkim
195216331Sjkim
196216331Sjkim    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
197216331Sjkim
198216331Sjkim    /* Ensure that we have a valid GPE number */
199216331Sjkim
200216331Sjkim    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
201216331Sjkim    if (GpeEventInfo)
202216331Sjkim    {
203216331Sjkim        Status = AcpiEvRemoveGpeReference (GpeEventInfo);
204216331Sjkim    }
205216331Sjkim
206216331Sjkim    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
207216331Sjkim    return_ACPI_STATUS (Status);
208216331Sjkim}
209216331Sjkim
210216331SjkimACPI_EXPORT_SYMBOL (AcpiDisableGpe)
211216331Sjkim
212216331Sjkim
213216331Sjkim/*******************************************************************************
214216331Sjkim *
215216331Sjkim * FUNCTION:    AcpiSetGpe
216216331Sjkim *
217216331Sjkim * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
218216331Sjkim *              GpeNumber           - GPE level within the GPE block
219216331Sjkim *              Action              - ACPI_GPE_ENABLE or ACPI_GPE_DISABLE
220216331Sjkim *
221216331Sjkim * RETURN:      Status
222216331Sjkim *
223216331Sjkim * DESCRIPTION: Enable or disable an individual GPE. This function bypasses
224278970Sjkim *              the reference count mechanism used in the AcpiEnableGpe(),
225278970Sjkim *              AcpiDisableGpe() interfaces.
226278970Sjkim *              This API is typically used by the GPE raw handler mode driver
227278970Sjkim *              to switch between the polling mode and the interrupt mode after
228278970Sjkim *              the driver has enabled the GPE.
229278970Sjkim *              The APIs should be invoked in this order:
230278970Sjkim *               AcpiEnableGpe()              <- Ensure the reference count > 0
231278970Sjkim *               AcpiSetGpe(ACPI_GPE_DISABLE) <- Enter polling mode
232278970Sjkim *               AcpiSetGpe(ACPI_GPE_ENABLE)  <- Leave polling mode
233278970Sjkim *               AcpiDisableGpe()             <- Decrease the reference count
234216331Sjkim *
235278970Sjkim * Note: If a GPE is shared by 2 silicon components, then both the drivers
236278970Sjkim *       should support GPE polling mode or disabling the GPE for long period
237278970Sjkim *       for one driver may break the other. So use it with care since all
238278970Sjkim *       firmware _Lxx/_Exx handlers currently rely on the GPE interrupt mode.
239216331Sjkim *
240216331Sjkim ******************************************************************************/
241216331Sjkim
242216331SjkimACPI_STATUS
243216331SjkimAcpiSetGpe (
244216331Sjkim    ACPI_HANDLE             GpeDevice,
245216331Sjkim    UINT32                  GpeNumber,
246216331Sjkim    UINT8                   Action)
247216331Sjkim{
248216331Sjkim    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
249216331Sjkim    ACPI_STATUS             Status;
250216331Sjkim    ACPI_CPU_FLAGS          Flags;
251216331Sjkim
252216331Sjkim
253216331Sjkim    ACPI_FUNCTION_TRACE (AcpiSetGpe);
254216331Sjkim
255216331Sjkim
256216331Sjkim    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
257216331Sjkim
258216331Sjkim    /* Ensure that we have a valid GPE number */
259216331Sjkim
260216331Sjkim    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
261216331Sjkim    if (!GpeEventInfo)
262216331Sjkim    {
263216331Sjkim        Status = AE_BAD_PARAMETER;
264216331Sjkim        goto UnlockAndExit;
265216331Sjkim    }
266216331Sjkim
267216331Sjkim    /* Perform the action */
268216331Sjkim
269216331Sjkim    switch (Action)
270216331Sjkim    {
271216331Sjkim    case ACPI_GPE_ENABLE:
272250838Sjkim
273278970Sjkim        Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_ENABLE);
274216331Sjkim        break;
275216331Sjkim
276216331Sjkim    case ACPI_GPE_DISABLE:
277250838Sjkim
278216331Sjkim        Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE);
279216331Sjkim        break;
280216331Sjkim
281216331Sjkim    default:
282250838Sjkim
283216331Sjkim        Status = AE_BAD_PARAMETER;
284216331Sjkim        break;
285216331Sjkim    }
286216331Sjkim
287216331SjkimUnlockAndExit:
288216331Sjkim    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
289216331Sjkim    return_ACPI_STATUS (Status);
290216331Sjkim}
291216331Sjkim
292216331SjkimACPI_EXPORT_SYMBOL (AcpiSetGpe)
293216331Sjkim
294216331Sjkim
295216331Sjkim/*******************************************************************************
296216331Sjkim *
297272444Sjkim * FUNCTION:    AcpiMarkGpeForWake
298272444Sjkim *
299272444Sjkim * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
300272444Sjkim *              GpeNumber           - GPE level within the GPE block
301272444Sjkim *
302272444Sjkim * RETURN:      Status
303272444Sjkim *
304272444Sjkim * DESCRIPTION: Mark a GPE as having the ability to wake the system. Simply
305272444Sjkim *              sets the ACPI_GPE_CAN_WAKE flag.
306272444Sjkim *
307272444Sjkim * Some potential callers of AcpiSetupGpeForWake may know in advance that
308272444Sjkim * there won't be any notify handlers installed for device wake notifications
309272444Sjkim * from the given GPE (one example is a button GPE in Linux). For these cases,
310272444Sjkim * AcpiMarkGpeForWake should be used instead of AcpiSetupGpeForWake.
311272444Sjkim * This will set the ACPI_GPE_CAN_WAKE flag for the GPE without trying to
312272444Sjkim * setup implicit wake notification for it (since there's no handler method).
313272444Sjkim *
314272444Sjkim ******************************************************************************/
315272444Sjkim
316272444SjkimACPI_STATUS
317272444SjkimAcpiMarkGpeForWake (
318272444Sjkim    ACPI_HANDLE             GpeDevice,
319272444Sjkim    UINT32                  GpeNumber)
320272444Sjkim{
321272444Sjkim    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
322272444Sjkim    ACPI_STATUS             Status = AE_BAD_PARAMETER;
323272444Sjkim    ACPI_CPU_FLAGS          Flags;
324272444Sjkim
325272444Sjkim
326272444Sjkim    ACPI_FUNCTION_TRACE (AcpiMarkGpeForWake);
327272444Sjkim
328272444Sjkim
329272444Sjkim    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
330272444Sjkim
331272444Sjkim    /* Ensure that we have a valid GPE number */
332272444Sjkim
333272444Sjkim    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
334272444Sjkim    if (GpeEventInfo)
335272444Sjkim    {
336272444Sjkim        /* Mark the GPE as a possible wake event */
337272444Sjkim
338272444Sjkim        GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE;
339272444Sjkim        Status = AE_OK;
340272444Sjkim    }
341272444Sjkim
342272444Sjkim    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
343272444Sjkim    return_ACPI_STATUS (Status);
344272444Sjkim}
345272444Sjkim
346272444SjkimACPI_EXPORT_SYMBOL (AcpiMarkGpeForWake)
347272444Sjkim
348272444Sjkim
349272444Sjkim/*******************************************************************************
350272444Sjkim *
351216331Sjkim * FUNCTION:    AcpiSetupGpeForWake
352216331Sjkim *
353216331Sjkim * PARAMETERS:  WakeDevice          - Device associated with the GPE (via _PRW)
354216331Sjkim *              GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
355216331Sjkim *              GpeNumber           - GPE level within the GPE block
356216331Sjkim *
357216331Sjkim * RETURN:      Status
358216331Sjkim *
359216331Sjkim * DESCRIPTION: Mark a GPE as having the ability to wake the system. This
360216331Sjkim *              interface is intended to be used as the host executes the
361216331Sjkim *              _PRW methods (Power Resources for Wake) in the system tables.
362216331Sjkim *              Each _PRW appears under a Device Object (The WakeDevice), and
363216331Sjkim *              contains the info for the wake GPE associated with the
364216331Sjkim *              WakeDevice.
365216331Sjkim *
366216331Sjkim ******************************************************************************/
367216331Sjkim
368216331SjkimACPI_STATUS
369216331SjkimAcpiSetupGpeForWake (
370216331Sjkim    ACPI_HANDLE             WakeDevice,
371216331Sjkim    ACPI_HANDLE             GpeDevice,
372216331Sjkim    UINT32                  GpeNumber)
373216331Sjkim{
374237412Sjkim    ACPI_STATUS             Status;
375216331Sjkim    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
376216331Sjkim    ACPI_NAMESPACE_NODE     *DeviceNode;
377238381Sjkim    ACPI_GPE_NOTIFY_INFO    *Notify;
378238381Sjkim    ACPI_GPE_NOTIFY_INFO    *NewNotify;
379216331Sjkim    ACPI_CPU_FLAGS          Flags;
380216331Sjkim
381216331Sjkim
382216331Sjkim    ACPI_FUNCTION_TRACE (AcpiSetupGpeForWake);
383216331Sjkim
384216331Sjkim
385216331Sjkim    /* Parameter Validation */
386216331Sjkim
387216331Sjkim    if (!WakeDevice)
388216331Sjkim    {
389216331Sjkim        /*
390216331Sjkim         * By forcing WakeDevice to be valid, we automatically enable the
391216331Sjkim         * implicit notify feature on all hosts.
392216331Sjkim         */
393216331Sjkim        return_ACPI_STATUS (AE_BAD_PARAMETER);
394216331Sjkim    }
395216331Sjkim
396219707Sjkim    /* Handle root object case */
397219707Sjkim
398219707Sjkim    if (WakeDevice == ACPI_ROOT_OBJECT)
399219707Sjkim    {
400219707Sjkim        DeviceNode = AcpiGbl_RootNode;
401219707Sjkim    }
402219707Sjkim    else
403219707Sjkim    {
404219707Sjkim        DeviceNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, WakeDevice);
405219707Sjkim    }
406219707Sjkim
407216331Sjkim    /* Validate WakeDevice is of type Device */
408216331Sjkim
409216331Sjkim    if (DeviceNode->Type != ACPI_TYPE_DEVICE)
410216331Sjkim    {
411216331Sjkim        return_ACPI_STATUS (AE_BAD_PARAMETER);
412216331Sjkim    }
413216331Sjkim
414238381Sjkim    /*
415238381Sjkim     * Allocate a new notify object up front, in case it is needed.
416238381Sjkim     * Memory allocation while holding a spinlock is a big no-no
417238381Sjkim     * on some hosts.
418238381Sjkim     */
419237652Sjkim    NewNotify = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_NOTIFY_INFO));
420237652Sjkim    if (!NewNotify)
421237652Sjkim    {
422237652Sjkim        return_ACPI_STATUS (AE_NO_MEMORY);
423237652Sjkim    }
424237652Sjkim
425216331Sjkim    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
426216331Sjkim
427216331Sjkim    /* Ensure that we have a valid GPE number */
428216331Sjkim
429216331Sjkim    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
430237412Sjkim    if (!GpeEventInfo)
431216331Sjkim    {
432237412Sjkim        Status = AE_BAD_PARAMETER;
433237412Sjkim        goto UnlockAndExit;
434237412Sjkim    }
435237412Sjkim
436237412Sjkim    /*
437237412Sjkim     * If there is no method or handler for this GPE, then the
438237412Sjkim     * WakeDevice will be notified whenever this GPE fires. This is
439237412Sjkim     * known as an "implicit notify". Note: The GPE is assumed to be
440237412Sjkim     * level-triggered (for windows compatibility).
441237412Sjkim     */
442278970Sjkim    if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) ==
443298714Sjkim        ACPI_GPE_DISPATCH_NONE)
444237412Sjkim    {
445216331Sjkim        /*
446237412Sjkim         * This is the first device for implicit notify on this GPE.
447237412Sjkim         * Just set the flags here, and enter the NOTIFY block below.
448216331Sjkim         */
449237412Sjkim        GpeEventInfo->Flags =
450237412Sjkim            (ACPI_GPE_DISPATCH_NOTIFY | ACPI_GPE_LEVEL_TRIGGERED);
451237412Sjkim    }
452237412Sjkim
453237412Sjkim    /*
454237412Sjkim     * If we already have an implicit notify on this GPE, add
455237412Sjkim     * this device to the notify list.
456237412Sjkim     */
457278970Sjkim    if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) ==
458298714Sjkim        ACPI_GPE_DISPATCH_NOTIFY)
459237412Sjkim    {
460237412Sjkim        /* Ensure that the device is not already in the list */
461237412Sjkim
462237412Sjkim        Notify = GpeEventInfo->Dispatch.NotifyList;
463237412Sjkim        while (Notify)
464216331Sjkim        {
465237412Sjkim            if (Notify->DeviceNode == DeviceNode)
466237412Sjkim            {
467237412Sjkim                Status = AE_ALREADY_EXISTS;
468237412Sjkim                goto UnlockAndExit;
469237412Sjkim            }
470237412Sjkim            Notify = Notify->Next;
471216331Sjkim        }
472216331Sjkim
473237412Sjkim        /* Add this device to the notify list for this GPE */
474237412Sjkim
475237652Sjkim        NewNotify->DeviceNode = DeviceNode;
476237652Sjkim        NewNotify->Next = GpeEventInfo->Dispatch.NotifyList;
477237652Sjkim        GpeEventInfo->Dispatch.NotifyList = NewNotify;
478237652Sjkim        NewNotify = NULL;
479216331Sjkim    }
480216331Sjkim
481237412Sjkim    /* Mark the GPE as a possible wake event */
482237412Sjkim
483237412Sjkim    GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE;
484237412Sjkim    Status = AE_OK;
485237412Sjkim
486238381Sjkim
487237412SjkimUnlockAndExit:
488216331Sjkim    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
489238381Sjkim
490238381Sjkim    /* Delete the notify object if it was not used above */
491238381Sjkim
492237652Sjkim    if (NewNotify)
493237652Sjkim    {
494237652Sjkim        ACPI_FREE (NewNotify);
495237652Sjkim    }
496216331Sjkim    return_ACPI_STATUS (Status);
497216331Sjkim}
498216331Sjkim
499216331SjkimACPI_EXPORT_SYMBOL (AcpiSetupGpeForWake)
500216331Sjkim
501216331Sjkim
502216331Sjkim/*******************************************************************************
503216331Sjkim *
504216331Sjkim * FUNCTION:    AcpiSetGpeWakeMask
505216331Sjkim *
506216331Sjkim * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
507216331Sjkim *              GpeNumber           - GPE level within the GPE block
508216331Sjkim *              Action              - Enable or Disable
509216331Sjkim *
510216331Sjkim * RETURN:      Status
511216331Sjkim *
512216331Sjkim * DESCRIPTION: Set or clear the GPE's wakeup enable mask bit. The GPE must
513216331Sjkim *              already be marked as a WAKE GPE.
514216331Sjkim *
515216331Sjkim ******************************************************************************/
516216331Sjkim
517216331SjkimACPI_STATUS
518216331SjkimAcpiSetGpeWakeMask (
519216331Sjkim    ACPI_HANDLE             GpeDevice,
520216331Sjkim    UINT32                  GpeNumber,
521216331Sjkim    UINT8                   Action)
522216331Sjkim{
523216331Sjkim    ACPI_STATUS             Status = AE_OK;
524216331Sjkim    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
525216331Sjkim    ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
526216331Sjkim    ACPI_CPU_FLAGS          Flags;
527216331Sjkim    UINT32                  RegisterBit;
528216331Sjkim
529216331Sjkim
530216331Sjkim    ACPI_FUNCTION_TRACE (AcpiSetGpeWakeMask);
531216331Sjkim
532216331Sjkim
533216331Sjkim    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
534216331Sjkim
535216331Sjkim    /*
536216331Sjkim     * Ensure that we have a valid GPE number and that this GPE is in
537216331Sjkim     * fact a wake GPE
538216331Sjkim     */
539216331Sjkim    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
540216331Sjkim    if (!GpeEventInfo)
541216331Sjkim    {
542216331Sjkim        Status = AE_BAD_PARAMETER;
543216331Sjkim        goto UnlockAndExit;
544216331Sjkim    }
545216331Sjkim
546216331Sjkim    if (!(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE))
547216331Sjkim    {
548216331Sjkim        Status = AE_TYPE;
549216331Sjkim        goto UnlockAndExit;
550216331Sjkim    }
551216331Sjkim
552216331Sjkim    GpeRegisterInfo = GpeEventInfo->RegisterInfo;
553216331Sjkim    if (!GpeRegisterInfo)
554216331Sjkim    {
555216331Sjkim        Status = AE_NOT_EXIST;
556216331Sjkim        goto UnlockAndExit;
557216331Sjkim    }
558216331Sjkim
559239340Sjkim    RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo);
560216331Sjkim
561216331Sjkim    /* Perform the action */
562216331Sjkim
563216331Sjkim    switch (Action)
564216331Sjkim    {
565216331Sjkim    case ACPI_GPE_ENABLE:
566250838Sjkim
567216331Sjkim        ACPI_SET_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit);
568216331Sjkim        break;
569216331Sjkim
570216331Sjkim    case ACPI_GPE_DISABLE:
571250838Sjkim
572216331Sjkim        ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit);
573216331Sjkim        break;
574216331Sjkim
575216331Sjkim    default:
576250838Sjkim
577216331Sjkim        ACPI_ERROR ((AE_INFO, "%u, Invalid action", Action));
578216331Sjkim        Status = AE_BAD_PARAMETER;
579216331Sjkim        break;
580216331Sjkim    }
581216331Sjkim
582216331SjkimUnlockAndExit:
583216331Sjkim    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
584216331Sjkim    return_ACPI_STATUS (Status);
585216331Sjkim}
586216331Sjkim
587216331SjkimACPI_EXPORT_SYMBOL (AcpiSetGpeWakeMask)
588216331Sjkim
589216331Sjkim
590216331Sjkim/*******************************************************************************
591216331Sjkim *
592216331Sjkim * FUNCTION:    AcpiClearGpe
593216331Sjkim *
594216331Sjkim * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
595216331Sjkim *              GpeNumber           - GPE level within the GPE block
596216331Sjkim *
597216331Sjkim * RETURN:      Status
598216331Sjkim *
599216331Sjkim * DESCRIPTION: Clear an ACPI event (general purpose)
600216331Sjkim *
601216331Sjkim ******************************************************************************/
602216331Sjkim
603216331SjkimACPI_STATUS
604216331SjkimAcpiClearGpe (
605216331Sjkim    ACPI_HANDLE             GpeDevice,
606216331Sjkim    UINT32                  GpeNumber)
607216331Sjkim{
608216331Sjkim    ACPI_STATUS             Status = AE_OK;
609216331Sjkim    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
610216331Sjkim    ACPI_CPU_FLAGS          Flags;
611216331Sjkim
612216331Sjkim
613216331Sjkim    ACPI_FUNCTION_TRACE (AcpiClearGpe);
614216331Sjkim
615216331Sjkim
616216331Sjkim    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
617216331Sjkim
618216331Sjkim    /* Ensure that we have a valid GPE number */
619216331Sjkim
620216331Sjkim    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
621216331Sjkim    if (!GpeEventInfo)
622216331Sjkim    {
623216331Sjkim        Status = AE_BAD_PARAMETER;
624216331Sjkim        goto UnlockAndExit;
625216331Sjkim    }
626216331Sjkim
627216331Sjkim    Status = AcpiHwClearGpe (GpeEventInfo);
628216331Sjkim
629216331SjkimUnlockAndExit:
630216331Sjkim    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
631216331Sjkim    return_ACPI_STATUS (Status);
632216331Sjkim}
633216331Sjkim
634216331SjkimACPI_EXPORT_SYMBOL (AcpiClearGpe)
635216331Sjkim
636216331Sjkim
637216331Sjkim/*******************************************************************************
638216331Sjkim *
639216331Sjkim * FUNCTION:    AcpiGetGpeStatus
640216331Sjkim *
641216331Sjkim * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
642216331Sjkim *              GpeNumber           - GPE level within the GPE block
643216331Sjkim *              EventStatus         - Where the current status of the event
644216331Sjkim *                                    will be returned
645216331Sjkim *
646216331Sjkim * RETURN:      Status
647216331Sjkim *
648216331Sjkim * DESCRIPTION: Get the current status of a GPE (signalled/not_signalled)
649216331Sjkim *
650216331Sjkim ******************************************************************************/
651216331Sjkim
652216331SjkimACPI_STATUS
653216331SjkimAcpiGetGpeStatus (
654216331Sjkim    ACPI_HANDLE             GpeDevice,
655216331Sjkim    UINT32                  GpeNumber,
656216331Sjkim    ACPI_EVENT_STATUS       *EventStatus)
657216331Sjkim{
658216331Sjkim    ACPI_STATUS             Status = AE_OK;
659216331Sjkim    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
660216331Sjkim    ACPI_CPU_FLAGS          Flags;
661216331Sjkim
662216331Sjkim
663216331Sjkim    ACPI_FUNCTION_TRACE (AcpiGetGpeStatus);
664216331Sjkim
665216331Sjkim
666216331Sjkim    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
667216331Sjkim
668216331Sjkim    /* Ensure that we have a valid GPE number */
669216331Sjkim
670216331Sjkim    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
671216331Sjkim    if (!GpeEventInfo)
672216331Sjkim    {
673216331Sjkim        Status = AE_BAD_PARAMETER;
674216331Sjkim        goto UnlockAndExit;
675216331Sjkim    }
676216331Sjkim
677216331Sjkim    /* Obtain status on the requested GPE number */
678216331Sjkim
679216331Sjkim    Status = AcpiHwGetGpeStatus (GpeEventInfo, EventStatus);
680216331Sjkim
681216331SjkimUnlockAndExit:
682216331Sjkim    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
683216331Sjkim    return_ACPI_STATUS (Status);
684216331Sjkim}
685216331Sjkim
686216331SjkimACPI_EXPORT_SYMBOL (AcpiGetGpeStatus)
687216331Sjkim
688216331Sjkim
689216331Sjkim/*******************************************************************************
690216331Sjkim *
691216331Sjkim * FUNCTION:    AcpiFinishGpe
692216331Sjkim *
693216331Sjkim * PARAMETERS:  GpeDevice           - Namespace node for the GPE Block
694216331Sjkim *                                    (NULL for FADT defined GPEs)
695216331Sjkim *              GpeNumber           - GPE level within the GPE block
696216331Sjkim *
697216331Sjkim * RETURN:      Status
698216331Sjkim *
699216331Sjkim * DESCRIPTION: Clear and conditionally reenable a GPE. This completes the GPE
700216331Sjkim *              processing. Intended for use by asynchronous host-installed
701216331Sjkim *              GPE handlers. The GPE is only reenabled if the EnableForRun bit
702216331Sjkim *              is set in the GPE info.
703216331Sjkim *
704216331Sjkim ******************************************************************************/
705216331Sjkim
706216331SjkimACPI_STATUS
707216331SjkimAcpiFinishGpe (
708216331Sjkim    ACPI_HANDLE             GpeDevice,
709216331Sjkim    UINT32                  GpeNumber)
710216331Sjkim{
711216331Sjkim    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
712216331Sjkim    ACPI_STATUS             Status;
713216331Sjkim    ACPI_CPU_FLAGS          Flags;
714216331Sjkim
715216331Sjkim
716216331Sjkim    ACPI_FUNCTION_TRACE (AcpiFinishGpe);
717216331Sjkim
718216331Sjkim
719216331Sjkim    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
720216331Sjkim
721216331Sjkim    /* Ensure that we have a valid GPE number */
722216331Sjkim
723216331Sjkim    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
724216331Sjkim    if (!GpeEventInfo)
725216331Sjkim    {
726216331Sjkim        Status = AE_BAD_PARAMETER;
727216331Sjkim        goto UnlockAndExit;
728216331Sjkim    }
729216331Sjkim
730216331Sjkim    Status = AcpiEvFinishGpe (GpeEventInfo);
731216331Sjkim
732216331SjkimUnlockAndExit:
733216331Sjkim    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
734216331Sjkim    return_ACPI_STATUS (Status);
735216331Sjkim}
736216331Sjkim
737216331SjkimACPI_EXPORT_SYMBOL (AcpiFinishGpe)
738216331Sjkim
739216331Sjkim
740216331Sjkim/******************************************************************************
741216331Sjkim *
742216331Sjkim * FUNCTION:    AcpiDisableAllGpes
743216331Sjkim *
744216331Sjkim * PARAMETERS:  None
745216331Sjkim *
746216331Sjkim * RETURN:      Status
747216331Sjkim *
748216331Sjkim * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
749216331Sjkim *
750216331Sjkim ******************************************************************************/
751216331Sjkim
752216331SjkimACPI_STATUS
753216331SjkimAcpiDisableAllGpes (
754216331Sjkim    void)
755216331Sjkim{
756216331Sjkim    ACPI_STATUS             Status;
757216331Sjkim
758216331Sjkim
759216331Sjkim    ACPI_FUNCTION_TRACE (AcpiDisableAllGpes);
760216331Sjkim
761216331Sjkim
762216331Sjkim    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
763216331Sjkim    if (ACPI_FAILURE (Status))
764216331Sjkim    {
765216331Sjkim        return_ACPI_STATUS (Status);
766216331Sjkim    }
767216331Sjkim
768216331Sjkim    Status = AcpiHwDisableAllGpes ();
769216331Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
770216331Sjkim
771216331Sjkim    return_ACPI_STATUS (Status);
772216331Sjkim}
773216331Sjkim
774216331SjkimACPI_EXPORT_SYMBOL (AcpiDisableAllGpes)
775216331Sjkim
776216331Sjkim
777216331Sjkim/******************************************************************************
778216331Sjkim *
779216331Sjkim * FUNCTION:    AcpiEnableAllRuntimeGpes
780216331Sjkim *
781216331Sjkim * PARAMETERS:  None
782216331Sjkim *
783216331Sjkim * RETURN:      Status
784216331Sjkim *
785216331Sjkim * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
786216331Sjkim *
787216331Sjkim ******************************************************************************/
788216331Sjkim
789216331SjkimACPI_STATUS
790216331SjkimAcpiEnableAllRuntimeGpes (
791216331Sjkim    void)
792216331Sjkim{
793216331Sjkim    ACPI_STATUS             Status;
794216331Sjkim
795216331Sjkim
796216331Sjkim    ACPI_FUNCTION_TRACE (AcpiEnableAllRuntimeGpes);
797216331Sjkim
798216331Sjkim
799216331Sjkim    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
800216331Sjkim    if (ACPI_FAILURE (Status))
801216331Sjkim    {
802216331Sjkim        return_ACPI_STATUS (Status);
803216331Sjkim    }
804216331Sjkim
805216331Sjkim    Status = AcpiHwEnableAllRuntimeGpes ();
806216331Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
807216331Sjkim
808216331Sjkim    return_ACPI_STATUS (Status);
809216331Sjkim}
810216331Sjkim
811216331SjkimACPI_EXPORT_SYMBOL (AcpiEnableAllRuntimeGpes)
812216331Sjkim
813216331Sjkim
814278970Sjkim/******************************************************************************
815278970Sjkim *
816278970Sjkim * FUNCTION:    AcpiEnableAllWakeupGpes
817278970Sjkim *
818278970Sjkim * PARAMETERS:  None
819278970Sjkim *
820278970Sjkim * RETURN:      Status
821278970Sjkim *
822278970Sjkim * DESCRIPTION: Enable all "wakeup" GPEs and disable all of the other GPEs, in
823278970Sjkim *              all GPE blocks.
824278970Sjkim *
825278970Sjkim ******************************************************************************/
826278970Sjkim
827278970SjkimACPI_STATUS
828278970SjkimAcpiEnableAllWakeupGpes (
829278970Sjkim    void)
830278970Sjkim{
831278970Sjkim    ACPI_STATUS             Status;
832278970Sjkim
833278970Sjkim
834278970Sjkim    ACPI_FUNCTION_TRACE (AcpiEnableAllWakeupGpes);
835278970Sjkim
836278970Sjkim
837278970Sjkim    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
838278970Sjkim    if (ACPI_FAILURE (Status))
839278970Sjkim    {
840278970Sjkim        return_ACPI_STATUS (Status);
841278970Sjkim    }
842278970Sjkim
843278970Sjkim    Status = AcpiHwEnableAllWakeupGpes ();
844278970Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
845278970Sjkim
846278970Sjkim    return_ACPI_STATUS (Status);
847278970Sjkim}
848278970Sjkim
849278970SjkimACPI_EXPORT_SYMBOL (AcpiEnableAllWakeupGpes)
850278970Sjkim
851278970Sjkim
852216331Sjkim/*******************************************************************************
853216331Sjkim *
854216331Sjkim * FUNCTION:    AcpiInstallGpeBlock
855216331Sjkim *
856216331Sjkim * PARAMETERS:  GpeDevice           - Handle to the parent GPE Block Device
857216331Sjkim *              GpeBlockAddress     - Address and SpaceID
858216331Sjkim *              RegisterCount       - Number of GPE register pairs in the block
859216331Sjkim *              InterruptNumber     - H/W interrupt for the block
860216331Sjkim *
861216331Sjkim * RETURN:      Status
862216331Sjkim *
863216331Sjkim * DESCRIPTION: Create and Install a block of GPE registers. The GPEs are not
864216331Sjkim *              enabled here.
865216331Sjkim *
866216331Sjkim ******************************************************************************/
867216331Sjkim
868216331SjkimACPI_STATUS
869216331SjkimAcpiInstallGpeBlock (
870216331Sjkim    ACPI_HANDLE             GpeDevice,
871216331Sjkim    ACPI_GENERIC_ADDRESS    *GpeBlockAddress,
872216331Sjkim    UINT32                  RegisterCount,
873216331Sjkim    UINT32                  InterruptNumber)
874216331Sjkim{
875216331Sjkim    ACPI_STATUS             Status;
876216331Sjkim    ACPI_OPERAND_OBJECT     *ObjDesc;
877216331Sjkim    ACPI_NAMESPACE_NODE     *Node;
878216331Sjkim    ACPI_GPE_BLOCK_INFO     *GpeBlock;
879216331Sjkim
880216331Sjkim
881216331Sjkim    ACPI_FUNCTION_TRACE (AcpiInstallGpeBlock);
882216331Sjkim
883216331Sjkim
884216331Sjkim    if ((!GpeDevice)       ||
885216331Sjkim        (!GpeBlockAddress) ||
886216331Sjkim        (!RegisterCount))
887216331Sjkim    {
888216331Sjkim        return_ACPI_STATUS (AE_BAD_PARAMETER);
889216331Sjkim    }
890216331Sjkim
891216331Sjkim    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
892216331Sjkim    if (ACPI_FAILURE (Status))
893216331Sjkim    {
894241973Sjkim        return_ACPI_STATUS (Status);
895216331Sjkim    }
896216331Sjkim
897216331Sjkim    Node = AcpiNsValidateHandle (GpeDevice);
898216331Sjkim    if (!Node)
899216331Sjkim    {
900216331Sjkim        Status = AE_BAD_PARAMETER;
901216331Sjkim        goto UnlockAndExit;
902216331Sjkim    }
903216331Sjkim
904272444Sjkim    /* Validate the parent device */
905272444Sjkim
906272444Sjkim    if (Node->Type != ACPI_TYPE_DEVICE)
907272444Sjkim    {
908272444Sjkim        Status = AE_TYPE;
909272444Sjkim        goto UnlockAndExit;
910272444Sjkim    }
911272444Sjkim
912272444Sjkim    if (Node->Object)
913272444Sjkim    {
914272444Sjkim        Status = AE_ALREADY_EXISTS;
915272444Sjkim        goto UnlockAndExit;
916272444Sjkim    }
917272444Sjkim
918216331Sjkim    /*
919216331Sjkim     * For user-installed GPE Block Devices, the GpeBlockBaseNumber
920216331Sjkim     * is always zero
921216331Sjkim     */
922272444Sjkim    Status = AcpiEvCreateGpeBlock (Node, GpeBlockAddress->Address,
923298714Sjkim        GpeBlockAddress->SpaceId, RegisterCount,
924298714Sjkim        0, InterruptNumber, &GpeBlock);
925216331Sjkim    if (ACPI_FAILURE (Status))
926216331Sjkim    {
927216331Sjkim        goto UnlockAndExit;
928216331Sjkim    }
929216331Sjkim
930216331Sjkim    /* Install block in the DeviceObject attached to the node */
931216331Sjkim
932216331Sjkim    ObjDesc = AcpiNsGetAttachedObject (Node);
933216331Sjkim    if (!ObjDesc)
934216331Sjkim    {
935216331Sjkim        /*
936216331Sjkim         * No object, create a new one (Device nodes do not always have
937216331Sjkim         * an attached object)
938216331Sjkim         */
939216331Sjkim        ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_DEVICE);
940216331Sjkim        if (!ObjDesc)
941216331Sjkim        {
942216331Sjkim            Status = AE_NO_MEMORY;
943216331Sjkim            goto UnlockAndExit;
944216331Sjkim        }
945216331Sjkim
946216331Sjkim        Status = AcpiNsAttachObject (Node, ObjDesc, ACPI_TYPE_DEVICE);
947216331Sjkim
948216331Sjkim        /* Remove local reference to the object */
949216331Sjkim
950216331Sjkim        AcpiUtRemoveReference (ObjDesc);
951216331Sjkim        if (ACPI_FAILURE (Status))
952216331Sjkim        {
953216331Sjkim            goto UnlockAndExit;
954216331Sjkim        }
955216331Sjkim    }
956216331Sjkim
957216331Sjkim    /* Now install the GPE block in the DeviceObject */
958216331Sjkim
959216331Sjkim    ObjDesc->Device.GpeBlock = GpeBlock;
960216331Sjkim
961216331Sjkim
962216331SjkimUnlockAndExit:
963216331Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
964216331Sjkim    return_ACPI_STATUS (Status);
965216331Sjkim}
966216331Sjkim
967216331SjkimACPI_EXPORT_SYMBOL (AcpiInstallGpeBlock)
968216331Sjkim
969216331Sjkim
970216331Sjkim/*******************************************************************************
971216331Sjkim *
972216331Sjkim * FUNCTION:    AcpiRemoveGpeBlock
973216331Sjkim *
974216331Sjkim * PARAMETERS:  GpeDevice           - Handle to the parent GPE Block Device
975216331Sjkim *
976216331Sjkim * RETURN:      Status
977216331Sjkim *
978216331Sjkim * DESCRIPTION: Remove a previously installed block of GPE registers
979216331Sjkim *
980216331Sjkim ******************************************************************************/
981216331Sjkim
982216331SjkimACPI_STATUS
983216331SjkimAcpiRemoveGpeBlock (
984216331Sjkim    ACPI_HANDLE             GpeDevice)
985216331Sjkim{
986216331Sjkim    ACPI_OPERAND_OBJECT     *ObjDesc;
987216331Sjkim    ACPI_STATUS             Status;
988216331Sjkim    ACPI_NAMESPACE_NODE     *Node;
989216331Sjkim
990216331Sjkim
991216331Sjkim    ACPI_FUNCTION_TRACE (AcpiRemoveGpeBlock);
992216331Sjkim
993216331Sjkim
994216331Sjkim    if (!GpeDevice)
995216331Sjkim    {
996216331Sjkim        return_ACPI_STATUS (AE_BAD_PARAMETER);
997216331Sjkim    }
998216331Sjkim
999216331Sjkim    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
1000216331Sjkim    if (ACPI_FAILURE (Status))
1001216331Sjkim    {
1002241973Sjkim        return_ACPI_STATUS (Status);
1003216331Sjkim    }
1004216331Sjkim
1005216331Sjkim    Node = AcpiNsValidateHandle (GpeDevice);
1006216331Sjkim    if (!Node)
1007216331Sjkim    {
1008216331Sjkim        Status = AE_BAD_PARAMETER;
1009216331Sjkim        goto UnlockAndExit;
1010216331Sjkim    }
1011216331Sjkim
1012272444Sjkim    /* Validate the parent device */
1013272444Sjkim
1014272444Sjkim    if (Node->Type != ACPI_TYPE_DEVICE)
1015272444Sjkim    {
1016272444Sjkim        Status = AE_TYPE;
1017272444Sjkim        goto UnlockAndExit;
1018272444Sjkim    }
1019272444Sjkim
1020216331Sjkim    /* Get the DeviceObject attached to the node */
1021216331Sjkim
1022216331Sjkim    ObjDesc = AcpiNsGetAttachedObject (Node);
1023216331Sjkim    if (!ObjDesc ||
1024216331Sjkim        !ObjDesc->Device.GpeBlock)
1025216331Sjkim    {
1026216331Sjkim        return_ACPI_STATUS (AE_NULL_OBJECT);
1027216331Sjkim    }
1028216331Sjkim
1029216331Sjkim    /* Delete the GPE block (but not the DeviceObject) */
1030216331Sjkim
1031216331Sjkim    Status = AcpiEvDeleteGpeBlock (ObjDesc->Device.GpeBlock);
1032216331Sjkim    if (ACPI_SUCCESS (Status))
1033216331Sjkim    {
1034216331Sjkim        ObjDesc->Device.GpeBlock = NULL;
1035216331Sjkim    }
1036216331Sjkim
1037216331SjkimUnlockAndExit:
1038216331Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
1039216331Sjkim    return_ACPI_STATUS (Status);
1040216331Sjkim}
1041216331Sjkim
1042216331SjkimACPI_EXPORT_SYMBOL (AcpiRemoveGpeBlock)
1043216331Sjkim
1044216331Sjkim
1045216331Sjkim/*******************************************************************************
1046216331Sjkim *
1047216331Sjkim * FUNCTION:    AcpiGetGpeDevice
1048216331Sjkim *
1049216331Sjkim * PARAMETERS:  Index               - System GPE index (0-CurrentGpeCount)
1050216331Sjkim *              GpeDevice           - Where the parent GPE Device is returned
1051216331Sjkim *
1052216331Sjkim * RETURN:      Status
1053216331Sjkim *
1054216331Sjkim * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL
1055216331Sjkim *              gpe device indicates that the gpe number is contained in one of
1056216331Sjkim *              the FADT-defined gpe blocks. Otherwise, the GPE block device.
1057216331Sjkim *
1058216331Sjkim ******************************************************************************/
1059216331Sjkim
1060216331SjkimACPI_STATUS
1061216331SjkimAcpiGetGpeDevice (
1062216331Sjkim    UINT32                  Index,
1063216331Sjkim    ACPI_HANDLE             *GpeDevice)
1064216331Sjkim{
1065216331Sjkim    ACPI_GPE_DEVICE_INFO    Info;
1066216331Sjkim    ACPI_STATUS             Status;
1067216331Sjkim
1068216331Sjkim
1069216331Sjkim    ACPI_FUNCTION_TRACE (AcpiGetGpeDevice);
1070216331Sjkim
1071216331Sjkim
1072216331Sjkim    if (!GpeDevice)
1073216331Sjkim    {
1074216331Sjkim        return_ACPI_STATUS (AE_BAD_PARAMETER);
1075216331Sjkim    }
1076216331Sjkim
1077216331Sjkim    if (Index >= AcpiCurrentGpeCount)
1078216331Sjkim    {
1079216331Sjkim        return_ACPI_STATUS (AE_NOT_EXIST);
1080216331Sjkim    }
1081216331Sjkim
1082216331Sjkim    /* Setup and walk the GPE list */
1083216331Sjkim
1084216331Sjkim    Info.Index = Index;
1085216331Sjkim    Info.Status = AE_NOT_EXIST;
1086216331Sjkim    Info.GpeDevice = NULL;
1087216331Sjkim    Info.NextBlockBaseIndex = 0;
1088216331Sjkim
1089216331Sjkim    Status = AcpiEvWalkGpeList (AcpiEvGetGpeDevice, &Info);
1090216331Sjkim    if (ACPI_FAILURE (Status))
1091216331Sjkim    {
1092216331Sjkim        return_ACPI_STATUS (Status);
1093216331Sjkim    }
1094216331Sjkim
1095216331Sjkim    *GpeDevice = ACPI_CAST_PTR (ACPI_HANDLE, Info.GpeDevice);
1096216331Sjkim    return_ACPI_STATUS (Info.Status);
1097216331Sjkim}
1098216331Sjkim
1099216331SjkimACPI_EXPORT_SYMBOL (AcpiGetGpeDevice)
1100231844Sjkim
1101231844Sjkim#endif /* !ACPI_REDUCED_HARDWARE */
1102