1 /******************************************************************************
2 *
3 * Module Name: evxfgpe - External Interfaces for General Purpose Events (GPEs)
4 *
5 *****************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2022, 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 MERCHANTABILITY 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 EXPORT_ACPI_INTERFACES
45
46 #include "acpi.h"
47 #include "accommon.h"
48 #include "acevents.h"
49 #include "acnamesp.h"
50
51 #define _COMPONENT ACPI_EVENTS
52 ACPI_MODULE_NAME ("evxfgpe")
53
54
55 #if (!ACPI_REDUCED_HARDWARE) /* Entire module */
56 /*******************************************************************************
57 *
58 * FUNCTION: AcpiUpdateAllGpes
59 *
60 * PARAMETERS: None
61 *
62 * RETURN: Status
63 *
64 * DESCRIPTION: Complete GPE initialization and enable all GPEs that have
65 * associated _Lxx or _Exx methods and are not pointed to by any
66 * device _PRW methods (this indicates that these GPEs are
67 * generally intended for system or device wakeup. Such GPEs
68 * have to be enabled directly when the devices whose _PRW
69 * methods point to them are set up for wakeup signaling.)
70 *
71 * NOTE: Should be called after any GPEs are added to the system. Primarily,
72 * after the system _PRW methods have been run, but also after a GPE Block
73 * Device has been added or if any new GPE methods have been added via a
74 * dynamic table load.
75 *
76 ******************************************************************************/
77
78 ACPI_STATUS
AcpiUpdateAllGpes(void)79 AcpiUpdateAllGpes (
80 void)
81 {
82 ACPI_STATUS Status;
83 BOOLEAN IsPollingNeeded = FALSE;
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,
101 &IsPollingNeeded);
102 if (ACPI_SUCCESS (Status))
103 {
104 AcpiGbl_AllGpesInitialized = TRUE;
105 }
106
107 UnlockAndExit:
108 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
109
110 if (IsPollingNeeded && AcpiGbl_AllGpesInitialized)
111 {
112 /* Poll GPEs to handle already triggered events */
113
114 AcpiEvGpeDetect (AcpiGbl_GpeXruptListHead);
115 }
116 return_ACPI_STATUS (Status);
117 }
118
ACPI_EXPORT_SYMBOL(AcpiUpdateAllGpes)119 ACPI_EXPORT_SYMBOL (AcpiUpdateAllGpes)
120
121
122 /*******************************************************************************
123 *
124 * FUNCTION: AcpiEnableGpe
125 *
126 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1
127 * GpeNumber - GPE level within the GPE block
128 *
129 * RETURN: Status
130 *
131 * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is
132 * hardware-enabled.
133 *
134 ******************************************************************************/
135
136 ACPI_STATUS
137 AcpiEnableGpe (
138 ACPI_HANDLE GpeDevice,
139 UINT32 GpeNumber)
140 {
141 ACPI_STATUS Status = AE_BAD_PARAMETER;
142 ACPI_GPE_EVENT_INFO *GpeEventInfo;
143 ACPI_CPU_FLAGS Flags;
144
145
146 ACPI_FUNCTION_TRACE (AcpiEnableGpe);
147
148
149 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
150
151 /*
152 * Ensure that we have a valid GPE number and that there is some way
153 * of handling the GPE (handler or a GPE method). In other words, we
154 * won't allow a valid GPE to be enabled if there is no way to handle it.
155 */
156 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
157 if (GpeEventInfo)
158 {
159 if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) !=
160 ACPI_GPE_DISPATCH_NONE)
161 {
162 Status = AcpiEvAddGpeReference (GpeEventInfo, TRUE);
163 if (ACPI_SUCCESS (Status) &&
164 ACPI_GPE_IS_POLLING_NEEDED (GpeEventInfo))
165 {
166 /* Poll edge-triggered GPEs to handle existing events */
167
168 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
169 (void) AcpiEvDetectGpe (
170 GpeDevice, GpeEventInfo, GpeNumber);
171 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
172 }
173 }
174 else
175 {
176 Status = AE_NO_HANDLER;
177 }
178 }
179
180 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
181 return_ACPI_STATUS (Status);
182 }
183
ACPI_EXPORT_SYMBOL(AcpiEnableGpe)184 ACPI_EXPORT_SYMBOL (AcpiEnableGpe)
185
186
187 /*******************************************************************************
188 *
189 * FUNCTION: AcpiDisableGpe
190 *
191 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1
192 * GpeNumber - GPE level within the GPE block
193 *
194 * RETURN: Status
195 *
196 * DESCRIPTION: Remove a reference to a GPE. When the last reference is
197 * removed, only then is the GPE disabled (for runtime GPEs), or
198 * the GPE mask bit disabled (for wake GPEs)
199 *
200 ******************************************************************************/
201
202 ACPI_STATUS
203 AcpiDisableGpe (
204 ACPI_HANDLE GpeDevice,
205 UINT32 GpeNumber)
206 {
207 ACPI_STATUS Status = AE_BAD_PARAMETER;
208 ACPI_GPE_EVENT_INFO *GpeEventInfo;
209 ACPI_CPU_FLAGS Flags;
210
211
212 ACPI_FUNCTION_TRACE (AcpiDisableGpe);
213
214
215 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
216
217 /* Ensure that we have a valid GPE number */
218
219 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
220 if (GpeEventInfo)
221 {
222 Status = AcpiEvRemoveGpeReference (GpeEventInfo);
223 }
224
225 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
226 return_ACPI_STATUS (Status);
227 }
228
ACPI_EXPORT_SYMBOL(AcpiDisableGpe)229 ACPI_EXPORT_SYMBOL (AcpiDisableGpe)
230
231
232 /*******************************************************************************
233 *
234 * FUNCTION: AcpiSetGpe
235 *
236 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1
237 * GpeNumber - GPE level within the GPE block
238 * Action - ACPI_GPE_ENABLE or ACPI_GPE_DISABLE
239 *
240 * RETURN: Status
241 *
242 * DESCRIPTION: Enable or disable an individual GPE. This function bypasses
243 * the reference count mechanism used in the AcpiEnableGpe(),
244 * AcpiDisableGpe() interfaces.
245 * This API is typically used by the GPE raw handler mode driver
246 * to switch between the polling mode and the interrupt mode after
247 * the driver has enabled the GPE.
248 * The APIs should be invoked in this order:
249 * AcpiEnableGpe() <- Ensure the reference count > 0
250 * AcpiSetGpe(ACPI_GPE_DISABLE) <- Enter polling mode
251 * AcpiSetGpe(ACPI_GPE_ENABLE) <- Leave polling mode
252 * AcpiDisableGpe() <- Decrease the reference count
253 *
254 * Note: If a GPE is shared by 2 silicon components, then both the drivers
255 * should support GPE polling mode or disabling the GPE for long period
256 * for one driver may break the other. So use it with care since all
257 * firmware _Lxx/_Exx handlers currently rely on the GPE interrupt mode.
258 *
259 ******************************************************************************/
260
261 ACPI_STATUS
262 AcpiSetGpe (
263 ACPI_HANDLE GpeDevice,
264 UINT32 GpeNumber,
265 UINT8 Action)
266 {
267 ACPI_GPE_EVENT_INFO *GpeEventInfo;
268 ACPI_STATUS Status;
269 ACPI_CPU_FLAGS Flags;
270
271
272 ACPI_FUNCTION_TRACE (AcpiSetGpe);
273
274
275 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
276
277 /* Ensure that we have a valid GPE number */
278
279 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
280 if (!GpeEventInfo)
281 {
282 Status = AE_BAD_PARAMETER;
283 goto UnlockAndExit;
284 }
285
286 /* Perform the action */
287
288 switch (Action)
289 {
290 case ACPI_GPE_ENABLE:
291
292 Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_ENABLE);
293 GpeEventInfo->DisableForDispatch = FALSE;
294 break;
295
296 case ACPI_GPE_DISABLE:
297
298 Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE);
299 GpeEventInfo->DisableForDispatch = TRUE;
300 break;
301
302 default:
303
304 Status = AE_BAD_PARAMETER;
305 break;
306 }
307
308 UnlockAndExit:
309 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
310 return_ACPI_STATUS (Status);
311 }
312
ACPI_EXPORT_SYMBOL(AcpiSetGpe)313 ACPI_EXPORT_SYMBOL (AcpiSetGpe)
314
315
316 /*******************************************************************************
317 *
318 * FUNCTION: AcpiMaskGpe
319 *
320 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1
321 * GpeNumber - GPE level within the GPE block
322 * IsMasked - Whether the GPE is masked or not
323 *
324 * RETURN: Status
325 *
326 * DESCRIPTION: Unconditionally mask/unmask the an individual GPE, ex., to
327 * prevent a GPE flooding.
328 *
329 ******************************************************************************/
330
331 ACPI_STATUS
332 AcpiMaskGpe (
333 ACPI_HANDLE GpeDevice,
334 UINT32 GpeNumber,
335 BOOLEAN IsMasked)
336 {
337 ACPI_GPE_EVENT_INFO *GpeEventInfo;
338 ACPI_STATUS Status;
339 ACPI_CPU_FLAGS Flags;
340
341
342 ACPI_FUNCTION_TRACE (AcpiMaskGpe);
343
344
345 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
346
347 /* Ensure that we have a valid GPE number */
348
349 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
350 if (!GpeEventInfo)
351 {
352 Status = AE_BAD_PARAMETER;
353 goto UnlockAndExit;
354 }
355
356 Status = AcpiEvMaskGpe (GpeEventInfo, IsMasked);
357
358 UnlockAndExit:
359 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
360 return_ACPI_STATUS (Status);
361 }
362
ACPI_EXPORT_SYMBOL(AcpiMaskGpe)363 ACPI_EXPORT_SYMBOL (AcpiMaskGpe)
364
365
366 /*******************************************************************************
367 *
368 * FUNCTION: AcpiMarkGpeForWake
369 *
370 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1
371 * GpeNumber - GPE level within the GPE block
372 *
373 * RETURN: Status
374 *
375 * DESCRIPTION: Mark a GPE as having the ability to wake the system. Simply
376 * sets the ACPI_GPE_CAN_WAKE flag.
377 *
378 * Some potential callers of AcpiSetupGpeForWake may know in advance that
379 * there won't be any notify handlers installed for device wake notifications
380 * from the given GPE (one example is a button GPE in Linux). For these cases,
381 * AcpiMarkGpeForWake should be used instead of AcpiSetupGpeForWake.
382 * This will set the ACPI_GPE_CAN_WAKE flag for the GPE without trying to
383 * setup implicit wake notification for it (since there's no handler method).
384 *
385 ******************************************************************************/
386
387 ACPI_STATUS
388 AcpiMarkGpeForWake (
389 ACPI_HANDLE GpeDevice,
390 UINT32 GpeNumber)
391 {
392 ACPI_GPE_EVENT_INFO *GpeEventInfo;
393 ACPI_STATUS Status = AE_BAD_PARAMETER;
394 ACPI_CPU_FLAGS Flags;
395
396
397 ACPI_FUNCTION_TRACE (AcpiMarkGpeForWake);
398
399
400 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
401
402 /* Ensure that we have a valid GPE number */
403
404 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
405 if (GpeEventInfo)
406 {
407 /* Mark the GPE as a possible wake event */
408
409 GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE;
410 Status = AE_OK;
411 }
412
413 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
414 return_ACPI_STATUS (Status);
415 }
416
ACPI_EXPORT_SYMBOL(AcpiMarkGpeForWake)417 ACPI_EXPORT_SYMBOL (AcpiMarkGpeForWake)
418
419
420 /*******************************************************************************
421 *
422 * FUNCTION: AcpiSetupGpeForWake
423 *
424 * PARAMETERS: WakeDevice - Device associated with the GPE (via _PRW)
425 * GpeDevice - Parent GPE Device. NULL for GPE0/GPE1
426 * GpeNumber - GPE level within the GPE block
427 *
428 * RETURN: Status
429 *
430 * DESCRIPTION: Mark a GPE as having the ability to wake the system. This
431 * interface is intended to be used as the host executes the
432 * _PRW methods (Power Resources for Wake) in the system tables.
433 * Each _PRW appears under a Device Object (The WakeDevice), and
434 * contains the info for the wake GPE associated with the
435 * WakeDevice.
436 *
437 ******************************************************************************/
438
439 ACPI_STATUS
440 AcpiSetupGpeForWake (
441 ACPI_HANDLE WakeDevice,
442 ACPI_HANDLE GpeDevice,
443 UINT32 GpeNumber)
444 {
445 ACPI_STATUS Status;
446 ACPI_GPE_EVENT_INFO *GpeEventInfo;
447 ACPI_NAMESPACE_NODE *DeviceNode;
448 ACPI_GPE_NOTIFY_INFO *Notify;
449 ACPI_GPE_NOTIFY_INFO *NewNotify;
450 ACPI_CPU_FLAGS Flags;
451
452
453 ACPI_FUNCTION_TRACE (AcpiSetupGpeForWake);
454
455
456 /* Parameter Validation */
457
458 if (!WakeDevice)
459 {
460 /*
461 * By forcing WakeDevice to be valid, we automatically enable the
462 * implicit notify feature on all hosts.
463 */
464 return_ACPI_STATUS (AE_BAD_PARAMETER);
465 }
466
467 /* Handle root object case */
468
469 if (WakeDevice == ACPI_ROOT_OBJECT)
470 {
471 DeviceNode = AcpiGbl_RootNode;
472 }
473 else
474 {
475 DeviceNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, WakeDevice);
476 }
477
478 /* Validate WakeDevice is of type Device */
479
480 if (DeviceNode->Type != ACPI_TYPE_DEVICE)
481 {
482 return_ACPI_STATUS (AE_BAD_PARAMETER);
483 }
484
485 /*
486 * Allocate a new notify object up front, in case it is needed.
487 * Memory allocation while holding a spinlock is a big no-no
488 * on some hosts.
489 */
490 NewNotify = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_NOTIFY_INFO));
491 if (!NewNotify)
492 {
493 return_ACPI_STATUS (AE_NO_MEMORY);
494 }
495
496 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
497
498 /* Ensure that we have a valid GPE number */
499
500 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
501 if (!GpeEventInfo)
502 {
503 Status = AE_BAD_PARAMETER;
504 goto UnlockAndExit;
505 }
506
507 /*
508 * If there is no method or handler for this GPE, then the
509 * WakeDevice will be notified whenever this GPE fires. This is
510 * known as an "implicit notify". Note: The GPE is assumed to be
511 * level-triggered (for windows compatibility).
512 */
513 if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) ==
514 ACPI_GPE_DISPATCH_NONE)
515 {
516 /*
517 * This is the first device for implicit notify on this GPE.
518 * Just set the flags here, and enter the NOTIFY block below.
519 */
520 GpeEventInfo->Flags =
521 (ACPI_GPE_DISPATCH_NOTIFY | ACPI_GPE_LEVEL_TRIGGERED);
522 }
523 else if (GpeEventInfo->Flags & ACPI_GPE_AUTO_ENABLED)
524 {
525 /*
526 * A reference to this GPE has been added during the GPE block
527 * initialization, so drop it now to prevent the GPE from being
528 * permanently enabled and clear its ACPI_GPE_AUTO_ENABLED flag.
529 */
530 (void) AcpiEvRemoveGpeReference (GpeEventInfo);
531 GpeEventInfo->Flags &= ~~ACPI_GPE_AUTO_ENABLED;
532 }
533
534 /*
535 * If we already have an implicit notify on this GPE, add
536 * this device to the notify list.
537 */
538 if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) ==
539 ACPI_GPE_DISPATCH_NOTIFY)
540 {
541 /* Ensure that the device is not already in the list */
542
543 Notify = GpeEventInfo->Dispatch.NotifyList;
544 while (Notify)
545 {
546 if (Notify->DeviceNode == DeviceNode)
547 {
548 Status = AE_ALREADY_EXISTS;
549 goto UnlockAndExit;
550 }
551 Notify = Notify->Next;
552 }
553
554 /* Add this device to the notify list for this GPE */
555
556 NewNotify->DeviceNode = DeviceNode;
557 NewNotify->Next = GpeEventInfo->Dispatch.NotifyList;
558 GpeEventInfo->Dispatch.NotifyList = NewNotify;
559 NewNotify = NULL;
560 }
561
562 /* Mark the GPE as a possible wake event */
563
564 GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE;
565 Status = AE_OK;
566
567
568 UnlockAndExit:
569 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
570
571 /* Delete the notify object if it was not used above */
572
573 if (NewNotify)
574 {
575 ACPI_FREE (NewNotify);
576 }
577 return_ACPI_STATUS (Status);
578 }
579
ACPI_EXPORT_SYMBOL(AcpiSetupGpeForWake)580 ACPI_EXPORT_SYMBOL (AcpiSetupGpeForWake)
581
582
583 /*******************************************************************************
584 *
585 * FUNCTION: AcpiSetGpeWakeMask
586 *
587 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1
588 * GpeNumber - GPE level within the GPE block
589 * Action - Enable or Disable
590 *
591 * RETURN: Status
592 *
593 * DESCRIPTION: Set or clear the GPE's wakeup enable mask bit. The GPE must
594 * already be marked as a WAKE GPE.
595 *
596 ******************************************************************************/
597
598 ACPI_STATUS
599 AcpiSetGpeWakeMask (
600 ACPI_HANDLE GpeDevice,
601 UINT32 GpeNumber,
602 UINT8 Action)
603 {
604 ACPI_STATUS Status = AE_OK;
605 ACPI_GPE_EVENT_INFO *GpeEventInfo;
606 ACPI_GPE_REGISTER_INFO *GpeRegisterInfo;
607 ACPI_CPU_FLAGS Flags;
608 UINT32 RegisterBit;
609
610
611 ACPI_FUNCTION_TRACE (AcpiSetGpeWakeMask);
612
613
614 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
615
616 /*
617 * Ensure that we have a valid GPE number and that this GPE is in
618 * fact a wake GPE
619 */
620 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
621 if (!GpeEventInfo)
622 {
623 Status = AE_BAD_PARAMETER;
624 goto UnlockAndExit;
625 }
626
627 if (!(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE))
628 {
629 Status = AE_TYPE;
630 goto UnlockAndExit;
631 }
632
633 GpeRegisterInfo = GpeEventInfo->RegisterInfo;
634 if (!GpeRegisterInfo)
635 {
636 Status = AE_NOT_EXIST;
637 goto UnlockAndExit;
638 }
639
640 RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo);
641
642 /* Perform the action */
643
644 switch (Action)
645 {
646 case ACPI_GPE_ENABLE:
647
648 ACPI_SET_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit);
649 break;
650
651 case ACPI_GPE_DISABLE:
652
653 ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit);
654 break;
655
656 default:
657
658 ACPI_ERROR ((AE_INFO, "%u, Invalid action", Action));
659 Status = AE_BAD_PARAMETER;
660 break;
661 }
662
663 UnlockAndExit:
664 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
665 return_ACPI_STATUS (Status);
666 }
667
ACPI_EXPORT_SYMBOL(AcpiSetGpeWakeMask)668 ACPI_EXPORT_SYMBOL (AcpiSetGpeWakeMask)
669
670
671 /*******************************************************************************
672 *
673 * FUNCTION: AcpiClearGpe
674 *
675 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1
676 * GpeNumber - GPE level within the GPE block
677 *
678 * RETURN: Status
679 *
680 * DESCRIPTION: Clear an ACPI event (general purpose)
681 *
682 ******************************************************************************/
683
684 ACPI_STATUS
685 AcpiClearGpe (
686 ACPI_HANDLE GpeDevice,
687 UINT32 GpeNumber)
688 {
689 ACPI_STATUS Status = AE_OK;
690 ACPI_GPE_EVENT_INFO *GpeEventInfo;
691 ACPI_CPU_FLAGS Flags;
692
693
694 ACPI_FUNCTION_TRACE (AcpiClearGpe);
695
696
697 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
698
699 /* Ensure that we have a valid GPE number */
700
701 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
702 if (!GpeEventInfo)
703 {
704 Status = AE_BAD_PARAMETER;
705 goto UnlockAndExit;
706 }
707
708 Status = AcpiHwClearGpe (GpeEventInfo);
709
710 UnlockAndExit:
711 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
712 return_ACPI_STATUS (Status);
713 }
714
ACPI_EXPORT_SYMBOL(AcpiClearGpe)715 ACPI_EXPORT_SYMBOL (AcpiClearGpe)
716
717
718 /*******************************************************************************
719 *
720 * FUNCTION: AcpiGetGpeStatus
721 *
722 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1
723 * GpeNumber - GPE level within the GPE block
724 * EventStatus - Where the current status of the event
725 * will be returned
726 *
727 * RETURN: Status
728 *
729 * DESCRIPTION: Get the current status of a GPE (signalled/not_signalled)
730 *
731 ******************************************************************************/
732
733 ACPI_STATUS
734 AcpiGetGpeStatus (
735 ACPI_HANDLE GpeDevice,
736 UINT32 GpeNumber,
737 ACPI_EVENT_STATUS *EventStatus)
738 {
739 ACPI_STATUS Status = AE_OK;
740 ACPI_GPE_EVENT_INFO *GpeEventInfo;
741 ACPI_CPU_FLAGS Flags;
742
743
744 ACPI_FUNCTION_TRACE (AcpiGetGpeStatus);
745
746
747 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
748
749 /* Ensure that we have a valid GPE number */
750
751 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
752 if (!GpeEventInfo)
753 {
754 Status = AE_BAD_PARAMETER;
755 goto UnlockAndExit;
756 }
757
758 /* Obtain status on the requested GPE number */
759
760 Status = AcpiHwGetGpeStatus (GpeEventInfo, EventStatus);
761
762 UnlockAndExit:
763 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
764 return_ACPI_STATUS (Status);
765 }
766
ACPI_EXPORT_SYMBOL(AcpiGetGpeStatus)767 ACPI_EXPORT_SYMBOL (AcpiGetGpeStatus)
768
769
770 /*******************************************************************************
771 *
772 * FUNCTION: AcpiDispatchGpe
773 *
774 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1
775 * GpeNumber - GPE level within the GPE block
776 *
777 * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
778 *
779 * DESCRIPTION: Detect and dispatch a General Purpose Event to either a function
780 * (e.g. EC) or method (e.g. _Lxx/_Exx) handler.
781 *
782 ******************************************************************************/
783
784 UINT32
785 AcpiDispatchGpe(
786 ACPI_HANDLE GpeDevice,
787 UINT32 GpeNumber)
788 {
789 ACPI_FUNCTION_TRACE(acpi_dispatch_gpe);
790
791 return (AcpiEvDetectGpe (GpeDevice, NULL, GpeNumber));
792 }
793
ACPI_EXPORT_SYMBOL(AcpiDispatchGpe)794 ACPI_EXPORT_SYMBOL (AcpiDispatchGpe)
795
796
797 /*******************************************************************************
798 *
799 * FUNCTION: AcpiFinishGpe
800 *
801 * PARAMETERS: GpeDevice - Namespace node for the GPE Block
802 * (NULL for FADT defined GPEs)
803 * GpeNumber - GPE level within the GPE block
804 *
805 * RETURN: Status
806 *
807 * DESCRIPTION: Clear and conditionally re-enable a GPE. This completes the GPE
808 * processing. Intended for use by asynchronous host-installed
809 * GPE handlers. The GPE is only re-enabled if the EnableForRun bit
810 * is set in the GPE info.
811 *
812 ******************************************************************************/
813
814 ACPI_STATUS
815 AcpiFinishGpe (
816 ACPI_HANDLE GpeDevice,
817 UINT32 GpeNumber)
818 {
819 ACPI_GPE_EVENT_INFO *GpeEventInfo;
820 ACPI_STATUS Status;
821 ACPI_CPU_FLAGS Flags;
822
823
824 ACPI_FUNCTION_TRACE (AcpiFinishGpe);
825
826
827 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
828
829 /* Ensure that we have a valid GPE number */
830
831 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
832 if (!GpeEventInfo)
833 {
834 Status = AE_BAD_PARAMETER;
835 goto UnlockAndExit;
836 }
837
838 Status = AcpiEvFinishGpe (GpeEventInfo);
839
840 UnlockAndExit:
841 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
842 return_ACPI_STATUS (Status);
843 }
844
ACPI_EXPORT_SYMBOL(AcpiFinishGpe)845 ACPI_EXPORT_SYMBOL (AcpiFinishGpe)
846
847
848 /******************************************************************************
849 *
850 * FUNCTION: AcpiDisableAllGpes
851 *
852 * PARAMETERS: None
853 *
854 * RETURN: Status
855 *
856 * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
857 *
858 ******************************************************************************/
859
860 ACPI_STATUS
861 AcpiDisableAllGpes (
862 void)
863 {
864 ACPI_STATUS Status;
865
866
867 ACPI_FUNCTION_TRACE (AcpiDisableAllGpes);
868
869
870 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
871 if (ACPI_FAILURE (Status))
872 {
873 return_ACPI_STATUS (Status);
874 }
875
876 Status = AcpiHwDisableAllGpes ();
877 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
878
879 return_ACPI_STATUS (Status);
880 }
881
ACPI_EXPORT_SYMBOL(AcpiDisableAllGpes)882 ACPI_EXPORT_SYMBOL (AcpiDisableAllGpes)
883
884
885 /******************************************************************************
886 *
887 * FUNCTION: AcpiEnableAllRuntimeGpes
888 *
889 * PARAMETERS: None
890 *
891 * RETURN: Status
892 *
893 * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
894 *
895 ******************************************************************************/
896
897 ACPI_STATUS
898 AcpiEnableAllRuntimeGpes (
899 void)
900 {
901 ACPI_STATUS Status;
902
903
904 ACPI_FUNCTION_TRACE (AcpiEnableAllRuntimeGpes);
905
906
907 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
908 if (ACPI_FAILURE (Status))
909 {
910 return_ACPI_STATUS (Status);
911 }
912
913 Status = AcpiHwEnableAllRuntimeGpes ();
914 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
915
916 return_ACPI_STATUS (Status);
917 }
918
ACPI_EXPORT_SYMBOL(AcpiEnableAllRuntimeGpes)919 ACPI_EXPORT_SYMBOL (AcpiEnableAllRuntimeGpes)
920
921
922 /******************************************************************************
923 *
924 * FUNCTION: AcpiEnableAllWakeupGpes
925 *
926 * PARAMETERS: None
927 *
928 * RETURN: Status
929 *
930 * DESCRIPTION: Enable all "wakeup" GPEs and disable all of the other GPEs, in
931 * all GPE blocks.
932 *
933 ******************************************************************************/
934
935 ACPI_STATUS
936 AcpiEnableAllWakeupGpes (
937 void)
938 {
939 ACPI_STATUS Status;
940
941
942 ACPI_FUNCTION_TRACE (AcpiEnableAllWakeupGpes);
943
944
945 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
946 if (ACPI_FAILURE (Status))
947 {
948 return_ACPI_STATUS (Status);
949 }
950
951 Status = AcpiHwEnableAllWakeupGpes ();
952 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
953
954 return_ACPI_STATUS (Status);
955 }
956
ACPI_EXPORT_SYMBOL(AcpiEnableAllWakeupGpes)957 ACPI_EXPORT_SYMBOL (AcpiEnableAllWakeupGpes)
958
959
960 /******************************************************************************
961 *
962 * FUNCTION: AcpiAnyGpeStatusSet
963 *
964 * PARAMETERS: None
965 *
966 * RETURN: Whether or not the status bit is set for any GPE
967 *
968 * DESCRIPTION: Check the status bits of all enabled GPEs and return TRUE if any
969 * of them is set or FALSE otherwise.
970 *
971 ******************************************************************************/
972
973 UINT32
974 AcpiAnyGpeStatusSet (
975 void)
976 {
977 ACPI_STATUS Status;
978 UINT8 Ret;
979
980
981 ACPI_FUNCTION_TRACE (AcpiAnyGpeStatusSet);
982
983 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
984 if (ACPI_FAILURE (Status))
985 {
986 return (FALSE);
987 }
988
989 Ret = AcpiHwCheckAllGpes ();
990 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
991
992 return (Ret);
993 }
994
ACPI_EXPORT_SYMBOL(AcpiAnyGpeStatusSet)995 ACPI_EXPORT_SYMBOL(AcpiAnyGpeStatusSet)
996
997
998 /*******************************************************************************
999 *
1000 * FUNCTION: AcpiInstallGpeBlock
1001 *
1002 * PARAMETERS: GpeDevice - Handle to the parent GPE Block Device
1003 * GpeBlockAddress - Address and SpaceID
1004 * RegisterCount - Number of GPE register pairs in the block
1005 * InterruptNumber - H/W interrupt for the block
1006 *
1007 * RETURN: Status
1008 *
1009 * DESCRIPTION: Create and Install a block of GPE registers. The GPEs are not
1010 * enabled here.
1011 *
1012 ******************************************************************************/
1013
1014 ACPI_STATUS
1015 AcpiInstallGpeBlock (
1016 ACPI_HANDLE GpeDevice,
1017 ACPI_GENERIC_ADDRESS *GpeBlockAddress,
1018 UINT32 RegisterCount,
1019 UINT32 InterruptNumber)
1020 {
1021 ACPI_STATUS Status;
1022 ACPI_OPERAND_OBJECT *ObjDesc;
1023 ACPI_NAMESPACE_NODE *Node;
1024 ACPI_GPE_BLOCK_INFO *GpeBlock;
1025
1026
1027 ACPI_FUNCTION_TRACE (AcpiInstallGpeBlock);
1028
1029
1030 if ((!GpeDevice) ||
1031 (!GpeBlockAddress) ||
1032 (!RegisterCount))
1033 {
1034 return_ACPI_STATUS (AE_BAD_PARAMETER);
1035 }
1036
1037 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
1038 if (ACPI_FAILURE (Status))
1039 {
1040 return_ACPI_STATUS (Status);
1041 }
1042
1043 Node = AcpiNsValidateHandle (GpeDevice);
1044 if (!Node)
1045 {
1046 Status = AE_BAD_PARAMETER;
1047 goto UnlockAndExit;
1048 }
1049
1050 /* Validate the parent device */
1051
1052 if (Node->Type != ACPI_TYPE_DEVICE)
1053 {
1054 Status = AE_TYPE;
1055 goto UnlockAndExit;
1056 }
1057
1058 if (Node->Object)
1059 {
1060 Status = AE_ALREADY_EXISTS;
1061 goto UnlockAndExit;
1062 }
1063
1064 /*
1065 * For user-installed GPE Block Devices, the GpeBlockBaseNumber
1066 * is always zero
1067 */
1068 Status = AcpiEvCreateGpeBlock (Node, GpeBlockAddress->Address,
1069 GpeBlockAddress->SpaceId, RegisterCount,
1070 0, InterruptNumber, &GpeBlock);
1071 if (ACPI_FAILURE (Status))
1072 {
1073 goto UnlockAndExit;
1074 }
1075
1076 /* Install block in the DeviceObject attached to the node */
1077
1078 ObjDesc = AcpiNsGetAttachedObject (Node);
1079 if (!ObjDesc)
1080 {
1081 /*
1082 * No object, create a new one (Device nodes do not always have
1083 * an attached object)
1084 */
1085 ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_DEVICE);
1086 if (!ObjDesc)
1087 {
1088 Status = AE_NO_MEMORY;
1089 goto UnlockAndExit;
1090 }
1091
1092 Status = AcpiNsAttachObject (Node, ObjDesc, ACPI_TYPE_DEVICE);
1093
1094 /* Remove local reference to the object */
1095
1096 AcpiUtRemoveReference (ObjDesc);
1097 if (ACPI_FAILURE (Status))
1098 {
1099 goto UnlockAndExit;
1100 }
1101 }
1102
1103 /* Now install the GPE block in the DeviceObject */
1104
1105 ObjDesc->Device.GpeBlock = GpeBlock;
1106
1107
1108 UnlockAndExit:
1109 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
1110 return_ACPI_STATUS (Status);
1111 }
1112
ACPI_EXPORT_SYMBOL(AcpiInstallGpeBlock)1113 ACPI_EXPORT_SYMBOL (AcpiInstallGpeBlock)
1114
1115
1116 /*******************************************************************************
1117 *
1118 * FUNCTION: AcpiRemoveGpeBlock
1119 *
1120 * PARAMETERS: GpeDevice - Handle to the parent GPE Block Device
1121 *
1122 * RETURN: Status
1123 *
1124 * DESCRIPTION: Remove a previously installed block of GPE registers
1125 *
1126 ******************************************************************************/
1127
1128 ACPI_STATUS
1129 AcpiRemoveGpeBlock (
1130 ACPI_HANDLE GpeDevice)
1131 {
1132 ACPI_OPERAND_OBJECT *ObjDesc;
1133 ACPI_STATUS Status;
1134 ACPI_NAMESPACE_NODE *Node;
1135
1136
1137 ACPI_FUNCTION_TRACE (AcpiRemoveGpeBlock);
1138
1139
1140 if (!GpeDevice)
1141 {
1142 return_ACPI_STATUS (AE_BAD_PARAMETER);
1143 }
1144
1145 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
1146 if (ACPI_FAILURE (Status))
1147 {
1148 return_ACPI_STATUS (Status);
1149 }
1150
1151 Node = AcpiNsValidateHandle (GpeDevice);
1152 if (!Node)
1153 {
1154 Status = AE_BAD_PARAMETER;
1155 goto UnlockAndExit;
1156 }
1157
1158 /* Validate the parent device */
1159
1160 if (Node->Type != ACPI_TYPE_DEVICE)
1161 {
1162 Status = AE_TYPE;
1163 goto UnlockAndExit;
1164 }
1165
1166 /* Get the DeviceObject attached to the node */
1167
1168 ObjDesc = AcpiNsGetAttachedObject (Node);
1169 if (!ObjDesc ||
1170 !ObjDesc->Device.GpeBlock)
1171 {
1172 return_ACPI_STATUS (AE_NULL_OBJECT);
1173 }
1174
1175 /* Delete the GPE block (but not the DeviceObject) */
1176
1177 Status = AcpiEvDeleteGpeBlock (ObjDesc->Device.GpeBlock);
1178 if (ACPI_SUCCESS (Status))
1179 {
1180 ObjDesc->Device.GpeBlock = NULL;
1181 }
1182
1183 UnlockAndExit:
1184 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
1185 return_ACPI_STATUS (Status);
1186 }
1187
ACPI_EXPORT_SYMBOL(AcpiRemoveGpeBlock)1188 ACPI_EXPORT_SYMBOL (AcpiRemoveGpeBlock)
1189
1190
1191 /*******************************************************************************
1192 *
1193 * FUNCTION: AcpiGetGpeDevice
1194 *
1195 * PARAMETERS: Index - System GPE index (0-CurrentGpeCount)
1196 * GpeDevice - Where the parent GPE Device is returned
1197 *
1198 * RETURN: Status
1199 *
1200 * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL
1201 * gpe device indicates that the gpe number is contained in one of
1202 * the FADT-defined gpe blocks. Otherwise, the GPE block device.
1203 *
1204 ******************************************************************************/
1205
1206 ACPI_STATUS
1207 AcpiGetGpeDevice (
1208 UINT32 Index,
1209 ACPI_HANDLE *GpeDevice)
1210 {
1211 ACPI_GPE_DEVICE_INFO Info;
1212 ACPI_STATUS Status;
1213
1214
1215 ACPI_FUNCTION_TRACE (AcpiGetGpeDevice);
1216
1217
1218 if (!GpeDevice)
1219 {
1220 return_ACPI_STATUS (AE_BAD_PARAMETER);
1221 }
1222
1223 if (Index >= AcpiCurrentGpeCount)
1224 {
1225 return_ACPI_STATUS (AE_NOT_EXIST);
1226 }
1227
1228 /* Setup and walk the GPE list */
1229
1230 Info.Index = Index;
1231 Info.Status = AE_NOT_EXIST;
1232 Info.GpeDevice = NULL;
1233 Info.NextBlockBaseIndex = 0;
1234
1235 Status = AcpiEvWalkGpeList (AcpiEvGetGpeDevice, &Info);
1236 if (ACPI_FAILURE (Status))
1237 {
1238 return_ACPI_STATUS (Status);
1239 }
1240
1241 *GpeDevice = ACPI_CAST_PTR (ACPI_HANDLE, Info.GpeDevice);
1242 return_ACPI_STATUS (Info.Status);
1243 }
1244
1245 ACPI_EXPORT_SYMBOL (AcpiGetGpeDevice)
1246
1247 #endif /* !ACPI_REDUCED_HARDWARE */
1248