evxfgpe.c revision 237652
1/******************************************************************************
2 *
3 * Module Name: evxfgpe - External Interfaces for General Purpose Events (GPEs)
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2012, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions, and the following disclaimer,
16 *    without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 *    substantially similar to the "NO WARRANTY" disclaimer below
19 *    ("Disclaimer") and any redistribution must be conditioned upon
20 *    including a substantially similar Disclaimer requirement for further
21 *    binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 *    of any contributors may be used to endorse or promote products derived
24 *    from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#define __EVXFGPE_C__
46
47#include <contrib/dev/acpica/include/acpi.h>
48#include <contrib/dev/acpica/include/accommon.h>
49#include <contrib/dev/acpica/include/acevents.h>
50#include <contrib/dev/acpica/include/acnamesp.h>
51
52#define _COMPONENT          ACPI_EVENTS
53        ACPI_MODULE_NAME    ("evxfgpe")
54
55
56#if (!ACPI_REDUCED_HARDWARE) /* Entire module */
57/*******************************************************************************
58 *
59 * FUNCTION:    AcpiUpdateAllGpes
60 *
61 * PARAMETERS:  None
62 *
63 * RETURN:      Status
64 *
65 * DESCRIPTION: Complete GPE initialization and enable all GPEs that have
66 *              associated _Lxx or _Exx methods and are not pointed to by any
67 *              device _PRW methods (this indicates that these GPEs are
68 *              generally intended for system or device wakeup. Such GPEs
69 *              have to be enabled directly when the devices whose _PRW
70 *              methods point to them are set up for wakeup signaling.)
71 *
72 * NOTE: Should be called after any GPEs are added to the system. Primarily,
73 * after the system _PRW methods have been run, but also after a GPE Block
74 * Device has been added or if any new GPE methods have been added via a
75 * dynamic table load.
76 *
77 ******************************************************************************/
78
79ACPI_STATUS
80AcpiUpdateAllGpes (
81    void)
82{
83    ACPI_STATUS             Status;
84
85
86    ACPI_FUNCTION_TRACE (AcpiUpdateGpes);
87
88
89    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
90    if (ACPI_FAILURE (Status))
91    {
92        return_ACPI_STATUS (Status);
93    }
94
95    if (AcpiGbl_AllGpesInitialized)
96    {
97        goto UnlockAndExit;
98    }
99
100    Status = AcpiEvWalkGpeList (AcpiEvInitializeGpeBlock, NULL);
101    if (ACPI_SUCCESS (Status))
102    {
103        AcpiGbl_AllGpesInitialized = TRUE;
104    }
105
106UnlockAndExit:
107    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
108    return_ACPI_STATUS (Status);
109}
110
111ACPI_EXPORT_SYMBOL (AcpiUpdateAllGpes)
112
113
114/*******************************************************************************
115 *
116 * FUNCTION:    AcpiEnableGpe
117 *
118 * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
119 *              GpeNumber           - GPE level within the GPE block
120 *
121 * RETURN:      Status
122 *
123 * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is
124 *              hardware-enabled.
125 *
126 ******************************************************************************/
127
128ACPI_STATUS
129AcpiEnableGpe (
130    ACPI_HANDLE             GpeDevice,
131    UINT32                  GpeNumber)
132{
133    ACPI_STATUS             Status = AE_BAD_PARAMETER;
134    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
135    ACPI_CPU_FLAGS          Flags;
136
137
138    ACPI_FUNCTION_TRACE (AcpiEnableGpe);
139
140
141    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
142
143    /* Ensure that we have a valid GPE number */
144
145    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
146    if (GpeEventInfo)
147    {
148        Status = AcpiEvAddGpeReference (GpeEventInfo);
149    }
150
151    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
152    return_ACPI_STATUS (Status);
153}
154
155ACPI_EXPORT_SYMBOL (AcpiEnableGpe)
156
157
158/*******************************************************************************
159 *
160 * FUNCTION:    AcpiDisableGpe
161 *
162 * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
163 *              GpeNumber           - GPE level within the GPE block
164 *
165 * RETURN:      Status
166 *
167 * DESCRIPTION: Remove a reference to a GPE. When the last reference is
168 *              removed, only then is the GPE disabled (for runtime GPEs), or
169 *              the GPE mask bit disabled (for wake GPEs)
170 *
171 ******************************************************************************/
172
173ACPI_STATUS
174AcpiDisableGpe (
175    ACPI_HANDLE             GpeDevice,
176    UINT32                  GpeNumber)
177{
178    ACPI_STATUS             Status = AE_BAD_PARAMETER;
179    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
180    ACPI_CPU_FLAGS          Flags;
181
182
183    ACPI_FUNCTION_TRACE (AcpiDisableGpe);
184
185
186    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
187
188    /* Ensure that we have a valid GPE number */
189
190    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
191    if (GpeEventInfo)
192    {
193        Status = AcpiEvRemoveGpeReference (GpeEventInfo);
194    }
195
196    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
197    return_ACPI_STATUS (Status);
198}
199
200ACPI_EXPORT_SYMBOL (AcpiDisableGpe)
201
202
203/*******************************************************************************
204 *
205 * FUNCTION:    AcpiSetGpe
206 *
207 * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
208 *              GpeNumber           - GPE level within the GPE block
209 *              Action              - ACPI_GPE_ENABLE or ACPI_GPE_DISABLE
210 *
211 * RETURN:      Status
212 *
213 * DESCRIPTION: Enable or disable an individual GPE. This function bypasses
214 *              the reference count mechanism used in the AcpiEnableGpe and
215 *              AcpiDisableGpe interfaces -- and should be used with care.
216 *
217 * Note: Typically used to disable a runtime GPE for short period of time,
218 * then re-enable it, without disturbing the existing reference counts. This
219 * is useful, for example, in the Embedded Controller (EC) driver.
220 *
221 ******************************************************************************/
222
223ACPI_STATUS
224AcpiSetGpe (
225    ACPI_HANDLE             GpeDevice,
226    UINT32                  GpeNumber,
227    UINT8                   Action)
228{
229    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
230    ACPI_STATUS             Status;
231    ACPI_CPU_FLAGS          Flags;
232
233
234    ACPI_FUNCTION_TRACE (AcpiSetGpe);
235
236
237    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
238
239    /* Ensure that we have a valid GPE number */
240
241    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
242    if (!GpeEventInfo)
243    {
244        Status = AE_BAD_PARAMETER;
245        goto UnlockAndExit;
246    }
247
248    /* Perform the action */
249
250    switch (Action)
251    {
252    case ACPI_GPE_ENABLE:
253        Status = AcpiEvEnableGpe (GpeEventInfo);
254        break;
255
256    case ACPI_GPE_DISABLE:
257        Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE);
258        break;
259
260    default:
261        Status = AE_BAD_PARAMETER;
262        break;
263    }
264
265UnlockAndExit:
266    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
267    return_ACPI_STATUS (Status);
268}
269
270ACPI_EXPORT_SYMBOL (AcpiSetGpe)
271
272
273/*******************************************************************************
274 *
275 * FUNCTION:    AcpiSetupGpeForWake
276 *
277 * PARAMETERS:  WakeDevice          - Device associated with the GPE (via _PRW)
278 *              GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
279 *              GpeNumber           - GPE level within the GPE block
280 *
281 * RETURN:      Status
282 *
283 * DESCRIPTION: Mark a GPE as having the ability to wake the system. This
284 *              interface is intended to be used as the host executes the
285 *              _PRW methods (Power Resources for Wake) in the system tables.
286 *              Each _PRW appears under a Device Object (The WakeDevice), and
287 *              contains the info for the wake GPE associated with the
288 *              WakeDevice.
289 *
290 ******************************************************************************/
291
292ACPI_STATUS
293AcpiSetupGpeForWake (
294    ACPI_HANDLE             WakeDevice,
295    ACPI_HANDLE             GpeDevice,
296    UINT32                  GpeNumber)
297{
298    ACPI_STATUS             Status;
299    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
300    ACPI_NAMESPACE_NODE     *DeviceNode;
301    ACPI_GPE_NOTIFY_INFO    *NewNotify, *Notify;
302    ACPI_CPU_FLAGS          Flags;
303
304
305    ACPI_FUNCTION_TRACE (AcpiSetupGpeForWake);
306
307
308    /* Parameter Validation */
309
310    if (!WakeDevice)
311    {
312        /*
313         * By forcing WakeDevice to be valid, we automatically enable the
314         * implicit notify feature on all hosts.
315         */
316        return_ACPI_STATUS (AE_BAD_PARAMETER);
317    }
318
319    /* Handle root object case */
320
321    if (WakeDevice == ACPI_ROOT_OBJECT)
322    {
323        DeviceNode = AcpiGbl_RootNode;
324    }
325    else
326    {
327        DeviceNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, WakeDevice);
328    }
329
330    /* Validate WakeDevice is of type Device */
331
332    if (DeviceNode->Type != ACPI_TYPE_DEVICE)
333    {
334        return_ACPI_STATUS (AE_BAD_PARAMETER);
335    }
336
337    NewNotify = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_NOTIFY_INFO));
338    if (!NewNotify)
339    {
340        return_ACPI_STATUS (AE_NO_MEMORY);
341    }
342
343    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
344
345    /* Ensure that we have a valid GPE number */
346
347    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
348    if (!GpeEventInfo)
349    {
350        Status = AE_BAD_PARAMETER;
351        goto UnlockAndExit;
352    }
353
354    /*
355     * If there is no method or handler for this GPE, then the
356     * WakeDevice will be notified whenever this GPE fires. This is
357     * known as an "implicit notify". Note: The GPE is assumed to be
358     * level-triggered (for windows compatibility).
359     */
360    if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
361            ACPI_GPE_DISPATCH_NONE)
362    {
363        /*
364         * This is the first device for implicit notify on this GPE.
365         * Just set the flags here, and enter the NOTIFY block below.
366         */
367        GpeEventInfo->Flags =
368            (ACPI_GPE_DISPATCH_NOTIFY | ACPI_GPE_LEVEL_TRIGGERED);
369    }
370
371    /*
372     * If we already have an implicit notify on this GPE, add
373     * this device to the notify list.
374     */
375    if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
376            ACPI_GPE_DISPATCH_NOTIFY)
377    {
378        /* Ensure that the device is not already in the list */
379
380        Notify = GpeEventInfo->Dispatch.NotifyList;
381        while (Notify)
382        {
383            if (Notify->DeviceNode == DeviceNode)
384            {
385                Status = AE_ALREADY_EXISTS;
386                goto UnlockAndExit;
387            }
388            Notify = Notify->Next;
389        }
390
391        /* Add this device to the notify list for this GPE */
392
393        NewNotify->DeviceNode = DeviceNode;
394        NewNotify->Next = GpeEventInfo->Dispatch.NotifyList;
395        GpeEventInfo->Dispatch.NotifyList = NewNotify;
396        NewNotify = NULL;
397    }
398
399    /* Mark the GPE as a possible wake event */
400
401    GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE;
402    Status = AE_OK;
403
404UnlockAndExit:
405    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
406    if (NewNotify)
407    {
408        ACPI_FREE (NewNotify);
409    }
410    return_ACPI_STATUS (Status);
411}
412
413ACPI_EXPORT_SYMBOL (AcpiSetupGpeForWake)
414
415
416/*******************************************************************************
417 *
418 * FUNCTION:    AcpiSetGpeWakeMask
419 *
420 * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
421 *              GpeNumber           - GPE level within the GPE block
422 *              Action              - Enable or Disable
423 *
424 * RETURN:      Status
425 *
426 * DESCRIPTION: Set or clear the GPE's wakeup enable mask bit. The GPE must
427 *              already be marked as a WAKE GPE.
428 *
429 ******************************************************************************/
430
431ACPI_STATUS
432AcpiSetGpeWakeMask (
433    ACPI_HANDLE             GpeDevice,
434    UINT32                  GpeNumber,
435    UINT8                   Action)
436{
437    ACPI_STATUS             Status = AE_OK;
438    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
439    ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
440    ACPI_CPU_FLAGS          Flags;
441    UINT32                  RegisterBit;
442
443
444    ACPI_FUNCTION_TRACE (AcpiSetGpeWakeMask);
445
446
447    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
448
449    /*
450     * Ensure that we have a valid GPE number and that this GPE is in
451     * fact a wake GPE
452     */
453    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
454    if (!GpeEventInfo)
455    {
456        Status = AE_BAD_PARAMETER;
457        goto UnlockAndExit;
458    }
459
460    if (!(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE))
461    {
462        Status = AE_TYPE;
463        goto UnlockAndExit;
464    }
465
466    GpeRegisterInfo = GpeEventInfo->RegisterInfo;
467    if (!GpeRegisterInfo)
468    {
469        Status = AE_NOT_EXIST;
470        goto UnlockAndExit;
471    }
472
473    RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo, GpeRegisterInfo);
474
475    /* Perform the action */
476
477    switch (Action)
478    {
479    case ACPI_GPE_ENABLE:
480        ACPI_SET_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit);
481        break;
482
483    case ACPI_GPE_DISABLE:
484        ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit);
485        break;
486
487    default:
488        ACPI_ERROR ((AE_INFO, "%u, Invalid action", Action));
489        Status = AE_BAD_PARAMETER;
490        break;
491    }
492
493UnlockAndExit:
494    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
495    return_ACPI_STATUS (Status);
496}
497
498ACPI_EXPORT_SYMBOL (AcpiSetGpeWakeMask)
499
500
501/*******************************************************************************
502 *
503 * FUNCTION:    AcpiClearGpe
504 *
505 * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
506 *              GpeNumber           - GPE level within the GPE block
507 *
508 * RETURN:      Status
509 *
510 * DESCRIPTION: Clear an ACPI event (general purpose)
511 *
512 ******************************************************************************/
513
514ACPI_STATUS
515AcpiClearGpe (
516    ACPI_HANDLE             GpeDevice,
517    UINT32                  GpeNumber)
518{
519    ACPI_STATUS             Status = AE_OK;
520    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
521    ACPI_CPU_FLAGS          Flags;
522
523
524    ACPI_FUNCTION_TRACE (AcpiClearGpe);
525
526
527    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
528
529    /* Ensure that we have a valid GPE number */
530
531    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
532    if (!GpeEventInfo)
533    {
534        Status = AE_BAD_PARAMETER;
535        goto UnlockAndExit;
536    }
537
538    Status = AcpiHwClearGpe (GpeEventInfo);
539
540UnlockAndExit:
541    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
542    return_ACPI_STATUS (Status);
543}
544
545ACPI_EXPORT_SYMBOL (AcpiClearGpe)
546
547
548/*******************************************************************************
549 *
550 * FUNCTION:    AcpiGetGpeStatus
551 *
552 * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
553 *              GpeNumber           - GPE level within the GPE block
554 *              EventStatus         - Where the current status of the event
555 *                                    will be returned
556 *
557 * RETURN:      Status
558 *
559 * DESCRIPTION: Get the current status of a GPE (signalled/not_signalled)
560 *
561 ******************************************************************************/
562
563ACPI_STATUS
564AcpiGetGpeStatus (
565    ACPI_HANDLE             GpeDevice,
566    UINT32                  GpeNumber,
567    ACPI_EVENT_STATUS       *EventStatus)
568{
569    ACPI_STATUS             Status = AE_OK;
570    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
571    ACPI_CPU_FLAGS          Flags;
572
573
574    ACPI_FUNCTION_TRACE (AcpiGetGpeStatus);
575
576
577    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
578
579    /* Ensure that we have a valid GPE number */
580
581    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
582    if (!GpeEventInfo)
583    {
584        Status = AE_BAD_PARAMETER;
585        goto UnlockAndExit;
586    }
587
588    /* Obtain status on the requested GPE number */
589
590    Status = AcpiHwGetGpeStatus (GpeEventInfo, EventStatus);
591
592UnlockAndExit:
593    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
594    return_ACPI_STATUS (Status);
595}
596
597ACPI_EXPORT_SYMBOL (AcpiGetGpeStatus)
598
599
600/*******************************************************************************
601 *
602 * FUNCTION:    AcpiFinishGpe
603 *
604 * PARAMETERS:  GpeDevice           - Namespace node for the GPE Block
605 *                                    (NULL for FADT defined GPEs)
606 *              GpeNumber           - GPE level within the GPE block
607 *
608 * RETURN:      Status
609 *
610 * DESCRIPTION: Clear and conditionally reenable a GPE. This completes the GPE
611 *              processing. Intended for use by asynchronous host-installed
612 *              GPE handlers. The GPE is only reenabled if the EnableForRun bit
613 *              is set in the GPE info.
614 *
615 ******************************************************************************/
616
617ACPI_STATUS
618AcpiFinishGpe (
619    ACPI_HANDLE             GpeDevice,
620    UINT32                  GpeNumber)
621{
622    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
623    ACPI_STATUS             Status;
624    ACPI_CPU_FLAGS          Flags;
625
626
627    ACPI_FUNCTION_TRACE (AcpiFinishGpe);
628
629
630    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
631
632    /* Ensure that we have a valid GPE number */
633
634    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
635    if (!GpeEventInfo)
636    {
637        Status = AE_BAD_PARAMETER;
638        goto UnlockAndExit;
639    }
640
641    Status = AcpiEvFinishGpe (GpeEventInfo);
642
643UnlockAndExit:
644    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
645    return_ACPI_STATUS (Status);
646}
647
648ACPI_EXPORT_SYMBOL (AcpiFinishGpe)
649
650
651/******************************************************************************
652 *
653 * FUNCTION:    AcpiDisableAllGpes
654 *
655 * PARAMETERS:  None
656 *
657 * RETURN:      Status
658 *
659 * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
660 *
661 ******************************************************************************/
662
663ACPI_STATUS
664AcpiDisableAllGpes (
665    void)
666{
667    ACPI_STATUS             Status;
668
669
670    ACPI_FUNCTION_TRACE (AcpiDisableAllGpes);
671
672
673    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
674    if (ACPI_FAILURE (Status))
675    {
676        return_ACPI_STATUS (Status);
677    }
678
679    Status = AcpiHwDisableAllGpes ();
680    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
681
682    return_ACPI_STATUS (Status);
683}
684
685ACPI_EXPORT_SYMBOL (AcpiDisableAllGpes)
686
687
688/******************************************************************************
689 *
690 * FUNCTION:    AcpiEnableAllRuntimeGpes
691 *
692 * PARAMETERS:  None
693 *
694 * RETURN:      Status
695 *
696 * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
697 *
698 ******************************************************************************/
699
700ACPI_STATUS
701AcpiEnableAllRuntimeGpes (
702    void)
703{
704    ACPI_STATUS             Status;
705
706
707    ACPI_FUNCTION_TRACE (AcpiEnableAllRuntimeGpes);
708
709
710    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
711    if (ACPI_FAILURE (Status))
712    {
713        return_ACPI_STATUS (Status);
714    }
715
716    Status = AcpiHwEnableAllRuntimeGpes ();
717    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
718
719    return_ACPI_STATUS (Status);
720}
721
722ACPI_EXPORT_SYMBOL (AcpiEnableAllRuntimeGpes)
723
724
725/*******************************************************************************
726 *
727 * FUNCTION:    AcpiInstallGpeBlock
728 *
729 * PARAMETERS:  GpeDevice           - Handle to the parent GPE Block Device
730 *              GpeBlockAddress     - Address and SpaceID
731 *              RegisterCount       - Number of GPE register pairs in the block
732 *              InterruptNumber     - H/W interrupt for the block
733 *
734 * RETURN:      Status
735 *
736 * DESCRIPTION: Create and Install a block of GPE registers. The GPEs are not
737 *              enabled here.
738 *
739 ******************************************************************************/
740
741ACPI_STATUS
742AcpiInstallGpeBlock (
743    ACPI_HANDLE             GpeDevice,
744    ACPI_GENERIC_ADDRESS    *GpeBlockAddress,
745    UINT32                  RegisterCount,
746    UINT32                  InterruptNumber)
747{
748    ACPI_STATUS             Status;
749    ACPI_OPERAND_OBJECT     *ObjDesc;
750    ACPI_NAMESPACE_NODE     *Node;
751    ACPI_GPE_BLOCK_INFO     *GpeBlock;
752
753
754    ACPI_FUNCTION_TRACE (AcpiInstallGpeBlock);
755
756
757    if ((!GpeDevice)       ||
758        (!GpeBlockAddress) ||
759        (!RegisterCount))
760    {
761        return_ACPI_STATUS (AE_BAD_PARAMETER);
762    }
763
764    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
765    if (ACPI_FAILURE (Status))
766    {
767        return (Status);
768    }
769
770    Node = AcpiNsValidateHandle (GpeDevice);
771    if (!Node)
772    {
773        Status = AE_BAD_PARAMETER;
774        goto UnlockAndExit;
775    }
776
777    /*
778     * For user-installed GPE Block Devices, the GpeBlockBaseNumber
779     * is always zero
780     */
781    Status = AcpiEvCreateGpeBlock (Node, GpeBlockAddress, RegisterCount,
782                0, InterruptNumber, &GpeBlock);
783    if (ACPI_FAILURE (Status))
784    {
785        goto UnlockAndExit;
786    }
787
788    /* Install block in the DeviceObject attached to the node */
789
790    ObjDesc = AcpiNsGetAttachedObject (Node);
791    if (!ObjDesc)
792    {
793        /*
794         * No object, create a new one (Device nodes do not always have
795         * an attached object)
796         */
797        ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_DEVICE);
798        if (!ObjDesc)
799        {
800            Status = AE_NO_MEMORY;
801            goto UnlockAndExit;
802        }
803
804        Status = AcpiNsAttachObject (Node, ObjDesc, ACPI_TYPE_DEVICE);
805
806        /* Remove local reference to the object */
807
808        AcpiUtRemoveReference (ObjDesc);
809        if (ACPI_FAILURE (Status))
810        {
811            goto UnlockAndExit;
812        }
813    }
814
815    /* Now install the GPE block in the DeviceObject */
816
817    ObjDesc->Device.GpeBlock = GpeBlock;
818
819
820UnlockAndExit:
821    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
822    return_ACPI_STATUS (Status);
823}
824
825ACPI_EXPORT_SYMBOL (AcpiInstallGpeBlock)
826
827
828/*******************************************************************************
829 *
830 * FUNCTION:    AcpiRemoveGpeBlock
831 *
832 * PARAMETERS:  GpeDevice           - Handle to the parent GPE Block Device
833 *
834 * RETURN:      Status
835 *
836 * DESCRIPTION: Remove a previously installed block of GPE registers
837 *
838 ******************************************************************************/
839
840ACPI_STATUS
841AcpiRemoveGpeBlock (
842    ACPI_HANDLE             GpeDevice)
843{
844    ACPI_OPERAND_OBJECT     *ObjDesc;
845    ACPI_STATUS             Status;
846    ACPI_NAMESPACE_NODE     *Node;
847
848
849    ACPI_FUNCTION_TRACE (AcpiRemoveGpeBlock);
850
851
852    if (!GpeDevice)
853    {
854        return_ACPI_STATUS (AE_BAD_PARAMETER);
855    }
856
857    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
858    if (ACPI_FAILURE (Status))
859    {
860        return (Status);
861    }
862
863    Node = AcpiNsValidateHandle (GpeDevice);
864    if (!Node)
865    {
866        Status = AE_BAD_PARAMETER;
867        goto UnlockAndExit;
868    }
869
870    /* Get the DeviceObject attached to the node */
871
872    ObjDesc = AcpiNsGetAttachedObject (Node);
873    if (!ObjDesc ||
874        !ObjDesc->Device.GpeBlock)
875    {
876        return_ACPI_STATUS (AE_NULL_OBJECT);
877    }
878
879    /* Delete the GPE block (but not the DeviceObject) */
880
881    Status = AcpiEvDeleteGpeBlock (ObjDesc->Device.GpeBlock);
882    if (ACPI_SUCCESS (Status))
883    {
884        ObjDesc->Device.GpeBlock = NULL;
885    }
886
887UnlockAndExit:
888    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
889    return_ACPI_STATUS (Status);
890}
891
892ACPI_EXPORT_SYMBOL (AcpiRemoveGpeBlock)
893
894
895/*******************************************************************************
896 *
897 * FUNCTION:    AcpiGetGpeDevice
898 *
899 * PARAMETERS:  Index               - System GPE index (0-CurrentGpeCount)
900 *              GpeDevice           - Where the parent GPE Device is returned
901 *
902 * RETURN:      Status
903 *
904 * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL
905 *              gpe device indicates that the gpe number is contained in one of
906 *              the FADT-defined gpe blocks. Otherwise, the GPE block device.
907 *
908 ******************************************************************************/
909
910ACPI_STATUS
911AcpiGetGpeDevice (
912    UINT32                  Index,
913    ACPI_HANDLE             *GpeDevice)
914{
915    ACPI_GPE_DEVICE_INFO    Info;
916    ACPI_STATUS             Status;
917
918
919    ACPI_FUNCTION_TRACE (AcpiGetGpeDevice);
920
921
922    if (!GpeDevice)
923    {
924        return_ACPI_STATUS (AE_BAD_PARAMETER);
925    }
926
927    if (Index >= AcpiCurrentGpeCount)
928    {
929        return_ACPI_STATUS (AE_NOT_EXIST);
930    }
931
932    /* Setup and walk the GPE list */
933
934    Info.Index = Index;
935    Info.Status = AE_NOT_EXIST;
936    Info.GpeDevice = NULL;
937    Info.NextBlockBaseIndex = 0;
938
939    Status = AcpiEvWalkGpeList (AcpiEvGetGpeDevice, &Info);
940    if (ACPI_FAILURE (Status))
941    {
942        return_ACPI_STATUS (Status);
943    }
944
945    *GpeDevice = ACPI_CAST_PTR (ACPI_HANDLE, Info.GpeDevice);
946    return_ACPI_STATUS (Info.Status);
947}
948
949ACPI_EXPORT_SYMBOL (AcpiGetGpeDevice)
950
951#endif /* !ACPI_REDUCED_HARDWARE */
952