evgpe.c revision 1.1 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 - 2010, 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 #include "acpi.h"
117 #include "accommon.h"
118 #include "acevents.h"
119 #include "acnamesp.h"
120
121 #define _COMPONENT ACPI_EVENTS
122 ACPI_MODULE_NAME ("evgpe")
123
124 /* Local prototypes */
125
126 static void ACPI_SYSTEM_XFACE
127 AcpiEvAsynchExecuteGpeMethod (
128 void *Context);
129
130 static void ACPI_SYSTEM_XFACE
131 AcpiEvAsynchEnableGpe (
132 void *Context);
133
134
135 /*******************************************************************************
136 *
137 * FUNCTION: AcpiEvUpdateGpeEnableMasks
138 *
139 * PARAMETERS: GpeEventInfo - GPE to update
140 *
141 * RETURN: Status
142 *
143 * DESCRIPTION: Updates GPE register enable masks based upon whether there are
144 * references (either wake or run) to this GPE
145 *
146 ******************************************************************************/
147
148 ACPI_STATUS
149 AcpiEvUpdateGpeEnableMasks (
150 ACPI_GPE_EVENT_INFO *GpeEventInfo)
151 {
152 ACPI_GPE_REGISTER_INFO *GpeRegisterInfo;
153 UINT8 RegisterBit;
154
155
156 ACPI_FUNCTION_TRACE (EvUpdateGpeEnableMasks);
157
158
159 GpeRegisterInfo = GpeEventInfo->RegisterInfo;
160 if (!GpeRegisterInfo)
161 {
162 return_ACPI_STATUS (AE_NOT_EXIST);
163 }
164
165 RegisterBit = (UINT8)
166 (1 << (GpeEventInfo->GpeNumber - GpeRegisterInfo->BaseGpeNumber));
167
168 /* Clear the wake/run bits up front */
169
170 ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, RegisterBit);
171 ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForRun, RegisterBit);
172
173 /* Set the mask bits only if there are references to this GPE */
174
175 if (GpeEventInfo->RuntimeCount)
176 {
177 ACPI_SET_BIT (GpeRegisterInfo->EnableForRun, RegisterBit);
178 }
179
180 if (GpeEventInfo->WakeupCount)
181 {
182 ACPI_SET_BIT (GpeRegisterInfo->EnableForWake, RegisterBit);
183 }
184
185 return_ACPI_STATUS (AE_OK);
186 }
187
188
189 /*******************************************************************************
190 *
191 * FUNCTION: AcpiEvEnableGpe
192 *
193 * PARAMETERS: GpeEventInfo - GPE to enable
194 *
195 * RETURN: Status
196 *
197 * DESCRIPTION: Hardware-enable a GPE. Always enables the GPE, regardless
198 * of type or number of references.
199 *
200 * Note: The GPE lock should be already acquired when this function is called.
201 *
202 ******************************************************************************/
203
204 ACPI_STATUS
205 AcpiEvEnableGpe (
206 ACPI_GPE_EVENT_INFO *GpeEventInfo)
207 {
208 ACPI_STATUS Status;
209
210
211 ACPI_FUNCTION_TRACE (EvEnableGpe);
212
213
214 /*
215 * We will only allow a GPE to be enabled if it has either an
216 * associated method (_Lxx/_Exx) or a handler. Otherwise, the
217 * GPE will be immediately disabled by AcpiEvGpeDispatch the
218 * first time it fires.
219 */
220 if (!(GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK))
221 {
222 return_ACPI_STATUS (AE_NO_HANDLER);
223 }
224
225 /* Ensure the HW enable masks are current */
226
227 Status = AcpiEvUpdateGpeEnableMasks (GpeEventInfo);
228 if (ACPI_FAILURE (Status))
229 {
230 return_ACPI_STATUS (Status);
231 }
232
233 /* Clear the GPE (of stale events) */
234
235 Status = AcpiHwClearGpe (GpeEventInfo);
236 if (ACPI_FAILURE (Status))
237 {
238 return_ACPI_STATUS (Status);
239 }
240
241 /* Enable the requested GPE */
242
243 Status = AcpiHwWriteGpeEnableReg (GpeEventInfo);
244 return_ACPI_STATUS (Status);
245 }
246
247
248 /*******************************************************************************
249 *
250 * FUNCTION: AcpiEvDisableGpe
251 *
252 * PARAMETERS: GpeEventInfo - GPE to disable
253 *
254 * RETURN: Status
255 *
256 * DESCRIPTION: Hardware-disable a GPE. Always disables the requested GPE,
257 * regardless of the type or number of references.
258 *
259 * Note: The GPE lock should be already acquired when this function is called.
260 *
261 ******************************************************************************/
262
263 ACPI_STATUS
264 AcpiEvDisableGpe (
265 ACPI_GPE_EVENT_INFO *GpeEventInfo)
266 {
267 ACPI_STATUS Status;
268
269
270 ACPI_FUNCTION_TRACE (EvDisableGpe);
271
272
273 /*
274 * Note: Always disable the GPE, even if we think that that it is already
275 * disabled. It is possible that the AML or some other code has enabled
276 * the GPE behind our back.
277 */
278
279 /* Ensure the HW enable masks are current */
280
281 Status = AcpiEvUpdateGpeEnableMasks (GpeEventInfo);
282 if (ACPI_FAILURE (Status))
283 {
284 return_ACPI_STATUS (Status);
285 }
286
287 /*
288 * Always H/W disable this GPE, even if we don't know the GPE type.
289 * Simply clear the enable bit for this particular GPE, but do not
290 * write out the current GPE enable mask since this may inadvertently
291 * enable GPEs too early. An example is a rogue GPE that has arrived
292 * during ACPICA initialization - possibly because AML or other code
293 * has enabled the GPE.
294 */
295 Status = AcpiHwLowDisableGpe (GpeEventInfo);
296 return_ACPI_STATUS (Status);
297 }
298
299
300 /*******************************************************************************
301 *
302 * FUNCTION: AcpiEvLowGetGpeInfo
303 *
304 * PARAMETERS: GpeNumber - Raw GPE number
305 * GpeBlock - A GPE info block
306 *
307 * RETURN: A GPE EventInfo struct. NULL if not a valid GPE (The GpeNumber
308 * is not within the specified GPE block)
309 *
310 * DESCRIPTION: Returns the EventInfo struct associated with this GPE. This is
311 * the low-level implementation of EvGetGpeEventInfo.
312 *
313 ******************************************************************************/
314
315 ACPI_GPE_EVENT_INFO *
316 AcpiEvLowGetGpeInfo (
317 UINT32 GpeNumber,
318 ACPI_GPE_BLOCK_INFO *GpeBlock)
319 {
320 UINT32 GpeIndex;
321
322
323 /*
324 * Validate that the GpeNumber is within the specified GpeBlock.
325 * (Two steps)
326 */
327 if (!GpeBlock ||
328 (GpeNumber < GpeBlock->BlockBaseNumber))
329 {
330 return (NULL);
331 }
332
333 GpeIndex = GpeNumber - GpeBlock->BlockBaseNumber;
334 if (GpeIndex >= GpeBlock->GpeCount)
335 {
336 return (NULL);
337 }
338
339 return (&GpeBlock->EventInfo[GpeIndex]);
340 }
341
342
343 /*******************************************************************************
344 *
345 * FUNCTION: AcpiEvGetGpeEventInfo
346 *
347 * PARAMETERS: GpeDevice - Device node. NULL for GPE0/GPE1
348 * GpeNumber - Raw GPE number
349 *
350 * RETURN: A GPE EventInfo struct. NULL if not a valid GPE
351 *
352 * DESCRIPTION: Returns the EventInfo struct associated with this GPE.
353 * Validates the GpeBlock and the GpeNumber
354 *
355 * Should be called only when the GPE lists are semaphore locked
356 * and not subject to change.
357 *
358 ******************************************************************************/
359
360 ACPI_GPE_EVENT_INFO *
361 AcpiEvGetGpeEventInfo (
362 ACPI_HANDLE GpeDevice,
363 UINT32 GpeNumber)
364 {
365 ACPI_OPERAND_OBJECT *ObjDesc;
366 ACPI_GPE_EVENT_INFO *GpeInfo;
367 UINT32 i;
368
369
370 ACPI_FUNCTION_ENTRY ();
371
372
373 /* A NULL GpeDevice means use the FADT-defined GPE block(s) */
374
375 if (!GpeDevice)
376 {
377 /* Examine GPE Block 0 and 1 (These blocks are permanent) */
378
379 for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++)
380 {
381 GpeInfo = AcpiEvLowGetGpeInfo (GpeNumber,
382 AcpiGbl_GpeFadtBlocks[i]);
383 if (GpeInfo)
384 {
385 return (GpeInfo);
386 }
387 }
388
389 /* The GpeNumber was not in the range of either FADT GPE block */
390
391 return (NULL);
392 }
393
394 /* A Non-NULL GpeDevice means this is a GPE Block Device */
395
396 ObjDesc = AcpiNsGetAttachedObject ((ACPI_NAMESPACE_NODE *) GpeDevice);
397 if (!ObjDesc ||
398 !ObjDesc->Device.GpeBlock)
399 {
400 return (NULL);
401 }
402
403 return (AcpiEvLowGetGpeInfo (GpeNumber, ObjDesc->Device.GpeBlock));
404 }
405
406
407 /*******************************************************************************
408 *
409 * FUNCTION: AcpiEvGpeDetect
410 *
411 * PARAMETERS: GpeXruptList - Interrupt block for this interrupt.
412 * Can have multiple GPE blocks attached.
413 *
414 * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
415 *
416 * DESCRIPTION: Detect if any GP events have occurred. This function is
417 * executed at interrupt level.
418 *
419 ******************************************************************************/
420
421 UINT32
422 AcpiEvGpeDetect (
423 ACPI_GPE_XRUPT_INFO *GpeXruptList)
424 {
425 ACPI_STATUS Status;
426 ACPI_GPE_BLOCK_INFO *GpeBlock;
427 ACPI_GPE_REGISTER_INFO *GpeRegisterInfo;
428 UINT32 IntStatus = ACPI_INTERRUPT_NOT_HANDLED;
429 UINT8 EnabledStatusByte;
430 UINT32 StatusReg;
431 UINT32 EnableReg;
432 ACPI_CPU_FLAGS Flags;
433 UINT32 i;
434 UINT32 j;
435
436
437 ACPI_FUNCTION_NAME (EvGpeDetect);
438
439 /* Check for the case where there are no GPEs */
440
441 if (!GpeXruptList)
442 {
443 return (IntStatus);
444 }
445
446 /*
447 * We need to obtain the GPE lock for both the data structs and registers
448 * Note: Not necessary to obtain the hardware lock, since the GPE
449 * registers are owned by the GpeLock.
450 */
451 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
452
453 /* Examine all GPE blocks attached to this interrupt level */
454
455 GpeBlock = GpeXruptList->GpeBlockListHead;
456 while (GpeBlock)
457 {
458 /*
459 * Read all of the 8-bit GPE status and enable registers in this GPE
460 * block, saving all of them. Find all currently active GP events.
461 */
462 for (i = 0; i < GpeBlock->RegisterCount; i++)
463 {
464 /* Get the next status/enable pair */
465
466 GpeRegisterInfo = &GpeBlock->RegisterInfo[i];
467
468 /* Read the Status Register */
469
470 Status = AcpiHwRead (&StatusReg, &GpeRegisterInfo->StatusAddress);
471 if (ACPI_FAILURE (Status))
472 {
473 goto UnlockAndExit;
474 }
475
476 /* Read the Enable Register */
477
478 Status = AcpiHwRead (&EnableReg, &GpeRegisterInfo->EnableAddress);
479 if (ACPI_FAILURE (Status))
480 {
481 goto UnlockAndExit;
482 }
483
484 ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
485 "Read GPE Register at GPE%X: Status=%02X, Enable=%02X\n",
486 GpeRegisterInfo->BaseGpeNumber, StatusReg, EnableReg));
487
488 /* Check if there is anything active at all in this register */
489
490 EnabledStatusByte = (UINT8) (StatusReg & EnableReg);
491 if (!EnabledStatusByte)
492 {
493 /* No active GPEs in this register, move on */
494
495 continue;
496 }
497
498 /* Now look at the individual GPEs in this byte register */
499
500 for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++)
501 {
502 /* Examine one GPE bit */
503
504 if (EnabledStatusByte & (1 << j))
505 {
506 /*
507 * Found an active GPE. Dispatch the event to a handler
508 * or method.
509 */
510 IntStatus |= AcpiEvGpeDispatch (
511 &GpeBlock->EventInfo[((ACPI_SIZE) i *
512 ACPI_GPE_REGISTER_WIDTH) + j],
513 j + GpeRegisterInfo->BaseGpeNumber);
514 }
515 }
516 }
517
518 GpeBlock = GpeBlock->Next;
519 }
520
521 UnlockAndExit:
522
523 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
524 return (IntStatus);
525 }
526
527
528 /*******************************************************************************
529 *
530 * FUNCTION: AcpiEvAsynchExecuteGpeMethod
531 *
532 * PARAMETERS: Context (GpeEventInfo) - Info for this GPE
533 *
534 * RETURN: None
535 *
536 * DESCRIPTION: Perform the actual execution of a GPE control method. This
537 * function is called from an invocation of AcpiOsExecute and
538 * therefore does NOT execute at interrupt level - so that
539 * the control method itself is not executed in the context of
540 * an interrupt handler.
541 *
542 ******************************************************************************/
543
544 static void ACPI_SYSTEM_XFACE
545 AcpiEvAsynchExecuteGpeMethod (
546 void *Context)
547 {
548 ACPI_GPE_EVENT_INFO *GpeEventInfo = Context;
549 ACPI_STATUS Status;
550 ACPI_GPE_EVENT_INFO *LocalGpeEventInfo;
551 ACPI_EVALUATE_INFO *Info;
552
553
554 ACPI_FUNCTION_TRACE (EvAsynchExecuteGpeMethod);
555
556
557 /* Allocate a local GPE block */
558
559 LocalGpeEventInfo = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_EVENT_INFO));
560 if (!LocalGpeEventInfo)
561 {
562 ACPI_EXCEPTION ((AE_INFO, AE_NO_MEMORY,
563 "while handling a GPE"));
564 return_VOID;
565 }
566
567 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
568 if (ACPI_FAILURE (Status))
569 {
570 return_VOID;
571 }
572
573 /* Must revalidate the GpeNumber/GpeBlock */
574
575 if (!AcpiEvValidGpeEvent (GpeEventInfo))
576 {
577 Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
578 return_VOID;
579 }
580
581 /* Update the GPE register masks for return to enabled state */
582
583 (void) AcpiEvUpdateGpeEnableMasks (GpeEventInfo);
584
585 /*
586 * Take a snapshot of the GPE info for this level - we copy the info to
587 * prevent a race condition with RemoveHandler/RemoveBlock.
588 */
589 ACPI_MEMCPY (LocalGpeEventInfo, GpeEventInfo,
590 sizeof (ACPI_GPE_EVENT_INFO));
591
592 Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
593 if (ACPI_FAILURE (Status))
594 {
595 return_VOID;
596 }
597
598 /*
599 * Must check for control method type dispatch one more time to avoid a
600 * race with EvGpeInstallHandler
601 */
602 if ((LocalGpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
603 ACPI_GPE_DISPATCH_METHOD)
604 {
605 /* Allocate the evaluation information block */
606
607 Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
608 if (!Info)
609 {
610 Status = AE_NO_MEMORY;
611 }
612 else
613 {
614 /*
615 * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the _Lxx/_Exx
616 * control method that corresponds to this GPE
617 */
618 Info->PrefixNode = LocalGpeEventInfo->Dispatch.MethodNode;
619 Info->Flags = ACPI_IGNORE_RETURN_VALUE;
620
621 Status = AcpiNsEvaluate (Info);
622 ACPI_FREE (Info);
623 }
624
625 if (ACPI_FAILURE (Status))
626 {
627 ACPI_EXCEPTION ((AE_INFO, Status,
628 "while evaluating GPE method [%4.4s]",
629 AcpiUtGetNodeName (LocalGpeEventInfo->Dispatch.MethodNode)));
630 }
631 }
632
633 /* Defer enabling of GPE until all notify handlers are done */
634
635 Status = AcpiOsExecute (OSL_NOTIFY_HANDLER,
636 AcpiEvAsynchEnableGpe, LocalGpeEventInfo);
637 if (ACPI_FAILURE (Status))
638 {
639 ACPI_FREE (LocalGpeEventInfo);
640 }
641 return_VOID;
642 }
643
644
645 /*******************************************************************************
646 *
647 * FUNCTION: AcpiEvAsynchEnableGpe
648 *
649 * PARAMETERS: Context (GpeEventInfo) - Info for this GPE
650 *
651 * RETURN: None
652 *
653 * DESCRIPTION: Asynchronous clear/enable for GPE. This allows the GPE to
654 * complete (i.e., finish execution of Notify)
655 *
656 ******************************************************************************/
657
658 static void ACPI_SYSTEM_XFACE
659 AcpiEvAsynchEnableGpe (
660 void *Context)
661 {
662 ACPI_GPE_EVENT_INFO *GpeEventInfo = Context;
663 ACPI_STATUS Status;
664
665
666 if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
667 ACPI_GPE_LEVEL_TRIGGERED)
668 {
669 /*
670 * GPE is level-triggered, we clear the GPE status bit after handling
671 * the event.
672 */
673 Status = AcpiHwClearGpe (GpeEventInfo);
674 if (ACPI_FAILURE (Status))
675 {
676 goto Exit;
677 }
678 }
679
680 /* Enable this GPE */
681
682 (void) AcpiHwWriteGpeEnableReg (GpeEventInfo);
683
684 Exit:
685 ACPI_FREE (GpeEventInfo);
686 return;
687 }
688
689
690 /*******************************************************************************
691 *
692 * FUNCTION: AcpiEvGpeDispatch
693 *
694 * PARAMETERS: GpeEventInfo - Info for this GPE
695 * GpeNumber - Number relative to the parent GPE block
696 *
697 * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
698 *
699 * DESCRIPTION: Dispatch a General Purpose Event to either a function (e.g. EC)
700 * or method (e.g. _Lxx/_Exx) handler.
701 *
702 * This function executes at interrupt level.
703 *
704 ******************************************************************************/
705
706 UINT32
707 AcpiEvGpeDispatch (
708 ACPI_GPE_EVENT_INFO *GpeEventInfo,
709 UINT32 GpeNumber)
710 {
711 ACPI_STATUS Status;
712
713
714 ACPI_FUNCTION_TRACE (EvGpeDispatch);
715
716
717 AcpiGpeCount++;
718
719 /*
720 * If edge-triggered, clear the GPE status bit now. Note that
721 * level-triggered events are cleared after the GPE is serviced.
722 */
723 if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
724 ACPI_GPE_EDGE_TRIGGERED)
725 {
726 Status = AcpiHwClearGpe (GpeEventInfo);
727 if (ACPI_FAILURE (Status))
728 {
729 ACPI_EXCEPTION ((AE_INFO, Status,
730 "Unable to clear GPE[0x%2X]", GpeNumber));
731 return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
732 }
733 }
734
735 /*
736 * Dispatch the GPE to either an installed handler, or the control method
737 * associated with this GPE (_Lxx or _Exx). If a handler exists, we invoke
738 * it and do not attempt to run the method. If there is neither a handler
739 * nor a method, we disable this GPE to prevent further such pointless
740 * events from firing.
741 */
742 switch (GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK)
743 {
744 case ACPI_GPE_DISPATCH_HANDLER:
745
746 /*
747 * Invoke the installed handler (at interrupt level)
748 * Ignore return status for now.
749 * TBD: leave GPE disabled on error?
750 */
751 (void) GpeEventInfo->Dispatch.Handler->Address (
752 GpeEventInfo->Dispatch.Handler->Context);
753
754 /* It is now safe to clear level-triggered events. */
755
756 if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
757 ACPI_GPE_LEVEL_TRIGGERED)
758 {
759 Status = AcpiHwClearGpe (GpeEventInfo);
760 if (ACPI_FAILURE (Status))
761 {
762 ACPI_EXCEPTION ((AE_INFO, Status,
763 "Unable to clear GPE[0x%2X]", GpeNumber));
764 return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
765 }
766 }
767 break;
768
769 case ACPI_GPE_DISPATCH_METHOD:
770
771 /*
772 * Disable the GPE, so it doesn't keep firing before the method has a
773 * chance to run (it runs asynchronously with interrupts enabled).
774 */
775 Status = AcpiEvDisableGpe (GpeEventInfo);
776 if (ACPI_FAILURE (Status))
777 {
778 ACPI_EXCEPTION ((AE_INFO, Status,
779 "Unable to disable GPE[0x%2X]", GpeNumber));
780 return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
781 }
782
783 /*
784 * Execute the method associated with the GPE
785 * NOTE: Level-triggered GPEs are cleared after the method completes.
786 */
787 Status = AcpiOsExecute (OSL_GPE_HANDLER,
788 AcpiEvAsynchExecuteGpeMethod, GpeEventInfo);
789 if (ACPI_FAILURE (Status))
790 {
791 ACPI_EXCEPTION ((AE_INFO, Status,
792 "Unable to queue handler for GPE[0x%2X] - event disabled",
793 GpeNumber));
794 }
795 break;
796
797 default:
798
799 /*
800 * No handler or method to run!
801 * 03/2010: This case should no longer be possible. We will not allow
802 * a GPE to be enabled if it has no handler or method.
803 */
804 ACPI_ERROR ((AE_INFO,
805 "No handler or method for GPE[0x%2X], disabling event",
806 GpeNumber));
807
808 /*
809 * Disable the GPE. The GPE will remain disabled a handler
810 * is installed or ACPICA is restarted.
811 */
812 Status = AcpiEvDisableGpe (GpeEventInfo);
813 if (ACPI_FAILURE (Status))
814 {
815 ACPI_EXCEPTION ((AE_INFO, Status,
816 "Unable to disable GPE[0x%2X]", GpeNumber));
817 return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
818 }
819 break;
820 }
821
822 return_UINT32 (ACPI_INTERRUPT_HANDLED);
823 }
824
825