]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - sys/contrib/dev/acpica/events/evgpe.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / sys / contrib / dev / acpica / events / evgpe.c
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 <contrib/dev/acpica/include/acpi.h>
117 #include <contrib/dev/acpica/include/accommon.h>
118 #include <contrib/dev/acpica/include/acevents.h>
119 #include <contrib/dev/acpica/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 GpeBlock 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