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