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