evxfgpe.c revision 272444
1216331Sjkim/******************************************************************************
2216331Sjkim *
3216331Sjkim * Module Name: evxfgpe - External Interfaces for General Purpose Events (GPEs)
4216331Sjkim *
5216331Sjkim *****************************************************************************/
6216331Sjkim
7217365Sjkim/*
8272444Sjkim * Copyright (C) 2000 - 2014, 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
44216331Sjkim#define __EVXFGPE_C__
45272444Sjkim#define EXPORT_ACPI_INTERFACES
46216331Sjkim
47216471Sjkim#include <contrib/dev/acpica/include/acpi.h>
48216471Sjkim#include <contrib/dev/acpica/include/accommon.h>
49216471Sjkim#include <contrib/dev/acpica/include/acevents.h>
50216471Sjkim#include <contrib/dev/acpica/include/acnamesp.h>
51216331Sjkim
52216331Sjkim#define _COMPONENT          ACPI_EVENTS
53216331Sjkim        ACPI_MODULE_NAME    ("evxfgpe")
54216331Sjkim
55216331Sjkim
56231844Sjkim#if (!ACPI_REDUCED_HARDWARE) /* Entire module */
57216331Sjkim/*******************************************************************************
58216331Sjkim *
59216331Sjkim * FUNCTION:    AcpiUpdateAllGpes
60216331Sjkim *
61216331Sjkim * PARAMETERS:  None
62216331Sjkim *
63216331Sjkim * RETURN:      Status
64216331Sjkim *
65216331Sjkim * DESCRIPTION: Complete GPE initialization and enable all GPEs that have
66216331Sjkim *              associated _Lxx or _Exx methods and are not pointed to by any
67216331Sjkim *              device _PRW methods (this indicates that these GPEs are
68216331Sjkim *              generally intended for system or device wakeup. Such GPEs
69216331Sjkim *              have to be enabled directly when the devices whose _PRW
70216331Sjkim *              methods point to them are set up for wakeup signaling.)
71216331Sjkim *
72216331Sjkim * NOTE: Should be called after any GPEs are added to the system. Primarily,
73216331Sjkim * after the system _PRW methods have been run, but also after a GPE Block
74216331Sjkim * Device has been added or if any new GPE methods have been added via a
75216331Sjkim * dynamic table load.
76216331Sjkim *
77216331Sjkim ******************************************************************************/
78216331Sjkim
79216331SjkimACPI_STATUS
80216331SjkimAcpiUpdateAllGpes (
81216331Sjkim    void)
82216331Sjkim{
83216331Sjkim    ACPI_STATUS             Status;
84216331Sjkim
85216331Sjkim
86238381Sjkim    ACPI_FUNCTION_TRACE (AcpiUpdateAllGpes);
87216331Sjkim
88216331Sjkim
89216331Sjkim    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
90216331Sjkim    if (ACPI_FAILURE (Status))
91216331Sjkim    {
92216331Sjkim        return_ACPI_STATUS (Status);
93216331Sjkim    }
94216331Sjkim
95216331Sjkim    if (AcpiGbl_AllGpesInitialized)
96216331Sjkim    {
97216331Sjkim        goto UnlockAndExit;
98216331Sjkim    }
99216331Sjkim
100216331Sjkim    Status = AcpiEvWalkGpeList (AcpiEvInitializeGpeBlock, NULL);
101216331Sjkim    if (ACPI_SUCCESS (Status))
102216331Sjkim    {
103216331Sjkim        AcpiGbl_AllGpesInitialized = TRUE;
104216331Sjkim    }
105216331Sjkim
106216331SjkimUnlockAndExit:
107216331Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
108216331Sjkim    return_ACPI_STATUS (Status);
109216331Sjkim}
110216331Sjkim
111216331SjkimACPI_EXPORT_SYMBOL (AcpiUpdateAllGpes)
112216331Sjkim
113216331Sjkim
114216331Sjkim/*******************************************************************************
115216331Sjkim *
116216331Sjkim * FUNCTION:    AcpiEnableGpe
117216331Sjkim *
118216331Sjkim * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
119216331Sjkim *              GpeNumber           - GPE level within the GPE block
120216331Sjkim *
121216331Sjkim * RETURN:      Status
122216331Sjkim *
123216331Sjkim * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is
124216331Sjkim *              hardware-enabled.
125216331Sjkim *
126216331Sjkim ******************************************************************************/
127216331Sjkim
128216331SjkimACPI_STATUS
129216331SjkimAcpiEnableGpe (
130216331Sjkim    ACPI_HANDLE             GpeDevice,
131216331Sjkim    UINT32                  GpeNumber)
132216331Sjkim{
133216331Sjkim    ACPI_STATUS             Status = AE_BAD_PARAMETER;
134216331Sjkim    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
135216331Sjkim    ACPI_CPU_FLAGS          Flags;
136216331Sjkim
137216331Sjkim
138216331Sjkim    ACPI_FUNCTION_TRACE (AcpiEnableGpe);
139216331Sjkim
140216331Sjkim
141216331Sjkim    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
142216331Sjkim
143272444Sjkim    /*
144272444Sjkim     * Ensure that we have a valid GPE number and that there is some way
145272444Sjkim     * of handling the GPE (handler or a GPE method). In other words, we
146272444Sjkim     * won't allow a valid GPE to be enabled if there is no way to handle it.
147272444Sjkim     */
148216331Sjkim    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
149216331Sjkim    if (GpeEventInfo)
150216331Sjkim    {
151272444Sjkim        if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) !=
152272444Sjkim            ACPI_GPE_DISPATCH_NONE)
153272444Sjkim        {
154272444Sjkim            Status = AcpiEvAddGpeReference (GpeEventInfo);
155272444Sjkim        }
156272444Sjkim        else
157272444Sjkim        {
158272444Sjkim            Status = AE_NO_HANDLER;
159272444Sjkim        }
160216331Sjkim    }
161216331Sjkim
162216331Sjkim    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
163216331Sjkim    return_ACPI_STATUS (Status);
164216331Sjkim}
165216331Sjkim
166216331SjkimACPI_EXPORT_SYMBOL (AcpiEnableGpe)
167216331Sjkim
168216331Sjkim
169216331Sjkim/*******************************************************************************
170216331Sjkim *
171216331Sjkim * FUNCTION:    AcpiDisableGpe
172216331Sjkim *
173216331Sjkim * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
174216331Sjkim *              GpeNumber           - GPE level within the GPE block
175216331Sjkim *
176216331Sjkim * RETURN:      Status
177216331Sjkim *
178216331Sjkim * DESCRIPTION: Remove a reference to a GPE. When the last reference is
179216331Sjkim *              removed, only then is the GPE disabled (for runtime GPEs), or
180216331Sjkim *              the GPE mask bit disabled (for wake GPEs)
181216331Sjkim *
182216331Sjkim ******************************************************************************/
183216331Sjkim
184216331SjkimACPI_STATUS
185216331SjkimAcpiDisableGpe (
186216331Sjkim    ACPI_HANDLE             GpeDevice,
187216331Sjkim    UINT32                  GpeNumber)
188216331Sjkim{
189216331Sjkim    ACPI_STATUS             Status = AE_BAD_PARAMETER;
190216331Sjkim    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
191216331Sjkim    ACPI_CPU_FLAGS          Flags;
192216331Sjkim
193216331Sjkim
194216331Sjkim    ACPI_FUNCTION_TRACE (AcpiDisableGpe);
195216331Sjkim
196216331Sjkim
197216331Sjkim    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
198216331Sjkim
199216331Sjkim    /* Ensure that we have a valid GPE number */
200216331Sjkim
201216331Sjkim    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
202216331Sjkim    if (GpeEventInfo)
203216331Sjkim    {
204216331Sjkim        Status = AcpiEvRemoveGpeReference (GpeEventInfo);
205216331Sjkim    }
206216331Sjkim
207216331Sjkim    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
208216331Sjkim    return_ACPI_STATUS (Status);
209216331Sjkim}
210216331Sjkim
211216331SjkimACPI_EXPORT_SYMBOL (AcpiDisableGpe)
212216331Sjkim
213216331Sjkim
214216331Sjkim/*******************************************************************************
215216331Sjkim *
216216331Sjkim * FUNCTION:    AcpiSetGpe
217216331Sjkim *
218216331Sjkim * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
219216331Sjkim *              GpeNumber           - GPE level within the GPE block
220216331Sjkim *              Action              - ACPI_GPE_ENABLE or ACPI_GPE_DISABLE
221216331Sjkim *
222216331Sjkim * RETURN:      Status
223216331Sjkim *
224216331Sjkim * DESCRIPTION: Enable or disable an individual GPE. This function bypasses
225216331Sjkim *              the reference count mechanism used in the AcpiEnableGpe and
226216331Sjkim *              AcpiDisableGpe interfaces -- and should be used with care.
227216331Sjkim *
228216331Sjkim * Note: Typically used to disable a runtime GPE for short period of time,
229216331Sjkim * then re-enable it, without disturbing the existing reference counts. This
230216331Sjkim * is useful, for example, in the Embedded Controller (EC) driver.
231216331Sjkim *
232216331Sjkim ******************************************************************************/
233216331Sjkim
234216331SjkimACPI_STATUS
235216331SjkimAcpiSetGpe (
236216331Sjkim    ACPI_HANDLE             GpeDevice,
237216331Sjkim    UINT32                  GpeNumber,
238216331Sjkim    UINT8                   Action)
239216331Sjkim{
240216331Sjkim    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
241216331Sjkim    ACPI_STATUS             Status;
242216331Sjkim    ACPI_CPU_FLAGS          Flags;
243216331Sjkim
244216331Sjkim
245216331Sjkim    ACPI_FUNCTION_TRACE (AcpiSetGpe);
246216331Sjkim
247216331Sjkim
248216331Sjkim    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
249216331Sjkim
250216331Sjkim    /* Ensure that we have a valid GPE number */
251216331Sjkim
252216331Sjkim    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
253216331Sjkim    if (!GpeEventInfo)
254216331Sjkim    {
255216331Sjkim        Status = AE_BAD_PARAMETER;
256216331Sjkim        goto UnlockAndExit;
257216331Sjkim    }
258216331Sjkim
259216331Sjkim    /* Perform the action */
260216331Sjkim
261216331Sjkim    switch (Action)
262216331Sjkim    {
263216331Sjkim    case ACPI_GPE_ENABLE:
264250838Sjkim
265216331Sjkim        Status = AcpiEvEnableGpe (GpeEventInfo);
266216331Sjkim        break;
267216331Sjkim
268216331Sjkim    case ACPI_GPE_DISABLE:
269250838Sjkim
270216331Sjkim        Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE);
271216331Sjkim        break;
272216331Sjkim
273216331Sjkim    default:
274250838Sjkim
275216331Sjkim        Status = AE_BAD_PARAMETER;
276216331Sjkim        break;
277216331Sjkim    }
278216331Sjkim
279216331SjkimUnlockAndExit:
280216331Sjkim    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
281216331Sjkim    return_ACPI_STATUS (Status);
282216331Sjkim}
283216331Sjkim
284216331SjkimACPI_EXPORT_SYMBOL (AcpiSetGpe)
285216331Sjkim
286216331Sjkim
287216331Sjkim/*******************************************************************************
288216331Sjkim *
289272444Sjkim * FUNCTION:    AcpiMarkGpeForWake
290272444Sjkim *
291272444Sjkim * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
292272444Sjkim *              GpeNumber           - GPE level within the GPE block
293272444Sjkim *
294272444Sjkim * RETURN:      Status
295272444Sjkim *
296272444Sjkim * DESCRIPTION: Mark a GPE as having the ability to wake the system. Simply
297272444Sjkim *              sets the ACPI_GPE_CAN_WAKE flag.
298272444Sjkim *
299272444Sjkim * Some potential callers of AcpiSetupGpeForWake may know in advance that
300272444Sjkim * there won't be any notify handlers installed for device wake notifications
301272444Sjkim * from the given GPE (one example is a button GPE in Linux). For these cases,
302272444Sjkim * AcpiMarkGpeForWake should be used instead of AcpiSetupGpeForWake.
303272444Sjkim * This will set the ACPI_GPE_CAN_WAKE flag for the GPE without trying to
304272444Sjkim * setup implicit wake notification for it (since there's no handler method).
305272444Sjkim *
306272444Sjkim ******************************************************************************/
307272444Sjkim
308272444SjkimACPI_STATUS
309272444SjkimAcpiMarkGpeForWake (
310272444Sjkim    ACPI_HANDLE             GpeDevice,
311272444Sjkim    UINT32                  GpeNumber)
312272444Sjkim{
313272444Sjkim    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
314272444Sjkim    ACPI_STATUS             Status = AE_BAD_PARAMETER;
315272444Sjkim    ACPI_CPU_FLAGS          Flags;
316272444Sjkim
317272444Sjkim
318272444Sjkim    ACPI_FUNCTION_TRACE (AcpiMarkGpeForWake);
319272444Sjkim
320272444Sjkim
321272444Sjkim    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
322272444Sjkim
323272444Sjkim    /* Ensure that we have a valid GPE number */
324272444Sjkim
325272444Sjkim    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
326272444Sjkim    if (GpeEventInfo)
327272444Sjkim    {
328272444Sjkim        /* Mark the GPE as a possible wake event */
329272444Sjkim
330272444Sjkim        GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE;
331272444Sjkim        Status = AE_OK;
332272444Sjkim    }
333272444Sjkim
334272444Sjkim    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
335272444Sjkim    return_ACPI_STATUS (Status);
336272444Sjkim}
337272444Sjkim
338272444SjkimACPI_EXPORT_SYMBOL (AcpiMarkGpeForWake)
339272444Sjkim
340272444Sjkim
341272444Sjkim/*******************************************************************************
342272444Sjkim *
343216331Sjkim * FUNCTION:    AcpiSetupGpeForWake
344216331Sjkim *
345216331Sjkim * PARAMETERS:  WakeDevice          - Device associated with the GPE (via _PRW)
346216331Sjkim *              GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
347216331Sjkim *              GpeNumber           - GPE level within the GPE block
348216331Sjkim *
349216331Sjkim * RETURN:      Status
350216331Sjkim *
351216331Sjkim * DESCRIPTION: Mark a GPE as having the ability to wake the system. This
352216331Sjkim *              interface is intended to be used as the host executes the
353216331Sjkim *              _PRW methods (Power Resources for Wake) in the system tables.
354216331Sjkim *              Each _PRW appears under a Device Object (The WakeDevice), and
355216331Sjkim *              contains the info for the wake GPE associated with the
356216331Sjkim *              WakeDevice.
357216331Sjkim *
358216331Sjkim ******************************************************************************/
359216331Sjkim
360216331SjkimACPI_STATUS
361216331SjkimAcpiSetupGpeForWake (
362216331Sjkim    ACPI_HANDLE             WakeDevice,
363216331Sjkim    ACPI_HANDLE             GpeDevice,
364216331Sjkim    UINT32                  GpeNumber)
365216331Sjkim{
366237412Sjkim    ACPI_STATUS             Status;
367216331Sjkim    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
368216331Sjkim    ACPI_NAMESPACE_NODE     *DeviceNode;
369238381Sjkim    ACPI_GPE_NOTIFY_INFO    *Notify;
370238381Sjkim    ACPI_GPE_NOTIFY_INFO    *NewNotify;
371216331Sjkim    ACPI_CPU_FLAGS          Flags;
372216331Sjkim
373216331Sjkim
374216331Sjkim    ACPI_FUNCTION_TRACE (AcpiSetupGpeForWake);
375216331Sjkim
376216331Sjkim
377216331Sjkim    /* Parameter Validation */
378216331Sjkim
379216331Sjkim    if (!WakeDevice)
380216331Sjkim    {
381216331Sjkim        /*
382216331Sjkim         * By forcing WakeDevice to be valid, we automatically enable the
383216331Sjkim         * implicit notify feature on all hosts.
384216331Sjkim         */
385216331Sjkim        return_ACPI_STATUS (AE_BAD_PARAMETER);
386216331Sjkim    }
387216331Sjkim
388219707Sjkim    /* Handle root object case */
389219707Sjkim
390219707Sjkim    if (WakeDevice == ACPI_ROOT_OBJECT)
391219707Sjkim    {
392219707Sjkim        DeviceNode = AcpiGbl_RootNode;
393219707Sjkim    }
394219707Sjkim    else
395219707Sjkim    {
396219707Sjkim        DeviceNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, WakeDevice);
397219707Sjkim    }
398219707Sjkim
399216331Sjkim    /* Validate WakeDevice is of type Device */
400216331Sjkim
401216331Sjkim    if (DeviceNode->Type != ACPI_TYPE_DEVICE)
402216331Sjkim    {
403216331Sjkim        return_ACPI_STATUS (AE_BAD_PARAMETER);
404216331Sjkim    }
405216331Sjkim
406238381Sjkim    /*
407238381Sjkim     * Allocate a new notify object up front, in case it is needed.
408238381Sjkim     * Memory allocation while holding a spinlock is a big no-no
409238381Sjkim     * on some hosts.
410238381Sjkim     */
411237652Sjkim    NewNotify = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_NOTIFY_INFO));
412237652Sjkim    if (!NewNotify)
413237652Sjkim    {
414237652Sjkim        return_ACPI_STATUS (AE_NO_MEMORY);
415237652Sjkim    }
416237652Sjkim
417216331Sjkim    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
418216331Sjkim
419216331Sjkim    /* Ensure that we have a valid GPE number */
420216331Sjkim
421216331Sjkim    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
422237412Sjkim    if (!GpeEventInfo)
423216331Sjkim    {
424237412Sjkim        Status = AE_BAD_PARAMETER;
425237412Sjkim        goto UnlockAndExit;
426237412Sjkim    }
427237412Sjkim
428237412Sjkim    /*
429237412Sjkim     * If there is no method or handler for this GPE, then the
430237412Sjkim     * WakeDevice will be notified whenever this GPE fires. This is
431237412Sjkim     * known as an "implicit notify". Note: The GPE is assumed to be
432237412Sjkim     * level-triggered (for windows compatibility).
433237412Sjkim     */
434237412Sjkim    if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
435237412Sjkim            ACPI_GPE_DISPATCH_NONE)
436237412Sjkim    {
437216331Sjkim        /*
438237412Sjkim         * This is the first device for implicit notify on this GPE.
439237412Sjkim         * Just set the flags here, and enter the NOTIFY block below.
440216331Sjkim         */
441237412Sjkim        GpeEventInfo->Flags =
442237412Sjkim            (ACPI_GPE_DISPATCH_NOTIFY | ACPI_GPE_LEVEL_TRIGGERED);
443237412Sjkim    }
444237412Sjkim
445237412Sjkim    /*
446237412Sjkim     * If we already have an implicit notify on this GPE, add
447237412Sjkim     * this device to the notify list.
448237412Sjkim     */
449237412Sjkim    if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
450237412Sjkim            ACPI_GPE_DISPATCH_NOTIFY)
451237412Sjkim    {
452237412Sjkim        /* Ensure that the device is not already in the list */
453237412Sjkim
454237412Sjkim        Notify = GpeEventInfo->Dispatch.NotifyList;
455237412Sjkim        while (Notify)
456216331Sjkim        {
457237412Sjkim            if (Notify->DeviceNode == DeviceNode)
458237412Sjkim            {
459237412Sjkim                Status = AE_ALREADY_EXISTS;
460237412Sjkim                goto UnlockAndExit;
461237412Sjkim            }
462237412Sjkim            Notify = Notify->Next;
463216331Sjkim        }
464216331Sjkim
465237412Sjkim        /* Add this device to the notify list for this GPE */
466237412Sjkim
467237652Sjkim        NewNotify->DeviceNode = DeviceNode;
468237652Sjkim        NewNotify->Next = GpeEventInfo->Dispatch.NotifyList;
469237652Sjkim        GpeEventInfo->Dispatch.NotifyList = NewNotify;
470237652Sjkim        NewNotify = NULL;
471216331Sjkim    }
472216331Sjkim
473237412Sjkim    /* Mark the GPE as a possible wake event */
474237412Sjkim
475237412Sjkim    GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE;
476237412Sjkim    Status = AE_OK;
477237412Sjkim
478238381Sjkim
479237412SjkimUnlockAndExit:
480216331Sjkim    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
481238381Sjkim
482238381Sjkim    /* Delete the notify object if it was not used above */
483238381Sjkim
484237652Sjkim    if (NewNotify)
485237652Sjkim    {
486237652Sjkim        ACPI_FREE (NewNotify);
487237652Sjkim    }
488216331Sjkim    return_ACPI_STATUS (Status);
489216331Sjkim}
490216331Sjkim
491216331SjkimACPI_EXPORT_SYMBOL (AcpiSetupGpeForWake)
492216331Sjkim
493216331Sjkim
494216331Sjkim/*******************************************************************************
495216331Sjkim *
496216331Sjkim * FUNCTION:    AcpiSetGpeWakeMask
497216331Sjkim *
498216331Sjkim * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
499216331Sjkim *              GpeNumber           - GPE level within the GPE block
500216331Sjkim *              Action              - Enable or Disable
501216331Sjkim *
502216331Sjkim * RETURN:      Status
503216331Sjkim *
504216331Sjkim * DESCRIPTION: Set or clear the GPE's wakeup enable mask bit. The GPE must
505216331Sjkim *              already be marked as a WAKE GPE.
506216331Sjkim *
507216331Sjkim ******************************************************************************/
508216331Sjkim
509216331SjkimACPI_STATUS
510216331SjkimAcpiSetGpeWakeMask (
511216331Sjkim    ACPI_HANDLE             GpeDevice,
512216331Sjkim    UINT32                  GpeNumber,
513216331Sjkim    UINT8                   Action)
514216331Sjkim{
515216331Sjkim    ACPI_STATUS             Status = AE_OK;
516216331Sjkim    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
517216331Sjkim    ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
518216331Sjkim    ACPI_CPU_FLAGS          Flags;
519216331Sjkim    UINT32                  RegisterBit;
520216331Sjkim
521216331Sjkim
522216331Sjkim    ACPI_FUNCTION_TRACE (AcpiSetGpeWakeMask);
523216331Sjkim
524216331Sjkim
525216331Sjkim    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
526216331Sjkim
527216331Sjkim    /*
528216331Sjkim     * Ensure that we have a valid GPE number and that this GPE is in
529216331Sjkim     * fact a wake GPE
530216331Sjkim     */
531216331Sjkim    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
532216331Sjkim    if (!GpeEventInfo)
533216331Sjkim    {
534216331Sjkim        Status = AE_BAD_PARAMETER;
535216331Sjkim        goto UnlockAndExit;
536216331Sjkim    }
537216331Sjkim
538216331Sjkim    if (!(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE))
539216331Sjkim    {
540216331Sjkim        Status = AE_TYPE;
541216331Sjkim        goto UnlockAndExit;
542216331Sjkim    }
543216331Sjkim
544216331Sjkim    GpeRegisterInfo = GpeEventInfo->RegisterInfo;
545216331Sjkim    if (!GpeRegisterInfo)
546216331Sjkim    {
547216331Sjkim        Status = AE_NOT_EXIST;
548216331Sjkim        goto UnlockAndExit;
549216331Sjkim    }
550216331Sjkim
551239340Sjkim    RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo);
552216331Sjkim
553216331Sjkim    /* Perform the action */
554216331Sjkim
555216331Sjkim    switch (Action)
556216331Sjkim    {
557216331Sjkim    case ACPI_GPE_ENABLE:
558250838Sjkim
559216331Sjkim        ACPI_SET_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit);
560216331Sjkim        break;
561216331Sjkim
562216331Sjkim    case ACPI_GPE_DISABLE:
563250838Sjkim
564216331Sjkim        ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit);
565216331Sjkim        break;
566216331Sjkim
567216331Sjkim    default:
568250838Sjkim
569216331Sjkim        ACPI_ERROR ((AE_INFO, "%u, Invalid action", Action));
570216331Sjkim        Status = AE_BAD_PARAMETER;
571216331Sjkim        break;
572216331Sjkim    }
573216331Sjkim
574216331SjkimUnlockAndExit:
575216331Sjkim    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
576216331Sjkim    return_ACPI_STATUS (Status);
577216331Sjkim}
578216331Sjkim
579216331SjkimACPI_EXPORT_SYMBOL (AcpiSetGpeWakeMask)
580216331Sjkim
581216331Sjkim
582216331Sjkim/*******************************************************************************
583216331Sjkim *
584216331Sjkim * FUNCTION:    AcpiClearGpe
585216331Sjkim *
586216331Sjkim * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
587216331Sjkim *              GpeNumber           - GPE level within the GPE block
588216331Sjkim *
589216331Sjkim * RETURN:      Status
590216331Sjkim *
591216331Sjkim * DESCRIPTION: Clear an ACPI event (general purpose)
592216331Sjkim *
593216331Sjkim ******************************************************************************/
594216331Sjkim
595216331SjkimACPI_STATUS
596216331SjkimAcpiClearGpe (
597216331Sjkim    ACPI_HANDLE             GpeDevice,
598216331Sjkim    UINT32                  GpeNumber)
599216331Sjkim{
600216331Sjkim    ACPI_STATUS             Status = AE_OK;
601216331Sjkim    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
602216331Sjkim    ACPI_CPU_FLAGS          Flags;
603216331Sjkim
604216331Sjkim
605216331Sjkim    ACPI_FUNCTION_TRACE (AcpiClearGpe);
606216331Sjkim
607216331Sjkim
608216331Sjkim    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
609216331Sjkim
610216331Sjkim    /* Ensure that we have a valid GPE number */
611216331Sjkim
612216331Sjkim    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
613216331Sjkim    if (!GpeEventInfo)
614216331Sjkim    {
615216331Sjkim        Status = AE_BAD_PARAMETER;
616216331Sjkim        goto UnlockAndExit;
617216331Sjkim    }
618216331Sjkim
619216331Sjkim    Status = AcpiHwClearGpe (GpeEventInfo);
620216331Sjkim
621216331SjkimUnlockAndExit:
622216331Sjkim    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
623216331Sjkim    return_ACPI_STATUS (Status);
624216331Sjkim}
625216331Sjkim
626216331SjkimACPI_EXPORT_SYMBOL (AcpiClearGpe)
627216331Sjkim
628216331Sjkim
629216331Sjkim/*******************************************************************************
630216331Sjkim *
631216331Sjkim * FUNCTION:    AcpiGetGpeStatus
632216331Sjkim *
633216331Sjkim * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
634216331Sjkim *              GpeNumber           - GPE level within the GPE block
635216331Sjkim *              EventStatus         - Where the current status of the event
636216331Sjkim *                                    will be returned
637216331Sjkim *
638216331Sjkim * RETURN:      Status
639216331Sjkim *
640216331Sjkim * DESCRIPTION: Get the current status of a GPE (signalled/not_signalled)
641216331Sjkim *
642216331Sjkim ******************************************************************************/
643216331Sjkim
644216331SjkimACPI_STATUS
645216331SjkimAcpiGetGpeStatus (
646216331Sjkim    ACPI_HANDLE             GpeDevice,
647216331Sjkim    UINT32                  GpeNumber,
648216331Sjkim    ACPI_EVENT_STATUS       *EventStatus)
649216331Sjkim{
650216331Sjkim    ACPI_STATUS             Status = AE_OK;
651216331Sjkim    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
652216331Sjkim    ACPI_CPU_FLAGS          Flags;
653216331Sjkim
654216331Sjkim
655216331Sjkim    ACPI_FUNCTION_TRACE (AcpiGetGpeStatus);
656216331Sjkim
657216331Sjkim
658216331Sjkim    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
659216331Sjkim
660216331Sjkim    /* Ensure that we have a valid GPE number */
661216331Sjkim
662216331Sjkim    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
663216331Sjkim    if (!GpeEventInfo)
664216331Sjkim    {
665216331Sjkim        Status = AE_BAD_PARAMETER;
666216331Sjkim        goto UnlockAndExit;
667216331Sjkim    }
668216331Sjkim
669216331Sjkim    /* Obtain status on the requested GPE number */
670216331Sjkim
671216331Sjkim    Status = AcpiHwGetGpeStatus (GpeEventInfo, EventStatus);
672216331Sjkim
673216331SjkimUnlockAndExit:
674216331Sjkim    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
675216331Sjkim    return_ACPI_STATUS (Status);
676216331Sjkim}
677216331Sjkim
678216331SjkimACPI_EXPORT_SYMBOL (AcpiGetGpeStatus)
679216331Sjkim
680216331Sjkim
681216331Sjkim/*******************************************************************************
682216331Sjkim *
683216331Sjkim * FUNCTION:    AcpiFinishGpe
684216331Sjkim *
685216331Sjkim * PARAMETERS:  GpeDevice           - Namespace node for the GPE Block
686216331Sjkim *                                    (NULL for FADT defined GPEs)
687216331Sjkim *              GpeNumber           - GPE level within the GPE block
688216331Sjkim *
689216331Sjkim * RETURN:      Status
690216331Sjkim *
691216331Sjkim * DESCRIPTION: Clear and conditionally reenable a GPE. This completes the GPE
692216331Sjkim *              processing. Intended for use by asynchronous host-installed
693216331Sjkim *              GPE handlers. The GPE is only reenabled if the EnableForRun bit
694216331Sjkim *              is set in the GPE info.
695216331Sjkim *
696216331Sjkim ******************************************************************************/
697216331Sjkim
698216331SjkimACPI_STATUS
699216331SjkimAcpiFinishGpe (
700216331Sjkim    ACPI_HANDLE             GpeDevice,
701216331Sjkim    UINT32                  GpeNumber)
702216331Sjkim{
703216331Sjkim    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
704216331Sjkim    ACPI_STATUS             Status;
705216331Sjkim    ACPI_CPU_FLAGS          Flags;
706216331Sjkim
707216331Sjkim
708216331Sjkim    ACPI_FUNCTION_TRACE (AcpiFinishGpe);
709216331Sjkim
710216331Sjkim
711216331Sjkim    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
712216331Sjkim
713216331Sjkim    /* Ensure that we have a valid GPE number */
714216331Sjkim
715216331Sjkim    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
716216331Sjkim    if (!GpeEventInfo)
717216331Sjkim    {
718216331Sjkim        Status = AE_BAD_PARAMETER;
719216331Sjkim        goto UnlockAndExit;
720216331Sjkim    }
721216331Sjkim
722216331Sjkim    Status = AcpiEvFinishGpe (GpeEventInfo);
723216331Sjkim
724216331SjkimUnlockAndExit:
725216331Sjkim    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
726216331Sjkim    return_ACPI_STATUS (Status);
727216331Sjkim}
728216331Sjkim
729216331SjkimACPI_EXPORT_SYMBOL (AcpiFinishGpe)
730216331Sjkim
731216331Sjkim
732216331Sjkim/******************************************************************************
733216331Sjkim *
734216331Sjkim * FUNCTION:    AcpiDisableAllGpes
735216331Sjkim *
736216331Sjkim * PARAMETERS:  None
737216331Sjkim *
738216331Sjkim * RETURN:      Status
739216331Sjkim *
740216331Sjkim * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
741216331Sjkim *
742216331Sjkim ******************************************************************************/
743216331Sjkim
744216331SjkimACPI_STATUS
745216331SjkimAcpiDisableAllGpes (
746216331Sjkim    void)
747216331Sjkim{
748216331Sjkim    ACPI_STATUS             Status;
749216331Sjkim
750216331Sjkim
751216331Sjkim    ACPI_FUNCTION_TRACE (AcpiDisableAllGpes);
752216331Sjkim
753216331Sjkim
754216331Sjkim    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
755216331Sjkim    if (ACPI_FAILURE (Status))
756216331Sjkim    {
757216331Sjkim        return_ACPI_STATUS (Status);
758216331Sjkim    }
759216331Sjkim
760216331Sjkim    Status = AcpiHwDisableAllGpes ();
761216331Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
762216331Sjkim
763216331Sjkim    return_ACPI_STATUS (Status);
764216331Sjkim}
765216331Sjkim
766216331SjkimACPI_EXPORT_SYMBOL (AcpiDisableAllGpes)
767216331Sjkim
768216331Sjkim
769216331Sjkim/******************************************************************************
770216331Sjkim *
771216331Sjkim * FUNCTION:    AcpiEnableAllRuntimeGpes
772216331Sjkim *
773216331Sjkim * PARAMETERS:  None
774216331Sjkim *
775216331Sjkim * RETURN:      Status
776216331Sjkim *
777216331Sjkim * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
778216331Sjkim *
779216331Sjkim ******************************************************************************/
780216331Sjkim
781216331SjkimACPI_STATUS
782216331SjkimAcpiEnableAllRuntimeGpes (
783216331Sjkim    void)
784216331Sjkim{
785216331Sjkim    ACPI_STATUS             Status;
786216331Sjkim
787216331Sjkim
788216331Sjkim    ACPI_FUNCTION_TRACE (AcpiEnableAllRuntimeGpes);
789216331Sjkim
790216331Sjkim
791216331Sjkim    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
792216331Sjkim    if (ACPI_FAILURE (Status))
793216331Sjkim    {
794216331Sjkim        return_ACPI_STATUS (Status);
795216331Sjkim    }
796216331Sjkim
797216331Sjkim    Status = AcpiHwEnableAllRuntimeGpes ();
798216331Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
799216331Sjkim
800216331Sjkim    return_ACPI_STATUS (Status);
801216331Sjkim}
802216331Sjkim
803216331SjkimACPI_EXPORT_SYMBOL (AcpiEnableAllRuntimeGpes)
804216331Sjkim
805216331Sjkim
806216331Sjkim/*******************************************************************************
807216331Sjkim *
808216331Sjkim * FUNCTION:    AcpiInstallGpeBlock
809216331Sjkim *
810216331Sjkim * PARAMETERS:  GpeDevice           - Handle to the parent GPE Block Device
811216331Sjkim *              GpeBlockAddress     - Address and SpaceID
812216331Sjkim *              RegisterCount       - Number of GPE register pairs in the block
813216331Sjkim *              InterruptNumber     - H/W interrupt for the block
814216331Sjkim *
815216331Sjkim * RETURN:      Status
816216331Sjkim *
817216331Sjkim * DESCRIPTION: Create and Install a block of GPE registers. The GPEs are not
818216331Sjkim *              enabled here.
819216331Sjkim *
820216331Sjkim ******************************************************************************/
821216331Sjkim
822216331SjkimACPI_STATUS
823216331SjkimAcpiInstallGpeBlock (
824216331Sjkim    ACPI_HANDLE             GpeDevice,
825216331Sjkim    ACPI_GENERIC_ADDRESS    *GpeBlockAddress,
826216331Sjkim    UINT32                  RegisterCount,
827216331Sjkim    UINT32                  InterruptNumber)
828216331Sjkim{
829216331Sjkim    ACPI_STATUS             Status;
830216331Sjkim    ACPI_OPERAND_OBJECT     *ObjDesc;
831216331Sjkim    ACPI_NAMESPACE_NODE     *Node;
832216331Sjkim    ACPI_GPE_BLOCK_INFO     *GpeBlock;
833216331Sjkim
834216331Sjkim
835216331Sjkim    ACPI_FUNCTION_TRACE (AcpiInstallGpeBlock);
836216331Sjkim
837216331Sjkim
838216331Sjkim    if ((!GpeDevice)       ||
839216331Sjkim        (!GpeBlockAddress) ||
840216331Sjkim        (!RegisterCount))
841216331Sjkim    {
842216331Sjkim        return_ACPI_STATUS (AE_BAD_PARAMETER);
843216331Sjkim    }
844216331Sjkim
845216331Sjkim    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
846216331Sjkim    if (ACPI_FAILURE (Status))
847216331Sjkim    {
848241973Sjkim        return_ACPI_STATUS (Status);
849216331Sjkim    }
850216331Sjkim
851216331Sjkim    Node = AcpiNsValidateHandle (GpeDevice);
852216331Sjkim    if (!Node)
853216331Sjkim    {
854216331Sjkim        Status = AE_BAD_PARAMETER;
855216331Sjkim        goto UnlockAndExit;
856216331Sjkim    }
857216331Sjkim
858272444Sjkim    /* Validate the parent device */
859272444Sjkim
860272444Sjkim    if (Node->Type != ACPI_TYPE_DEVICE)
861272444Sjkim    {
862272444Sjkim        Status = AE_TYPE;
863272444Sjkim        goto UnlockAndExit;
864272444Sjkim    }
865272444Sjkim
866272444Sjkim    if (Node->Object)
867272444Sjkim    {
868272444Sjkim        Status = AE_ALREADY_EXISTS;
869272444Sjkim        goto UnlockAndExit;
870272444Sjkim    }
871272444Sjkim
872216331Sjkim    /*
873216331Sjkim     * For user-installed GPE Block Devices, the GpeBlockBaseNumber
874216331Sjkim     * is always zero
875216331Sjkim     */
876272444Sjkim    Status = AcpiEvCreateGpeBlock (Node, GpeBlockAddress->Address,
877272444Sjkim                GpeBlockAddress->SpaceId, RegisterCount,
878216331Sjkim                0, InterruptNumber, &GpeBlock);
879216331Sjkim    if (ACPI_FAILURE (Status))
880216331Sjkim    {
881216331Sjkim        goto UnlockAndExit;
882216331Sjkim    }
883216331Sjkim
884216331Sjkim    /* Install block in the DeviceObject attached to the node */
885216331Sjkim
886216331Sjkim    ObjDesc = AcpiNsGetAttachedObject (Node);
887216331Sjkim    if (!ObjDesc)
888216331Sjkim    {
889216331Sjkim        /*
890216331Sjkim         * No object, create a new one (Device nodes do not always have
891216331Sjkim         * an attached object)
892216331Sjkim         */
893216331Sjkim        ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_DEVICE);
894216331Sjkim        if (!ObjDesc)
895216331Sjkim        {
896216331Sjkim            Status = AE_NO_MEMORY;
897216331Sjkim            goto UnlockAndExit;
898216331Sjkim        }
899216331Sjkim
900216331Sjkim        Status = AcpiNsAttachObject (Node, ObjDesc, ACPI_TYPE_DEVICE);
901216331Sjkim
902216331Sjkim        /* Remove local reference to the object */
903216331Sjkim
904216331Sjkim        AcpiUtRemoveReference (ObjDesc);
905216331Sjkim        if (ACPI_FAILURE (Status))
906216331Sjkim        {
907216331Sjkim            goto UnlockAndExit;
908216331Sjkim        }
909216331Sjkim    }
910216331Sjkim
911216331Sjkim    /* Now install the GPE block in the DeviceObject */
912216331Sjkim
913216331Sjkim    ObjDesc->Device.GpeBlock = GpeBlock;
914216331Sjkim
915216331Sjkim
916216331SjkimUnlockAndExit:
917216331Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
918216331Sjkim    return_ACPI_STATUS (Status);
919216331Sjkim}
920216331Sjkim
921216331SjkimACPI_EXPORT_SYMBOL (AcpiInstallGpeBlock)
922216331Sjkim
923216331Sjkim
924216331Sjkim/*******************************************************************************
925216331Sjkim *
926216331Sjkim * FUNCTION:    AcpiRemoveGpeBlock
927216331Sjkim *
928216331Sjkim * PARAMETERS:  GpeDevice           - Handle to the parent GPE Block Device
929216331Sjkim *
930216331Sjkim * RETURN:      Status
931216331Sjkim *
932216331Sjkim * DESCRIPTION: Remove a previously installed block of GPE registers
933216331Sjkim *
934216331Sjkim ******************************************************************************/
935216331Sjkim
936216331SjkimACPI_STATUS
937216331SjkimAcpiRemoveGpeBlock (
938216331Sjkim    ACPI_HANDLE             GpeDevice)
939216331Sjkim{
940216331Sjkim    ACPI_OPERAND_OBJECT     *ObjDesc;
941216331Sjkim    ACPI_STATUS             Status;
942216331Sjkim    ACPI_NAMESPACE_NODE     *Node;
943216331Sjkim
944216331Sjkim
945216331Sjkim    ACPI_FUNCTION_TRACE (AcpiRemoveGpeBlock);
946216331Sjkim
947216331Sjkim
948216331Sjkim    if (!GpeDevice)
949216331Sjkim    {
950216331Sjkim        return_ACPI_STATUS (AE_BAD_PARAMETER);
951216331Sjkim    }
952216331Sjkim
953216331Sjkim    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
954216331Sjkim    if (ACPI_FAILURE (Status))
955216331Sjkim    {
956241973Sjkim        return_ACPI_STATUS (Status);
957216331Sjkim    }
958216331Sjkim
959216331Sjkim    Node = AcpiNsValidateHandle (GpeDevice);
960216331Sjkim    if (!Node)
961216331Sjkim    {
962216331Sjkim        Status = AE_BAD_PARAMETER;
963216331Sjkim        goto UnlockAndExit;
964216331Sjkim    }
965216331Sjkim
966272444Sjkim    /* Validate the parent device */
967272444Sjkim
968272444Sjkim    if (Node->Type != ACPI_TYPE_DEVICE)
969272444Sjkim    {
970272444Sjkim        Status = AE_TYPE;
971272444Sjkim        goto UnlockAndExit;
972272444Sjkim    }
973272444Sjkim
974216331Sjkim    /* Get the DeviceObject attached to the node */
975216331Sjkim
976216331Sjkim    ObjDesc = AcpiNsGetAttachedObject (Node);
977216331Sjkim    if (!ObjDesc ||
978216331Sjkim        !ObjDesc->Device.GpeBlock)
979216331Sjkim    {
980216331Sjkim        return_ACPI_STATUS (AE_NULL_OBJECT);
981216331Sjkim    }
982216331Sjkim
983216331Sjkim    /* Delete the GPE block (but not the DeviceObject) */
984216331Sjkim
985216331Sjkim    Status = AcpiEvDeleteGpeBlock (ObjDesc->Device.GpeBlock);
986216331Sjkim    if (ACPI_SUCCESS (Status))
987216331Sjkim    {
988216331Sjkim        ObjDesc->Device.GpeBlock = NULL;
989216331Sjkim    }
990216331Sjkim
991216331SjkimUnlockAndExit:
992216331Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
993216331Sjkim    return_ACPI_STATUS (Status);
994216331Sjkim}
995216331Sjkim
996216331SjkimACPI_EXPORT_SYMBOL (AcpiRemoveGpeBlock)
997216331Sjkim
998216331Sjkim
999216331Sjkim/*******************************************************************************
1000216331Sjkim *
1001216331Sjkim * FUNCTION:    AcpiGetGpeDevice
1002216331Sjkim *
1003216331Sjkim * PARAMETERS:  Index               - System GPE index (0-CurrentGpeCount)
1004216331Sjkim *              GpeDevice           - Where the parent GPE Device is returned
1005216331Sjkim *
1006216331Sjkim * RETURN:      Status
1007216331Sjkim *
1008216331Sjkim * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL
1009216331Sjkim *              gpe device indicates that the gpe number is contained in one of
1010216331Sjkim *              the FADT-defined gpe blocks. Otherwise, the GPE block device.
1011216331Sjkim *
1012216331Sjkim ******************************************************************************/
1013216331Sjkim
1014216331SjkimACPI_STATUS
1015216331SjkimAcpiGetGpeDevice (
1016216331Sjkim    UINT32                  Index,
1017216331Sjkim    ACPI_HANDLE             *GpeDevice)
1018216331Sjkim{
1019216331Sjkim    ACPI_GPE_DEVICE_INFO    Info;
1020216331Sjkim    ACPI_STATUS             Status;
1021216331Sjkim
1022216331Sjkim
1023216331Sjkim    ACPI_FUNCTION_TRACE (AcpiGetGpeDevice);
1024216331Sjkim
1025216331Sjkim
1026216331Sjkim    if (!GpeDevice)
1027216331Sjkim    {
1028216331Sjkim        return_ACPI_STATUS (AE_BAD_PARAMETER);
1029216331Sjkim    }
1030216331Sjkim
1031216331Sjkim    if (Index >= AcpiCurrentGpeCount)
1032216331Sjkim    {
1033216331Sjkim        return_ACPI_STATUS (AE_NOT_EXIST);
1034216331Sjkim    }
1035216331Sjkim
1036216331Sjkim    /* Setup and walk the GPE list */
1037216331Sjkim
1038216331Sjkim    Info.Index = Index;
1039216331Sjkim    Info.Status = AE_NOT_EXIST;
1040216331Sjkim    Info.GpeDevice = NULL;
1041216331Sjkim    Info.NextBlockBaseIndex = 0;
1042216331Sjkim
1043216331Sjkim    Status = AcpiEvWalkGpeList (AcpiEvGetGpeDevice, &Info);
1044216331Sjkim    if (ACPI_FAILURE (Status))
1045216331Sjkim    {
1046216331Sjkim        return_ACPI_STATUS (Status);
1047216331Sjkim    }
1048216331Sjkim
1049216331Sjkim    *GpeDevice = ACPI_CAST_PTR (ACPI_HANDLE, Info.GpeDevice);
1050216331Sjkim    return_ACPI_STATUS (Info.Status);
1051216331Sjkim}
1052216331Sjkim
1053216331SjkimACPI_EXPORT_SYMBOL (AcpiGetGpeDevice)
1054231844Sjkim
1055231844Sjkim#endif /* !ACPI_REDUCED_HARDWARE */
1056