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