]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/acpi/acpica/evxface.c
Merge remote-tracking branch 'ipsec-next/master'
[karo-tx-linux.git] / drivers / acpi / acpica / evxface.c
1 /******************************************************************************
2  *
3  * Module Name: evxface - External interfaces for ACPI events
4  *
5  *****************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2013, Intel Corp.
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/export.h>
45 #include <acpi/acpi.h>
46 #include "accommon.h"
47 #include "acnamesp.h"
48 #include "acevents.h"
49 #include "acinterp.h"
50
51 #define _COMPONENT          ACPI_EVENTS
52 ACPI_MODULE_NAME("evxface")
53
54
55 /*******************************************************************************
56  *
57  * FUNCTION:    acpi_install_notify_handler
58  *
59  * PARAMETERS:  device          - The device for which notifies will be handled
60  *              handler_type    - The type of handler:
61  *                                  ACPI_SYSTEM_NOTIFY: System Handler (00-7F)
62  *                                  ACPI_DEVICE_NOTIFY: Device Handler (80-FF)
63  *                                  ACPI_ALL_NOTIFY:    Both System and Device
64  *              handler         - Address of the handler
65  *              context         - Value passed to the handler on each GPE
66  *
67  * RETURN:      Status
68  *
69  * DESCRIPTION: Install a handler for notifications on an ACPI Device,
70  *              thermal_zone, or Processor object.
71  *
72  * NOTES:       The Root namespace object may have only one handler for each
73  *              type of notify (System/Device). Device/Thermal/Processor objects
74  *              may have one device notify handler, and multiple system notify
75  *              handlers.
76  *
77  ******************************************************************************/
78 acpi_status
79 acpi_install_notify_handler(acpi_handle device,
80                             u32 handler_type,
81                             acpi_notify_handler handler, void *context)
82 {
83         struct acpi_namespace_node *node =
84             ACPI_CAST_PTR(struct acpi_namespace_node, device);
85         union acpi_operand_object *obj_desc;
86         union acpi_operand_object *handler_obj;
87         acpi_status status;
88         u32 i;
89
90         ACPI_FUNCTION_TRACE(acpi_install_notify_handler);
91
92         /* Parameter validation */
93
94         if ((!device) || (!handler) || (!handler_type) ||
95             (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) {
96                 return_ACPI_STATUS(AE_BAD_PARAMETER);
97         }
98
99         status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
100         if (ACPI_FAILURE(status)) {
101                 return_ACPI_STATUS(status);
102         }
103
104         /*
105          * Root Object:
106          * Registering a notify handler on the root object indicates that the
107          * caller wishes to receive notifications for all objects. Note that
108          * only one global handler can be registered per notify type.
109          * Ensure that a handler is not already installed.
110          */
111         if (device == ACPI_ROOT_OBJECT) {
112                 for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) {
113                         if (handler_type & (i + 1)) {
114                                 if (acpi_gbl_global_notify[i].handler) {
115                                         status = AE_ALREADY_EXISTS;
116                                         goto unlock_and_exit;
117                                 }
118
119                                 acpi_gbl_global_notify[i].handler = handler;
120                                 acpi_gbl_global_notify[i].context = context;
121                         }
122                 }
123
124                 goto unlock_and_exit;   /* Global notify handler installed, all done */
125         }
126
127         /*
128          * All Other Objects:
129          * Caller will only receive notifications specific to the target
130          * object. Note that only certain object types are allowed to
131          * receive notifications.
132          */
133
134         /* Are Notifies allowed on this object? */
135
136         if (!acpi_ev_is_notify_object(node)) {
137                 status = AE_TYPE;
138                 goto unlock_and_exit;
139         }
140
141         /* Check for an existing internal object, might not exist */
142
143         obj_desc = acpi_ns_get_attached_object(node);
144         if (!obj_desc) {
145
146                 /* Create a new object */
147
148                 obj_desc = acpi_ut_create_internal_object(node->type);
149                 if (!obj_desc) {
150                         status = AE_NO_MEMORY;
151                         goto unlock_and_exit;
152                 }
153
154                 /* Attach new object to the Node, remove local reference */
155
156                 status = acpi_ns_attach_object(device, obj_desc, node->type);
157                 acpi_ut_remove_reference(obj_desc);
158                 if (ACPI_FAILURE(status)) {
159                         goto unlock_and_exit;
160                 }
161         }
162
163         /* Ensure that the handler is not already installed in the lists */
164
165         for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) {
166                 if (handler_type & (i + 1)) {
167                         handler_obj = obj_desc->common_notify.notify_list[i];
168                         while (handler_obj) {
169                                 if (handler_obj->notify.handler == handler) {
170                                         status = AE_ALREADY_EXISTS;
171                                         goto unlock_and_exit;
172                                 }
173
174                                 handler_obj = handler_obj->notify.next[i];
175                         }
176                 }
177         }
178
179         /* Create and populate a new notify handler object */
180
181         handler_obj = acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_NOTIFY);
182         if (!handler_obj) {
183                 status = AE_NO_MEMORY;
184                 goto unlock_and_exit;
185         }
186
187         handler_obj->notify.node = node;
188         handler_obj->notify.handler_type = handler_type;
189         handler_obj->notify.handler = handler;
190         handler_obj->notify.context = context;
191
192         /* Install the handler at the list head(s) */
193
194         for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) {
195                 if (handler_type & (i + 1)) {
196                         handler_obj->notify.next[i] =
197                             obj_desc->common_notify.notify_list[i];
198
199                         obj_desc->common_notify.notify_list[i] = handler_obj;
200                 }
201         }
202
203         /* Add an extra reference if handler was installed in both lists */
204
205         if (handler_type == ACPI_ALL_NOTIFY) {
206                 acpi_ut_add_reference(handler_obj);
207         }
208
209 unlock_and_exit:
210         (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
211         return_ACPI_STATUS(status);
212 }
213
214 ACPI_EXPORT_SYMBOL(acpi_install_notify_handler)
215
216 /*******************************************************************************
217  *
218  * FUNCTION:    acpi_remove_notify_handler
219  *
220  * PARAMETERS:  device          - The device for which the handler is installed
221  *              handler_type    - The type of handler:
222  *                                  ACPI_SYSTEM_NOTIFY: System Handler (00-7F)
223  *                                  ACPI_DEVICE_NOTIFY: Device Handler (80-FF)
224  *                                  ACPI_ALL_NOTIFY:    Both System and Device
225  *              handler         - Address of the handler
226  *
227  * RETURN:      Status
228  *
229  * DESCRIPTION: Remove a handler for notifies on an ACPI device
230  *
231  ******************************************************************************/
232 acpi_status
233 acpi_remove_notify_handler(acpi_handle device,
234                            u32 handler_type, acpi_notify_handler handler)
235 {
236         struct acpi_namespace_node *node =
237             ACPI_CAST_PTR(struct acpi_namespace_node, device);
238         union acpi_operand_object *obj_desc;
239         union acpi_operand_object *handler_obj;
240         union acpi_operand_object *previous_handler_obj;
241         acpi_status status;
242         u32 i;
243
244         ACPI_FUNCTION_TRACE(acpi_remove_notify_handler);
245
246         /* Parameter validation */
247
248         if ((!device) || (!handler) || (!handler_type) ||
249             (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) {
250                 return_ACPI_STATUS(AE_BAD_PARAMETER);
251         }
252
253         /* Make sure all deferred notify tasks are completed */
254
255         acpi_os_wait_events_complete();
256
257         status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
258         if (ACPI_FAILURE(status)) {
259                 return_ACPI_STATUS(status);
260         }
261
262         /* Root Object. Global handlers are removed here */
263
264         if (device == ACPI_ROOT_OBJECT) {
265                 for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) {
266                         if (handler_type & (i + 1)) {
267                                 if (!acpi_gbl_global_notify[i].handler ||
268                                     (acpi_gbl_global_notify[i].handler !=
269                                      handler)) {
270                                         status = AE_NOT_EXIST;
271                                         goto unlock_and_exit;
272                                 }
273
274                                 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
275                                                   "Removing global notify handler\n"));
276
277                                 acpi_gbl_global_notify[i].handler = NULL;
278                                 acpi_gbl_global_notify[i].context = NULL;
279                         }
280                 }
281
282                 goto unlock_and_exit;
283         }
284
285         /* All other objects: Are Notifies allowed on this object? */
286
287         if (!acpi_ev_is_notify_object(node)) {
288                 status = AE_TYPE;
289                 goto unlock_and_exit;
290         }
291
292         /* Must have an existing internal object */
293
294         obj_desc = acpi_ns_get_attached_object(node);
295         if (!obj_desc) {
296                 status = AE_NOT_EXIST;
297                 goto unlock_and_exit;
298         }
299
300         /* Internal object exists. Find the handler and remove it */
301
302         for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) {
303                 if (handler_type & (i + 1)) {
304                         handler_obj = obj_desc->common_notify.notify_list[i];
305                         previous_handler_obj = NULL;
306
307                         /* Attempt to find the handler in the handler list */
308
309                         while (handler_obj &&
310                                (handler_obj->notify.handler != handler)) {
311                                 previous_handler_obj = handler_obj;
312                                 handler_obj = handler_obj->notify.next[i];
313                         }
314
315                         if (!handler_obj) {
316                                 status = AE_NOT_EXIST;
317                                 goto unlock_and_exit;
318                         }
319
320                         /* Remove the handler object from the list */
321
322                         if (previous_handler_obj) {     /* Handler is not at the list head */
323                                 previous_handler_obj->notify.next[i] =
324                                     handler_obj->notify.next[i];
325                         } else {        /* Handler is at the list head */
326
327                                 obj_desc->common_notify.notify_list[i] =
328                                     handler_obj->notify.next[i];
329                         }
330
331                         acpi_ut_remove_reference(handler_obj);
332                 }
333         }
334
335 unlock_and_exit:
336         (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
337         return_ACPI_STATUS(status);
338 }
339
340 ACPI_EXPORT_SYMBOL(acpi_remove_notify_handler)
341
342 /*******************************************************************************
343  *
344  * FUNCTION:    acpi_install_exception_handler
345  *
346  * PARAMETERS:  handler         - Pointer to the handler function for the
347  *                                event
348  *
349  * RETURN:      Status
350  *
351  * DESCRIPTION: Saves the pointer to the handler function
352  *
353  ******************************************************************************/
354 #ifdef ACPI_FUTURE_USAGE
355 acpi_status acpi_install_exception_handler(acpi_exception_handler handler)
356 {
357         acpi_status status;
358
359         ACPI_FUNCTION_TRACE(acpi_install_exception_handler);
360
361         status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
362         if (ACPI_FAILURE(status)) {
363                 return_ACPI_STATUS(status);
364         }
365
366         /* Don't allow two handlers. */
367
368         if (acpi_gbl_exception_handler) {
369                 status = AE_ALREADY_EXISTS;
370                 goto cleanup;
371         }
372
373         /* Install the handler */
374
375         acpi_gbl_exception_handler = handler;
376
377       cleanup:
378         (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
379         return_ACPI_STATUS(status);
380 }
381
382 ACPI_EXPORT_SYMBOL(acpi_install_exception_handler)
383 #endif                          /*  ACPI_FUTURE_USAGE  */
384
385 #if (!ACPI_REDUCED_HARDWARE)
386 /*******************************************************************************
387  *
388  * FUNCTION:    acpi_install_sci_handler
389  *
390  * PARAMETERS:  address             - Address of the handler
391  *              context             - Value passed to the handler on each SCI
392  *
393  * RETURN:      Status
394  *
395  * DESCRIPTION: Install a handler for a System Control Interrupt.
396  *
397  ******************************************************************************/
398 acpi_status acpi_install_sci_handler(acpi_sci_handler address, void *context)
399 {
400         struct acpi_sci_handler_info *new_sci_handler;
401         struct acpi_sci_handler_info *sci_handler;
402         acpi_cpu_flags flags;
403         acpi_status status;
404
405         ACPI_FUNCTION_TRACE(acpi_install_sci_handler);
406
407         if (!address) {
408                 return_ACPI_STATUS(AE_BAD_PARAMETER);
409         }
410
411         /* Allocate and init a handler object */
412
413         new_sci_handler = ACPI_ALLOCATE(sizeof(struct acpi_sci_handler_info));
414         if (!new_sci_handler) {
415                 return_ACPI_STATUS(AE_NO_MEMORY);
416         }
417
418         new_sci_handler->address = address;
419         new_sci_handler->context = context;
420
421         status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
422         if (ACPI_FAILURE(status)) {
423                 goto exit;
424         }
425
426         /* Lock list during installation */
427
428         flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
429         sci_handler = acpi_gbl_sci_handler_list;
430
431         /* Ensure handler does not already exist */
432
433         while (sci_handler) {
434                 if (address == sci_handler->address) {
435                         status = AE_ALREADY_EXISTS;
436                         goto unlock_and_exit;
437                 }
438
439                 sci_handler = sci_handler->next;
440         }
441
442         /* Install the new handler into the global list (at head) */
443
444         new_sci_handler->next = acpi_gbl_sci_handler_list;
445         acpi_gbl_sci_handler_list = new_sci_handler;
446
447       unlock_and_exit:
448
449         acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
450         (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
451
452       exit:
453         if (ACPI_FAILURE(status)) {
454                 ACPI_FREE(new_sci_handler);
455         }
456         return_ACPI_STATUS(status);
457 }
458
459 /*******************************************************************************
460  *
461  * FUNCTION:    acpi_remove_sci_handler
462  *
463  * PARAMETERS:  address             - Address of the handler
464  *
465  * RETURN:      Status
466  *
467  * DESCRIPTION: Remove a handler for a System Control Interrupt.
468  *
469  ******************************************************************************/
470
471 acpi_status acpi_remove_sci_handler(acpi_sci_handler address)
472 {
473         struct acpi_sci_handler_info *prev_sci_handler;
474         struct acpi_sci_handler_info *next_sci_handler;
475         acpi_cpu_flags flags;
476         acpi_status status;
477
478         ACPI_FUNCTION_TRACE(acpi_remove_sci_handler);
479
480         if (!address) {
481                 return_ACPI_STATUS(AE_BAD_PARAMETER);
482         }
483
484         status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
485         if (ACPI_FAILURE(status)) {
486                 return_ACPI_STATUS(status);
487         }
488
489         /* Remove the SCI handler with lock */
490
491         flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
492
493         prev_sci_handler = NULL;
494         next_sci_handler = acpi_gbl_sci_handler_list;
495         while (next_sci_handler) {
496                 if (next_sci_handler->address == address) {
497
498                         /* Unlink and free the SCI handler info block */
499
500                         if (prev_sci_handler) {
501                                 prev_sci_handler->next = next_sci_handler->next;
502                         } else {
503                                 acpi_gbl_sci_handler_list =
504                                     next_sci_handler->next;
505                         }
506
507                         acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
508                         ACPI_FREE(next_sci_handler);
509                         goto unlock_and_exit;
510                 }
511
512                 prev_sci_handler = next_sci_handler;
513                 next_sci_handler = next_sci_handler->next;
514         }
515
516         acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
517         status = AE_NOT_EXIST;
518
519       unlock_and_exit:
520         (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
521         return_ACPI_STATUS(status);
522 }
523
524 /*******************************************************************************
525  *
526  * FUNCTION:    acpi_install_global_event_handler
527  *
528  * PARAMETERS:  handler         - Pointer to the global event handler function
529  *              context         - Value passed to the handler on each event
530  *
531  * RETURN:      Status
532  *
533  * DESCRIPTION: Saves the pointer to the handler function. The global handler
534  *              is invoked upon each incoming GPE and Fixed Event. It is
535  *              invoked at interrupt level at the time of the event dispatch.
536  *              Can be used to update event counters, etc.
537  *
538  ******************************************************************************/
539
540 acpi_status
541 acpi_install_global_event_handler(acpi_gbl_event_handler handler, void *context)
542 {
543         acpi_status status;
544
545         ACPI_FUNCTION_TRACE(acpi_install_global_event_handler);
546
547         /* Parameter validation */
548
549         if (!handler) {
550                 return_ACPI_STATUS(AE_BAD_PARAMETER);
551         }
552
553         status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
554         if (ACPI_FAILURE(status)) {
555                 return_ACPI_STATUS(status);
556         }
557
558         /* Don't allow two handlers. */
559
560         if (acpi_gbl_global_event_handler) {
561                 status = AE_ALREADY_EXISTS;
562                 goto cleanup;
563         }
564
565         acpi_gbl_global_event_handler = handler;
566         acpi_gbl_global_event_handler_context = context;
567
568       cleanup:
569         (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
570         return_ACPI_STATUS(status);
571 }
572
573 ACPI_EXPORT_SYMBOL(acpi_install_global_event_handler)
574
575 /*******************************************************************************
576  *
577  * FUNCTION:    acpi_install_fixed_event_handler
578  *
579  * PARAMETERS:  event           - Event type to enable.
580  *              handler         - Pointer to the handler function for the
581  *                                event
582  *              context         - Value passed to the handler on each GPE
583  *
584  * RETURN:      Status
585  *
586  * DESCRIPTION: Saves the pointer to the handler function and then enables the
587  *              event.
588  *
589  ******************************************************************************/
590 acpi_status
591 acpi_install_fixed_event_handler(u32 event,
592                                  acpi_event_handler handler, void *context)
593 {
594         acpi_status status;
595
596         ACPI_FUNCTION_TRACE(acpi_install_fixed_event_handler);
597
598         /* Parameter validation */
599
600         if (event > ACPI_EVENT_MAX) {
601                 return_ACPI_STATUS(AE_BAD_PARAMETER);
602         }
603
604         status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
605         if (ACPI_FAILURE(status)) {
606                 return_ACPI_STATUS(status);
607         }
608
609         /* Do not allow multiple handlers */
610
611         if (acpi_gbl_fixed_event_handlers[event].handler) {
612                 status = AE_ALREADY_EXISTS;
613                 goto cleanup;
614         }
615
616         /* Install the handler before enabling the event */
617
618         acpi_gbl_fixed_event_handlers[event].handler = handler;
619         acpi_gbl_fixed_event_handlers[event].context = context;
620
621         status = acpi_clear_event(event);
622         if (ACPI_SUCCESS(status))
623                 status = acpi_enable_event(event, 0);
624         if (ACPI_FAILURE(status)) {
625                 ACPI_WARNING((AE_INFO,
626                               "Could not enable fixed event - %s (%u)",
627                               acpi_ut_get_event_name(event), event));
628
629                 /* Remove the handler */
630
631                 acpi_gbl_fixed_event_handlers[event].handler = NULL;
632                 acpi_gbl_fixed_event_handlers[event].context = NULL;
633         } else {
634                 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
635                                   "Enabled fixed event %s (%X), Handler=%p\n",
636                                   acpi_ut_get_event_name(event), event,
637                                   handler));
638         }
639
640       cleanup:
641         (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
642         return_ACPI_STATUS(status);
643 }
644
645 ACPI_EXPORT_SYMBOL(acpi_install_fixed_event_handler)
646
647 /*******************************************************************************
648  *
649  * FUNCTION:    acpi_remove_fixed_event_handler
650  *
651  * PARAMETERS:  event           - Event type to disable.
652  *              handler         - Address of the handler
653  *
654  * RETURN:      Status
655  *
656  * DESCRIPTION: Disables the event and unregisters the event handler.
657  *
658  ******************************************************************************/
659 acpi_status
660 acpi_remove_fixed_event_handler(u32 event, acpi_event_handler handler)
661 {
662         acpi_status status = AE_OK;
663
664         ACPI_FUNCTION_TRACE(acpi_remove_fixed_event_handler);
665
666         /* Parameter validation */
667
668         if (event > ACPI_EVENT_MAX) {
669                 return_ACPI_STATUS(AE_BAD_PARAMETER);
670         }
671
672         status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
673         if (ACPI_FAILURE(status)) {
674                 return_ACPI_STATUS(status);
675         }
676
677         /* Disable the event before removing the handler */
678
679         status = acpi_disable_event(event, 0);
680
681         /* Always Remove the handler */
682
683         acpi_gbl_fixed_event_handlers[event].handler = NULL;
684         acpi_gbl_fixed_event_handlers[event].context = NULL;
685
686         if (ACPI_FAILURE(status)) {
687                 ACPI_WARNING((AE_INFO,
688                               "Could not disable fixed event - %s (%u)",
689                               acpi_ut_get_event_name(event), event));
690         } else {
691                 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
692                                   "Disabled fixed event - %s (%X)\n",
693                                   acpi_ut_get_event_name(event), event));
694         }
695
696         (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
697         return_ACPI_STATUS(status);
698 }
699
700 ACPI_EXPORT_SYMBOL(acpi_remove_fixed_event_handler)
701
702 /*******************************************************************************
703  *
704  * FUNCTION:    acpi_install_gpe_handler
705  *
706  * PARAMETERS:  gpe_device      - Namespace node for the GPE (NULL for FADT
707  *                                defined GPEs)
708  *              gpe_number      - The GPE number within the GPE block
709  *              type            - Whether this GPE should be treated as an
710  *                                edge- or level-triggered interrupt.
711  *              address         - Address of the handler
712  *              context         - Value passed to the handler on each GPE
713  *
714  * RETURN:      Status
715  *
716  * DESCRIPTION: Install a handler for a General Purpose Event.
717  *
718  ******************************************************************************/
719 acpi_status
720 acpi_install_gpe_handler(acpi_handle gpe_device,
721                          u32 gpe_number,
722                          u32 type, acpi_gpe_handler address, void *context)
723 {
724         struct acpi_gpe_event_info *gpe_event_info;
725         struct acpi_gpe_handler_info *handler;
726         acpi_status status;
727         acpi_cpu_flags flags;
728
729         ACPI_FUNCTION_TRACE(acpi_install_gpe_handler);
730
731         /* Parameter validation */
732
733         if ((!address) || (type & ~ACPI_GPE_XRUPT_TYPE_MASK)) {
734                 return_ACPI_STATUS(AE_BAD_PARAMETER);
735         }
736
737         status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
738         if (ACPI_FAILURE(status)) {
739                 return_ACPI_STATUS(status);
740         }
741
742         /* Allocate and init handler object (before lock) */
743
744         handler = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_handler_info));
745         if (!handler) {
746                 status = AE_NO_MEMORY;
747                 goto unlock_and_exit;
748         }
749
750         flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
751
752         /* Ensure that we have a valid GPE number */
753
754         gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
755         if (!gpe_event_info) {
756                 status = AE_BAD_PARAMETER;
757                 goto free_and_exit;
758         }
759
760         /* Make sure that there isn't a handler there already */
761
762         if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
763             ACPI_GPE_DISPATCH_HANDLER) {
764                 status = AE_ALREADY_EXISTS;
765                 goto free_and_exit;
766         }
767
768         handler->address = address;
769         handler->context = context;
770         handler->method_node = gpe_event_info->dispatch.method_node;
771         handler->original_flags = (u8)(gpe_event_info->flags &
772                                        (ACPI_GPE_XRUPT_TYPE_MASK |
773                                         ACPI_GPE_DISPATCH_MASK));
774
775         /*
776          * If the GPE is associated with a method, it may have been enabled
777          * automatically during initialization, in which case it has to be
778          * disabled now to avoid spurious execution of the handler.
779          */
780
781         if ((handler->original_flags & ACPI_GPE_DISPATCH_METHOD)
782             && gpe_event_info->runtime_count) {
783                 handler->originally_enabled = 1;
784                 (void)acpi_ev_remove_gpe_reference(gpe_event_info);
785         }
786
787         /* Install the handler */
788
789         gpe_event_info->dispatch.handler = handler;
790
791         /* Setup up dispatch flags to indicate handler (vs. method/notify) */
792
793         gpe_event_info->flags &=
794             ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
795         gpe_event_info->flags |= (u8) (type | ACPI_GPE_DISPATCH_HANDLER);
796
797         acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
798
799 unlock_and_exit:
800         (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
801         return_ACPI_STATUS(status);
802
803 free_and_exit:
804         acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
805         ACPI_FREE(handler);
806         goto unlock_and_exit;
807 }
808
809 ACPI_EXPORT_SYMBOL(acpi_install_gpe_handler)
810
811 /*******************************************************************************
812  *
813  * FUNCTION:    acpi_remove_gpe_handler
814  *
815  * PARAMETERS:  gpe_device      - Namespace node for the GPE (NULL for FADT
816  *                                defined GPEs)
817  *              gpe_number      - The event to remove a handler
818  *              address         - Address of the handler
819  *
820  * RETURN:      Status
821  *
822  * DESCRIPTION: Remove a handler for a General Purpose acpi_event.
823  *
824  ******************************************************************************/
825 acpi_status
826 acpi_remove_gpe_handler(acpi_handle gpe_device,
827                         u32 gpe_number, acpi_gpe_handler address)
828 {
829         struct acpi_gpe_event_info *gpe_event_info;
830         struct acpi_gpe_handler_info *handler;
831         acpi_status status;
832         acpi_cpu_flags flags;
833
834         ACPI_FUNCTION_TRACE(acpi_remove_gpe_handler);
835
836         /* Parameter validation */
837
838         if (!address) {
839                 return_ACPI_STATUS(AE_BAD_PARAMETER);
840         }
841
842         /* Make sure all deferred GPE tasks are completed */
843
844         acpi_os_wait_events_complete();
845
846         status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
847         if (ACPI_FAILURE(status)) {
848                 return_ACPI_STATUS(status);
849         }
850
851         flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
852
853         /* Ensure that we have a valid GPE number */
854
855         gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
856         if (!gpe_event_info) {
857                 status = AE_BAD_PARAMETER;
858                 goto unlock_and_exit;
859         }
860
861         /* Make sure that a handler is indeed installed */
862
863         if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) !=
864             ACPI_GPE_DISPATCH_HANDLER) {
865                 status = AE_NOT_EXIST;
866                 goto unlock_and_exit;
867         }
868
869         /* Make sure that the installed handler is the same */
870
871         if (gpe_event_info->dispatch.handler->address != address) {
872                 status = AE_BAD_PARAMETER;
873                 goto unlock_and_exit;
874         }
875
876         /* Remove the handler */
877
878         handler = gpe_event_info->dispatch.handler;
879
880         /* Restore Method node (if any), set dispatch flags */
881
882         gpe_event_info->dispatch.method_node = handler->method_node;
883         gpe_event_info->flags &=
884                 ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
885         gpe_event_info->flags |= handler->original_flags;
886
887         /*
888          * If the GPE was previously associated with a method and it was
889          * enabled, it should be enabled at this point to restore the
890          * post-initialization configuration.
891          */
892         if ((handler->original_flags & ACPI_GPE_DISPATCH_METHOD) &&
893             handler->originally_enabled) {
894                 (void)acpi_ev_add_gpe_reference(gpe_event_info);
895         }
896
897         /* Now we can free the handler object */
898
899         ACPI_FREE(handler);
900
901 unlock_and_exit:
902         acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
903
904         (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
905         return_ACPI_STATUS(status);
906 }
907
908 ACPI_EXPORT_SYMBOL(acpi_remove_gpe_handler)
909
910 /*******************************************************************************
911  *
912  * FUNCTION:    acpi_acquire_global_lock
913  *
914  * PARAMETERS:  timeout         - How long the caller is willing to wait
915  *              handle          - Where the handle to the lock is returned
916  *                                (if acquired)
917  *
918  * RETURN:      Status
919  *
920  * DESCRIPTION: Acquire the ACPI Global Lock
921  *
922  * Note: Allows callers with the same thread ID to acquire the global lock
923  * multiple times. In other words, externally, the behavior of the global lock
924  * is identical to an AML mutex. On the first acquire, a new handle is
925  * returned. On any subsequent calls to acquire by the same thread, the same
926  * handle is returned.
927  *
928  ******************************************************************************/
929 acpi_status acpi_acquire_global_lock(u16 timeout, u32 * handle)
930 {
931         acpi_status status;
932
933         if (!handle) {
934                 return (AE_BAD_PARAMETER);
935         }
936
937         /* Must lock interpreter to prevent race conditions */
938
939         acpi_ex_enter_interpreter();
940
941         status = acpi_ex_acquire_mutex_object(timeout,
942                                               acpi_gbl_global_lock_mutex,
943                                               acpi_os_get_thread_id());
944
945         if (ACPI_SUCCESS(status)) {
946
947                 /* Return the global lock handle (updated in acpi_ev_acquire_global_lock) */
948
949                 *handle = acpi_gbl_global_lock_handle;
950         }
951
952         acpi_ex_exit_interpreter();
953         return (status);
954 }
955
956 ACPI_EXPORT_SYMBOL(acpi_acquire_global_lock)
957
958 /*******************************************************************************
959  *
960  * FUNCTION:    acpi_release_global_lock
961  *
962  * PARAMETERS:  handle      - Returned from acpi_acquire_global_lock
963  *
964  * RETURN:      Status
965  *
966  * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid.
967  *
968  ******************************************************************************/
969 acpi_status acpi_release_global_lock(u32 handle)
970 {
971         acpi_status status;
972
973         if (!handle || (handle != acpi_gbl_global_lock_handle)) {
974                 return (AE_NOT_ACQUIRED);
975         }
976
977         status = acpi_ex_release_mutex_object(acpi_gbl_global_lock_mutex);
978         return (status);
979 }
980
981 ACPI_EXPORT_SYMBOL(acpi_release_global_lock)
982 #endif                          /* !ACPI_REDUCED_HARDWARE */