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