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