]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/acpi/acpica/evxface.c
Merge remote-tracking branch 'asoc/fix/wm0010' into asoc-linus
[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_global_event_handler
389  *
390  * PARAMETERS:  handler         - Pointer to the global event handler function
391  *              context         - Value passed to the handler on each event
392  *
393  * RETURN:      Status
394  *
395  * DESCRIPTION: Saves the pointer to the handler function. The global handler
396  *              is invoked upon each incoming GPE and Fixed Event. It is
397  *              invoked at interrupt level at the time of the event dispatch.
398  *              Can be used to update event counters, etc.
399  *
400  ******************************************************************************/
401 acpi_status
402 acpi_install_global_event_handler(acpi_gbl_event_handler handler, void *context)
403 {
404         acpi_status status;
405
406         ACPI_FUNCTION_TRACE(acpi_install_global_event_handler);
407
408         /* Parameter validation */
409
410         if (!handler) {
411                 return_ACPI_STATUS(AE_BAD_PARAMETER);
412         }
413
414         status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
415         if (ACPI_FAILURE(status)) {
416                 return_ACPI_STATUS(status);
417         }
418
419         /* Don't allow two handlers. */
420
421         if (acpi_gbl_global_event_handler) {
422                 status = AE_ALREADY_EXISTS;
423                 goto cleanup;
424         }
425
426         acpi_gbl_global_event_handler = handler;
427         acpi_gbl_global_event_handler_context = context;
428
429       cleanup:
430         (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
431         return_ACPI_STATUS(status);
432 }
433
434 ACPI_EXPORT_SYMBOL(acpi_install_global_event_handler)
435
436 /*******************************************************************************
437  *
438  * FUNCTION:    acpi_install_fixed_event_handler
439  *
440  * PARAMETERS:  event           - Event type to enable.
441  *              handler         - Pointer to the handler function for the
442  *                                event
443  *              context         - Value passed to the handler on each GPE
444  *
445  * RETURN:      Status
446  *
447  * DESCRIPTION: Saves the pointer to the handler function and then enables the
448  *              event.
449  *
450  ******************************************************************************/
451 acpi_status
452 acpi_install_fixed_event_handler(u32 event,
453                                  acpi_event_handler handler, void *context)
454 {
455         acpi_status status;
456
457         ACPI_FUNCTION_TRACE(acpi_install_fixed_event_handler);
458
459         /* Parameter validation */
460
461         if (event > ACPI_EVENT_MAX) {
462                 return_ACPI_STATUS(AE_BAD_PARAMETER);
463         }
464
465         status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
466         if (ACPI_FAILURE(status)) {
467                 return_ACPI_STATUS(status);
468         }
469
470         /* Do not allow multiple handlers */
471
472         if (acpi_gbl_fixed_event_handlers[event].handler) {
473                 status = AE_ALREADY_EXISTS;
474                 goto cleanup;
475         }
476
477         /* Install the handler before enabling the event */
478
479         acpi_gbl_fixed_event_handlers[event].handler = handler;
480         acpi_gbl_fixed_event_handlers[event].context = context;
481
482         status = acpi_clear_event(event);
483         if (ACPI_SUCCESS(status))
484                 status = acpi_enable_event(event, 0);
485         if (ACPI_FAILURE(status)) {
486                 ACPI_WARNING((AE_INFO,
487                               "Could not enable fixed event - %s (%u)",
488                               acpi_ut_get_event_name(event), event));
489
490                 /* Remove the handler */
491
492                 acpi_gbl_fixed_event_handlers[event].handler = NULL;
493                 acpi_gbl_fixed_event_handlers[event].context = NULL;
494         } else {
495                 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
496                                   "Enabled fixed event %s (%X), Handler=%p\n",
497                                   acpi_ut_get_event_name(event), event,
498                                   handler));
499         }
500
501       cleanup:
502         (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
503         return_ACPI_STATUS(status);
504 }
505
506 ACPI_EXPORT_SYMBOL(acpi_install_fixed_event_handler)
507
508 /*******************************************************************************
509  *
510  * FUNCTION:    acpi_remove_fixed_event_handler
511  *
512  * PARAMETERS:  event           - Event type to disable.
513  *              handler         - Address of the handler
514  *
515  * RETURN:      Status
516  *
517  * DESCRIPTION: Disables the event and unregisters the event handler.
518  *
519  ******************************************************************************/
520 acpi_status
521 acpi_remove_fixed_event_handler(u32 event, acpi_event_handler handler)
522 {
523         acpi_status status = AE_OK;
524
525         ACPI_FUNCTION_TRACE(acpi_remove_fixed_event_handler);
526
527         /* Parameter validation */
528
529         if (event > ACPI_EVENT_MAX) {
530                 return_ACPI_STATUS(AE_BAD_PARAMETER);
531         }
532
533         status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
534         if (ACPI_FAILURE(status)) {
535                 return_ACPI_STATUS(status);
536         }
537
538         /* Disable the event before removing the handler */
539
540         status = acpi_disable_event(event, 0);
541
542         /* Always Remove the handler */
543
544         acpi_gbl_fixed_event_handlers[event].handler = NULL;
545         acpi_gbl_fixed_event_handlers[event].context = NULL;
546
547         if (ACPI_FAILURE(status)) {
548                 ACPI_WARNING((AE_INFO,
549                               "Could not disable fixed event - %s (%u)",
550                               acpi_ut_get_event_name(event), event));
551         } else {
552                 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
553                                   "Disabled fixed event - %s (%X)\n",
554                                   acpi_ut_get_event_name(event), event));
555         }
556
557         (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
558         return_ACPI_STATUS(status);
559 }
560
561 ACPI_EXPORT_SYMBOL(acpi_remove_fixed_event_handler)
562
563 /*******************************************************************************
564  *
565  * FUNCTION:    acpi_install_gpe_handler
566  *
567  * PARAMETERS:  gpe_device      - Namespace node for the GPE (NULL for FADT
568  *                                defined GPEs)
569  *              gpe_number      - The GPE number within the GPE block
570  *              type            - Whether this GPE should be treated as an
571  *                                edge- or level-triggered interrupt.
572  *              address         - Address of the handler
573  *              context         - Value passed to the handler on each GPE
574  *
575  * RETURN:      Status
576  *
577  * DESCRIPTION: Install a handler for a General Purpose Event.
578  *
579  ******************************************************************************/
580 acpi_status
581 acpi_install_gpe_handler(acpi_handle gpe_device,
582                          u32 gpe_number,
583                          u32 type, acpi_gpe_handler address, void *context)
584 {
585         struct acpi_gpe_event_info *gpe_event_info;
586         struct acpi_gpe_handler_info *handler;
587         acpi_status status;
588         acpi_cpu_flags flags;
589
590         ACPI_FUNCTION_TRACE(acpi_install_gpe_handler);
591
592         /* Parameter validation */
593
594         if ((!address) || (type & ~ACPI_GPE_XRUPT_TYPE_MASK)) {
595                 return_ACPI_STATUS(AE_BAD_PARAMETER);
596         }
597
598         status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
599         if (ACPI_FAILURE(status)) {
600                 return_ACPI_STATUS(status);
601         }
602
603         /* Allocate and init handler object (before lock) */
604
605         handler = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_handler_info));
606         if (!handler) {
607                 status = AE_NO_MEMORY;
608                 goto unlock_and_exit;
609         }
610
611         flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
612
613         /* Ensure that we have a valid GPE number */
614
615         gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
616         if (!gpe_event_info) {
617                 status = AE_BAD_PARAMETER;
618                 goto free_and_exit;
619         }
620
621         /* Make sure that there isn't a handler there already */
622
623         if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
624             ACPI_GPE_DISPATCH_HANDLER) {
625                 status = AE_ALREADY_EXISTS;
626                 goto free_and_exit;
627         }
628
629         handler->address = address;
630         handler->context = context;
631         handler->method_node = gpe_event_info->dispatch.method_node;
632         handler->original_flags = (u8)(gpe_event_info->flags &
633                                        (ACPI_GPE_XRUPT_TYPE_MASK |
634                                         ACPI_GPE_DISPATCH_MASK));
635
636         /*
637          * If the GPE is associated with a method, it may have been enabled
638          * automatically during initialization, in which case it has to be
639          * disabled now to avoid spurious execution of the handler.
640          */
641
642         if ((handler->original_flags & ACPI_GPE_DISPATCH_METHOD)
643             && gpe_event_info->runtime_count) {
644                 handler->originally_enabled = 1;
645                 (void)acpi_ev_remove_gpe_reference(gpe_event_info);
646         }
647
648         /* Install the handler */
649
650         gpe_event_info->dispatch.handler = handler;
651
652         /* Setup up dispatch flags to indicate handler (vs. method/notify) */
653
654         gpe_event_info->flags &=
655             ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
656         gpe_event_info->flags |= (u8) (type | ACPI_GPE_DISPATCH_HANDLER);
657
658         acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
659
660 unlock_and_exit:
661         (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
662         return_ACPI_STATUS(status);
663
664 free_and_exit:
665         acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
666         ACPI_FREE(handler);
667         goto unlock_and_exit;
668 }
669
670 ACPI_EXPORT_SYMBOL(acpi_install_gpe_handler)
671
672 /*******************************************************************************
673  *
674  * FUNCTION:    acpi_remove_gpe_handler
675  *
676  * PARAMETERS:  gpe_device      - Namespace node for the GPE (NULL for FADT
677  *                                defined GPEs)
678  *              gpe_number      - The event to remove a handler
679  *              address         - Address of the handler
680  *
681  * RETURN:      Status
682  *
683  * DESCRIPTION: Remove a handler for a General Purpose acpi_event.
684  *
685  ******************************************************************************/
686 acpi_status
687 acpi_remove_gpe_handler(acpi_handle gpe_device,
688                         u32 gpe_number, acpi_gpe_handler address)
689 {
690         struct acpi_gpe_event_info *gpe_event_info;
691         struct acpi_gpe_handler_info *handler;
692         acpi_status status;
693         acpi_cpu_flags flags;
694
695         ACPI_FUNCTION_TRACE(acpi_remove_gpe_handler);
696
697         /* Parameter validation */
698
699         if (!address) {
700                 return_ACPI_STATUS(AE_BAD_PARAMETER);
701         }
702
703         /* Make sure all deferred GPE tasks are completed */
704
705         acpi_os_wait_events_complete();
706
707         status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
708         if (ACPI_FAILURE(status)) {
709                 return_ACPI_STATUS(status);
710         }
711
712         flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
713
714         /* Ensure that we have a valid GPE number */
715
716         gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
717         if (!gpe_event_info) {
718                 status = AE_BAD_PARAMETER;
719                 goto unlock_and_exit;
720         }
721
722         /* Make sure that a handler is indeed installed */
723
724         if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) !=
725             ACPI_GPE_DISPATCH_HANDLER) {
726                 status = AE_NOT_EXIST;
727                 goto unlock_and_exit;
728         }
729
730         /* Make sure that the installed handler is the same */
731
732         if (gpe_event_info->dispatch.handler->address != address) {
733                 status = AE_BAD_PARAMETER;
734                 goto unlock_and_exit;
735         }
736
737         /* Remove the handler */
738
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 &=
745                 ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
746         gpe_event_info->flags |= handler->original_flags;
747
748         /*
749          * If the GPE was previously associated with a method and it was
750          * enabled, it should be enabled at this point to restore the
751          * post-initialization configuration.
752          */
753         if ((handler->original_flags & ACPI_GPE_DISPATCH_METHOD) &&
754             handler->originally_enabled) {
755                 (void)acpi_ev_add_gpe_reference(gpe_event_info);
756         }
757
758         /* Now we can free the handler object */
759
760         ACPI_FREE(handler);
761
762 unlock_and_exit:
763         acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
764
765         (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
766         return_ACPI_STATUS(status);
767 }
768
769 ACPI_EXPORT_SYMBOL(acpi_remove_gpe_handler)
770
771 /*******************************************************************************
772  *
773  * FUNCTION:    acpi_acquire_global_lock
774  *
775  * PARAMETERS:  timeout         - How long the caller is willing to wait
776  *              handle          - Where the handle to the lock is returned
777  *                                (if acquired)
778  *
779  * RETURN:      Status
780  *
781  * DESCRIPTION: Acquire the ACPI Global Lock
782  *
783  * Note: Allows callers with the same thread ID to acquire the global lock
784  * multiple times. In other words, externally, the behavior of the global lock
785  * is identical to an AML mutex. On the first acquire, a new handle is
786  * returned. On any subsequent calls to acquire by the same thread, the same
787  * handle is returned.
788  *
789  ******************************************************************************/
790 acpi_status acpi_acquire_global_lock(u16 timeout, u32 * handle)
791 {
792         acpi_status status;
793
794         if (!handle) {
795                 return (AE_BAD_PARAMETER);
796         }
797
798         /* Must lock interpreter to prevent race conditions */
799
800         acpi_ex_enter_interpreter();
801
802         status = acpi_ex_acquire_mutex_object(timeout,
803                                               acpi_gbl_global_lock_mutex,
804                                               acpi_os_get_thread_id());
805
806         if (ACPI_SUCCESS(status)) {
807
808                 /* Return the global lock handle (updated in acpi_ev_acquire_global_lock) */
809
810                 *handle = acpi_gbl_global_lock_handle;
811         }
812
813         acpi_ex_exit_interpreter();
814         return (status);
815 }
816
817 ACPI_EXPORT_SYMBOL(acpi_acquire_global_lock)
818
819 /*******************************************************************************
820  *
821  * FUNCTION:    acpi_release_global_lock
822  *
823  * PARAMETERS:  handle      - Returned from acpi_acquire_global_lock
824  *
825  * RETURN:      Status
826  *
827  * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid.
828  *
829  ******************************************************************************/
830 acpi_status acpi_release_global_lock(u32 handle)
831 {
832         acpi_status status;
833
834         if (!handle || (handle != acpi_gbl_global_lock_handle)) {
835                 return (AE_NOT_ACQUIRED);
836         }
837
838         status = acpi_ex_release_mutex_object(acpi_gbl_global_lock_mutex);
839         return (status);
840 }
841
842 ACPI_EXPORT_SYMBOL(acpi_release_global_lock)
843 #endif                          /* !ACPI_REDUCED_HARDWARE */