evxfgpe.c revision 237412
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    *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    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
338
339    /* Ensure that we have a valid GPE number */
340
341    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
342    if (!GpeEventInfo)
343    {
344        Status = AE_BAD_PARAMETER;
345        goto UnlockAndExit;
346    }
347
348    /*
349     * If there is no method or handler for this GPE, then the
350     * WakeDevice will be notified whenever this GPE fires. This is
351     * known as an "implicit notify". Note: The GPE is assumed to be
352     * level-triggered (for windows compatibility).
353     */
354    if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
355            ACPI_GPE_DISPATCH_NONE)
356    {
357        /*
358         * This is the first device for implicit notify on this GPE.
359         * Just set the flags here, and enter the NOTIFY block below.
360         */
361        GpeEventInfo->Flags =
362            (ACPI_GPE_DISPATCH_NOTIFY | ACPI_GPE_LEVEL_TRIGGERED);
363    }
364
365    /*
366     * If we already have an implicit notify on this GPE, add
367     * this device to the notify list.
368     */
369    if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
370            ACPI_GPE_DISPATCH_NOTIFY)
371    {
372        /* Ensure that the device is not already in the list */
373
374        Notify = GpeEventInfo->Dispatch.NotifyList;
375        while (Notify)
376        {
377            if (Notify->DeviceNode == DeviceNode)
378            {
379                Status = AE_ALREADY_EXISTS;
380                goto UnlockAndExit;
381            }
382            Notify = Notify->Next;
383        }
384
385        /* Add this device to the notify list for this GPE */
386
387        Notify = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_NOTIFY_INFO));
388        if (!Notify)
389        {
390            Status = AE_NO_MEMORY;
391            goto UnlockAndExit;
392        }
393
394        Notify->DeviceNode = DeviceNode;
395        Notify->Next = GpeEventInfo->Dispatch.NotifyList;
396        GpeEventInfo->Dispatch.NotifyList = Notify;
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    return_ACPI_STATUS (Status);
407}
408
409ACPI_EXPORT_SYMBOL (AcpiSetupGpeForWake)
410
411
412/*******************************************************************************
413 *
414 * FUNCTION:    AcpiSetGpeWakeMask
415 *
416 * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
417 *              GpeNumber           - GPE level within the GPE block
418 *              Action              - Enable or Disable
419 *
420 * RETURN:      Status
421 *
422 * DESCRIPTION: Set or clear the GPE's wakeup enable mask bit. The GPE must
423 *              already be marked as a WAKE GPE.
424 *
425 ******************************************************************************/
426
427ACPI_STATUS
428AcpiSetGpeWakeMask (
429    ACPI_HANDLE             GpeDevice,
430    UINT32                  GpeNumber,
431    UINT8                   Action)
432{
433    ACPI_STATUS             Status = AE_OK;
434    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
435    ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
436    ACPI_CPU_FLAGS          Flags;
437    UINT32                  RegisterBit;
438
439
440    ACPI_FUNCTION_TRACE (AcpiSetGpeWakeMask);
441
442
443    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
444
445    /*
446     * Ensure that we have a valid GPE number and that this GPE is in
447     * fact a wake GPE
448     */
449    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
450    if (!GpeEventInfo)
451    {
452        Status = AE_BAD_PARAMETER;
453        goto UnlockAndExit;
454    }
455
456    if (!(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE))
457    {
458        Status = AE_TYPE;
459        goto UnlockAndExit;
460    }
461
462    GpeRegisterInfo = GpeEventInfo->RegisterInfo;
463    if (!GpeRegisterInfo)
464    {
465        Status = AE_NOT_EXIST;
466        goto UnlockAndExit;
467    }
468
469    RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo, GpeRegisterInfo);
470
471    /* Perform the action */
472
473    switch (Action)
474    {
475    case ACPI_GPE_ENABLE:
476        ACPI_SET_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit);
477        break;
478
479    case ACPI_GPE_DISABLE:
480        ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit);
481        break;
482
483    default:
484        ACPI_ERROR ((AE_INFO, "%u, Invalid action", Action));
485        Status = AE_BAD_PARAMETER;
486        break;
487    }
488
489UnlockAndExit:
490    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
491    return_ACPI_STATUS (Status);
492}
493
494ACPI_EXPORT_SYMBOL (AcpiSetGpeWakeMask)
495
496
497/*******************************************************************************
498 *
499 * FUNCTION:    AcpiClearGpe
500 *
501 * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
502 *              GpeNumber           - GPE level within the GPE block
503 *
504 * RETURN:      Status
505 *
506 * DESCRIPTION: Clear an ACPI event (general purpose)
507 *
508 ******************************************************************************/
509
510ACPI_STATUS
511AcpiClearGpe (
512    ACPI_HANDLE             GpeDevice,
513    UINT32                  GpeNumber)
514{
515    ACPI_STATUS             Status = AE_OK;
516    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
517    ACPI_CPU_FLAGS          Flags;
518
519
520    ACPI_FUNCTION_TRACE (AcpiClearGpe);
521
522
523    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
524
525    /* Ensure that we have a valid GPE number */
526
527    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
528    if (!GpeEventInfo)
529    {
530        Status = AE_BAD_PARAMETER;
531        goto UnlockAndExit;
532    }
533
534    Status = AcpiHwClearGpe (GpeEventInfo);
535
536UnlockAndExit:
537    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
538    return_ACPI_STATUS (Status);
539}
540
541ACPI_EXPORT_SYMBOL (AcpiClearGpe)
542
543
544/*******************************************************************************
545 *
546 * FUNCTION:    AcpiGetGpeStatus
547 *
548 * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
549 *              GpeNumber           - GPE level within the GPE block
550 *              EventStatus         - Where the current status of the event
551 *                                    will be returned
552 *
553 * RETURN:      Status
554 *
555 * DESCRIPTION: Get the current status of a GPE (signalled/not_signalled)
556 *
557 ******************************************************************************/
558
559ACPI_STATUS
560AcpiGetGpeStatus (
561    ACPI_HANDLE             GpeDevice,
562    UINT32                  GpeNumber,
563    ACPI_EVENT_STATUS       *EventStatus)
564{
565    ACPI_STATUS             Status = AE_OK;
566    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
567    ACPI_CPU_FLAGS          Flags;
568
569
570    ACPI_FUNCTION_TRACE (AcpiGetGpeStatus);
571
572
573    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
574
575    /* Ensure that we have a valid GPE number */
576
577    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
578    if (!GpeEventInfo)
579    {
580        Status = AE_BAD_PARAMETER;
581        goto UnlockAndExit;
582    }
583
584    /* Obtain status on the requested GPE number */
585
586    Status = AcpiHwGetGpeStatus (GpeEventInfo, EventStatus);
587
588UnlockAndExit:
589    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
590    return_ACPI_STATUS (Status);
591}
592
593ACPI_EXPORT_SYMBOL (AcpiGetGpeStatus)
594
595
596/*******************************************************************************
597 *
598 * FUNCTION:    AcpiFinishGpe
599 *
600 * PARAMETERS:  GpeDevice           - Namespace node for the GPE Block
601 *                                    (NULL for FADT defined GPEs)
602 *              GpeNumber           - GPE level within the GPE block
603 *
604 * RETURN:      Status
605 *
606 * DESCRIPTION: Clear and conditionally reenable a GPE. This completes the GPE
607 *              processing. Intended for use by asynchronous host-installed
608 *              GPE handlers. The GPE is only reenabled if the EnableForRun bit
609 *              is set in the GPE info.
610 *
611 ******************************************************************************/
612
613ACPI_STATUS
614AcpiFinishGpe (
615    ACPI_HANDLE             GpeDevice,
616    UINT32                  GpeNumber)
617{
618    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
619    ACPI_STATUS             Status;
620    ACPI_CPU_FLAGS          Flags;
621
622
623    ACPI_FUNCTION_TRACE (AcpiFinishGpe);
624
625
626    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
627
628    /* Ensure that we have a valid GPE number */
629
630    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
631    if (!GpeEventInfo)
632    {
633        Status = AE_BAD_PARAMETER;
634        goto UnlockAndExit;
635    }
636
637    Status = AcpiEvFinishGpe (GpeEventInfo);
638
639UnlockAndExit:
640    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
641    return_ACPI_STATUS (Status);
642}
643
644ACPI_EXPORT_SYMBOL (AcpiFinishGpe)
645
646
647/******************************************************************************
648 *
649 * FUNCTION:    AcpiDisableAllGpes
650 *
651 * PARAMETERS:  None
652 *
653 * RETURN:      Status
654 *
655 * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
656 *
657 ******************************************************************************/
658
659ACPI_STATUS
660AcpiDisableAllGpes (
661    void)
662{
663    ACPI_STATUS             Status;
664
665
666    ACPI_FUNCTION_TRACE (AcpiDisableAllGpes);
667
668
669    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
670    if (ACPI_FAILURE (Status))
671    {
672        return_ACPI_STATUS (Status);
673    }
674
675    Status = AcpiHwDisableAllGpes ();
676    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
677
678    return_ACPI_STATUS (Status);
679}
680
681ACPI_EXPORT_SYMBOL (AcpiDisableAllGpes)
682
683
684/******************************************************************************
685 *
686 * FUNCTION:    AcpiEnableAllRuntimeGpes
687 *
688 * PARAMETERS:  None
689 *
690 * RETURN:      Status
691 *
692 * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
693 *
694 ******************************************************************************/
695
696ACPI_STATUS
697AcpiEnableAllRuntimeGpes (
698    void)
699{
700    ACPI_STATUS             Status;
701
702
703    ACPI_FUNCTION_TRACE (AcpiEnableAllRuntimeGpes);
704
705
706    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
707    if (ACPI_FAILURE (Status))
708    {
709        return_ACPI_STATUS (Status);
710    }
711
712    Status = AcpiHwEnableAllRuntimeGpes ();
713    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
714
715    return_ACPI_STATUS (Status);
716}
717
718ACPI_EXPORT_SYMBOL (AcpiEnableAllRuntimeGpes)
719
720
721/*******************************************************************************
722 *
723 * FUNCTION:    AcpiInstallGpeBlock
724 *
725 * PARAMETERS:  GpeDevice           - Handle to the parent GPE Block Device
726 *              GpeBlockAddress     - Address and SpaceID
727 *              RegisterCount       - Number of GPE register pairs in the block
728 *              InterruptNumber     - H/W interrupt for the block
729 *
730 * RETURN:      Status
731 *
732 * DESCRIPTION: Create and Install a block of GPE registers. The GPEs are not
733 *              enabled here.
734 *
735 ******************************************************************************/
736
737ACPI_STATUS
738AcpiInstallGpeBlock (
739    ACPI_HANDLE             GpeDevice,
740    ACPI_GENERIC_ADDRESS    *GpeBlockAddress,
741    UINT32                  RegisterCount,
742    UINT32                  InterruptNumber)
743{
744    ACPI_STATUS             Status;
745    ACPI_OPERAND_OBJECT     *ObjDesc;
746    ACPI_NAMESPACE_NODE     *Node;
747    ACPI_GPE_BLOCK_INFO     *GpeBlock;
748
749
750    ACPI_FUNCTION_TRACE (AcpiInstallGpeBlock);
751
752
753    if ((!GpeDevice)       ||
754        (!GpeBlockAddress) ||
755        (!RegisterCount))
756    {
757        return_ACPI_STATUS (AE_BAD_PARAMETER);
758    }
759
760    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
761    if (ACPI_FAILURE (Status))
762    {
763        return (Status);
764    }
765
766    Node = AcpiNsValidateHandle (GpeDevice);
767    if (!Node)
768    {
769        Status = AE_BAD_PARAMETER;
770        goto UnlockAndExit;
771    }
772
773    /*
774     * For user-installed GPE Block Devices, the GpeBlockBaseNumber
775     * is always zero
776     */
777    Status = AcpiEvCreateGpeBlock (Node, GpeBlockAddress, RegisterCount,
778                0, InterruptNumber, &GpeBlock);
779    if (ACPI_FAILURE (Status))
780    {
781        goto UnlockAndExit;
782    }
783
784    /* Install block in the DeviceObject attached to the node */
785
786    ObjDesc = AcpiNsGetAttachedObject (Node);
787    if (!ObjDesc)
788    {
789        /*
790         * No object, create a new one (Device nodes do not always have
791         * an attached object)
792         */
793        ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_DEVICE);
794        if (!ObjDesc)
795        {
796            Status = AE_NO_MEMORY;
797            goto UnlockAndExit;
798        }
799
800        Status = AcpiNsAttachObject (Node, ObjDesc, ACPI_TYPE_DEVICE);
801
802        /* Remove local reference to the object */
803
804        AcpiUtRemoveReference (ObjDesc);
805        if (ACPI_FAILURE (Status))
806        {
807            goto UnlockAndExit;
808        }
809    }
810
811    /* Now install the GPE block in the DeviceObject */
812
813    ObjDesc->Device.GpeBlock = GpeBlock;
814
815
816UnlockAndExit:
817    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
818    return_ACPI_STATUS (Status);
819}
820
821ACPI_EXPORT_SYMBOL (AcpiInstallGpeBlock)
822
823
824/*******************************************************************************
825 *
826 * FUNCTION:    AcpiRemoveGpeBlock
827 *
828 * PARAMETERS:  GpeDevice           - Handle to the parent GPE Block Device
829 *
830 * RETURN:      Status
831 *
832 * DESCRIPTION: Remove a previously installed block of GPE registers
833 *
834 ******************************************************************************/
835
836ACPI_STATUS
837AcpiRemoveGpeBlock (
838    ACPI_HANDLE             GpeDevice)
839{
840    ACPI_OPERAND_OBJECT     *ObjDesc;
841    ACPI_STATUS             Status;
842    ACPI_NAMESPACE_NODE     *Node;
843
844
845    ACPI_FUNCTION_TRACE (AcpiRemoveGpeBlock);
846
847
848    if (!GpeDevice)
849    {
850        return_ACPI_STATUS (AE_BAD_PARAMETER);
851    }
852
853    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
854    if (ACPI_FAILURE (Status))
855    {
856        return (Status);
857    }
858
859    Node = AcpiNsValidateHandle (GpeDevice);
860    if (!Node)
861    {
862        Status = AE_BAD_PARAMETER;
863        goto UnlockAndExit;
864    }
865
866    /* Get the DeviceObject attached to the node */
867
868    ObjDesc = AcpiNsGetAttachedObject (Node);
869    if (!ObjDesc ||
870        !ObjDesc->Device.GpeBlock)
871    {
872        return_ACPI_STATUS (AE_NULL_OBJECT);
873    }
874
875    /* Delete the GPE block (but not the DeviceObject) */
876
877    Status = AcpiEvDeleteGpeBlock (ObjDesc->Device.GpeBlock);
878    if (ACPI_SUCCESS (Status))
879    {
880        ObjDesc->Device.GpeBlock = NULL;
881    }
882
883UnlockAndExit:
884    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
885    return_ACPI_STATUS (Status);
886}
887
888ACPI_EXPORT_SYMBOL (AcpiRemoveGpeBlock)
889
890
891/*******************************************************************************
892 *
893 * FUNCTION:    AcpiGetGpeDevice
894 *
895 * PARAMETERS:  Index               - System GPE index (0-CurrentGpeCount)
896 *              GpeDevice           - Where the parent GPE Device is returned
897 *
898 * RETURN:      Status
899 *
900 * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL
901 *              gpe device indicates that the gpe number is contained in one of
902 *              the FADT-defined gpe blocks. Otherwise, the GPE block device.
903 *
904 ******************************************************************************/
905
906ACPI_STATUS
907AcpiGetGpeDevice (
908    UINT32                  Index,
909    ACPI_HANDLE             *GpeDevice)
910{
911    ACPI_GPE_DEVICE_INFO    Info;
912    ACPI_STATUS             Status;
913
914
915    ACPI_FUNCTION_TRACE (AcpiGetGpeDevice);
916
917
918    if (!GpeDevice)
919    {
920        return_ACPI_STATUS (AE_BAD_PARAMETER);
921    }
922
923    if (Index >= AcpiCurrentGpeCount)
924    {
925        return_ACPI_STATUS (AE_NOT_EXIST);
926    }
927
928    /* Setup and walk the GPE list */
929
930    Info.Index = Index;
931    Info.Status = AE_NOT_EXIST;
932    Info.GpeDevice = NULL;
933    Info.NextBlockBaseIndex = 0;
934
935    Status = AcpiEvWalkGpeList (AcpiEvGetGpeDevice, &Info);
936    if (ACPI_FAILURE (Status))
937    {
938        return_ACPI_STATUS (Status);
939    }
940
941    *GpeDevice = ACPI_CAST_PTR (ACPI_HANDLE, Info.GpeDevice);
942    return_ACPI_STATUS (Info.Status);
943}
944
945ACPI_EXPORT_SYMBOL (AcpiGetGpeDevice)
946
947#endif /* !ACPI_REDUCED_HARDWARE */
948