evxfgpe.c revision 1.1.1.4 1 /******************************************************************************
2 *
3 * Module Name: evxfgpe - External Interfaces for General Purpose Events (GPEs)
4 *
5 *****************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2014, 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 #define __EVXFGPE_C__
45 #define EXPORT_ACPI_INTERFACES
46
47 #include "acpi.h"
48 #include "accommon.h"
49 #include "acevents.h"
50 #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
79 ACPI_STATUS
80 AcpiUpdateAllGpes (
81 void)
82 {
83 ACPI_STATUS Status;
84
85
86 ACPI_FUNCTION_TRACE (AcpiUpdateAllGpes);
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
106 UnlockAndExit:
107 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
108 return_ACPI_STATUS (Status);
109 }
110
111 ACPI_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
128 ACPI_STATUS
129 AcpiEnableGpe (
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 /*
144 * Ensure that we have a valid GPE number and that there is some way
145 * of handling the GPE (handler or a GPE method). In other words, we
146 * won't allow a valid GPE to be enabled if there is no way to handle it.
147 */
148 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
149 if (GpeEventInfo)
150 {
151 if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) !=
152 ACPI_GPE_DISPATCH_NONE)
153 {
154 Status = AcpiEvAddGpeReference (GpeEventInfo);
155 }
156 else
157 {
158 Status = AE_NO_HANDLER;
159 }
160 }
161
162 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
163 return_ACPI_STATUS (Status);
164 }
165
166 ACPI_EXPORT_SYMBOL (AcpiEnableGpe)
167
168
169 /*******************************************************************************
170 *
171 * FUNCTION: AcpiDisableGpe
172 *
173 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1
174 * GpeNumber - GPE level within the GPE block
175 *
176 * RETURN: Status
177 *
178 * DESCRIPTION: Remove a reference to a GPE. When the last reference is
179 * removed, only then is the GPE disabled (for runtime GPEs), or
180 * the GPE mask bit disabled (for wake GPEs)
181 *
182 ******************************************************************************/
183
184 ACPI_STATUS
185 AcpiDisableGpe (
186 ACPI_HANDLE GpeDevice,
187 UINT32 GpeNumber)
188 {
189 ACPI_STATUS Status = AE_BAD_PARAMETER;
190 ACPI_GPE_EVENT_INFO *GpeEventInfo;
191 ACPI_CPU_FLAGS Flags;
192
193
194 ACPI_FUNCTION_TRACE (AcpiDisableGpe);
195
196
197 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
198
199 /* Ensure that we have a valid GPE number */
200
201 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
202 if (GpeEventInfo)
203 {
204 Status = AcpiEvRemoveGpeReference (GpeEventInfo);
205 }
206
207 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
208 return_ACPI_STATUS (Status);
209 }
210
211 ACPI_EXPORT_SYMBOL (AcpiDisableGpe)
212
213
214 /*******************************************************************************
215 *
216 * FUNCTION: AcpiSetGpe
217 *
218 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1
219 * GpeNumber - GPE level within the GPE block
220 * Action - ACPI_GPE_ENABLE or ACPI_GPE_DISABLE
221 *
222 * RETURN: Status
223 *
224 * DESCRIPTION: Enable or disable an individual GPE. This function bypasses
225 * the reference count mechanism used in the AcpiEnableGpe and
226 * AcpiDisableGpe interfaces -- and should be used with care.
227 *
228 * Note: Typically used to disable a runtime GPE for short period of time,
229 * then re-enable it, without disturbing the existing reference counts. This
230 * is useful, for example, in the Embedded Controller (EC) driver.
231 *
232 ******************************************************************************/
233
234 ACPI_STATUS
235 AcpiSetGpe (
236 ACPI_HANDLE GpeDevice,
237 UINT32 GpeNumber,
238 UINT8 Action)
239 {
240 ACPI_GPE_EVENT_INFO *GpeEventInfo;
241 ACPI_STATUS Status;
242 ACPI_CPU_FLAGS Flags;
243
244
245 ACPI_FUNCTION_TRACE (AcpiSetGpe);
246
247
248 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
249
250 /* Ensure that we have a valid GPE number */
251
252 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
253 if (!GpeEventInfo)
254 {
255 Status = AE_BAD_PARAMETER;
256 goto UnlockAndExit;
257 }
258
259 /* Perform the action */
260
261 switch (Action)
262 {
263 case ACPI_GPE_ENABLE:
264
265 Status = AcpiEvEnableGpe (GpeEventInfo);
266 break;
267
268 case ACPI_GPE_DISABLE:
269
270 Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE);
271 break;
272
273 default:
274
275 Status = AE_BAD_PARAMETER;
276 break;
277 }
278
279 UnlockAndExit:
280 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
281 return_ACPI_STATUS (Status);
282 }
283
284 ACPI_EXPORT_SYMBOL (AcpiSetGpe)
285
286
287 /*******************************************************************************
288 *
289 * FUNCTION: AcpiMarkGpeForWake
290 *
291 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1
292 * GpeNumber - GPE level within the GPE block
293 *
294 * RETURN: Status
295 *
296 * DESCRIPTION: Mark a GPE as having the ability to wake the system. Simply
297 * sets the ACPI_GPE_CAN_WAKE flag.
298 *
299 * Some potential callers of AcpiSetupGpeForWake may know in advance that
300 * there won't be any notify handlers installed for device wake notifications
301 * from the given GPE (one example is a button GPE in Linux). For these cases,
302 * AcpiMarkGpeForWake should be used instead of AcpiSetupGpeForWake.
303 * This will set the ACPI_GPE_CAN_WAKE flag for the GPE without trying to
304 * setup implicit wake notification for it (since there's no handler method).
305 *
306 ******************************************************************************/
307
308 ACPI_STATUS
309 AcpiMarkGpeForWake (
310 ACPI_HANDLE GpeDevice,
311 UINT32 GpeNumber)
312 {
313 ACPI_GPE_EVENT_INFO *GpeEventInfo;
314 ACPI_STATUS Status = AE_BAD_PARAMETER;
315 ACPI_CPU_FLAGS Flags;
316
317
318 ACPI_FUNCTION_TRACE (AcpiMarkGpeForWake);
319
320
321 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
322
323 /* Ensure that we have a valid GPE number */
324
325 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
326 if (GpeEventInfo)
327 {
328 /* Mark the GPE as a possible wake event */
329
330 GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE;
331 Status = AE_OK;
332 }
333
334 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
335 return_ACPI_STATUS (Status);
336 }
337
338 ACPI_EXPORT_SYMBOL (AcpiMarkGpeForWake)
339
340
341 /*******************************************************************************
342 *
343 * FUNCTION: AcpiSetupGpeForWake
344 *
345 * PARAMETERS: WakeDevice - Device associated with the GPE (via _PRW)
346 * GpeDevice - Parent GPE Device. NULL for GPE0/GPE1
347 * GpeNumber - GPE level within the GPE block
348 *
349 * RETURN: Status
350 *
351 * DESCRIPTION: Mark a GPE as having the ability to wake the system. This
352 * interface is intended to be used as the host executes the
353 * _PRW methods (Power Resources for Wake) in the system tables.
354 * Each _PRW appears under a Device Object (The WakeDevice), and
355 * contains the info for the wake GPE associated with the
356 * WakeDevice.
357 *
358 ******************************************************************************/
359
360 ACPI_STATUS
361 AcpiSetupGpeForWake (
362 ACPI_HANDLE WakeDevice,
363 ACPI_HANDLE GpeDevice,
364 UINT32 GpeNumber)
365 {
366 ACPI_STATUS Status;
367 ACPI_GPE_EVENT_INFO *GpeEventInfo;
368 ACPI_NAMESPACE_NODE *DeviceNode;
369 ACPI_GPE_NOTIFY_INFO *Notify;
370 ACPI_GPE_NOTIFY_INFO *NewNotify;
371 ACPI_CPU_FLAGS Flags;
372
373
374 ACPI_FUNCTION_TRACE (AcpiSetupGpeForWake);
375
376
377 /* Parameter Validation */
378
379 if (!WakeDevice)
380 {
381 /*
382 * By forcing WakeDevice to be valid, we automatically enable the
383 * implicit notify feature on all hosts.
384 */
385 return_ACPI_STATUS (AE_BAD_PARAMETER);
386 }
387
388 /* Handle root object case */
389
390 if (WakeDevice == ACPI_ROOT_OBJECT)
391 {
392 DeviceNode = AcpiGbl_RootNode;
393 }
394 else
395 {
396 DeviceNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, WakeDevice);
397 }
398
399 /* Validate WakeDevice is of type Device */
400
401 if (DeviceNode->Type != ACPI_TYPE_DEVICE)
402 {
403 return_ACPI_STATUS (AE_BAD_PARAMETER);
404 }
405
406 /*
407 * Allocate a new notify object up front, in case it is needed.
408 * Memory allocation while holding a spinlock is a big no-no
409 * on some hosts.
410 */
411 NewNotify = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_NOTIFY_INFO));
412 if (!NewNotify)
413 {
414 return_ACPI_STATUS (AE_NO_MEMORY);
415 }
416
417 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
418
419 /* Ensure that we have a valid GPE number */
420
421 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
422 if (!GpeEventInfo)
423 {
424 Status = AE_BAD_PARAMETER;
425 goto UnlockAndExit;
426 }
427
428 /*
429 * If there is no method or handler for this GPE, then the
430 * WakeDevice will be notified whenever this GPE fires. This is
431 * known as an "implicit notify". Note: The GPE is assumed to be
432 * level-triggered (for windows compatibility).
433 */
434 if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
435 ACPI_GPE_DISPATCH_NONE)
436 {
437 /*
438 * This is the first device for implicit notify on this GPE.
439 * Just set the flags here, and enter the NOTIFY block below.
440 */
441 GpeEventInfo->Flags =
442 (ACPI_GPE_DISPATCH_NOTIFY | ACPI_GPE_LEVEL_TRIGGERED);
443 }
444
445 /*
446 * If we already have an implicit notify on this GPE, add
447 * this device to the notify list.
448 */
449 if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
450 ACPI_GPE_DISPATCH_NOTIFY)
451 {
452 /* Ensure that the device is not already in the list */
453
454 Notify = GpeEventInfo->Dispatch.NotifyList;
455 while (Notify)
456 {
457 if (Notify->DeviceNode == DeviceNode)
458 {
459 Status = AE_ALREADY_EXISTS;
460 goto UnlockAndExit;
461 }
462 Notify = Notify->Next;
463 }
464
465 /* Add this device to the notify list for this GPE */
466
467 NewNotify->DeviceNode = DeviceNode;
468 NewNotify->Next = GpeEventInfo->Dispatch.NotifyList;
469 GpeEventInfo->Dispatch.NotifyList = NewNotify;
470 NewNotify = NULL;
471 }
472
473 /* Mark the GPE as a possible wake event */
474
475 GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE;
476 Status = AE_OK;
477
478
479 UnlockAndExit:
480 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
481
482 /* Delete the notify object if it was not used above */
483
484 if (NewNotify)
485 {
486 ACPI_FREE (NewNotify);
487 }
488 return_ACPI_STATUS (Status);
489 }
490
491 ACPI_EXPORT_SYMBOL (AcpiSetupGpeForWake)
492
493
494 /*******************************************************************************
495 *
496 * FUNCTION: AcpiSetGpeWakeMask
497 *
498 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1
499 * GpeNumber - GPE level within the GPE block
500 * Action - Enable or Disable
501 *
502 * RETURN: Status
503 *
504 * DESCRIPTION: Set or clear the GPE's wakeup enable mask bit. The GPE must
505 * already be marked as a WAKE GPE.
506 *
507 ******************************************************************************/
508
509 ACPI_STATUS
510 AcpiSetGpeWakeMask (
511 ACPI_HANDLE GpeDevice,
512 UINT32 GpeNumber,
513 UINT8 Action)
514 {
515 ACPI_STATUS Status = AE_OK;
516 ACPI_GPE_EVENT_INFO *GpeEventInfo;
517 ACPI_GPE_REGISTER_INFO *GpeRegisterInfo;
518 ACPI_CPU_FLAGS Flags;
519 UINT32 RegisterBit;
520
521
522 ACPI_FUNCTION_TRACE (AcpiSetGpeWakeMask);
523
524
525 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
526
527 /*
528 * Ensure that we have a valid GPE number and that this GPE is in
529 * fact a wake GPE
530 */
531 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
532 if (!GpeEventInfo)
533 {
534 Status = AE_BAD_PARAMETER;
535 goto UnlockAndExit;
536 }
537
538 if (!(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE))
539 {
540 Status = AE_TYPE;
541 goto UnlockAndExit;
542 }
543
544 GpeRegisterInfo = GpeEventInfo->RegisterInfo;
545 if (!GpeRegisterInfo)
546 {
547 Status = AE_NOT_EXIST;
548 goto UnlockAndExit;
549 }
550
551 RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo);
552
553 /* Perform the action */
554
555 switch (Action)
556 {
557 case ACPI_GPE_ENABLE:
558
559 ACPI_SET_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit);
560 break;
561
562 case ACPI_GPE_DISABLE:
563
564 ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit);
565 break;
566
567 default:
568
569 ACPI_ERROR ((AE_INFO, "%u, Invalid action", Action));
570 Status = AE_BAD_PARAMETER;
571 break;
572 }
573
574 UnlockAndExit:
575 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
576 return_ACPI_STATUS (Status);
577 }
578
579 ACPI_EXPORT_SYMBOL (AcpiSetGpeWakeMask)
580
581
582 /*******************************************************************************
583 *
584 * FUNCTION: AcpiClearGpe
585 *
586 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1
587 * GpeNumber - GPE level within the GPE block
588 *
589 * RETURN: Status
590 *
591 * DESCRIPTION: Clear an ACPI event (general purpose)
592 *
593 ******************************************************************************/
594
595 ACPI_STATUS
596 AcpiClearGpe (
597 ACPI_HANDLE GpeDevice,
598 UINT32 GpeNumber)
599 {
600 ACPI_STATUS Status = AE_OK;
601 ACPI_GPE_EVENT_INFO *GpeEventInfo;
602 ACPI_CPU_FLAGS Flags;
603
604
605 ACPI_FUNCTION_TRACE (AcpiClearGpe);
606
607
608 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
609
610 /* Ensure that we have a valid GPE number */
611
612 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
613 if (!GpeEventInfo)
614 {
615 Status = AE_BAD_PARAMETER;
616 goto UnlockAndExit;
617 }
618
619 Status = AcpiHwClearGpe (GpeEventInfo);
620
621 UnlockAndExit:
622 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
623 return_ACPI_STATUS (Status);
624 }
625
626 ACPI_EXPORT_SYMBOL (AcpiClearGpe)
627
628
629 /*******************************************************************************
630 *
631 * FUNCTION: AcpiGetGpeStatus
632 *
633 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1
634 * GpeNumber - GPE level within the GPE block
635 * EventStatus - Where the current status of the event
636 * will be returned
637 *
638 * RETURN: Status
639 *
640 * DESCRIPTION: Get the current status of a GPE (signalled/not_signalled)
641 *
642 ******************************************************************************/
643
644 ACPI_STATUS
645 AcpiGetGpeStatus (
646 ACPI_HANDLE GpeDevice,
647 UINT32 GpeNumber,
648 ACPI_EVENT_STATUS *EventStatus)
649 {
650 ACPI_STATUS Status = AE_OK;
651 ACPI_GPE_EVENT_INFO *GpeEventInfo;
652 ACPI_CPU_FLAGS Flags;
653
654
655 ACPI_FUNCTION_TRACE (AcpiGetGpeStatus);
656
657
658 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
659
660 /* Ensure that we have a valid GPE number */
661
662 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
663 if (!GpeEventInfo)
664 {
665 Status = AE_BAD_PARAMETER;
666 goto UnlockAndExit;
667 }
668
669 /* Obtain status on the requested GPE number */
670
671 Status = AcpiHwGetGpeStatus (GpeEventInfo, EventStatus);
672
673 UnlockAndExit:
674 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
675 return_ACPI_STATUS (Status);
676 }
677
678 ACPI_EXPORT_SYMBOL (AcpiGetGpeStatus)
679
680
681 /*******************************************************************************
682 *
683 * FUNCTION: AcpiFinishGpe
684 *
685 * PARAMETERS: GpeDevice - Namespace node for the GPE Block
686 * (NULL for FADT defined GPEs)
687 * GpeNumber - GPE level within the GPE block
688 *
689 * RETURN: Status
690 *
691 * DESCRIPTION: Clear and conditionally reenable a GPE. This completes the GPE
692 * processing. Intended for use by asynchronous host-installed
693 * GPE handlers. The GPE is only reenabled if the EnableForRun bit
694 * is set in the GPE info.
695 *
696 ******************************************************************************/
697
698 ACPI_STATUS
699 AcpiFinishGpe (
700 ACPI_HANDLE GpeDevice,
701 UINT32 GpeNumber)
702 {
703 ACPI_GPE_EVENT_INFO *GpeEventInfo;
704 ACPI_STATUS Status;
705 ACPI_CPU_FLAGS Flags;
706
707
708 ACPI_FUNCTION_TRACE (AcpiFinishGpe);
709
710
711 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
712
713 /* Ensure that we have a valid GPE number */
714
715 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
716 if (!GpeEventInfo)
717 {
718 Status = AE_BAD_PARAMETER;
719 goto UnlockAndExit;
720 }
721
722 Status = AcpiEvFinishGpe (GpeEventInfo);
723
724 UnlockAndExit:
725 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
726 return_ACPI_STATUS (Status);
727 }
728
729 ACPI_EXPORT_SYMBOL (AcpiFinishGpe)
730
731
732 /******************************************************************************
733 *
734 * FUNCTION: AcpiDisableAllGpes
735 *
736 * PARAMETERS: None
737 *
738 * RETURN: Status
739 *
740 * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
741 *
742 ******************************************************************************/
743
744 ACPI_STATUS
745 AcpiDisableAllGpes (
746 void)
747 {
748 ACPI_STATUS Status;
749
750
751 ACPI_FUNCTION_TRACE (AcpiDisableAllGpes);
752
753
754 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
755 if (ACPI_FAILURE (Status))
756 {
757 return_ACPI_STATUS (Status);
758 }
759
760 Status = AcpiHwDisableAllGpes ();
761 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
762
763 return_ACPI_STATUS (Status);
764 }
765
766 ACPI_EXPORT_SYMBOL (AcpiDisableAllGpes)
767
768
769 /******************************************************************************
770 *
771 * FUNCTION: AcpiEnableAllRuntimeGpes
772 *
773 * PARAMETERS: None
774 *
775 * RETURN: Status
776 *
777 * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
778 *
779 ******************************************************************************/
780
781 ACPI_STATUS
782 AcpiEnableAllRuntimeGpes (
783 void)
784 {
785 ACPI_STATUS Status;
786
787
788 ACPI_FUNCTION_TRACE (AcpiEnableAllRuntimeGpes);
789
790
791 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
792 if (ACPI_FAILURE (Status))
793 {
794 return_ACPI_STATUS (Status);
795 }
796
797 Status = AcpiHwEnableAllRuntimeGpes ();
798 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
799
800 return_ACPI_STATUS (Status);
801 }
802
803 ACPI_EXPORT_SYMBOL (AcpiEnableAllRuntimeGpes)
804
805
806 /*******************************************************************************
807 *
808 * FUNCTION: AcpiInstallGpeBlock
809 *
810 * PARAMETERS: GpeDevice - Handle to the parent GPE Block Device
811 * GpeBlockAddress - Address and SpaceID
812 * RegisterCount - Number of GPE register pairs in the block
813 * InterruptNumber - H/W interrupt for the block
814 *
815 * RETURN: Status
816 *
817 * DESCRIPTION: Create and Install a block of GPE registers. The GPEs are not
818 * enabled here.
819 *
820 ******************************************************************************/
821
822 ACPI_STATUS
823 AcpiInstallGpeBlock (
824 ACPI_HANDLE GpeDevice,
825 ACPI_GENERIC_ADDRESS *GpeBlockAddress,
826 UINT32 RegisterCount,
827 UINT32 InterruptNumber)
828 {
829 ACPI_STATUS Status;
830 ACPI_OPERAND_OBJECT *ObjDesc;
831 ACPI_NAMESPACE_NODE *Node;
832 ACPI_GPE_BLOCK_INFO *GpeBlock;
833
834
835 ACPI_FUNCTION_TRACE (AcpiInstallGpeBlock);
836
837
838 if ((!GpeDevice) ||
839 (!GpeBlockAddress) ||
840 (!RegisterCount))
841 {
842 return_ACPI_STATUS (AE_BAD_PARAMETER);
843 }
844
845 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
846 if (ACPI_FAILURE (Status))
847 {
848 return_ACPI_STATUS (Status);
849 }
850
851 Node = AcpiNsValidateHandle (GpeDevice);
852 if (!Node)
853 {
854 Status = AE_BAD_PARAMETER;
855 goto UnlockAndExit;
856 }
857
858 /* Validate the parent device */
859
860 if (Node->Type != ACPI_TYPE_DEVICE)
861 {
862 Status = AE_TYPE;
863 goto UnlockAndExit;
864 }
865
866 if (Node->Object)
867 {
868 Status = AE_ALREADY_EXISTS;
869 goto UnlockAndExit;
870 }
871
872 /*
873 * For user-installed GPE Block Devices, the GpeBlockBaseNumber
874 * is always zero
875 */
876 Status = AcpiEvCreateGpeBlock (Node, GpeBlockAddress->Address,
877 GpeBlockAddress->SpaceId, RegisterCount,
878 0, InterruptNumber, &GpeBlock);
879 if (ACPI_FAILURE (Status))
880 {
881 goto UnlockAndExit;
882 }
883
884 /* Install block in the DeviceObject attached to the node */
885
886 ObjDesc = AcpiNsGetAttachedObject (Node);
887 if (!ObjDesc)
888 {
889 /*
890 * No object, create a new one (Device nodes do not always have
891 * an attached object)
892 */
893 ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_DEVICE);
894 if (!ObjDesc)
895 {
896 Status = AE_NO_MEMORY;
897 goto UnlockAndExit;
898 }
899
900 Status = AcpiNsAttachObject (Node, ObjDesc, ACPI_TYPE_DEVICE);
901
902 /* Remove local reference to the object */
903
904 AcpiUtRemoveReference (ObjDesc);
905 if (ACPI_FAILURE (Status))
906 {
907 goto UnlockAndExit;
908 }
909 }
910
911 /* Now install the GPE block in the DeviceObject */
912
913 ObjDesc->Device.GpeBlock = GpeBlock;
914
915
916 UnlockAndExit:
917 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
918 return_ACPI_STATUS (Status);
919 }
920
921 ACPI_EXPORT_SYMBOL (AcpiInstallGpeBlock)
922
923
924 /*******************************************************************************
925 *
926 * FUNCTION: AcpiRemoveGpeBlock
927 *
928 * PARAMETERS: GpeDevice - Handle to the parent GPE Block Device
929 *
930 * RETURN: Status
931 *
932 * DESCRIPTION: Remove a previously installed block of GPE registers
933 *
934 ******************************************************************************/
935
936 ACPI_STATUS
937 AcpiRemoveGpeBlock (
938 ACPI_HANDLE GpeDevice)
939 {
940 ACPI_OPERAND_OBJECT *ObjDesc;
941 ACPI_STATUS Status;
942 ACPI_NAMESPACE_NODE *Node;
943
944
945 ACPI_FUNCTION_TRACE (AcpiRemoveGpeBlock);
946
947
948 if (!GpeDevice)
949 {
950 return_ACPI_STATUS (AE_BAD_PARAMETER);
951 }
952
953 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
954 if (ACPI_FAILURE (Status))
955 {
956 return_ACPI_STATUS (Status);
957 }
958
959 Node = AcpiNsValidateHandle (GpeDevice);
960 if (!Node)
961 {
962 Status = AE_BAD_PARAMETER;
963 goto UnlockAndExit;
964 }
965
966 /* Validate the parent device */
967
968 if (Node->Type != ACPI_TYPE_DEVICE)
969 {
970 Status = AE_TYPE;
971 goto UnlockAndExit;
972 }
973
974 /* Get the DeviceObject attached to the node */
975
976 ObjDesc = AcpiNsGetAttachedObject (Node);
977 if (!ObjDesc ||
978 !ObjDesc->Device.GpeBlock)
979 {
980 return_ACPI_STATUS (AE_NULL_OBJECT);
981 }
982
983 /* Delete the GPE block (but not the DeviceObject) */
984
985 Status = AcpiEvDeleteGpeBlock (ObjDesc->Device.GpeBlock);
986 if (ACPI_SUCCESS (Status))
987 {
988 ObjDesc->Device.GpeBlock = NULL;
989 }
990
991 UnlockAndExit:
992 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
993 return_ACPI_STATUS (Status);
994 }
995
996 ACPI_EXPORT_SYMBOL (AcpiRemoveGpeBlock)
997
998
999 /*******************************************************************************
1000 *
1001 * FUNCTION: AcpiGetGpeDevice
1002 *
1003 * PARAMETERS: Index - System GPE index (0-CurrentGpeCount)
1004 * GpeDevice - Where the parent GPE Device is returned
1005 *
1006 * RETURN: Status
1007 *
1008 * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL
1009 * gpe device indicates that the gpe number is contained in one of
1010 * the FADT-defined gpe blocks. Otherwise, the GPE block device.
1011 *
1012 ******************************************************************************/
1013
1014 ACPI_STATUS
1015 AcpiGetGpeDevice (
1016 UINT32 Index,
1017 ACPI_HANDLE *GpeDevice)
1018 {
1019 ACPI_GPE_DEVICE_INFO Info;
1020 ACPI_STATUS Status;
1021
1022
1023 ACPI_FUNCTION_TRACE (AcpiGetGpeDevice);
1024
1025
1026 if (!GpeDevice)
1027 {
1028 return_ACPI_STATUS (AE_BAD_PARAMETER);
1029 }
1030
1031 if (Index >= AcpiCurrentGpeCount)
1032 {
1033 return_ACPI_STATUS (AE_NOT_EXIST);
1034 }
1035
1036 /* Setup and walk the GPE list */
1037
1038 Info.Index = Index;
1039 Info.Status = AE_NOT_EXIST;
1040 Info.GpeDevice = NULL;
1041 Info.NextBlockBaseIndex = 0;
1042
1043 Status = AcpiEvWalkGpeList (AcpiEvGetGpeDevice, &Info);
1044 if (ACPI_FAILURE (Status))
1045 {
1046 return_ACPI_STATUS (Status);
1047 }
1048
1049 *GpeDevice = ACPI_CAST_PTR (ACPI_HANDLE, Info.GpeDevice);
1050 return_ACPI_STATUS (Info.Status);
1051 }
1052
1053 ACPI_EXPORT_SYMBOL (AcpiGetGpeDevice)
1054
1055 #endif /* !ACPI_REDUCED_HARDWARE */
1056