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