Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/dev/acpica/components/events/evgpe.c
48526 views
1
/******************************************************************************
2
*
3
* Module Name: evgpe - General Purpose Event handling and dispatch
4
*
5
*****************************************************************************/
6
7
/******************************************************************************
8
*
9
* 1. Copyright Notice
10
*
11
* Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
12
* All rights reserved.
13
*
14
* 2. License
15
*
16
* 2.1. This is your license from Intel Corp. under its intellectual property
17
* rights. You may have additional license terms from the party that provided
18
* you this software, covering your right to use that party's intellectual
19
* property rights.
20
*
21
* 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22
* copy of the source code appearing in this file ("Covered Code") an
23
* irrevocable, perpetual, worldwide license under Intel's copyrights in the
24
* base code distributed originally by Intel ("Original Intel Code") to copy,
25
* make derivatives, distribute, use and display any portion of the Covered
26
* Code in any form, with the right to sublicense such rights; and
27
*
28
* 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29
* license (with the right to sublicense), under only those claims of Intel
30
* patents that are infringed by the Original Intel Code, to make, use, sell,
31
* offer to sell, and import the Covered Code and derivative works thereof
32
* solely to the minimum extent necessary to exercise the above copyright
33
* license, and in no event shall the patent license extend to any additions
34
* to or modifications of the Original Intel Code. No other license or right
35
* is granted directly or by implication, estoppel or otherwise;
36
*
37
* The above copyright and patent license is granted only if the following
38
* conditions are met:
39
*
40
* 3. Conditions
41
*
42
* 3.1. Redistribution of Source with Rights to Further Distribute Source.
43
* Redistribution of source code of any substantial portion of the Covered
44
* Code or modification with rights to further distribute source must include
45
* the above Copyright Notice, the above License, this list of Conditions,
46
* and the following Disclaimer and Export Compliance provision. In addition,
47
* Licensee must cause all Covered Code to which Licensee contributes to
48
* contain a file documenting the changes Licensee made to create that Covered
49
* Code and the date of any change. Licensee must include in that file the
50
* documentation of any changes made by any predecessor Licensee. Licensee
51
* must include a prominent statement that the modification is derived,
52
* directly or indirectly, from Original Intel Code.
53
*
54
* 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55
* Redistribution of source code of any substantial portion of the Covered
56
* Code or modification without rights to further distribute source must
57
* include the following Disclaimer and Export Compliance provision in the
58
* documentation and/or other materials provided with distribution. In
59
* addition, Licensee may not authorize further sublicense of source of any
60
* portion of the Covered Code, and must include terms to the effect that the
61
* license from Licensee to its licensee is limited to the intellectual
62
* property embodied in the software Licensee provides to its licensee, and
63
* not to intellectual property embodied in modifications its licensee may
64
* make.
65
*
66
* 3.3. Redistribution of Executable. Redistribution in executable form of any
67
* substantial portion of the Covered Code or modification must reproduce the
68
* above Copyright Notice, and the following Disclaimer and Export Compliance
69
* provision in the documentation and/or other materials provided with the
70
* distribution.
71
*
72
* 3.4. Intel retains all right, title, and interest in and to the Original
73
* Intel Code.
74
*
75
* 3.5. Neither the name Intel nor any other trademark owned or controlled by
76
* Intel shall be used in advertising or otherwise to promote the sale, use or
77
* other dealings in products derived from or relating to the Covered Code
78
* without prior written authorization from Intel.
79
*
80
* 4. Disclaimer and Export Compliance
81
*
82
* 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83
* HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84
* IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
85
* INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
86
* UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
87
* IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88
* PARTICULAR PURPOSE.
89
*
90
* 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91
* OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92
* COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93
* SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94
* CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95
* HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
96
* SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97
* LIMITED REMEDY.
98
*
99
* 4.3. Licensee shall not export, either directly or indirectly, any of this
100
* software or system incorporating such software without first obtaining any
101
* required license or other approval from the U. S. Department of Commerce or
102
* any other agency or department of the United States Government. In the
103
* event Licensee exports any such software from the United States or
104
* re-exports any such software from a foreign destination, Licensee shall
105
* ensure that the distribution and export/re-export of the software is in
106
* compliance with all laws, regulations, orders, or other restrictions of the
107
* U.S. Export Administration Regulations. Licensee agrees that neither it nor
108
* any of its subsidiaries will export/re-export any technical data, process,
109
* software, or service, directly or indirectly, to any country for which the
110
* United States government or any agency thereof requires an export license,
111
* other governmental approval, or letter of assurance, without first obtaining
112
* such license, approval or letter.
113
*
114
*****************************************************************************
115
*
116
* Alternatively, you may choose to be licensed under the terms of the
117
* following license:
118
*
119
* Redistribution and use in source and binary forms, with or without
120
* modification, are permitted provided that the following conditions
121
* are met:
122
* 1. Redistributions of source code must retain the above copyright
123
* notice, this list of conditions, and the following disclaimer,
124
* without modification.
125
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
126
* substantially similar to the "NO WARRANTY" disclaimer below
127
* ("Disclaimer") and any redistribution must be conditioned upon
128
* including a substantially similar Disclaimer requirement for further
129
* binary redistribution.
130
* 3. Neither the names of the above-listed copyright holders nor the names
131
* of any contributors may be used to endorse or promote products derived
132
* from this software without specific prior written permission.
133
*
134
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
135
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
136
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
137
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
138
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
139
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
140
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
141
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
142
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
143
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
144
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
145
*
146
* Alternatively, you may choose to be licensed under the terms of the
147
* GNU General Public License ("GPL") version 2 as published by the Free
148
* Software Foundation.
149
*
150
*****************************************************************************/
151
152
#include <contrib/dev/acpica/include/acpi.h>
153
#include <contrib/dev/acpica/include/accommon.h>
154
#include <contrib/dev/acpica/include/acevents.h>
155
#include <contrib/dev/acpica/include/acnamesp.h>
156
157
#define _COMPONENT ACPI_EVENTS
158
ACPI_MODULE_NAME ("evgpe")
159
160
#if (!ACPI_REDUCED_HARDWARE) /* Entire module */
161
162
/* Local prototypes */
163
164
static void ACPI_SYSTEM_XFACE
165
AcpiEvAsynchExecuteGpeMethod (
166
void *Context);
167
168
static void ACPI_SYSTEM_XFACE
169
AcpiEvAsynchEnableGpe (
170
void *Context);
171
172
173
/*******************************************************************************
174
*
175
* FUNCTION: AcpiEvUpdateGpeEnableMask
176
*
177
* PARAMETERS: GpeEventInfo - GPE to update
178
*
179
* RETURN: Status
180
*
181
* DESCRIPTION: Updates GPE register enable mask based upon whether there are
182
* runtime references to this GPE
183
*
184
******************************************************************************/
185
186
ACPI_STATUS
187
AcpiEvUpdateGpeEnableMask (
188
ACPI_GPE_EVENT_INFO *GpeEventInfo)
189
{
190
ACPI_GPE_REGISTER_INFO *GpeRegisterInfo;
191
UINT32 RegisterBit;
192
193
194
ACPI_FUNCTION_TRACE (EvUpdateGpeEnableMask);
195
196
197
GpeRegisterInfo = GpeEventInfo->RegisterInfo;
198
if (!GpeRegisterInfo)
199
{
200
return_ACPI_STATUS (AE_NOT_EXIST);
201
}
202
203
RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo);
204
205
/* Clear the run bit up front */
206
207
ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForRun, RegisterBit);
208
209
/* Set the mask bit only if there are references to this GPE */
210
211
if (GpeEventInfo->RuntimeCount)
212
{
213
ACPI_SET_BIT (GpeRegisterInfo->EnableForRun, (UINT8) RegisterBit);
214
}
215
216
GpeRegisterInfo->EnableMask = GpeRegisterInfo->EnableForRun;
217
return_ACPI_STATUS (AE_OK);
218
}
219
220
221
/*******************************************************************************
222
*
223
* FUNCTION: AcpiEvEnableGpe
224
*
225
* PARAMETERS: GpeEventInfo - GPE to enable
226
*
227
* RETURN: Status
228
*
229
* DESCRIPTION: Enable a GPE.
230
*
231
******************************************************************************/
232
233
ACPI_STATUS
234
AcpiEvEnableGpe (
235
ACPI_GPE_EVENT_INFO *GpeEventInfo)
236
{
237
ACPI_STATUS Status;
238
239
240
ACPI_FUNCTION_TRACE (EvEnableGpe);
241
242
243
/* Enable the requested GPE */
244
245
Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_ENABLE);
246
return_ACPI_STATUS (Status);
247
}
248
249
250
/*******************************************************************************
251
*
252
* FUNCTION: AcpiEvMaskGpe
253
*
254
* PARAMETERS: GpeEventInfo - GPE to be blocked/unblocked
255
* IsMasked - Whether the GPE is masked or not
256
*
257
* RETURN: Status
258
*
259
* DESCRIPTION: Unconditionally mask/unmask a GPE during runtime.
260
*
261
******************************************************************************/
262
263
ACPI_STATUS
264
AcpiEvMaskGpe (
265
ACPI_GPE_EVENT_INFO *GpeEventInfo,
266
BOOLEAN IsMasked)
267
{
268
ACPI_GPE_REGISTER_INFO *GpeRegisterInfo;
269
UINT32 RegisterBit;
270
271
272
ACPI_FUNCTION_TRACE (EvMaskGpe);
273
274
275
GpeRegisterInfo = GpeEventInfo->RegisterInfo;
276
if (!GpeRegisterInfo)
277
{
278
return_ACPI_STATUS (AE_NOT_EXIST);
279
}
280
281
RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo);
282
283
/* Perform the action */
284
285
if (IsMasked)
286
{
287
if (RegisterBit & GpeRegisterInfo->MaskForRun)
288
{
289
return_ACPI_STATUS (AE_BAD_PARAMETER);
290
}
291
292
(void) AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE);
293
ACPI_SET_BIT (GpeRegisterInfo->MaskForRun, (UINT8) RegisterBit);
294
}
295
else
296
{
297
if (!(RegisterBit & GpeRegisterInfo->MaskForRun))
298
{
299
return_ACPI_STATUS (AE_BAD_PARAMETER);
300
}
301
302
ACPI_CLEAR_BIT (GpeRegisterInfo->MaskForRun, (UINT8) RegisterBit);
303
if (GpeEventInfo->RuntimeCount &&
304
!GpeEventInfo->DisableForDispatch)
305
{
306
(void) AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_ENABLE);
307
}
308
}
309
310
return_ACPI_STATUS (AE_OK);
311
}
312
313
314
/*******************************************************************************
315
*
316
* FUNCTION: AcpiEvAddGpeReference
317
*
318
* PARAMETERS: GpeEventInfo - Add a reference to this GPE
319
* ClearOnEnable - Clear GPE status before enabling it
320
*
321
* RETURN: Status
322
*
323
* DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is
324
* hardware-enabled.
325
*
326
******************************************************************************/
327
328
ACPI_STATUS
329
AcpiEvAddGpeReference (
330
ACPI_GPE_EVENT_INFO *GpeEventInfo,
331
BOOLEAN ClearOnEnable)
332
{
333
ACPI_STATUS Status = AE_OK;
334
335
336
ACPI_FUNCTION_TRACE (EvAddGpeReference);
337
338
339
if (GpeEventInfo->RuntimeCount == ACPI_UINT8_MAX)
340
{
341
return_ACPI_STATUS (AE_LIMIT);
342
}
343
344
GpeEventInfo->RuntimeCount++;
345
if (GpeEventInfo->RuntimeCount == 1)
346
{
347
/* Enable on first reference */
348
349
if (ClearOnEnable)
350
{
351
(void) AcpiHwClearGpe (GpeEventInfo);
352
}
353
354
Status = AcpiEvUpdateGpeEnableMask (GpeEventInfo);
355
if (ACPI_SUCCESS (Status))
356
{
357
Status = AcpiEvEnableGpe (GpeEventInfo);
358
}
359
360
if (ACPI_FAILURE (Status))
361
{
362
GpeEventInfo->RuntimeCount--;
363
}
364
}
365
366
return_ACPI_STATUS (Status);
367
}
368
369
370
/*******************************************************************************
371
*
372
* FUNCTION: AcpiEvRemoveGpeReference
373
*
374
* PARAMETERS: GpeEventInfo - Remove a reference to this GPE
375
*
376
* RETURN: Status
377
*
378
* DESCRIPTION: Remove a reference to a GPE. When the last reference is
379
* removed, the GPE is hardware-disabled.
380
*
381
******************************************************************************/
382
383
ACPI_STATUS
384
AcpiEvRemoveGpeReference (
385
ACPI_GPE_EVENT_INFO *GpeEventInfo)
386
{
387
ACPI_STATUS Status = AE_OK;
388
389
390
ACPI_FUNCTION_TRACE (EvRemoveGpeReference);
391
392
393
if (!GpeEventInfo->RuntimeCount)
394
{
395
return_ACPI_STATUS (AE_LIMIT);
396
}
397
398
GpeEventInfo->RuntimeCount--;
399
if (!GpeEventInfo->RuntimeCount)
400
{
401
/* Disable on last reference */
402
403
Status = AcpiEvUpdateGpeEnableMask (GpeEventInfo);
404
if (ACPI_SUCCESS (Status))
405
{
406
Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE);
407
}
408
409
if (ACPI_FAILURE (Status))
410
{
411
GpeEventInfo->RuntimeCount++;
412
}
413
}
414
415
return_ACPI_STATUS (Status);
416
}
417
418
419
/*******************************************************************************
420
*
421
* FUNCTION: AcpiEvLowGetGpeInfo
422
*
423
* PARAMETERS: GpeNumber - Raw GPE number
424
* GpeBlock - A GPE info block
425
*
426
* RETURN: A GPE EventInfo struct. NULL if not a valid GPE (The GpeNumber
427
* is not within the specified GPE block)
428
*
429
* DESCRIPTION: Returns the EventInfo struct associated with this GPE. This is
430
* the low-level implementation of EvGetGpeEventInfo.
431
*
432
******************************************************************************/
433
434
ACPI_GPE_EVENT_INFO *
435
AcpiEvLowGetGpeInfo (
436
UINT32 GpeNumber,
437
ACPI_GPE_BLOCK_INFO *GpeBlock)
438
{
439
UINT32 GpeIndex;
440
441
442
/*
443
* Validate that the GpeNumber is within the specified GpeBlock.
444
* (Two steps)
445
*/
446
if (!GpeBlock ||
447
(GpeNumber < GpeBlock->BlockBaseNumber))
448
{
449
return (NULL);
450
}
451
452
GpeIndex = GpeNumber - GpeBlock->BlockBaseNumber;
453
if (GpeIndex >= GpeBlock->GpeCount)
454
{
455
return (NULL);
456
}
457
458
return (&GpeBlock->EventInfo[GpeIndex]);
459
}
460
461
462
/*******************************************************************************
463
*
464
* FUNCTION: AcpiEvGetGpeEventInfo
465
*
466
* PARAMETERS: GpeDevice - Device node. NULL for GPE0/GPE1
467
* GpeNumber - Raw GPE number
468
*
469
* RETURN: A GPE EventInfo struct. NULL if not a valid GPE
470
*
471
* DESCRIPTION: Returns the EventInfo struct associated with this GPE.
472
* Validates the GpeBlock and the GpeNumber
473
*
474
* Should be called only when the GPE lists are semaphore locked
475
* and not subject to change.
476
*
477
******************************************************************************/
478
479
ACPI_GPE_EVENT_INFO *
480
AcpiEvGetGpeEventInfo (
481
ACPI_HANDLE GpeDevice,
482
UINT32 GpeNumber)
483
{
484
ACPI_OPERAND_OBJECT *ObjDesc;
485
ACPI_GPE_EVENT_INFO *GpeInfo;
486
UINT32 i;
487
488
489
ACPI_FUNCTION_ENTRY ();
490
491
492
/* A NULL GpeDevice means use the FADT-defined GPE block(s) */
493
494
if (!GpeDevice)
495
{
496
/* Examine GPE Block 0 and 1 (These blocks are permanent) */
497
498
for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++)
499
{
500
GpeInfo = AcpiEvLowGetGpeInfo (GpeNumber,
501
AcpiGbl_GpeFadtBlocks[i]);
502
if (GpeInfo)
503
{
504
return (GpeInfo);
505
}
506
}
507
508
/* The GpeNumber was not in the range of either FADT GPE block */
509
510
return (NULL);
511
}
512
513
/* A Non-NULL GpeDevice means this is a GPE Block Device */
514
515
ObjDesc = AcpiNsGetAttachedObject ((ACPI_NAMESPACE_NODE *) GpeDevice);
516
if (!ObjDesc ||
517
!ObjDesc->Device.GpeBlock)
518
{
519
return (NULL);
520
}
521
522
return (AcpiEvLowGetGpeInfo (GpeNumber, ObjDesc->Device.GpeBlock));
523
}
524
525
526
/*******************************************************************************
527
*
528
* FUNCTION: AcpiEvGpeDetect
529
*
530
* PARAMETERS: GpeXruptList - Interrupt block for this interrupt.
531
* Can have multiple GPE blocks attached.
532
*
533
* RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
534
*
535
* DESCRIPTION: Detect if any GP events have occurred. This function is
536
* executed at interrupt level.
537
*
538
******************************************************************************/
539
540
UINT32
541
AcpiEvGpeDetect (
542
ACPI_GPE_XRUPT_INFO *GpeXruptList)
543
{
544
ACPI_GPE_BLOCK_INFO *GpeBlock;
545
ACPI_NAMESPACE_NODE *GpeDevice;
546
ACPI_GPE_REGISTER_INFO *GpeRegisterInfo;
547
ACPI_GPE_EVENT_INFO *GpeEventInfo;
548
UINT32 GpeNumber;
549
UINT32 IntStatus = ACPI_INTERRUPT_NOT_HANDLED;
550
ACPI_CPU_FLAGS Flags;
551
UINT32 i;
552
UINT32 j;
553
554
555
ACPI_FUNCTION_NAME (EvGpeDetect);
556
557
/* Check for the case where there are no GPEs */
558
559
if (!GpeXruptList)
560
{
561
return (IntStatus);
562
}
563
564
/*
565
* We need to obtain the GPE lock for both the data structs and registers
566
* Note: Not necessary to obtain the hardware lock, since the GPE
567
* registers are owned by the GpeLock.
568
*/
569
Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
570
571
/* Examine all GPE blocks attached to this interrupt level */
572
573
GpeBlock = GpeXruptList->GpeBlockListHead;
574
while (GpeBlock)
575
{
576
GpeDevice = GpeBlock->Node;
577
578
/*
579
* Read all of the 8-bit GPE status and enable registers in this GPE
580
* block, saving all of them. Find all currently active GP events.
581
*/
582
for (i = 0; i < GpeBlock->RegisterCount; i++)
583
{
584
/* Get the next status/enable pair */
585
586
GpeRegisterInfo = &GpeBlock->RegisterInfo[i];
587
588
/*
589
* Optimization: If there are no GPEs enabled within this
590
* register, we can safely ignore the entire register.
591
*/
592
if (!(GpeRegisterInfo->EnableForRun |
593
GpeRegisterInfo->EnableForWake))
594
{
595
ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
596
"Ignore disabled registers for GPE %02X-%02X: "
597
"RunEnable=%02X, WakeEnable=%02X\n",
598
GpeRegisterInfo->BaseGpeNumber,
599
GpeRegisterInfo->BaseGpeNumber + (ACPI_GPE_REGISTER_WIDTH - 1),
600
GpeRegisterInfo->EnableForRun,
601
GpeRegisterInfo->EnableForWake));
602
continue;
603
}
604
605
/* Now look at the individual GPEs in this byte register */
606
607
for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++)
608
{
609
/* Detect and dispatch one GPE bit */
610
611
GpeEventInfo = &GpeBlock->EventInfo[((ACPI_SIZE) i *
612
ACPI_GPE_REGISTER_WIDTH) + j];
613
GpeNumber = j + GpeRegisterInfo->BaseGpeNumber;
614
AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
615
IntStatus |= AcpiEvDetectGpe (
616
GpeDevice, GpeEventInfo, GpeNumber);
617
Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
618
}
619
}
620
621
GpeBlock = GpeBlock->Next;
622
}
623
624
AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
625
return (IntStatus);
626
}
627
628
629
/*******************************************************************************
630
*
631
* FUNCTION: AcpiEvAsynchExecuteGpeMethod
632
*
633
* PARAMETERS: Context (GpeEventInfo) - Info for this GPE
634
*
635
* RETURN: None
636
*
637
* DESCRIPTION: Perform the actual execution of a GPE control method. This
638
* function is called from an invocation of AcpiOsExecute and
639
* therefore does NOT execute at interrupt level - so that
640
* the control method itself is not executed in the context of
641
* an interrupt handler.
642
*
643
******************************************************************************/
644
645
static void ACPI_SYSTEM_XFACE
646
AcpiEvAsynchExecuteGpeMethod (
647
void *Context)
648
{
649
ACPI_GPE_EVENT_INFO *GpeEventInfo = Context;
650
ACPI_STATUS Status = AE_OK;
651
ACPI_EVALUATE_INFO *Info;
652
ACPI_GPE_NOTIFY_INFO *Notify;
653
654
655
ACPI_FUNCTION_TRACE (EvAsynchExecuteGpeMethod);
656
657
658
/* Do the correct dispatch - normal method or implicit notify */
659
660
switch (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags))
661
{
662
case ACPI_GPE_DISPATCH_NOTIFY:
663
/*
664
* Implicit notify.
665
* Dispatch a DEVICE_WAKE notify to the appropriate handler.
666
* NOTE: the request is queued for execution after this method
667
* completes. The notify handlers are NOT invoked synchronously
668
* from this thread -- because handlers may in turn run other
669
* control methods.
670
*
671
* June 2012: Expand implicit notify mechanism to support
672
* notifies on multiple device objects.
673
*/
674
Notify = GpeEventInfo->Dispatch.NotifyList;
675
while (ACPI_SUCCESS (Status) && Notify)
676
{
677
Status = AcpiEvQueueNotifyRequest (
678
Notify->DeviceNode, ACPI_NOTIFY_DEVICE_WAKE);
679
680
Notify = Notify->Next;
681
}
682
break;
683
684
case ACPI_GPE_DISPATCH_METHOD:
685
686
/* Allocate the evaluation information block */
687
688
Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
689
if (!Info)
690
{
691
Status = AE_NO_MEMORY;
692
}
693
else
694
{
695
/*
696
* Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the
697
* _Lxx/_Exx control method that corresponds to this GPE
698
*/
699
Info->PrefixNode = GpeEventInfo->Dispatch.MethodNode;
700
Info->Flags = ACPI_IGNORE_RETURN_VALUE;
701
702
Status = AcpiNsEvaluate (Info);
703
ACPI_FREE (Info);
704
}
705
706
if (ACPI_FAILURE (Status))
707
{
708
ACPI_EXCEPTION ((AE_INFO, Status,
709
"while evaluating GPE method [%4.4s]",
710
AcpiUtGetNodeName (GpeEventInfo->Dispatch.MethodNode)));
711
}
712
break;
713
714
default:
715
716
goto ErrorExit; /* Should never happen */
717
}
718
719
/* Defer enabling of GPE until all notify handlers are done */
720
721
Status = AcpiOsExecute (OSL_NOTIFY_HANDLER,
722
AcpiEvAsynchEnableGpe, GpeEventInfo);
723
if (ACPI_SUCCESS (Status))
724
{
725
return_VOID;
726
}
727
728
ErrorExit:
729
AcpiEvAsynchEnableGpe (GpeEventInfo);
730
return_VOID;
731
}
732
733
734
/*******************************************************************************
735
*
736
* FUNCTION: AcpiEvAsynchEnableGpe
737
*
738
* PARAMETERS: Context (GpeEventInfo) - Info for this GPE
739
* Callback from AcpiOsExecute
740
*
741
* RETURN: None
742
*
743
* DESCRIPTION: Asynchronous clear/enable for GPE. This allows the GPE to
744
* complete (i.e., finish execution of Notify)
745
*
746
******************************************************************************/
747
748
static void ACPI_SYSTEM_XFACE
749
AcpiEvAsynchEnableGpe (
750
void *Context)
751
{
752
ACPI_GPE_EVENT_INFO *GpeEventInfo = Context;
753
ACPI_CPU_FLAGS Flags;
754
755
756
Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
757
(void) AcpiEvFinishGpe (GpeEventInfo);
758
AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
759
760
return;
761
}
762
763
764
/*******************************************************************************
765
*
766
* FUNCTION: AcpiEvFinishGpe
767
*
768
* PARAMETERS: GpeEventInfo - Info for this GPE
769
*
770
* RETURN: Status
771
*
772
* DESCRIPTION: Clear/Enable a GPE. Common code that is used after execution
773
* of a GPE method or a synchronous or asynchronous GPE handler.
774
*
775
******************************************************************************/
776
777
ACPI_STATUS
778
AcpiEvFinishGpe (
779
ACPI_GPE_EVENT_INFO *GpeEventInfo)
780
{
781
ACPI_STATUS Status;
782
783
784
if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
785
ACPI_GPE_LEVEL_TRIGGERED)
786
{
787
/*
788
* GPE is level-triggered, we clear the GPE status bit after
789
* handling the event.
790
*/
791
Status = AcpiHwClearGpe (GpeEventInfo);
792
if (ACPI_FAILURE (Status))
793
{
794
return (Status);
795
}
796
}
797
798
/*
799
* Enable this GPE, conditionally. This means that the GPE will
800
* only be physically enabled if the EnableMask bit is set
801
* in the EventInfo.
802
*/
803
(void) AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_CONDITIONAL_ENABLE);
804
GpeEventInfo->DisableForDispatch = FALSE;
805
return (AE_OK);
806
}
807
808
809
/*******************************************************************************
810
*
811
* FUNCTION: AcpiEvDetectGpe
812
*
813
* PARAMETERS: GpeDevice - Device node. NULL for GPE0/GPE1
814
* GpeEventInfo - Info for this GPE
815
* GpeNumber - Number relative to the parent GPE block
816
*
817
* RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
818
*
819
* DESCRIPTION: Detect and dispatch a General Purpose Event to either a function
820
* (e.g. EC) or method (e.g. _Lxx/_Exx) handler.
821
* NOTE: GPE is W1C, so it is possible to handle a single GPE from both
822
* task and irq context in parallel as long as the process to
823
* detect and mask the GPE is atomic.
824
* However the atomicity of ACPI_GPE_DISPATCH_RAW_HANDLER is
825
* dependent on the raw handler itself.
826
*
827
******************************************************************************/
828
829
UINT32
830
AcpiEvDetectGpe (
831
ACPI_NAMESPACE_NODE *GpeDevice,
832
ACPI_GPE_EVENT_INFO *GpeEventInfo,
833
UINT32 GpeNumber)
834
{
835
UINT32 IntStatus = ACPI_INTERRUPT_NOT_HANDLED;
836
UINT8 EnabledStatusByte;
837
UINT64 StatusReg;
838
UINT64 EnableReg;
839
UINT32 RegisterBit;
840
ACPI_GPE_REGISTER_INFO *GpeRegisterInfo;
841
ACPI_GPE_HANDLER_INFO *GpeHandlerInfo;
842
ACPI_CPU_FLAGS Flags;
843
ACPI_STATUS Status;
844
845
846
ACPI_FUNCTION_TRACE (EvGpeDetect);
847
848
849
Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
850
851
if (!GpeEventInfo)
852
{
853
GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
854
if (!GpeEventInfo)
855
{
856
goto ErrorExit;
857
}
858
}
859
860
/* Get the info block for the entire GPE register */
861
862
GpeRegisterInfo = GpeEventInfo->RegisterInfo;
863
864
/* Get the register bitmask for this GPE */
865
866
RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo);
867
868
/* GPE currently enabled (enable bit == 1)? */
869
870
Status = AcpiHwRead (&EnableReg, &GpeRegisterInfo->EnableAddress);
871
if (ACPI_FAILURE (Status))
872
{
873
goto ErrorExit;
874
}
875
876
/* GPE currently active (status bit == 1)? */
877
878
Status = AcpiHwRead (&StatusReg, &GpeRegisterInfo->StatusAddress);
879
if (ACPI_FAILURE (Status))
880
{
881
goto ErrorExit;
882
}
883
884
/* Check if there is anything active at all in this GPE */
885
886
ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
887
"Read registers for GPE %02X: Status=%02X, Enable=%02X, "
888
"RunEnable=%02X, WakeEnable=%02X\n",
889
GpeNumber,
890
(UINT32) (StatusReg & RegisterBit),
891
(UINT32) (EnableReg & RegisterBit),
892
GpeRegisterInfo->EnableForRun,
893
GpeRegisterInfo->EnableForWake));
894
895
EnabledStatusByte = (UINT8) (StatusReg & EnableReg);
896
if (!(EnabledStatusByte & RegisterBit))
897
{
898
goto ErrorExit;
899
}
900
901
/* Invoke global event handler if present */
902
903
AcpiGpeCount++;
904
if (AcpiGbl_GlobalEventHandler)
905
{
906
AcpiGbl_GlobalEventHandler (ACPI_EVENT_TYPE_GPE,
907
GpeDevice, GpeNumber,
908
AcpiGbl_GlobalEventHandlerContext);
909
}
910
911
/* Found an active GPE */
912
913
if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) ==
914
ACPI_GPE_DISPATCH_RAW_HANDLER)
915
{
916
/* Dispatch the event to a raw handler */
917
918
GpeHandlerInfo = GpeEventInfo->Dispatch.Handler;
919
920
/*
921
* There is no protection around the namespace node
922
* and the GPE handler to ensure a safe destruction
923
* because:
924
* 1. The namespace node is expected to always
925
* exist after loading a table.
926
* 2. The GPE handler is expected to be flushed by
927
* AcpiOsWaitEventsComplete() before the
928
* destruction.
929
*/
930
AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
931
IntStatus |= GpeHandlerInfo->Address (
932
GpeDevice, GpeNumber, GpeHandlerInfo->Context);
933
Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
934
}
935
else
936
{
937
/* Dispatch the event to a standard handler or method. */
938
939
IntStatus |= AcpiEvGpeDispatch (GpeDevice,
940
GpeEventInfo, GpeNumber);
941
}
942
943
ErrorExit:
944
AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
945
return (IntStatus);
946
}
947
948
949
/*******************************************************************************
950
*
951
* FUNCTION: AcpiEvGpeDispatch
952
*
953
* PARAMETERS: GpeDevice - Device node. NULL for GPE0/GPE1
954
* GpeEventInfo - Info for this GPE
955
* GpeNumber - Number relative to the parent GPE block
956
*
957
* RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
958
*
959
* DESCRIPTION: Dispatch a General Purpose Event to either a function (e.g. EC)
960
* or method (e.g. _Lxx/_Exx) handler.
961
*
962
******************************************************************************/
963
964
UINT32
965
AcpiEvGpeDispatch (
966
ACPI_NAMESPACE_NODE *GpeDevice,
967
ACPI_GPE_EVENT_INFO *GpeEventInfo,
968
UINT32 GpeNumber)
969
{
970
ACPI_STATUS Status;
971
UINT32 ReturnValue;
972
973
974
ACPI_FUNCTION_TRACE (EvGpeDispatch);
975
976
977
/*
978
* Always disable the GPE so that it does not keep firing before
979
* any asynchronous activity completes (either from the execution
980
* of a GPE method or an asynchronous GPE handler.)
981
*
982
* If there is no handler or method to run, just disable the
983
* GPE and leave it disabled permanently to prevent further such
984
* pointless events from firing.
985
*/
986
Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE);
987
if (ACPI_FAILURE (Status))
988
{
989
ACPI_EXCEPTION ((AE_INFO, Status,
990
"Unable to disable GPE %02X", GpeNumber));
991
return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
992
}
993
994
/*
995
* If edge-triggered, clear the GPE status bit now. Note that
996
* level-triggered events are cleared after the GPE is serviced.
997
*/
998
if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
999
ACPI_GPE_EDGE_TRIGGERED)
1000
{
1001
Status = AcpiHwClearGpe (GpeEventInfo);
1002
if (ACPI_FAILURE (Status))
1003
{
1004
ACPI_EXCEPTION ((AE_INFO, Status,
1005
"Unable to clear GPE %02X", GpeNumber));
1006
(void) AcpiHwLowSetGpe (
1007
GpeEventInfo, ACPI_GPE_CONDITIONAL_ENABLE);
1008
return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
1009
}
1010
}
1011
1012
GpeEventInfo->DisableForDispatch = TRUE;
1013
1014
/*
1015
* Dispatch the GPE to either an installed handler or the control
1016
* method associated with this GPE (_Lxx or _Exx). If a handler
1017
* exists, we invoke it and do not attempt to run the method.
1018
* If there is neither a handler nor a method, leave the GPE
1019
* disabled.
1020
*/
1021
switch (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags))
1022
{
1023
case ACPI_GPE_DISPATCH_HANDLER:
1024
1025
/* Invoke the installed handler (at interrupt level) */
1026
1027
ReturnValue = GpeEventInfo->Dispatch.Handler->Address (
1028
GpeDevice, GpeNumber,
1029
GpeEventInfo->Dispatch.Handler->Context);
1030
1031
/* If requested, clear (if level-triggered) and re-enable the GPE */
1032
1033
if (ReturnValue & ACPI_REENABLE_GPE)
1034
{
1035
(void) AcpiEvFinishGpe (GpeEventInfo);
1036
}
1037
break;
1038
1039
case ACPI_GPE_DISPATCH_METHOD:
1040
case ACPI_GPE_DISPATCH_NOTIFY:
1041
/*
1042
* Execute the method associated with the GPE
1043
* NOTE: Level-triggered GPEs are cleared after the method completes.
1044
*/
1045
Status = AcpiOsExecute (OSL_GPE_HANDLER,
1046
AcpiEvAsynchExecuteGpeMethod, GpeEventInfo);
1047
if (ACPI_FAILURE (Status))
1048
{
1049
ACPI_EXCEPTION ((AE_INFO, Status,
1050
"Unable to queue handler for GPE %02X - event disabled",
1051
GpeNumber));
1052
}
1053
break;
1054
1055
default:
1056
/*
1057
* No handler or method to run!
1058
* 03/2010: This case should no longer be possible. We will not allow
1059
* a GPE to be enabled if it has no handler or method.
1060
*/
1061
ACPI_ERROR ((AE_INFO,
1062
"No handler or method for GPE %02X, disabling event",
1063
GpeNumber));
1064
break;
1065
}
1066
1067
return_UINT32 (ACPI_INTERRUPT_HANDLED);
1068
}
1069
1070
#endif /* !ACPI_REDUCED_HARDWARE */
1071
1072