Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.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                 /* Make sure the handler is not already installed */
279
280                 if (((handler_type & ACPI_SYSTEM_NOTIFY) &&
281                      acpi_gbl_system_notify.handler) ||
282                     ((handler_type & ACPI_DEVICE_NOTIFY) &&
283                      acpi_gbl_device_notify.handler)) {
284                         status = AE_ALREADY_EXISTS;
285                         goto unlock_and_exit;
286                 }
287
288                 if (handler_type & ACPI_SYSTEM_NOTIFY) {
289                         acpi_gbl_system_notify.node = node;
290                         acpi_gbl_system_notify.handler = handler;
291                         acpi_gbl_system_notify.context = context;
292                 }
293
294                 if (handler_type & ACPI_DEVICE_NOTIFY) {
295                         acpi_gbl_device_notify.node = node;
296                         acpi_gbl_device_notify.handler = handler;
297                         acpi_gbl_device_notify.context = context;
298                 }
299
300                 /* Global notify handler installed */
301         }
302
303         /*
304          * All Other Objects:
305          * Caller will only receive notifications specific to the target object.
306          * Note that only certain object types can receive notifications.
307          */
308         else {
309                 /* Notifies allowed on this object? */
310
311                 if (!acpi_ev_is_notify_object(node)) {
312                         status = AE_TYPE;
313                         goto unlock_and_exit;
314                 }
315
316                 /* Check for an existing internal object */
317
318                 obj_desc = acpi_ns_get_attached_object(node);
319                 if (obj_desc) {
320                         /* Object exists - make sure there's no handler */
321
322                         if (((handler_type & ACPI_SYSTEM_NOTIFY) &&
323                              obj_desc->common_notify.system_notify) ||
324                             ((handler_type & ACPI_DEVICE_NOTIFY) &&
325                              obj_desc->common_notify.device_notify)) {
326                                 status = AE_ALREADY_EXISTS;
327                                 goto unlock_and_exit;
328                         }
329                 } else {
330                         /* Create a new object */
331
332                         obj_desc = acpi_ut_create_internal_object(node->type);
333                         if (!obj_desc) {
334                                 status = AE_NO_MEMORY;
335                                 goto unlock_and_exit;
336                         }
337
338                         /* Attach new object to the Node */
339
340                         status =
341                             acpi_ns_attach_object(device, obj_desc, node->type);
342
343                         /* Remove local reference to the object */
344
345                         acpi_ut_remove_reference(obj_desc);
346                         if (ACPI_FAILURE(status)) {
347                                 goto unlock_and_exit;
348                         }
349                 }
350
351                 /* Install the handler */
352
353                 notify_obj =
354                     acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_NOTIFY);
355                 if (!notify_obj) {
356                         status = AE_NO_MEMORY;
357                         goto unlock_and_exit;
358                 }
359
360                 notify_obj->notify.node = node;
361                 notify_obj->notify.handler = handler;
362                 notify_obj->notify.context = context;
363
364                 if (handler_type & ACPI_SYSTEM_NOTIFY) {
365                         obj_desc->common_notify.system_notify = notify_obj;
366                 }
367
368                 if (handler_type & ACPI_DEVICE_NOTIFY) {
369                         obj_desc->common_notify.device_notify = notify_obj;
370                 }
371
372                 if (handler_type == ACPI_ALL_NOTIFY) {
373                         /* Extra ref if installed in both */
374
375                         acpi_ut_add_reference(notify_obj);
376                 }
377         }
378
379       unlock_and_exit:
380         (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
381         return_ACPI_STATUS(status);
382 }
383
384 EXPORT_SYMBOL(acpi_install_notify_handler);
385
386 /*******************************************************************************
387  *
388  * FUNCTION:    acpi_remove_notify_handler
389  *
390  * PARAMETERS:  Device          - The device for which notifies will be handled
391  *              handler_type    - The type of handler:
392  *                                  ACPI_SYSTEM_NOTIFY: system_handler (00-7f)
393  *                                  ACPI_DEVICE_NOTIFY: driver_handler (80-ff)
394  *                                  ACPI_ALL_NOTIFY:  both system and device
395  *              Handler         - Address of the handler
396  *
397  * RETURN:      Status
398  *
399  * DESCRIPTION: Remove a handler for notifies on an ACPI device
400  *
401  ******************************************************************************/
402
403 acpi_status
404 acpi_remove_notify_handler(acpi_handle device,
405                            u32 handler_type, acpi_notify_handler handler)
406 {
407         union acpi_operand_object *notify_obj;
408         union acpi_operand_object *obj_desc;
409         struct acpi_namespace_node *node;
410         acpi_status status;
411
412         ACPI_FUNCTION_TRACE("acpi_remove_notify_handler");
413
414         /* Parameter validation */
415
416         if ((!device) ||
417             (!handler) || (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) {
418                 return_ACPI_STATUS(AE_BAD_PARAMETER);
419         }
420
421         status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
422         if (ACPI_FAILURE(status)) {
423                 return_ACPI_STATUS(status);
424         }
425
426         /* Convert and validate the device handle */
427
428         node = acpi_ns_map_handle_to_node(device);
429         if (!node) {
430                 status = AE_BAD_PARAMETER;
431                 goto unlock_and_exit;
432         }
433
434         /* Root Object */
435
436         if (device == ACPI_ROOT_OBJECT) {
437                 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
438                                   "Removing notify handler for namespace root object\n"));
439
440                 if (((handler_type & ACPI_SYSTEM_NOTIFY) &&
441                      !acpi_gbl_system_notify.handler) ||
442                     ((handler_type & ACPI_DEVICE_NOTIFY) &&
443                      !acpi_gbl_device_notify.handler)) {
444                         status = AE_NOT_EXIST;
445                         goto unlock_and_exit;
446                 }
447
448                 /* Make sure all deferred tasks are completed */
449
450                 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
451                 acpi_os_wait_events_complete(NULL);
452                 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
453                 if (ACPI_FAILURE(status)) {
454                         return_ACPI_STATUS(status);
455                 }
456
457                 if (handler_type & ACPI_SYSTEM_NOTIFY) {
458                         acpi_gbl_system_notify.node = NULL;
459                         acpi_gbl_system_notify.handler = NULL;
460                         acpi_gbl_system_notify.context = NULL;
461                 }
462
463                 if (handler_type & ACPI_DEVICE_NOTIFY) {
464                         acpi_gbl_device_notify.node = NULL;
465                         acpi_gbl_device_notify.handler = NULL;
466                         acpi_gbl_device_notify.context = NULL;
467                 }
468         }
469
470         /* All Other Objects */
471
472         else {
473                 /* Notifies allowed on this object? */
474
475                 if (!acpi_ev_is_notify_object(node)) {
476                         status = AE_TYPE;
477                         goto unlock_and_exit;
478                 }
479
480                 /* Check for an existing internal object */
481
482                 obj_desc = acpi_ns_get_attached_object(node);
483                 if (!obj_desc) {
484                         status = AE_NOT_EXIST;
485                         goto unlock_and_exit;
486                 }
487
488                 /* Object exists - make sure there's an existing handler */
489
490                 if (handler_type & ACPI_SYSTEM_NOTIFY) {
491                         notify_obj = obj_desc->common_notify.system_notify;
492                         if ((!notify_obj) ||
493                             (notify_obj->notify.handler != handler)) {
494                                 status = AE_BAD_PARAMETER;
495                                 goto unlock_and_exit;
496                         }
497                         /* Make sure all deferred tasks are completed */
498
499                         (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
500                         acpi_os_wait_events_complete(NULL);
501                         status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
502                         if (ACPI_FAILURE(status)) {
503                                 return_ACPI_STATUS(status);
504                         }
505
506                         /* Remove the handler */
507                         obj_desc->common_notify.system_notify = NULL;
508                         acpi_ut_remove_reference(notify_obj);
509                 }
510
511                 if (handler_type & ACPI_DEVICE_NOTIFY) {
512                         notify_obj = obj_desc->common_notify.device_notify;
513                         if ((!notify_obj) ||
514                             (notify_obj->notify.handler != handler)) {
515                                 status = AE_BAD_PARAMETER;
516                                 goto unlock_and_exit;
517                         }
518                         /* Make sure all deferred tasks are completed */
519
520                         (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
521                         acpi_os_wait_events_complete(NULL);
522                         status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
523                         if (ACPI_FAILURE(status)) {
524                                 return_ACPI_STATUS(status);
525                         }
526
527                         /* Remove the handler */
528                         obj_desc->common_notify.device_notify = NULL;
529                         acpi_ut_remove_reference(notify_obj);
530                 }
531         }
532
533       unlock_and_exit:
534         (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
535         return_ACPI_STATUS(status);
536 }
537
538 EXPORT_SYMBOL(acpi_remove_notify_handler);
539
540 /*******************************************************************************
541  *
542  * FUNCTION:    acpi_install_gpe_handler
543  *
544  * PARAMETERS:  gpe_device      - Namespace node for the GPE (NULL for FADT
545  *                                defined GPEs)
546  *              gpe_number      - The GPE number within the GPE block
547  *              Type            - Whether this GPE should be treated as an
548  *                                edge- or level-triggered interrupt.
549  *              Address         - Address of the handler
550  *              Context         - Value passed to the handler on each GPE
551  *
552  * RETURN:      Status
553  *
554  * DESCRIPTION: Install a handler for a General Purpose Event.
555  *
556  ******************************************************************************/
557
558 acpi_status
559 acpi_install_gpe_handler(acpi_handle gpe_device,
560                          u32 gpe_number,
561                          u32 type, acpi_event_handler address, void *context)
562 {
563         struct acpi_gpe_event_info *gpe_event_info;
564         struct acpi_handler_info *handler;
565         acpi_status status;
566         acpi_cpu_flags flags;
567
568         ACPI_FUNCTION_TRACE("acpi_install_gpe_handler");
569
570         /* Parameter validation */
571
572         if ((!address) || (type > ACPI_GPE_XRUPT_TYPE_MASK)) {
573                 return_ACPI_STATUS(AE_BAD_PARAMETER);
574         }
575
576         status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
577         if (ACPI_FAILURE(status)) {
578                 return_ACPI_STATUS(status);
579         }
580
581         /* Ensure that we have a valid GPE number */
582
583         gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
584         if (!gpe_event_info) {
585                 status = AE_BAD_PARAMETER;
586                 goto unlock_and_exit;
587         }
588
589         /* Make sure that there isn't a handler there already */
590
591         if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
592             ACPI_GPE_DISPATCH_HANDLER) {
593                 status = AE_ALREADY_EXISTS;
594                 goto unlock_and_exit;
595         }
596
597         /* Allocate and init handler object */
598
599         handler = ACPI_MEM_CALLOCATE(sizeof(struct acpi_handler_info));
600         if (!handler) {
601                 status = AE_NO_MEMORY;
602                 goto unlock_and_exit;
603         }
604
605         handler->address = address;
606         handler->context = context;
607         handler->method_node = gpe_event_info->dispatch.method_node;
608
609         /* Disable the GPE before installing the handler */
610
611         status = acpi_ev_disable_gpe(gpe_event_info);
612         if (ACPI_FAILURE(status)) {
613                 goto unlock_and_exit;
614         }
615
616         /* Install the handler */
617
618         flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
619         gpe_event_info->dispatch.handler = handler;
620
621         /* Setup up dispatch flags to indicate handler (vs. method) */
622
623         gpe_event_info->flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);  /* Clear bits */
624         gpe_event_info->flags |= (u8) (type | ACPI_GPE_DISPATCH_HANDLER);
625
626         acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
627
628       unlock_and_exit:
629         (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
630         return_ACPI_STATUS(status);
631 }
632
633 EXPORT_SYMBOL(acpi_install_gpe_handler);
634
635 /*******************************************************************************
636  *
637  * FUNCTION:    acpi_remove_gpe_handler
638  *
639  * PARAMETERS:  gpe_device      - Namespace node for the GPE (NULL for FADT
640  *                                defined GPEs)
641  *              gpe_number      - The event to remove a handler
642  *              Address         - Address of the handler
643  *
644  * RETURN:      Status
645  *
646  * DESCRIPTION: Remove a handler for a General Purpose acpi_event.
647  *
648  ******************************************************************************/
649
650 acpi_status
651 acpi_remove_gpe_handler(acpi_handle gpe_device,
652                         u32 gpe_number, acpi_event_handler address)
653 {
654         struct acpi_gpe_event_info *gpe_event_info;
655         struct acpi_handler_info *handler;
656         acpi_status status;
657         acpi_cpu_flags flags;
658
659         ACPI_FUNCTION_TRACE("acpi_remove_gpe_handler");
660
661         /* Parameter validation */
662
663         if (!address) {
664                 return_ACPI_STATUS(AE_BAD_PARAMETER);
665         }
666
667         status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
668         if (ACPI_FAILURE(status)) {
669                 return_ACPI_STATUS(status);
670         }
671
672         /* Ensure that we have a valid GPE number */
673
674         gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
675         if (!gpe_event_info) {
676                 status = AE_BAD_PARAMETER;
677                 goto unlock_and_exit;
678         }
679
680         /* Make sure that a handler is indeed installed */
681
682         if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) !=
683             ACPI_GPE_DISPATCH_HANDLER) {
684                 status = AE_NOT_EXIST;
685                 goto unlock_and_exit;
686         }
687
688         /* Make sure that the installed handler is the same */
689
690         if (gpe_event_info->dispatch.handler->address != address) {
691                 status = AE_BAD_PARAMETER;
692                 goto unlock_and_exit;
693         }
694
695         /* Disable the GPE before removing the handler */
696
697         status = acpi_ev_disable_gpe(gpe_event_info);
698         if (ACPI_FAILURE(status)) {
699                 goto unlock_and_exit;
700         }
701
702         /* Make sure all deferred tasks are completed */
703
704         (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
705         acpi_os_wait_events_complete(NULL);
706         status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
707         if (ACPI_FAILURE(status)) {
708                 return_ACPI_STATUS(status);
709         }
710
711         /* Remove the handler */
712
713         flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
714         handler = gpe_event_info->dispatch.handler;
715
716         /* Restore Method node (if any), set dispatch flags */
717
718         gpe_event_info->dispatch.method_node = handler->method_node;
719         gpe_event_info->flags &= ~ACPI_GPE_DISPATCH_MASK;       /* Clear bits */
720         if (handler->method_node) {
721                 gpe_event_info->flags |= ACPI_GPE_DISPATCH_METHOD;
722         }
723         acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
724
725         /* Now we can free the handler object */
726
727         ACPI_MEM_FREE(handler);
728
729       unlock_and_exit:
730         (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
731         return_ACPI_STATUS(status);
732 }
733
734 EXPORT_SYMBOL(acpi_remove_gpe_handler);
735
736 /*******************************************************************************
737  *
738  * FUNCTION:    acpi_acquire_global_lock
739  *
740  * PARAMETERS:  Timeout         - How long the caller is willing to wait
741  *              Handle          - Where the handle to the lock is returned
742  *                                (if acquired)
743  *
744  * RETURN:      Status
745  *
746  * DESCRIPTION: Acquire the ACPI Global Lock
747  *
748  ******************************************************************************/
749
750 acpi_status acpi_acquire_global_lock(u16 timeout, u32 * handle)
751 {
752         acpi_status status;
753
754         if (!handle) {
755                 return (AE_BAD_PARAMETER);
756         }
757
758         status = acpi_ex_enter_interpreter();
759         if (ACPI_FAILURE(status)) {
760                 return (status);
761         }
762
763         status = acpi_ev_acquire_global_lock(timeout);
764         acpi_ex_exit_interpreter();
765
766         if (ACPI_SUCCESS(status)) {
767                 acpi_gbl_global_lock_handle++;
768                 *handle = acpi_gbl_global_lock_handle;
769         }
770
771         return (status);
772 }
773
774 EXPORT_SYMBOL(acpi_acquire_global_lock);
775
776 /*******************************************************************************
777  *
778  * FUNCTION:    acpi_release_global_lock
779  *
780  * PARAMETERS:  Handle      - Returned from acpi_acquire_global_lock
781  *
782  * RETURN:      Status
783  *
784  * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid.
785  *
786  ******************************************************************************/
787
788 acpi_status acpi_release_global_lock(u32 handle)
789 {
790         acpi_status status;
791
792         if (handle != acpi_gbl_global_lock_handle) {
793                 return (AE_NOT_ACQUIRED);
794         }
795
796         status = acpi_ev_release_global_lock();
797         return (status);
798 }
799
800 EXPORT_SYMBOL(acpi_release_global_lock);