1 /******************************************************************************
3 * Module Name: evxface - External interfaces for ACPI events
5 *****************************************************************************/
8 * Copyright (C) 2000 - 2016, Intel Corp.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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.
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.
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.
44 #define EXPORT_ACPI_INTERFACES
46 #include <acpi/acpi.h>
52 #define _COMPONENT ACPI_EVENTS
53 ACPI_MODULE_NAME("evxface")
54 #if (!ACPI_REDUCED_HARDWARE)
55 /* Local prototypes */
57 acpi_ev_install_gpe_handler(acpi_handle gpe_device
,
61 acpi_gpe_handler address
, void *context
);
66 /*******************************************************************************
68 * FUNCTION: acpi_install_notify_handler
70 * PARAMETERS: device - The device for which notifies will be handled
71 * handler_type - The type of handler:
72 * ACPI_SYSTEM_NOTIFY: System Handler (00-7F)
73 * ACPI_DEVICE_NOTIFY: Device Handler (80-FF)
74 * ACPI_ALL_NOTIFY: Both System and Device
75 * handler - Address of the handler
76 * context - Value passed to the handler on each GPE
80 * DESCRIPTION: Install a handler for notifications on an ACPI Device,
81 * thermal_zone, or Processor object.
83 * NOTES: The Root namespace object may have only one handler for each
84 * type of notify (System/Device). Device/Thermal/Processor objects
85 * may have one device notify handler, and multiple system notify
88 ******************************************************************************/
91 acpi_install_notify_handler(acpi_handle device
,
93 acpi_notify_handler handler
, void *context
)
95 struct acpi_namespace_node
*node
=
96 ACPI_CAST_PTR(struct acpi_namespace_node
, device
);
97 union acpi_operand_object
*obj_desc
;
98 union acpi_operand_object
*handler_obj
;
102 ACPI_FUNCTION_TRACE(acpi_install_notify_handler
);
104 /* Parameter validation */
106 if ((!device
) || (!handler
) || (!handler_type
) ||
107 (handler_type
> ACPI_MAX_NOTIFY_HANDLER_TYPE
)) {
108 return_ACPI_STATUS(AE_BAD_PARAMETER
);
111 status
= acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE
);
112 if (ACPI_FAILURE(status
)) {
113 return_ACPI_STATUS(status
);
118 * Registering a notify handler on the root object indicates that the
119 * caller wishes to receive notifications for all objects. Note that
120 * only one global handler can be registered per notify type.
121 * Ensure that a handler is not already installed.
123 if (device
== ACPI_ROOT_OBJECT
) {
124 for (i
= 0; i
< ACPI_NUM_NOTIFY_TYPES
; i
++) {
125 if (handler_type
& (i
+ 1)) {
126 if (acpi_gbl_global_notify
[i
].handler
) {
127 status
= AE_ALREADY_EXISTS
;
128 goto unlock_and_exit
;
131 acpi_gbl_global_notify
[i
].handler
= handler
;
132 acpi_gbl_global_notify
[i
].context
= context
;
136 goto unlock_and_exit
; /* Global notify handler installed, all done */
141 * Caller will only receive notifications specific to the target
142 * object. Note that only certain object types are allowed to
143 * receive notifications.
146 /* Are Notifies allowed on this object? */
148 if (!acpi_ev_is_notify_object(node
)) {
150 goto unlock_and_exit
;
153 /* Check for an existing internal object, might not exist */
155 obj_desc
= acpi_ns_get_attached_object(node
);
158 /* Create a new object */
160 obj_desc
= acpi_ut_create_internal_object(node
->type
);
162 status
= AE_NO_MEMORY
;
163 goto unlock_and_exit
;
166 /* Attach new object to the Node, remove local reference */
168 status
= acpi_ns_attach_object(device
, obj_desc
, node
->type
);
169 acpi_ut_remove_reference(obj_desc
);
170 if (ACPI_FAILURE(status
)) {
171 goto unlock_and_exit
;
175 /* Ensure that the handler is not already installed in the lists */
177 for (i
= 0; i
< ACPI_NUM_NOTIFY_TYPES
; i
++) {
178 if (handler_type
& (i
+ 1)) {
179 handler_obj
= obj_desc
->common_notify
.notify_list
[i
];
180 while (handler_obj
) {
181 if (handler_obj
->notify
.handler
== handler
) {
182 status
= AE_ALREADY_EXISTS
;
183 goto unlock_and_exit
;
186 handler_obj
= handler_obj
->notify
.next
[i
];
191 /* Create and populate a new notify handler object */
193 handler_obj
= acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_NOTIFY
);
195 status
= AE_NO_MEMORY
;
196 goto unlock_and_exit
;
199 handler_obj
->notify
.node
= node
;
200 handler_obj
->notify
.handler_type
= handler_type
;
201 handler_obj
->notify
.handler
= handler
;
202 handler_obj
->notify
.context
= context
;
204 /* Install the handler at the list head(s) */
206 for (i
= 0; i
< ACPI_NUM_NOTIFY_TYPES
; i
++) {
207 if (handler_type
& (i
+ 1)) {
208 handler_obj
->notify
.next
[i
] =
209 obj_desc
->common_notify
.notify_list
[i
];
211 obj_desc
->common_notify
.notify_list
[i
] = handler_obj
;
215 /* Add an extra reference if handler was installed in both lists */
217 if (handler_type
== ACPI_ALL_NOTIFY
) {
218 acpi_ut_add_reference(handler_obj
);
222 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE
);
223 return_ACPI_STATUS(status
);
226 ACPI_EXPORT_SYMBOL(acpi_install_notify_handler
)
228 /*******************************************************************************
230 * FUNCTION: acpi_remove_notify_handler
232 * PARAMETERS: device - The device for which the handler is installed
233 * handler_type - The type of handler:
234 * ACPI_SYSTEM_NOTIFY: System Handler (00-7F)
235 * ACPI_DEVICE_NOTIFY: Device Handler (80-FF)
236 * ACPI_ALL_NOTIFY: Both System and Device
237 * handler - Address of the handler
241 * DESCRIPTION: Remove a handler for notifies on an ACPI device
243 ******************************************************************************/
245 acpi_remove_notify_handler(acpi_handle device
,
246 u32 handler_type
, acpi_notify_handler handler
)
248 struct acpi_namespace_node
*node
=
249 ACPI_CAST_PTR(struct acpi_namespace_node
, device
);
250 union acpi_operand_object
*obj_desc
;
251 union acpi_operand_object
*handler_obj
;
252 union acpi_operand_object
*previous_handler_obj
;
253 acpi_status status
= AE_OK
;
256 ACPI_FUNCTION_TRACE(acpi_remove_notify_handler
);
258 /* Parameter validation */
260 if ((!device
) || (!handler
) || (!handler_type
) ||
261 (handler_type
> ACPI_MAX_NOTIFY_HANDLER_TYPE
)) {
262 return_ACPI_STATUS(AE_BAD_PARAMETER
);
265 /* Root Object. Global handlers are removed here */
267 if (device
== ACPI_ROOT_OBJECT
) {
268 for (i
= 0; i
< ACPI_NUM_NOTIFY_TYPES
; i
++) {
269 if (handler_type
& (i
+ 1)) {
271 acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE
);
272 if (ACPI_FAILURE(status
)) {
273 return_ACPI_STATUS(status
);
276 if (!acpi_gbl_global_notify
[i
].handler
||
277 (acpi_gbl_global_notify
[i
].handler
!=
279 status
= AE_NOT_EXIST
;
280 goto unlock_and_exit
;
283 ACPI_DEBUG_PRINT((ACPI_DB_INFO
,
284 "Removing global notify handler\n"));
286 acpi_gbl_global_notify
[i
].handler
= NULL
;
287 acpi_gbl_global_notify
[i
].context
= NULL
;
289 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE
);
291 /* Make sure all deferred notify tasks are completed */
293 acpi_os_wait_events_complete();
297 return_ACPI_STATUS(AE_OK
);
300 /* All other objects: Are Notifies allowed on this object? */
302 if (!acpi_ev_is_notify_object(node
)) {
303 return_ACPI_STATUS(AE_TYPE
);
306 /* Must have an existing internal object */
308 obj_desc
= acpi_ns_get_attached_object(node
);
310 return_ACPI_STATUS(AE_NOT_EXIST
);
313 /* Internal object exists. Find the handler and remove it */
315 for (i
= 0; i
< ACPI_NUM_NOTIFY_TYPES
; i
++) {
316 if (handler_type
& (i
+ 1)) {
317 status
= acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE
);
318 if (ACPI_FAILURE(status
)) {
319 return_ACPI_STATUS(status
);
322 handler_obj
= obj_desc
->common_notify
.notify_list
[i
];
323 previous_handler_obj
= NULL
;
325 /* Attempt to find the handler in the handler list */
327 while (handler_obj
&&
328 (handler_obj
->notify
.handler
!= handler
)) {
329 previous_handler_obj
= handler_obj
;
330 handler_obj
= handler_obj
->notify
.next
[i
];
334 status
= AE_NOT_EXIST
;
335 goto unlock_and_exit
;
338 /* Remove the handler object from the list */
340 if (previous_handler_obj
) { /* Handler is not at the list head */
341 previous_handler_obj
->notify
.next
[i
] =
342 handler_obj
->notify
.next
[i
];
343 } else { /* Handler is at the list head */
345 obj_desc
->common_notify
.notify_list
[i
] =
346 handler_obj
->notify
.next
[i
];
349 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE
);
351 /* Make sure all deferred notify tasks are completed */
353 acpi_os_wait_events_complete();
354 acpi_ut_remove_reference(handler_obj
);
358 return_ACPI_STATUS(status
);
361 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE
);
362 return_ACPI_STATUS(status
);
365 ACPI_EXPORT_SYMBOL(acpi_remove_notify_handler
)
367 /*******************************************************************************
369 * FUNCTION: acpi_install_exception_handler
371 * PARAMETERS: handler - Pointer to the handler function for the
376 * DESCRIPTION: Saves the pointer to the handler function
378 ******************************************************************************/
379 #ifdef ACPI_FUTURE_USAGE
380 acpi_status
acpi_install_exception_handler(acpi_exception_handler handler
)
384 ACPI_FUNCTION_TRACE(acpi_install_exception_handler
);
386 status
= acpi_ut_acquire_mutex(ACPI_MTX_EVENTS
);
387 if (ACPI_FAILURE(status
)) {
388 return_ACPI_STATUS(status
);
391 /* Don't allow two handlers. */
393 if (acpi_gbl_exception_handler
) {
394 status
= AE_ALREADY_EXISTS
;
398 /* Install the handler */
400 acpi_gbl_exception_handler
= handler
;
403 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS
);
404 return_ACPI_STATUS(status
);
407 ACPI_EXPORT_SYMBOL(acpi_install_exception_handler
)
410 #if (!ACPI_REDUCED_HARDWARE)
411 /*******************************************************************************
413 * FUNCTION: acpi_install_sci_handler
415 * PARAMETERS: address - Address of the handler
416 * context - Value passed to the handler on each SCI
420 * DESCRIPTION: Install a handler for a System Control Interrupt.
422 ******************************************************************************/
423 acpi_status
acpi_install_sci_handler(acpi_sci_handler address
, void *context
)
425 struct acpi_sci_handler_info
*new_sci_handler
;
426 struct acpi_sci_handler_info
*sci_handler
;
427 acpi_cpu_flags flags
;
430 ACPI_FUNCTION_TRACE(acpi_install_sci_handler
);
433 return_ACPI_STATUS(AE_BAD_PARAMETER
);
436 /* Allocate and init a handler object */
438 new_sci_handler
= ACPI_ALLOCATE(sizeof(struct acpi_sci_handler_info
));
439 if (!new_sci_handler
) {
440 return_ACPI_STATUS(AE_NO_MEMORY
);
443 new_sci_handler
->address
= address
;
444 new_sci_handler
->context
= context
;
446 status
= acpi_ut_acquire_mutex(ACPI_MTX_EVENTS
);
447 if (ACPI_FAILURE(status
)) {
451 /* Lock list during installation */
453 flags
= acpi_os_acquire_lock(acpi_gbl_gpe_lock
);
454 sci_handler
= acpi_gbl_sci_handler_list
;
456 /* Ensure handler does not already exist */
458 while (sci_handler
) {
459 if (address
== sci_handler
->address
) {
460 status
= AE_ALREADY_EXISTS
;
461 goto unlock_and_exit
;
464 sci_handler
= sci_handler
->next
;
467 /* Install the new handler into the global list (at head) */
469 new_sci_handler
->next
= acpi_gbl_sci_handler_list
;
470 acpi_gbl_sci_handler_list
= new_sci_handler
;
474 acpi_os_release_lock(acpi_gbl_gpe_lock
, flags
);
475 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS
);
478 if (ACPI_FAILURE(status
)) {
479 ACPI_FREE(new_sci_handler
);
481 return_ACPI_STATUS(status
);
484 ACPI_EXPORT_SYMBOL(acpi_install_sci_handler
)
486 /*******************************************************************************
488 * FUNCTION: acpi_remove_sci_handler
490 * PARAMETERS: address - Address of the handler
494 * DESCRIPTION: Remove a handler for a System Control Interrupt.
496 ******************************************************************************/
497 acpi_status
acpi_remove_sci_handler(acpi_sci_handler address
)
499 struct acpi_sci_handler_info
*prev_sci_handler
;
500 struct acpi_sci_handler_info
*next_sci_handler
;
501 acpi_cpu_flags flags
;
504 ACPI_FUNCTION_TRACE(acpi_remove_sci_handler
);
507 return_ACPI_STATUS(AE_BAD_PARAMETER
);
510 status
= acpi_ut_acquire_mutex(ACPI_MTX_EVENTS
);
511 if (ACPI_FAILURE(status
)) {
512 return_ACPI_STATUS(status
);
515 /* Remove the SCI handler with lock */
517 flags
= acpi_os_acquire_lock(acpi_gbl_gpe_lock
);
519 prev_sci_handler
= NULL
;
520 next_sci_handler
= acpi_gbl_sci_handler_list
;
521 while (next_sci_handler
) {
522 if (next_sci_handler
->address
== address
) {
524 /* Unlink and free the SCI handler info block */
526 if (prev_sci_handler
) {
527 prev_sci_handler
->next
= next_sci_handler
->next
;
529 acpi_gbl_sci_handler_list
=
530 next_sci_handler
->next
;
533 acpi_os_release_lock(acpi_gbl_gpe_lock
, flags
);
534 ACPI_FREE(next_sci_handler
);
535 goto unlock_and_exit
;
538 prev_sci_handler
= next_sci_handler
;
539 next_sci_handler
= next_sci_handler
->next
;
542 acpi_os_release_lock(acpi_gbl_gpe_lock
, flags
);
543 status
= AE_NOT_EXIST
;
546 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS
);
547 return_ACPI_STATUS(status
);
550 ACPI_EXPORT_SYMBOL(acpi_remove_sci_handler
)
552 /*******************************************************************************
554 * FUNCTION: acpi_install_global_event_handler
556 * PARAMETERS: handler - Pointer to the global event handler function
557 * context - Value passed to the handler on each event
561 * DESCRIPTION: Saves the pointer to the handler function. The global handler
562 * is invoked upon each incoming GPE and Fixed Event. It is
563 * invoked at interrupt level at the time of the event dispatch.
564 * Can be used to update event counters, etc.
566 ******************************************************************************/
568 acpi_install_global_event_handler(acpi_gbl_event_handler handler
, void *context
)
572 ACPI_FUNCTION_TRACE(acpi_install_global_event_handler
);
574 /* Parameter validation */
577 return_ACPI_STATUS(AE_BAD_PARAMETER
);
580 status
= acpi_ut_acquire_mutex(ACPI_MTX_EVENTS
);
581 if (ACPI_FAILURE(status
)) {
582 return_ACPI_STATUS(status
);
585 /* Don't allow two handlers. */
587 if (acpi_gbl_global_event_handler
) {
588 status
= AE_ALREADY_EXISTS
;
592 acpi_gbl_global_event_handler
= handler
;
593 acpi_gbl_global_event_handler_context
= context
;
596 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS
);
597 return_ACPI_STATUS(status
);
600 ACPI_EXPORT_SYMBOL(acpi_install_global_event_handler
)
602 /*******************************************************************************
604 * FUNCTION: acpi_install_fixed_event_handler
606 * PARAMETERS: event - Event type to enable.
607 * handler - Pointer to the handler function for the
609 * context - Value passed to the handler on each GPE
613 * DESCRIPTION: Saves the pointer to the handler function and then enables the
616 ******************************************************************************/
618 acpi_install_fixed_event_handler(u32 event
,
619 acpi_event_handler handler
, void *context
)
623 ACPI_FUNCTION_TRACE(acpi_install_fixed_event_handler
);
625 /* Parameter validation */
627 if (event
> ACPI_EVENT_MAX
) {
628 return_ACPI_STATUS(AE_BAD_PARAMETER
);
631 status
= acpi_ut_acquire_mutex(ACPI_MTX_EVENTS
);
632 if (ACPI_FAILURE(status
)) {
633 return_ACPI_STATUS(status
);
636 /* Do not allow multiple handlers */
638 if (acpi_gbl_fixed_event_handlers
[event
].handler
) {
639 status
= AE_ALREADY_EXISTS
;
643 /* Install the handler before enabling the event */
645 acpi_gbl_fixed_event_handlers
[event
].handler
= handler
;
646 acpi_gbl_fixed_event_handlers
[event
].context
= context
;
648 status
= acpi_clear_event(event
);
649 if (ACPI_SUCCESS(status
))
650 status
= acpi_enable_event(event
, 0);
651 if (ACPI_FAILURE(status
)) {
652 ACPI_WARNING((AE_INFO
,
653 "Could not enable fixed event - %s (%u)",
654 acpi_ut_get_event_name(event
), event
));
656 /* Remove the handler */
658 acpi_gbl_fixed_event_handlers
[event
].handler
= NULL
;
659 acpi_gbl_fixed_event_handlers
[event
].context
= NULL
;
661 ACPI_DEBUG_PRINT((ACPI_DB_INFO
,
662 "Enabled fixed event %s (%X), Handler=%p\n",
663 acpi_ut_get_event_name(event
), event
,
668 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS
);
669 return_ACPI_STATUS(status
);
672 ACPI_EXPORT_SYMBOL(acpi_install_fixed_event_handler
)
674 /*******************************************************************************
676 * FUNCTION: acpi_remove_fixed_event_handler
678 * PARAMETERS: event - Event type to disable.
679 * handler - Address of the handler
683 * DESCRIPTION: Disables the event and unregisters the event handler.
685 ******************************************************************************/
687 acpi_remove_fixed_event_handler(u32 event
, acpi_event_handler handler
)
689 acpi_status status
= AE_OK
;
691 ACPI_FUNCTION_TRACE(acpi_remove_fixed_event_handler
);
693 /* Parameter validation */
695 if (event
> ACPI_EVENT_MAX
) {
696 return_ACPI_STATUS(AE_BAD_PARAMETER
);
699 status
= acpi_ut_acquire_mutex(ACPI_MTX_EVENTS
);
700 if (ACPI_FAILURE(status
)) {
701 return_ACPI_STATUS(status
);
704 /* Disable the event before removing the handler */
706 status
= acpi_disable_event(event
, 0);
708 /* Always Remove the handler */
710 acpi_gbl_fixed_event_handlers
[event
].handler
= NULL
;
711 acpi_gbl_fixed_event_handlers
[event
].context
= NULL
;
713 if (ACPI_FAILURE(status
)) {
714 ACPI_WARNING((AE_INFO
,
715 "Could not disable fixed event - %s (%u)",
716 acpi_ut_get_event_name(event
), event
));
718 ACPI_DEBUG_PRINT((ACPI_DB_INFO
,
719 "Disabled fixed event - %s (%X)\n",
720 acpi_ut_get_event_name(event
), event
));
723 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS
);
724 return_ACPI_STATUS(status
);
727 ACPI_EXPORT_SYMBOL(acpi_remove_fixed_event_handler
)
729 /*******************************************************************************
731 * FUNCTION: acpi_ev_install_gpe_handler
733 * PARAMETERS: gpe_device - Namespace node for the GPE (NULL for FADT
735 * gpe_number - The GPE number within the GPE block
736 * type - Whether this GPE should be treated as an
737 * edge- or level-triggered interrupt.
738 * is_raw_handler - Whether this GPE should be handled using
739 * the special GPE handler mode.
740 * address - Address of the handler
741 * context - Value passed to the handler on each GPE
745 * DESCRIPTION: Internal function to install a handler for a General Purpose
748 ******************************************************************************/
750 acpi_ev_install_gpe_handler(acpi_handle gpe_device
,
754 acpi_gpe_handler address
, void *context
)
756 struct acpi_gpe_event_info
*gpe_event_info
;
757 struct acpi_gpe_handler_info
*handler
;
759 acpi_cpu_flags flags
;
761 ACPI_FUNCTION_TRACE(ev_install_gpe_handler
);
763 /* Parameter validation */
765 if ((!address
) || (type
& ~ACPI_GPE_XRUPT_TYPE_MASK
)) {
766 return_ACPI_STATUS(AE_BAD_PARAMETER
);
769 status
= acpi_ut_acquire_mutex(ACPI_MTX_EVENTS
);
770 if (ACPI_FAILURE(status
)) {
771 return_ACPI_STATUS(status
);
774 /* Allocate and init handler object (before lock) */
776 handler
= ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_handler_info
));
778 status
= AE_NO_MEMORY
;
779 goto unlock_and_exit
;
782 flags
= acpi_os_acquire_lock(acpi_gbl_gpe_lock
);
784 /* Ensure that we have a valid GPE number */
786 gpe_event_info
= acpi_ev_get_gpe_event_info(gpe_device
, gpe_number
);
787 if (!gpe_event_info
) {
788 status
= AE_BAD_PARAMETER
;
792 /* Make sure that there isn't a handler there already */
794 if ((ACPI_GPE_DISPATCH_TYPE(gpe_event_info
->flags
) ==
795 ACPI_GPE_DISPATCH_HANDLER
) ||
796 (ACPI_GPE_DISPATCH_TYPE(gpe_event_info
->flags
) ==
797 ACPI_GPE_DISPATCH_RAW_HANDLER
)) {
798 status
= AE_ALREADY_EXISTS
;
802 handler
->address
= address
;
803 handler
->context
= context
;
804 handler
->method_node
= gpe_event_info
->dispatch
.method_node
;
805 handler
->original_flags
= (u8
)(gpe_event_info
->flags
&
806 (ACPI_GPE_XRUPT_TYPE_MASK
|
807 ACPI_GPE_DISPATCH_MASK
));
810 * If the GPE is associated with a method, it may have been enabled
811 * automatically during initialization, in which case it has to be
812 * disabled now to avoid spurious execution of the handler.
814 if (((ACPI_GPE_DISPATCH_TYPE(handler
->original_flags
) ==
815 ACPI_GPE_DISPATCH_METHOD
) ||
816 (ACPI_GPE_DISPATCH_TYPE(handler
->original_flags
) ==
817 ACPI_GPE_DISPATCH_NOTIFY
)) && gpe_event_info
->runtime_count
) {
818 handler
->originally_enabled
= TRUE
;
819 (void)acpi_ev_remove_gpe_reference(gpe_event_info
);
821 /* Sanity check of original type against new type */
824 (u32
)(gpe_event_info
->flags
& ACPI_GPE_XRUPT_TYPE_MASK
)) {
825 ACPI_WARNING((AE_INFO
,
826 "GPE type mismatch (level/edge)"));
830 /* Install the handler */
832 gpe_event_info
->dispatch
.handler
= handler
;
834 /* Setup up dispatch flags to indicate handler (vs. method/notify) */
836 gpe_event_info
->flags
&=
837 ~(ACPI_GPE_XRUPT_TYPE_MASK
| ACPI_GPE_DISPATCH_MASK
);
838 gpe_event_info
->flags
|=
840 (is_raw_handler
? ACPI_GPE_DISPATCH_RAW_HANDLER
:
841 ACPI_GPE_DISPATCH_HANDLER
));
843 acpi_os_release_lock(acpi_gbl_gpe_lock
, flags
);
846 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS
);
847 return_ACPI_STATUS(status
);
850 acpi_os_release_lock(acpi_gbl_gpe_lock
, flags
);
852 goto unlock_and_exit
;
855 /*******************************************************************************
857 * FUNCTION: acpi_install_gpe_handler
859 * PARAMETERS: gpe_device - Namespace node for the GPE (NULL for FADT
861 * gpe_number - The GPE number within the GPE block
862 * type - Whether this GPE should be treated as an
863 * edge- or level-triggered interrupt.
864 * address - Address of the handler
865 * context - Value passed to the handler on each GPE
869 * DESCRIPTION: Install a handler for a General Purpose Event.
871 ******************************************************************************/
874 acpi_install_gpe_handler(acpi_handle gpe_device
,
876 u32 type
, acpi_gpe_handler address
, void *context
)
880 ACPI_FUNCTION_TRACE(acpi_install_gpe_handler
);
882 status
= acpi_ev_install_gpe_handler(gpe_device
, gpe_number
, type
,
883 FALSE
, address
, context
);
885 return_ACPI_STATUS(status
);
888 ACPI_EXPORT_SYMBOL(acpi_install_gpe_handler
)
890 /*******************************************************************************
892 * FUNCTION: acpi_install_gpe_raw_handler
894 * PARAMETERS: gpe_device - Namespace node for the GPE (NULL for FADT
896 * gpe_number - The GPE number within the GPE block
897 * type - Whether this GPE should be treated as an
898 * edge- or level-triggered interrupt.
899 * address - Address of the handler
900 * context - Value passed to the handler on each GPE
904 * DESCRIPTION: Install a handler for a General Purpose Event.
906 ******************************************************************************/
908 acpi_install_gpe_raw_handler(acpi_handle gpe_device
,
910 u32 type
, acpi_gpe_handler address
, void *context
)
914 ACPI_FUNCTION_TRACE(acpi_install_gpe_raw_handler
);
916 status
= acpi_ev_install_gpe_handler(gpe_device
, gpe_number
, type
,
917 TRUE
, address
, context
);
919 return_ACPI_STATUS(status
);
922 ACPI_EXPORT_SYMBOL(acpi_install_gpe_raw_handler
)
924 /*******************************************************************************
926 * FUNCTION: acpi_remove_gpe_handler
928 * PARAMETERS: gpe_device - Namespace node for the GPE (NULL for FADT
930 * gpe_number - The event to remove a handler
931 * address - Address of the handler
935 * DESCRIPTION: Remove a handler for a General Purpose acpi_event.
937 ******************************************************************************/
939 acpi_remove_gpe_handler(acpi_handle gpe_device
,
940 u32 gpe_number
, acpi_gpe_handler address
)
942 struct acpi_gpe_event_info
*gpe_event_info
;
943 struct acpi_gpe_handler_info
*handler
;
945 acpi_cpu_flags flags
;
947 ACPI_FUNCTION_TRACE(acpi_remove_gpe_handler
);
949 /* Parameter validation */
952 return_ACPI_STATUS(AE_BAD_PARAMETER
);
955 status
= acpi_ut_acquire_mutex(ACPI_MTX_EVENTS
);
956 if (ACPI_FAILURE(status
)) {
957 return_ACPI_STATUS(status
);
960 flags
= acpi_os_acquire_lock(acpi_gbl_gpe_lock
);
962 /* Ensure that we have a valid GPE number */
964 gpe_event_info
= acpi_ev_get_gpe_event_info(gpe_device
, gpe_number
);
965 if (!gpe_event_info
) {
966 status
= AE_BAD_PARAMETER
;
967 goto unlock_and_exit
;
970 /* Make sure that a handler is indeed installed */
972 if ((ACPI_GPE_DISPATCH_TYPE(gpe_event_info
->flags
) !=
973 ACPI_GPE_DISPATCH_HANDLER
) &&
974 (ACPI_GPE_DISPATCH_TYPE(gpe_event_info
->flags
) !=
975 ACPI_GPE_DISPATCH_RAW_HANDLER
)) {
976 status
= AE_NOT_EXIST
;
977 goto unlock_and_exit
;
980 /* Make sure that the installed handler is the same */
982 if (gpe_event_info
->dispatch
.handler
->address
!= address
) {
983 status
= AE_BAD_PARAMETER
;
984 goto unlock_and_exit
;
987 /* Remove the handler */
989 handler
= gpe_event_info
->dispatch
.handler
;
990 gpe_event_info
->dispatch
.handler
= NULL
;
992 /* Restore Method node (if any), set dispatch flags */
994 gpe_event_info
->dispatch
.method_node
= handler
->method_node
;
995 gpe_event_info
->flags
&=
996 ~(ACPI_GPE_XRUPT_TYPE_MASK
| ACPI_GPE_DISPATCH_MASK
);
997 gpe_event_info
->flags
|= handler
->original_flags
;
1000 * If the GPE was previously associated with a method and it was
1001 * enabled, it should be enabled at this point to restore the
1002 * post-initialization configuration.
1004 if (((ACPI_GPE_DISPATCH_TYPE(handler
->original_flags
) ==
1005 ACPI_GPE_DISPATCH_METHOD
) ||
1006 (ACPI_GPE_DISPATCH_TYPE(handler
->original_flags
) ==
1007 ACPI_GPE_DISPATCH_NOTIFY
)) && handler
->originally_enabled
) {
1008 (void)acpi_ev_add_gpe_reference(gpe_event_info
);
1011 acpi_os_release_lock(acpi_gbl_gpe_lock
, flags
);
1012 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS
);
1014 /* Make sure all deferred GPE tasks are completed */
1016 acpi_os_wait_events_complete();
1018 /* Now we can free the handler object */
1021 return_ACPI_STATUS(status
);
1024 acpi_os_release_lock(acpi_gbl_gpe_lock
, flags
);
1026 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS
);
1027 return_ACPI_STATUS(status
);
1030 ACPI_EXPORT_SYMBOL(acpi_remove_gpe_handler
)
1032 /*******************************************************************************
1034 * FUNCTION: acpi_acquire_global_lock
1036 * PARAMETERS: timeout - How long the caller is willing to wait
1037 * handle - Where the handle to the lock is returned
1042 * DESCRIPTION: Acquire the ACPI Global Lock
1044 * Note: Allows callers with the same thread ID to acquire the global lock
1045 * multiple times. In other words, externally, the behavior of the global lock
1046 * is identical to an AML mutex. On the first acquire, a new handle is
1047 * returned. On any subsequent calls to acquire by the same thread, the same
1048 * handle is returned.
1050 ******************************************************************************/
1051 acpi_status
acpi_acquire_global_lock(u16 timeout
, u32
*handle
)
1056 return (AE_BAD_PARAMETER
);
1059 /* Must lock interpreter to prevent race conditions */
1061 acpi_ex_enter_interpreter();
1063 status
= acpi_ex_acquire_mutex_object(timeout
,
1064 acpi_gbl_global_lock_mutex
,
1065 acpi_os_get_thread_id());
1067 if (ACPI_SUCCESS(status
)) {
1069 /* Return the global lock handle (updated in acpi_ev_acquire_global_lock) */
1071 *handle
= acpi_gbl_global_lock_handle
;
1074 acpi_ex_exit_interpreter();
1078 ACPI_EXPORT_SYMBOL(acpi_acquire_global_lock
)
1080 /*******************************************************************************
1082 * FUNCTION: acpi_release_global_lock
1084 * PARAMETERS: handle - Returned from acpi_acquire_global_lock
1088 * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid.
1090 ******************************************************************************/
1091 acpi_status
acpi_release_global_lock(u32 handle
)
1095 if (!handle
|| (handle
!= acpi_gbl_global_lock_handle
)) {
1096 return (AE_NOT_ACQUIRED
);
1099 status
= acpi_ex_release_mutex_object(acpi_gbl_global_lock_mutex
);
1103 ACPI_EXPORT_SYMBOL(acpi_release_global_lock
)
1104 #endif /* !ACPI_REDUCED_HARDWARE */