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