[ACPI] ACPICA 20060210
[pandora-kernel.git] / drivers / acpi / events / evxface.c
1 /******************************************************************************
2  *
3  * Module Name: evxface - External interfaces for ACPI events
4  *
5  *****************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2006, 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 <linux/module.h>
45
46 #include <acpi/acpi.h>
47 #include <acpi/acnamesp.h>
48 #include <acpi/acevents.h>
49 #include <acpi/acinterp.h>
50
51 #define _COMPONENT          ACPI_EVENTS
52 ACPI_MODULE_NAME("evxface")
53
54 /*******************************************************************************
55  *
56  * FUNCTION:    acpi_install_exception_handler
57  *
58  * PARAMETERS:  Handler         - Pointer to the handler function for the
59  *                                event
60  *
61  * RETURN:      Status
62  *
63  * DESCRIPTION: Saves the pointer to the handler function
64  *
65  ******************************************************************************/
66 #ifdef ACPI_FUTURE_USAGE
67 acpi_status acpi_install_exception_handler(acpi_exception_handler handler)
68 {
69         acpi_status status;
70
71         ACPI_FUNCTION_TRACE("acpi_install_exception_handler");
72
73         status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
74         if (ACPI_FAILURE(status)) {
75                 return_ACPI_STATUS(status);
76         }
77
78         /* Don't allow two handlers. */
79
80         if (acpi_gbl_exception_handler) {
81                 status = AE_ALREADY_EXISTS;
82                 goto cleanup;
83         }
84
85         /* Install the handler */
86
87         acpi_gbl_exception_handler = handler;
88
89       cleanup:
90         (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
91         return_ACPI_STATUS(status);
92 }
93 #endif                          /*  ACPI_FUTURE_USAGE  */
94
95 /*******************************************************************************
96  *
97  * FUNCTION:    acpi_install_fixed_event_handler
98  *
99  * PARAMETERS:  Event           - Event type to enable.
100  *              Handler         - Pointer to the handler function for the
101  *                                event
102  *              Context         - Value passed to the handler on each GPE
103  *
104  * RETURN:      Status
105  *
106  * DESCRIPTION: Saves the pointer to the handler function and then enables the
107  *              event.
108  *
109  ******************************************************************************/
110
111 acpi_status
112 acpi_install_fixed_event_handler(u32 event,
113                                  acpi_event_handler handler, void *context)
114 {
115         acpi_status status;
116
117         ACPI_FUNCTION_TRACE("acpi_install_fixed_event_handler");
118
119         /* Parameter validation */
120
121         if (event > ACPI_EVENT_MAX) {
122                 return_ACPI_STATUS(AE_BAD_PARAMETER);
123         }
124
125         status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
126         if (ACPI_FAILURE(status)) {
127                 return_ACPI_STATUS(status);
128         }
129
130         /* Don't allow two handlers. */
131
132         if (NULL != acpi_gbl_fixed_event_handlers[event].handler) {
133                 status = AE_ALREADY_EXISTS;
134                 goto cleanup;
135         }
136
137         /* Install the handler before enabling the event */
138
139         acpi_gbl_fixed_event_handlers[event].handler = handler;
140         acpi_gbl_fixed_event_handlers[event].context = context;
141
142         status = acpi_clear_event(event);
143         if (ACPI_SUCCESS(status))
144                 status = acpi_enable_event(event, 0);
145         if (ACPI_FAILURE(status)) {
146                 ACPI_WARNING((AE_INFO, "Could not enable fixed event %X",
147                               event));
148
149                 /* Remove the handler */
150
151                 acpi_gbl_fixed_event_handlers[event].handler = NULL;
152                 acpi_gbl_fixed_event_handlers[event].context = NULL;
153         } else {
154                 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
155                                   "Enabled fixed event %X, Handler=%p\n", event,
156                                   handler));
157         }
158
159       cleanup:
160         (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
161         return_ACPI_STATUS(status);
162 }
163
164 EXPORT_SYMBOL(acpi_install_fixed_event_handler);
165
166 /*******************************************************************************
167  *
168  * FUNCTION:    acpi_remove_fixed_event_handler
169  *
170  * PARAMETERS:  Event           - Event type to disable.
171  *              Handler         - Address of the handler
172  *
173  * RETURN:      Status
174  *
175  * DESCRIPTION: Disables the event and unregisters the event handler.
176  *
177  ******************************************************************************/
178
179 acpi_status
180 acpi_remove_fixed_event_handler(u32 event, acpi_event_handler handler)
181 {
182         acpi_status status = AE_OK;
183
184         ACPI_FUNCTION_TRACE("acpi_remove_fixed_event_handler");
185
186         /* Parameter validation */
187
188         if (event > ACPI_EVENT_MAX) {
189                 return_ACPI_STATUS(AE_BAD_PARAMETER);
190         }
191
192         status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
193         if (ACPI_FAILURE(status)) {
194                 return_ACPI_STATUS(status);
195         }
196
197         /* Disable the event before removing the handler */
198
199         status = acpi_disable_event(event, 0);
200
201         /* Always Remove the handler */
202
203         acpi_gbl_fixed_event_handlers[event].handler = NULL;
204         acpi_gbl_fixed_event_handlers[event].context = NULL;
205
206         if (ACPI_FAILURE(status)) {
207                 ACPI_WARNING((AE_INFO,
208                               "Could not write to fixed event enable register %X",
209                               event));
210         } else {
211                 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Disabled fixed event %X\n",
212                                   event));
213         }
214
215         (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
216         return_ACPI_STATUS(status);
217 }
218
219 EXPORT_SYMBOL(acpi_remove_fixed_event_handler);
220
221 /*******************************************************************************
222  *
223  * FUNCTION:    acpi_install_notify_handler
224  *
225  * PARAMETERS:  Device          - The device for which notifies will be handled
226  *              handler_type    - The type of handler:
227  *                                  ACPI_SYSTEM_NOTIFY: system_handler (00-7f)
228  *                                  ACPI_DEVICE_NOTIFY: driver_handler (80-ff)
229  *                                  ACPI_ALL_NOTIFY:  both system and device
230  *              Handler         - Address of the handler
231  *              Context         - Value passed to the handler on each GPE
232  *
233  * RETURN:      Status
234  *
235  * DESCRIPTION: Install a handler for notifies on an ACPI device
236  *
237  ******************************************************************************/
238
239 acpi_status
240 acpi_install_notify_handler(acpi_handle device,
241                             u32 handler_type,
242                             acpi_notify_handler handler, void *context)
243 {
244         union acpi_operand_object *obj_desc;
245         union acpi_operand_object *notify_obj;
246         struct acpi_namespace_node *node;
247         acpi_status status;
248
249         ACPI_FUNCTION_TRACE("acpi_install_notify_handler");
250
251         /* Parameter validation */
252
253         if ((!device) ||
254             (!handler) || (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) {
255                 return_ACPI_STATUS(AE_BAD_PARAMETER);
256         }
257
258         status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
259         if (ACPI_FAILURE(status)) {
260                 return_ACPI_STATUS(status);
261         }
262
263         /* Convert and validate the device handle */
264
265         node = acpi_ns_map_handle_to_node(device);
266         if (!node) {
267                 status = AE_BAD_PARAMETER;
268                 goto unlock_and_exit;
269         }
270
271         /*
272          * Root Object:
273          * Registering a notify handler on the root object indicates that the
274          * caller wishes to receive notifications for all objects.  Note that
275          * only one <external> global handler can be regsitered (per notify type).
276          */
277         if (device == ACPI_ROOT_OBJECT) {
278
279                 /* Make sure the handler is not already installed */
280
281                 if (((handler_type & ACPI_SYSTEM_NOTIFY) &&
282                      acpi_gbl_system_notify.handler) ||
283                     ((handler_type & ACPI_DEVICE_NOTIFY) &&
284                      acpi_gbl_device_notify.handler)) {
285                         status = AE_ALREADY_EXISTS;
286                         goto unlock_and_exit;
287                 }
288
289                 if (handler_type & ACPI_SYSTEM_NOTIFY) {
290                         acpi_gbl_system_notify.node = node;
291                         acpi_gbl_system_notify.handler = handler;
292                         acpi_gbl_system_notify.context = context;
293                 }
294
295                 if (handler_type & ACPI_DEVICE_NOTIFY) {
296                         acpi_gbl_device_notify.node = node;
297                         acpi_gbl_device_notify.handler = handler;
298                         acpi_gbl_device_notify.context = context;
299                 }
300
301                 /* Global notify handler installed */
302         }
303
304         /*
305          * All Other Objects:
306          * Caller will only receive notifications specific to the target object.
307          * Note that only certain object types can receive notifications.
308          */
309         else {
310                 /* Notifies allowed on this object? */
311
312                 if (!acpi_ev_is_notify_object(node)) {
313                         status = AE_TYPE;
314                         goto unlock_and_exit;
315                 }
316
317                 /* Check for an existing internal object */
318
319                 obj_desc = acpi_ns_get_attached_object(node);
320                 if (obj_desc) {
321
322                         /* Object exists - make sure there's no handler */
323
324                         if (((handler_type & ACPI_SYSTEM_NOTIFY) &&
325                              obj_desc->common_notify.system_notify) ||
326                             ((handler_type & ACPI_DEVICE_NOTIFY) &&
327                              obj_desc->common_notify.device_notify)) {
328                                 status = AE_ALREADY_EXISTS;
329                                 goto unlock_and_exit;
330                         }
331                 } else {
332                         /* Create a new object */
333
334                         obj_desc = acpi_ut_create_internal_object(node->type);
335                         if (!obj_desc) {
336                                 status = AE_NO_MEMORY;
337                                 goto unlock_and_exit;
338                         }
339
340                         /* Attach new object to the Node */
341
342                         status =
343                             acpi_ns_attach_object(device, obj_desc, node->type);
344
345                         /* Remove local reference to the object */
346
347                         acpi_ut_remove_reference(obj_desc);
348                         if (ACPI_FAILURE(status)) {
349                                 goto unlock_and_exit;
350                         }
351                 }
352
353                 /* Install the handler */
354
355                 notify_obj =
356                     acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_NOTIFY);
357                 if (!notify_obj) {
358                         status = AE_NO_MEMORY;
359                         goto unlock_and_exit;
360                 }
361
362                 notify_obj->notify.node = node;
363                 notify_obj->notify.handler = handler;
364                 notify_obj->notify.context = context;
365
366                 if (handler_type & ACPI_SYSTEM_NOTIFY) {
367                         obj_desc->common_notify.system_notify = notify_obj;
368                 }
369
370                 if (handler_type & ACPI_DEVICE_NOTIFY) {
371                         obj_desc->common_notify.device_notify = notify_obj;
372                 }
373
374                 if (handler_type == ACPI_ALL_NOTIFY) {
375
376                         /* Extra ref if installed in both */
377
378                         acpi_ut_add_reference(notify_obj);
379                 }
380         }
381
382       unlock_and_exit:
383         (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
384         return_ACPI_STATUS(status);
385 }
386
387 EXPORT_SYMBOL(acpi_install_notify_handler);
388
389 /*******************************************************************************
390  *
391  * FUNCTION:    acpi_remove_notify_handler
392  *
393  * PARAMETERS:  Device          - The device for which notifies will be handled
394  *              handler_type    - The type of handler:
395  *                                  ACPI_SYSTEM_NOTIFY: system_handler (00-7f)
396  *                                  ACPI_DEVICE_NOTIFY: driver_handler (80-ff)
397  *                                  ACPI_ALL_NOTIFY:  both system and device
398  *              Handler         - Address of the handler
399  *
400  * RETURN:      Status
401  *
402  * DESCRIPTION: Remove a handler for notifies on an ACPI device
403  *
404  ******************************************************************************/
405
406 acpi_status
407 acpi_remove_notify_handler(acpi_handle device,
408                            u32 handler_type, acpi_notify_handler handler)
409 {
410         union acpi_operand_object *notify_obj;
411         union acpi_operand_object *obj_desc;
412         struct acpi_namespace_node *node;
413         acpi_status status;
414
415         ACPI_FUNCTION_TRACE("acpi_remove_notify_handler");
416
417         /* Parameter validation */
418
419         if ((!device) ||
420             (!handler) || (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) {
421                 return_ACPI_STATUS(AE_BAD_PARAMETER);
422         }
423
424         status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
425         if (ACPI_FAILURE(status)) {
426                 return_ACPI_STATUS(status);
427         }
428
429         /* Convert and validate the device handle */
430
431         node = acpi_ns_map_handle_to_node(device);
432         if (!node) {
433                 status = AE_BAD_PARAMETER;
434                 goto unlock_and_exit;
435         }
436
437         /* Root Object */
438
439         if (device == ACPI_ROOT_OBJECT) {
440                 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
441                                   "Removing notify handler for namespace root object\n"));
442
443                 if (((handler_type & ACPI_SYSTEM_NOTIFY) &&
444                      !acpi_gbl_system_notify.handler) ||
445                     ((handler_type & ACPI_DEVICE_NOTIFY) &&
446                      !acpi_gbl_device_notify.handler)) {
447                         status = AE_NOT_EXIST;
448                         goto unlock_and_exit;
449                 }
450
451                 /* Make sure all deferred tasks are completed */
452
453                 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
454                 acpi_os_wait_events_complete(NULL);
455                 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
456                 if (ACPI_FAILURE(status)) {
457                         return_ACPI_STATUS(status);
458                 }
459
460                 if (handler_type & ACPI_SYSTEM_NOTIFY) {
461                         acpi_gbl_system_notify.node = NULL;
462                         acpi_gbl_system_notify.handler = NULL;
463                         acpi_gbl_system_notify.context = NULL;
464                 }
465
466                 if (handler_type & ACPI_DEVICE_NOTIFY) {
467                         acpi_gbl_device_notify.node = NULL;
468                         acpi_gbl_device_notify.handler = NULL;
469                         acpi_gbl_device_notify.context = NULL;
470                 }
471         }
472
473         /* All Other Objects */
474
475         else {
476                 /* Notifies allowed on this object? */
477
478                 if (!acpi_ev_is_notify_object(node)) {
479                         status = AE_TYPE;
480                         goto unlock_and_exit;
481                 }
482
483                 /* Check for an existing internal object */
484
485                 obj_desc = acpi_ns_get_attached_object(node);
486                 if (!obj_desc) {
487                         status = AE_NOT_EXIST;
488                         goto unlock_and_exit;
489                 }
490
491                 /* Object exists - make sure there's an existing handler */
492
493                 if (handler_type & ACPI_SYSTEM_NOTIFY) {
494                         notify_obj = obj_desc->common_notify.system_notify;
495                         if ((!notify_obj) ||
496                             (notify_obj->notify.handler != handler)) {
497                                 status = AE_BAD_PARAMETER;
498                                 goto unlock_and_exit;
499                         }
500                         /* Make sure all deferred tasks are completed */
501
502                         (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
503                         acpi_os_wait_events_complete(NULL);
504                         status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
505                         if (ACPI_FAILURE(status)) {
506                                 return_ACPI_STATUS(status);
507                         }
508
509                         /* Remove the handler */
510                         obj_desc->common_notify.system_notify = NULL;
511                         acpi_ut_remove_reference(notify_obj);
512                 }
513
514                 if (handler_type & ACPI_DEVICE_NOTIFY) {
515                         notify_obj = obj_desc->common_notify.device_notify;
516                         if ((!notify_obj) ||
517                             (notify_obj->notify.handler != handler)) {
518                                 status = AE_BAD_PARAMETER;
519                                 goto unlock_and_exit;
520                         }
521                         /* Make sure all deferred tasks are completed */
522
523                         (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
524                         acpi_os_wait_events_complete(NULL);
525                         status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
526                         if (ACPI_FAILURE(status)) {
527                                 return_ACPI_STATUS(status);
528                         }
529
530                         /* Remove the handler */
531                         obj_desc->common_notify.device_notify = NULL;
532                         acpi_ut_remove_reference(notify_obj);
533                 }
534         }
535
536       unlock_and_exit:
537         (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
538         return_ACPI_STATUS(status);
539 }
540
541 EXPORT_SYMBOL(acpi_remove_notify_handler);
542
543 /*******************************************************************************
544  *
545  * FUNCTION:    acpi_install_gpe_handler
546  *
547  * PARAMETERS:  gpe_device      - Namespace node for the GPE (NULL for FADT
548  *                                defined GPEs)
549  *              gpe_number      - The GPE number within the GPE block
550  *              Type            - Whether this GPE should be treated as an
551  *                                edge- or level-triggered interrupt.
552  *              Address         - Address of the handler
553  *              Context         - Value passed to the handler on each GPE
554  *
555  * RETURN:      Status
556  *
557  * DESCRIPTION: Install a handler for a General Purpose Event.
558  *
559  ******************************************************************************/
560
561 acpi_status
562 acpi_install_gpe_handler(acpi_handle gpe_device,
563                          u32 gpe_number,
564                          u32 type, acpi_event_handler address, void *context)
565 {
566         struct acpi_gpe_event_info *gpe_event_info;
567         struct acpi_handler_info *handler;
568         acpi_status status;
569         acpi_cpu_flags flags;
570
571         ACPI_FUNCTION_TRACE("acpi_install_gpe_handler");
572
573         /* Parameter validation */
574
575         if ((!address) || (type > ACPI_GPE_XRUPT_TYPE_MASK)) {
576                 return_ACPI_STATUS(AE_BAD_PARAMETER);
577         }
578
579         status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
580         if (ACPI_FAILURE(status)) {
581                 return_ACPI_STATUS(status);
582         }
583
584         /* Ensure that we have a valid GPE number */
585
586         gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
587         if (!gpe_event_info) {
588                 status = AE_BAD_PARAMETER;
589                 goto unlock_and_exit;
590         }
591
592         /* Make sure that there isn't a handler there already */
593
594         if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
595             ACPI_GPE_DISPATCH_HANDLER) {
596                 status = AE_ALREADY_EXISTS;
597                 goto unlock_and_exit;
598         }
599
600         /* Allocate and init handler object */
601
602         handler = ACPI_MEM_CALLOCATE(sizeof(struct acpi_handler_info));
603         if (!handler) {
604                 status = AE_NO_MEMORY;
605                 goto unlock_and_exit;
606         }
607
608         handler->address = address;
609         handler->context = context;
610         handler->method_node = gpe_event_info->dispatch.method_node;
611
612         /* Disable the GPE before installing the handler */
613
614         status = acpi_ev_disable_gpe(gpe_event_info);
615         if (ACPI_FAILURE(status)) {
616                 goto unlock_and_exit;
617         }
618
619         /* Install the handler */
620
621         flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
622         gpe_event_info->dispatch.handler = handler;
623
624         /* Setup up dispatch flags to indicate handler (vs. method) */
625
626         gpe_event_info->flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);  /* Clear bits */
627         gpe_event_info->flags |= (u8) (type | ACPI_GPE_DISPATCH_HANDLER);
628
629         acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
630
631       unlock_and_exit:
632         (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
633         return_ACPI_STATUS(status);
634 }
635
636 EXPORT_SYMBOL(acpi_install_gpe_handler);
637
638 /*******************************************************************************
639  *
640  * FUNCTION:    acpi_remove_gpe_handler
641  *
642  * PARAMETERS:  gpe_device      - Namespace node for the GPE (NULL for FADT
643  *                                defined GPEs)
644  *              gpe_number      - The event to remove a handler
645  *              Address         - Address of the handler
646  *
647  * RETURN:      Status
648  *
649  * DESCRIPTION: Remove a handler for a General Purpose acpi_event.
650  *
651  ******************************************************************************/
652
653 acpi_status
654 acpi_remove_gpe_handler(acpi_handle gpe_device,
655                         u32 gpe_number, acpi_event_handler address)
656 {
657         struct acpi_gpe_event_info *gpe_event_info;
658         struct acpi_handler_info *handler;
659         acpi_status status;
660         acpi_cpu_flags flags;
661
662         ACPI_FUNCTION_TRACE("acpi_remove_gpe_handler");
663
664         /* Parameter validation */
665
666         if (!address) {
667                 return_ACPI_STATUS(AE_BAD_PARAMETER);
668         }
669
670         status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
671         if (ACPI_FAILURE(status)) {
672                 return_ACPI_STATUS(status);
673         }
674
675         /* Ensure that we have a valid GPE number */
676
677         gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
678         if (!gpe_event_info) {
679                 status = AE_BAD_PARAMETER;
680                 goto unlock_and_exit;
681         }
682
683         /* Make sure that a handler is indeed installed */
684
685         if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) !=
686             ACPI_GPE_DISPATCH_HANDLER) {
687                 status = AE_NOT_EXIST;
688                 goto unlock_and_exit;
689         }
690
691         /* Make sure that the installed handler is the same */
692
693         if (gpe_event_info->dispatch.handler->address != address) {
694                 status = AE_BAD_PARAMETER;
695                 goto unlock_and_exit;
696         }
697
698         /* Disable the GPE before removing the handler */
699
700         status = acpi_ev_disable_gpe(gpe_event_info);
701         if (ACPI_FAILURE(status)) {
702                 goto unlock_and_exit;
703         }
704
705         /* Make sure all deferred tasks are completed */
706
707         (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
708         acpi_os_wait_events_complete(NULL);
709         status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
710         if (ACPI_FAILURE(status)) {
711                 return_ACPI_STATUS(status);
712         }
713
714         /* Remove the handler */
715
716         flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
717         handler = gpe_event_info->dispatch.handler;
718
719         /* Restore Method node (if any), set dispatch flags */
720
721         gpe_event_info->dispatch.method_node = handler->method_node;
722         gpe_event_info->flags &= ~ACPI_GPE_DISPATCH_MASK;       /* Clear bits */
723         if (handler->method_node) {
724                 gpe_event_info->flags |= ACPI_GPE_DISPATCH_METHOD;
725         }
726         acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
727
728         /* Now we can free the handler object */
729
730         ACPI_MEM_FREE(handler);
731
732       unlock_and_exit:
733         (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
734         return_ACPI_STATUS(status);
735 }
736
737 EXPORT_SYMBOL(acpi_remove_gpe_handler);
738
739 /*******************************************************************************
740  *
741  * FUNCTION:    acpi_acquire_global_lock
742  *
743  * PARAMETERS:  Timeout         - How long the caller is willing to wait
744  *              Handle          - Where the handle to the lock is returned
745  *                                (if acquired)
746  *
747  * RETURN:      Status
748  *
749  * DESCRIPTION: Acquire the ACPI Global Lock
750  *
751  ******************************************************************************/
752
753 acpi_status acpi_acquire_global_lock(u16 timeout, u32 * handle)
754 {
755         acpi_status status;
756
757         if (!handle) {
758                 return (AE_BAD_PARAMETER);
759         }
760
761         status = acpi_ex_enter_interpreter();
762         if (ACPI_FAILURE(status)) {
763                 return (status);
764         }
765
766         status = acpi_ev_acquire_global_lock(timeout);
767         acpi_ex_exit_interpreter();
768
769         if (ACPI_SUCCESS(status)) {
770                 acpi_gbl_global_lock_handle++;
771                 *handle = acpi_gbl_global_lock_handle;
772         }
773
774         return (status);
775 }
776
777 EXPORT_SYMBOL(acpi_acquire_global_lock);
778
779 /*******************************************************************************
780  *
781  * FUNCTION:    acpi_release_global_lock
782  *
783  * PARAMETERS:  Handle      - Returned from acpi_acquire_global_lock
784  *
785  * RETURN:      Status
786  *
787  * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid.
788  *
789  ******************************************************************************/
790
791 acpi_status acpi_release_global_lock(u32 handle)
792 {
793         acpi_status status;
794
795         if (handle != acpi_gbl_global_lock_handle) {
796                 return (AE_NOT_ACQUIRED);
797         }
798
799         status = acpi_ev_release_global_lock();
800         return (status);
801 }
802
803 EXPORT_SYMBOL(acpi_release_global_lock);