ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / drivers / acpi / events / evgpe.c
1 /******************************************************************************
2  *
3  * Module Name: evgpe - General Purpose Event handling and dispatch
4  *
5  *****************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2004, R. Byron Moore
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    substantially similar to the "NO WARRANTY" disclaimer below
19  *    ("Disclaimer") and any redistribution must be conditioned upon
20  *    including a substantially similar Disclaimer requirement for further
21  *    binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  *    of any contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43
44 #include <acpi/acpi.h>
45 #include <acpi/acevents.h>
46 #include <acpi/acnamesp.h>
47
48 #define _COMPONENT          ACPI_EVENTS
49          ACPI_MODULE_NAME    ("evgpe")
50
51
52 /*******************************************************************************
53  *
54  * FUNCTION:    acpi_ev_get_gpe_event_info
55  *
56  * PARAMETERS:  gpe_device          - Device node.  NULL for GPE0/GPE1
57  *              gpe_number          - Raw GPE number
58  *
59  * RETURN:      A GPE event_info struct. NULL if not a valid GPE
60  *
61  * DESCRIPTION: Returns the event_info struct associated with this GPE.
62  *              Validates the gpe_block and the gpe_number
63  *
64  *              Should be called only when the GPE lists are semaphore locked
65  *              and not subject to change.
66  *
67  ******************************************************************************/
68
69 struct acpi_gpe_event_info *
70 acpi_ev_get_gpe_event_info (
71         acpi_handle                     gpe_device,
72         u32                             gpe_number)
73 {
74         union acpi_operand_object       *obj_desc;
75         struct acpi_gpe_block_info      *gpe_block;
76         acpi_native_uint                i;
77
78
79         ACPI_FUNCTION_ENTRY ();
80
81
82         /* A NULL gpe_block means use the FADT-defined GPE block(s) */
83
84         if (!gpe_device) {
85                 /* Examine GPE Block 0 and 1 (These blocks are permanent) */
86
87                 for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++) {
88                         gpe_block = acpi_gbl_gpe_fadt_blocks[i];
89                         if (gpe_block) {
90                                 if ((gpe_number >= gpe_block->block_base_number) &&
91                                         (gpe_number < gpe_block->block_base_number + (gpe_block->register_count * 8))) {
92                                         return (&gpe_block->event_info[gpe_number - gpe_block->block_base_number]);
93                                 }
94                         }
95                 }
96
97                 /* The gpe_number was not in the range of either FADT GPE block */
98
99                 return (NULL);
100         }
101
102         /* A Non-NULL gpe_device means this is a GPE Block Device */
103
104         obj_desc = acpi_ns_get_attached_object ((struct acpi_namespace_node *) gpe_device);
105         if (!obj_desc ||
106                 !obj_desc->device.gpe_block) {
107                 return (NULL);
108         }
109
110         gpe_block = obj_desc->device.gpe_block;
111
112         if ((gpe_number >= gpe_block->block_base_number) &&
113                 (gpe_number < gpe_block->block_base_number + (gpe_block->register_count * 8))) {
114                 return (&gpe_block->event_info[gpe_number - gpe_block->block_base_number]);
115         }
116
117         return (NULL);
118 }
119
120
121 /*******************************************************************************
122  *
123  * FUNCTION:    acpi_ev_gpe_detect
124  *
125  * PARAMETERS:  gpe_xrupt_list      - Interrupt block for this interrupt.
126  *                                    Can have multiple GPE blocks attached.
127  *
128  * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
129  *
130  * DESCRIPTION: Detect if any GP events have occurred.  This function is
131  *              executed at interrupt level.
132  *
133  ******************************************************************************/
134
135 u32
136 acpi_ev_gpe_detect (
137         struct acpi_gpe_xrupt_info      *gpe_xrupt_list)
138 {
139         u32                             int_status = ACPI_INTERRUPT_NOT_HANDLED;
140         u8                              enabled_status_byte;
141         struct acpi_gpe_register_info   *gpe_register_info;
142         u32                             in_value;
143         acpi_status                     status;
144         struct acpi_gpe_block_info      *gpe_block;
145         u32                             i;
146         u32                             j;
147
148
149         ACPI_FUNCTION_NAME ("ev_gpe_detect");
150
151         /* Check for the case where there are no GPEs */
152
153         if (!gpe_xrupt_list) {
154                 return (int_status);
155         }
156
157         /* Examine all GPE blocks attached to this interrupt level */
158
159         acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_ISR);
160         gpe_block = gpe_xrupt_list->gpe_block_list_head;
161         while (gpe_block) {
162                 /*
163                  * Read all of the 8-bit GPE status and enable registers
164                  * in this GPE block, saving all of them.
165                  * Find all currently active GP events.
166                  */
167                 for (i = 0; i < gpe_block->register_count; i++) {
168                         /* Get the next status/enable pair */
169
170                         gpe_register_info = &gpe_block->register_info[i];
171
172                         /* Read the Status Register */
173
174                         status = acpi_hw_low_level_read (ACPI_GPE_REGISTER_WIDTH, &in_value,
175                                          &gpe_register_info->status_address);
176                         gpe_register_info->status = (u8) in_value;
177                         if (ACPI_FAILURE (status)) {
178                                 goto unlock_and_exit;
179                         }
180
181                         /* Read the Enable Register */
182
183                         status = acpi_hw_low_level_read (ACPI_GPE_REGISTER_WIDTH, &in_value,
184                                          &gpe_register_info->enable_address);
185                         gpe_register_info->enable = (u8) in_value;
186                         if (ACPI_FAILURE (status)) {
187                                 goto unlock_and_exit;
188                         }
189
190                         ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
191                                 "GPE pair: Status %8.8X%8.8X = %02X, Enable %8.8X%8.8X = %02X\n",
192                                 ACPI_FORMAT_UINT64 (gpe_register_info->status_address.address),
193                                 gpe_register_info->status,
194                                 ACPI_FORMAT_UINT64 (gpe_register_info->enable_address.address),
195                                 gpe_register_info->enable));
196
197                         /* First check if there is anything active at all in this register */
198
199                         enabled_status_byte = (u8) (gpe_register_info->status &
200                                            gpe_register_info->enable);
201                         if (!enabled_status_byte) {
202                                 /* No active GPEs in this register, move on */
203
204                                 continue;
205                         }
206
207                         /* Now look at the individual GPEs in this byte register */
208
209                         for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
210                                 /* Examine one GPE bit */
211
212                                 if (enabled_status_byte & acpi_gbl_decode_to8bit[j]) {
213                                         /*
214                                          * Found an active GPE. Dispatch the event to a handler
215                                          * or method.
216                                          */
217                                         int_status |= acpi_ev_gpe_dispatch (
218                                                           &gpe_block->event_info[(i * ACPI_GPE_REGISTER_WIDTH) + j],
219                                                           j + gpe_register_info->base_gpe_number);
220                                 }
221                         }
222                 }
223
224                 gpe_block = gpe_block->next;
225         }
226
227 unlock_and_exit:
228
229         acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_ISR);
230         return (int_status);
231 }
232
233
234 /*******************************************************************************
235  *
236  * FUNCTION:    acpi_ev_asynch_execute_gpe_method
237  *
238  * PARAMETERS:  Context (gpe_event_info) - Info for this GPE
239  *
240  * RETURN:      None
241  *
242  * DESCRIPTION: Perform the actual execution of a GPE control method.  This
243  *              function is called from an invocation of acpi_os_queue_for_execution
244  *              (and therefore does NOT execute at interrupt level) so that
245  *              the control method itself is not executed in the context of
246  *              an interrupt handler.
247  *
248  ******************************************************************************/
249
250 static void ACPI_SYSTEM_XFACE
251 acpi_ev_asynch_execute_gpe_method (
252         void                            *context)
253 {
254         struct acpi_gpe_event_info      *gpe_event_info = (void *) context;
255         u32                             gpe_number = 0;
256         acpi_status                     status;
257         struct acpi_gpe_event_info      local_gpe_event_info;
258
259
260         ACPI_FUNCTION_TRACE ("ev_asynch_execute_gpe_method");
261
262
263         status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
264         if (ACPI_FAILURE (status)) {
265                 return_VOID;
266         }
267
268         /* Must revalidate the gpe_number/gpe_block */
269
270         if (!acpi_ev_valid_gpe_event (gpe_event_info)) {
271                 status = acpi_ut_release_mutex (ACPI_MTX_EVENTS);
272                 return_VOID;
273         }
274
275         /*
276          * Take a snapshot of the GPE info for this level - we copy the
277          * info to prevent a race condition with remove_handler/remove_block.
278          */
279         ACPI_MEMCPY (&local_gpe_event_info, gpe_event_info, sizeof (struct acpi_gpe_event_info));
280
281         status = acpi_ut_release_mutex (ACPI_MTX_EVENTS);
282         if (ACPI_FAILURE (status)) {
283                 return_VOID;
284         }
285
286         if (local_gpe_event_info.method_node) {
287                 /*
288                  * Invoke the GPE Method (_Lxx, _Exx):
289                  * (Evaluate the _Lxx/_Exx control method that corresponds to this GPE.)
290                  */
291                 status = acpi_ns_evaluate_by_handle (local_gpe_event_info.method_node, NULL, NULL);
292                 if (ACPI_FAILURE (status)) {
293                         ACPI_REPORT_ERROR (("%s while evaluating method [%4.4s] for GPE[%2X]\n",
294                                 acpi_format_exception (status),
295                                 acpi_ut_get_node_name (local_gpe_event_info.method_node), gpe_number));
296                 }
297         }
298
299         if ((local_gpe_event_info.flags & ACPI_GPE_XRUPT_TYPE_MASK) == ACPI_GPE_LEVEL_TRIGGERED) {
300                 /*
301                  * GPE is level-triggered, we clear the GPE status bit after handling
302                  * the event.
303                  */
304                 status = acpi_hw_clear_gpe (&local_gpe_event_info);
305                 if (ACPI_FAILURE (status)) {
306                         return_VOID;
307                 }
308         }
309
310         /* Enable this GPE */
311
312         (void) acpi_hw_enable_gpe (&local_gpe_event_info);
313         return_VOID;
314 }
315
316
317 /*******************************************************************************
318  *
319  * FUNCTION:    acpi_ev_gpe_dispatch
320  *
321  * PARAMETERS:  gpe_event_info  - info for this GPE
322  *              gpe_number      - Number relative to the parent GPE block
323  *
324  * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
325  *
326  * DESCRIPTION: Dispatch a General Purpose Event to either a function (e.g. EC)
327  *              or method (e.g. _Lxx/_Exx) handler.
328  *
329  *              This function executes at interrupt level.
330  *
331  ******************************************************************************/
332
333 u32
334 acpi_ev_gpe_dispatch (
335         struct acpi_gpe_event_info      *gpe_event_info,
336         u32                             gpe_number)
337 {
338         acpi_status                     status;
339
340
341         ACPI_FUNCTION_TRACE ("ev_gpe_dispatch");
342
343
344         /*
345          * If edge-triggered, clear the GPE status bit now.  Note that
346          * level-triggered events are cleared after the GPE is serviced.
347          */
348         if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) == ACPI_GPE_EDGE_TRIGGERED) {
349                 status = acpi_hw_clear_gpe (gpe_event_info);
350                 if (ACPI_FAILURE (status)) {
351                         ACPI_REPORT_ERROR (("acpi_ev_gpe_dispatch: Unable to clear GPE[%2X]\n",
352                                 gpe_number));
353                         return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
354                 }
355         }
356
357         /*
358          * Dispatch the GPE to either an installed handler, or the control
359          * method associated with this GPE (_Lxx or _Exx).
360          * If a handler exists, we invoke it and do not attempt to run the method.
361          * If there is neither a handler nor a method, we disable the level to
362          * prevent further events from coming in here.
363          */
364         if (gpe_event_info->handler) {
365                 /* Invoke the installed handler (at interrupt level) */
366
367                 gpe_event_info->handler (gpe_event_info->context);
368
369                 /* It is now safe to clear level-triggered events. */
370
371                 if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) == ACPI_GPE_LEVEL_TRIGGERED) {
372                         status = acpi_hw_clear_gpe (gpe_event_info);
373                         if (ACPI_FAILURE (status)) {
374                                 ACPI_REPORT_ERROR ((
375                                         "acpi_ev_gpe_dispatch: Unable to clear GPE[%2X]\n",
376                                         gpe_number));
377                                 return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
378                         }
379                 }
380         }
381         else if (gpe_event_info->method_node) {
382                 /*
383                  * Disable GPE, so it doesn't keep firing before the method has a
384                  * chance to run.
385                  */
386                 status = acpi_hw_disable_gpe (gpe_event_info);
387                 if (ACPI_FAILURE (status)) {
388                         ACPI_REPORT_ERROR ((
389                                 "acpi_ev_gpe_dispatch: Unable to disable GPE[%2X]\n",
390                                 gpe_number));
391                         return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
392                 }
393
394                 /*
395                  * Execute the method associated with the GPE
396                  * NOTE: Level-triggered GPEs are cleared after the method completes.
397                  */
398                 if (ACPI_FAILURE (acpi_os_queue_for_execution (OSD_PRIORITY_GPE,
399                                  acpi_ev_asynch_execute_gpe_method,
400                                  gpe_event_info))) {
401                         ACPI_REPORT_ERROR ((
402                                 "acpi_ev_gpe_dispatch: Unable to queue handler for GPE[%2X], event is disabled\n",
403                                 gpe_number));
404                 }
405         }
406         else {
407                 /* No handler or method to run! */
408
409                 ACPI_REPORT_ERROR ((
410                         "acpi_ev_gpe_dispatch: No handler or method for GPE[%2X], disabling event\n",
411                         gpe_number));
412
413                 /*
414                  * Disable the GPE.  The GPE will remain disabled until the ACPI
415                  * Core Subsystem is restarted, or a handler is installed.
416                  */
417                 status = acpi_hw_disable_gpe (gpe_event_info);
418                 if (ACPI_FAILURE (status)) {
419                         ACPI_REPORT_ERROR ((
420                                 "acpi_ev_gpe_dispatch: Unable to disable GPE[%2X]\n",
421                                 gpe_number));
422                         return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
423                 }
424         }
425
426         return_VALUE (ACPI_INTERRUPT_HANDLED);
427 }
428