X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Facpi%2Fevents%2Fevxface.c;h=923fd2b46955284a99a2baaa29eeec9c8086e45d;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=d2fe466e774809b2418249ad03570be5e9606e86;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/drivers/acpi/events/evxface.c b/drivers/acpi/events/evxface.c index d2fe466e7..923fd2b46 100644 --- a/drivers/acpi/events/evxface.c +++ b/drivers/acpi/events/evxface.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2004, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -41,15 +41,56 @@ * POSSIBILITY OF SUCH DAMAGES. */ - #include #include #include #include #define _COMPONENT ACPI_EVENTS - ACPI_MODULE_NAME ("evxface") +ACPI_MODULE_NAME("evxface") +/******************************************************************************* + * + * FUNCTION: acpi_install_exception_handler + * + * PARAMETERS: Handler - Pointer to the handler function for the + * event + * + * RETURN: Status + * + * DESCRIPTION: Saves the pointer to the handler function + * + ******************************************************************************/ +#ifdef ACPI_FUTURE_USAGE +acpi_status acpi_install_exception_handler(acpi_exception_handler handler) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_install_exception_handler); + + status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Don't allow two handlers. */ + + if (acpi_gbl_exception_handler) { + status = AE_ALREADY_EXISTS; + goto cleanup; + } + + /* Install the handler */ + + acpi_gbl_exception_handler = handler; + + cleanup: + (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_install_exception_handler) +#endif /* ACPI_FUTURE_USAGE */ /******************************************************************************* * @@ -66,28 +107,23 @@ * event. * ******************************************************************************/ - acpi_status -acpi_install_fixed_event_handler ( - u32 event, - acpi_event_handler handler, - void *context) +acpi_install_fixed_event_handler(u32 event, + acpi_event_handler handler, void *context) { - acpi_status status; - - - ACPI_FUNCTION_TRACE ("acpi_install_fixed_event_handler"); + acpi_status status; + ACPI_FUNCTION_TRACE(acpi_install_fixed_event_handler); /* Parameter validation */ if (event > ACPI_EVENT_MAX) { - return_ACPI_STATUS (AE_BAD_PARAMETER); + return_ACPI_STATUS(AE_BAD_PARAMETER); } - status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS); - if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); + status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); } /* Don't allow two handlers. */ @@ -102,26 +138,29 @@ acpi_install_fixed_event_handler ( acpi_gbl_fixed_event_handlers[event].handler = handler; acpi_gbl_fixed_event_handlers[event].context = context; - status = acpi_enable_event (event, 0); - if (ACPI_FAILURE (status)) { - ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Could not enable fixed event.\n")); + status = acpi_clear_event(event); + if (ACPI_SUCCESS(status)) + status = acpi_enable_event(event, 0); + if (ACPI_FAILURE(status)) { + ACPI_WARNING((AE_INFO, "Could not enable fixed event %X", + event)); /* Remove the handler */ acpi_gbl_fixed_event_handlers[event].handler = NULL; acpi_gbl_fixed_event_handlers[event].context = NULL; - } - else { - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, - "Enabled fixed event %X, Handler=%p\n", event, handler)); + } else { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Enabled fixed event %X, Handler=%p\n", event, + handler)); } - -cleanup: - (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS); - return_ACPI_STATUS (status); + cleanup: + (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); + return_ACPI_STATUS(status); } +ACPI_EXPORT_SYMBOL(acpi_install_fixed_event_handler) /******************************************************************************* * @@ -135,50 +174,47 @@ cleanup: * DESCRIPTION: Disables the event and unregisters the event handler. * ******************************************************************************/ - acpi_status -acpi_remove_fixed_event_handler ( - u32 event, - acpi_event_handler handler) +acpi_remove_fixed_event_handler(u32 event, acpi_event_handler handler) { - acpi_status status = AE_OK; - - - ACPI_FUNCTION_TRACE ("acpi_remove_fixed_event_handler"); + acpi_status status = AE_OK; + ACPI_FUNCTION_TRACE(acpi_remove_fixed_event_handler); /* Parameter validation */ if (event > ACPI_EVENT_MAX) { - return_ACPI_STATUS (AE_BAD_PARAMETER); + return_ACPI_STATUS(AE_BAD_PARAMETER); } - status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS); - if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); + status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); } /* Disable the event before removing the handler */ - status = acpi_disable_event (event, 0); + status = acpi_disable_event(event, 0); /* Always Remove the handler */ acpi_gbl_fixed_event_handlers[event].handler = NULL; acpi_gbl_fixed_event_handlers[event].context = NULL; - if (ACPI_FAILURE (status)) { - ACPI_DEBUG_PRINT ((ACPI_DB_WARN, - "Could not write to fixed event enable register.\n")); - } - else { - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Disabled fixed event %X.\n", event)); + if (ACPI_FAILURE(status)) { + ACPI_WARNING((AE_INFO, + "Could not write to fixed event enable register %X", + event)); + } else { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Disabled fixed event %X\n", + event)); } - (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS); - return_ACPI_STATUS (status); + (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); + return_ACPI_STATUS(status); } +ACPI_EXPORT_SYMBOL(acpi_remove_fixed_event_handler) /******************************************************************************* * @@ -188,6 +224,7 @@ acpi_remove_fixed_event_handler ( * handler_type - The type of handler: * ACPI_SYSTEM_NOTIFY: system_handler (00-7f) * ACPI_DEVICE_NOTIFY: driver_handler (80-ff) + * ACPI_ALL_NOTIFY: both system and device * Handler - Address of the handler * Context - Value passed to the handler on each GPE * @@ -196,39 +233,33 @@ acpi_remove_fixed_event_handler ( * DESCRIPTION: Install a handler for notifies on an ACPI device * ******************************************************************************/ - acpi_status -acpi_install_notify_handler ( - acpi_handle device, - u32 handler_type, - acpi_notify_handler handler, - void *context) +acpi_install_notify_handler(acpi_handle device, + u32 handler_type, + acpi_notify_handler handler, void *context) { - union acpi_operand_object *obj_desc; - union acpi_operand_object *notify_obj; - struct acpi_namespace_node *node; - acpi_status status; - - - ACPI_FUNCTION_TRACE ("acpi_install_notify_handler"); + union acpi_operand_object *obj_desc; + union acpi_operand_object *notify_obj; + struct acpi_namespace_node *node; + acpi_status status; + ACPI_FUNCTION_TRACE(acpi_install_notify_handler); /* Parameter validation */ - if ((!device) || - (!handler) || - (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) { - return_ACPI_STATUS (AE_BAD_PARAMETER); + if ((!device) || + (!handler) || (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) { + return_ACPI_STATUS(AE_BAD_PARAMETER); } - status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); } /* Convert and validate the device handle */ - node = acpi_ns_map_handle_to_node (device); + node = acpi_ns_map_handle_to_node(device); if (!node) { status = AE_BAD_PARAMETER; goto unlock_and_exit; @@ -241,23 +272,25 @@ acpi_install_notify_handler ( * only one global handler can be regsitered (per notify type). */ if (device == ACPI_ROOT_OBJECT) { + /* Make sure the handler is not already installed */ - if (((handler_type == ACPI_SYSTEM_NOTIFY) && - acpi_gbl_system_notify.handler) || - ((handler_type == ACPI_DEVICE_NOTIFY) && - acpi_gbl_device_notify.handler)) { + if (((handler_type & ACPI_SYSTEM_NOTIFY) && + acpi_gbl_system_notify.handler) || + ((handler_type & ACPI_DEVICE_NOTIFY) && + acpi_gbl_device_notify.handler)) { status = AE_ALREADY_EXISTS; goto unlock_and_exit; } - if (handler_type == ACPI_SYSTEM_NOTIFY) { - acpi_gbl_system_notify.node = node; + if (handler_type & ACPI_SYSTEM_NOTIFY) { + acpi_gbl_system_notify.node = node; acpi_gbl_system_notify.handler = handler; acpi_gbl_system_notify.context = context; } - else /* ACPI_DEVICE_NOTIFY */ { - acpi_gbl_device_notify.node = node; + + if (handler_type & ACPI_DEVICE_NOTIFY) { + acpi_gbl_device_notify.node = node; acpi_gbl_device_notify.handler = handler; acpi_gbl_device_notify.context = context; } @@ -273,29 +306,29 @@ acpi_install_notify_handler ( else { /* Notifies allowed on this object? */ - if (!acpi_ev_is_notify_object (node)) { + if (!acpi_ev_is_notify_object(node)) { status = AE_TYPE; goto unlock_and_exit; } /* Check for an existing internal object */ - obj_desc = acpi_ns_get_attached_object (node); + obj_desc = acpi_ns_get_attached_object(node); if (obj_desc) { + /* Object exists - make sure there's no handler */ - if (((handler_type == ACPI_SYSTEM_NOTIFY) && - obj_desc->common_notify.system_notify) || - ((handler_type == ACPI_DEVICE_NOTIFY) && - obj_desc->common_notify.device_notify)) { + if (((handler_type & ACPI_SYSTEM_NOTIFY) && + obj_desc->common_notify.system_notify) || + ((handler_type & ACPI_DEVICE_NOTIFY) && + obj_desc->common_notify.device_notify)) { status = AE_ALREADY_EXISTS; goto unlock_and_exit; } - } - else { + } else { /* Create a new object */ - obj_desc = acpi_ut_create_internal_object (node->type); + obj_desc = acpi_ut_create_internal_object(node->type); if (!obj_desc) { status = AE_NO_MEMORY; goto unlock_and_exit; @@ -303,43 +336,52 @@ acpi_install_notify_handler ( /* Attach new object to the Node */ - status = acpi_ns_attach_object (device, obj_desc, node->type); + status = + acpi_ns_attach_object(device, obj_desc, node->type); /* Remove local reference to the object */ - acpi_ut_remove_reference (obj_desc); - - if (ACPI_FAILURE (status)) { + acpi_ut_remove_reference(obj_desc); + if (ACPI_FAILURE(status)) { goto unlock_and_exit; } } /* Install the handler */ - notify_obj = acpi_ut_create_internal_object (ACPI_TYPE_LOCAL_NOTIFY); + notify_obj = + acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_NOTIFY); if (!notify_obj) { status = AE_NO_MEMORY; goto unlock_and_exit; } - notify_obj->notify.node = node; + notify_obj->notify.node = node; notify_obj->notify.handler = handler; notify_obj->notify.context = context; - if (handler_type == ACPI_SYSTEM_NOTIFY) { + if (handler_type & ACPI_SYSTEM_NOTIFY) { obj_desc->common_notify.system_notify = notify_obj; } - else /* ACPI_DEVICE_NOTIFY */ { + + if (handler_type & ACPI_DEVICE_NOTIFY) { obj_desc->common_notify.device_notify = notify_obj; } - } + if (handler_type == ACPI_ALL_NOTIFY) { + + /* Extra ref if installed in both */ + + acpi_ut_add_reference(notify_obj); + } + } -unlock_and_exit: - (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); - return_ACPI_STATUS (status); + unlock_and_exit: + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + return_ACPI_STATUS(status); } +ACPI_EXPORT_SYMBOL(acpi_install_notify_handler) /******************************************************************************* * @@ -349,89 +391,95 @@ unlock_and_exit: * handler_type - The type of handler: * ACPI_SYSTEM_NOTIFY: system_handler (00-7f) * ACPI_DEVICE_NOTIFY: driver_handler (80-ff) + * ACPI_ALL_NOTIFY: both system and device * Handler - Address of the handler + * * RETURN: Status * * DESCRIPTION: Remove a handler for notifies on an ACPI device * ******************************************************************************/ - acpi_status -acpi_remove_notify_handler ( - acpi_handle device, - u32 handler_type, - acpi_notify_handler handler) +acpi_remove_notify_handler(acpi_handle device, + u32 handler_type, acpi_notify_handler handler) { - union acpi_operand_object *notify_obj; - union acpi_operand_object *obj_desc; - struct acpi_namespace_node *node; - acpi_status status; - - - ACPI_FUNCTION_TRACE ("acpi_remove_notify_handler"); + union acpi_operand_object *notify_obj; + union acpi_operand_object *obj_desc; + struct acpi_namespace_node *node; + acpi_status status; + ACPI_FUNCTION_TRACE(acpi_remove_notify_handler); /* Parameter validation */ - if ((!device) || - (!handler) || - (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) { - return_ACPI_STATUS (AE_BAD_PARAMETER); + if ((!device) || + (!handler) || (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) { + status = AE_BAD_PARAMETER; + goto exit; } - status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + goto exit; } /* Convert and validate the device handle */ - node = acpi_ns_map_handle_to_node (device); + node = acpi_ns_map_handle_to_node(device); if (!node) { status = AE_BAD_PARAMETER; goto unlock_and_exit; } - /* - * Root Object - */ + /* Root Object */ + if (device == ACPI_ROOT_OBJECT) { - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Removing notify handler for ROOT object.\n")); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Removing notify handler for namespace root object\n")); - if (((handler_type == ACPI_SYSTEM_NOTIFY) && - !acpi_gbl_system_notify.handler) || - ((handler_type == ACPI_DEVICE_NOTIFY) && - !acpi_gbl_device_notify.handler)) { + if (((handler_type & ACPI_SYSTEM_NOTIFY) && + !acpi_gbl_system_notify.handler) || + ((handler_type & ACPI_DEVICE_NOTIFY) && + !acpi_gbl_device_notify.handler)) { status = AE_NOT_EXIST; goto unlock_and_exit; } - if (handler_type == ACPI_SYSTEM_NOTIFY) { - acpi_gbl_system_notify.node = NULL; + /* Make sure all deferred tasks are completed */ + + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + acpi_os_wait_events_complete(NULL); + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + goto exit; + } + + if (handler_type & ACPI_SYSTEM_NOTIFY) { + acpi_gbl_system_notify.node = NULL; acpi_gbl_system_notify.handler = NULL; acpi_gbl_system_notify.context = NULL; } - else { - acpi_gbl_device_notify.node = NULL; + + if (handler_type & ACPI_DEVICE_NOTIFY) { + acpi_gbl_device_notify.node = NULL; acpi_gbl_device_notify.handler = NULL; acpi_gbl_device_notify.context = NULL; } } - /* - * All Other Objects - */ + /* All Other Objects */ + else { /* Notifies allowed on this object? */ - if (!acpi_ev_is_notify_object (node)) { + if (!acpi_ev_is_notify_object(node)) { status = AE_TYPE; goto unlock_and_exit; } /* Check for an existing internal object */ - obj_desc = acpi_ns_get_attached_object (node); + obj_desc = acpi_ns_get_attached_object(node); if (!obj_desc) { status = AE_NOT_EXIST; goto unlock_and_exit; @@ -439,47 +487,77 @@ acpi_remove_notify_handler ( /* Object exists - make sure there's an existing handler */ - if (handler_type == ACPI_SYSTEM_NOTIFY) { + if (handler_type & ACPI_SYSTEM_NOTIFY) { notify_obj = obj_desc->common_notify.system_notify; - } - else { - notify_obj = obj_desc->common_notify.device_notify; - } + if (!notify_obj) { + status = AE_NOT_EXIST; + goto unlock_and_exit; + } - if ((!notify_obj) || - (notify_obj->notify.handler != handler)) { - status = AE_BAD_PARAMETER; - goto unlock_and_exit; - } + if (notify_obj->notify.handler != handler) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + /* Make sure all deferred tasks are completed */ - /* Remove the handler */ + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + acpi_os_wait_events_complete(NULL); + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + goto exit; + } - if (handler_type == ACPI_SYSTEM_NOTIFY) { + /* Remove the handler */ obj_desc->common_notify.system_notify = NULL; + acpi_ut_remove_reference(notify_obj); } - else { + + if (handler_type & ACPI_DEVICE_NOTIFY) { + notify_obj = obj_desc->common_notify.device_notify; + if (!notify_obj) { + status = AE_NOT_EXIST; + goto unlock_and_exit; + } + + if (notify_obj->notify.handler != handler) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + /* Make sure all deferred tasks are completed */ + + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + acpi_os_wait_events_complete(NULL); + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + goto exit; + } + + /* Remove the handler */ obj_desc->common_notify.device_notify = NULL; + acpi_ut_remove_reference(notify_obj); } - - acpi_ut_remove_reference (notify_obj); } - -unlock_and_exit: - (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); - return_ACPI_STATUS (status); + unlock_and_exit: + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + exit: + if (ACPI_FAILURE(status)) + ACPI_EXCEPTION((AE_INFO, status, "Removing notify handler")); + return_ACPI_STATUS(status); } +ACPI_EXPORT_SYMBOL(acpi_remove_notify_handler) /******************************************************************************* * * FUNCTION: acpi_install_gpe_handler * - * PARAMETERS: gpe_number - The GPE number within the GPE block - * gpe_block - GPE block (NULL == FADT GPEs) + * PARAMETERS: gpe_device - Namespace node for the GPE (NULL for FADT + * defined GPEs) + * gpe_number - The GPE number within the GPE block * Type - Whether this GPE should be treated as an * edge- or level-triggered interrupt. - * Handler - Address of the handler + * Address - Address of the handler * Context - Value passed to the handler on each GPE * * RETURN: Status @@ -487,36 +565,33 @@ unlock_and_exit: * DESCRIPTION: Install a handler for a General Purpose Event. * ******************************************************************************/ - acpi_status -acpi_install_gpe_handler ( - acpi_handle gpe_device, - u32 gpe_number, - u32 type, - acpi_gpe_handler handler, - void *context) +acpi_install_gpe_handler(acpi_handle gpe_device, + u32 gpe_number, + u32 type, acpi_event_handler address, void *context) { - acpi_status status; - struct acpi_gpe_event_info *gpe_event_info; - - - ACPI_FUNCTION_TRACE ("acpi_install_gpe_handler"); + struct acpi_gpe_event_info *gpe_event_info; + struct acpi_handler_info *handler; + acpi_status status; + acpi_cpu_flags flags; + ACPI_FUNCTION_TRACE(acpi_install_gpe_handler); /* Parameter validation */ - if (!handler) { - return_ACPI_STATUS (AE_BAD_PARAMETER); + if ((!address) || (type > ACPI_GPE_XRUPT_TYPE_MASK)) { + status = AE_BAD_PARAMETER; + goto exit; } - status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS); - if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); + status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); + if (ACPI_FAILURE(status)) { + goto exit; } /* Ensure that we have a valid GPE number */ - gpe_event_info = acpi_ev_get_gpe_event_info (gpe_device, gpe_number); + gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); if (!gpe_event_info) { status = AE_BAD_PARAMETER; goto unlock_and_exit; @@ -524,144 +599,184 @@ acpi_install_gpe_handler ( /* Make sure that there isn't a handler there already */ - if (gpe_event_info->handler) { + if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == + ACPI_GPE_DISPATCH_HANDLER) { status = AE_ALREADY_EXISTS; goto unlock_and_exit; } - /* Install the handler */ + /* Allocate and init handler object */ + + handler = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_handler_info)); + if (!handler) { + status = AE_NO_MEMORY; + goto unlock_and_exit; + } - acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR); - gpe_event_info->handler = handler; - gpe_event_info->context = context; - gpe_event_info->flags = (u8) type; - acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR); + handler->address = address; + handler->context = context; + handler->method_node = gpe_event_info->dispatch.method_node; - /* Clear the GPE (of stale events), the enable it */ + /* Disable the GPE before installing the handler */ - status = acpi_hw_clear_gpe (gpe_event_info); - if (ACPI_FAILURE (status)) { + status = acpi_ev_disable_gpe(gpe_event_info); + if (ACPI_FAILURE(status)) { goto unlock_and_exit; } - status = acpi_hw_enable_gpe (gpe_event_info); + /* Install the handler */ + + flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); + gpe_event_info->dispatch.handler = handler; + + /* Setup up dispatch flags to indicate handler (vs. method) */ + gpe_event_info->flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); /* Clear bits */ + gpe_event_info->flags |= (u8) (type | ACPI_GPE_DISPATCH_HANDLER); -unlock_and_exit: - (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS); - return_ACPI_STATUS (status); + acpi_os_release_lock(acpi_gbl_gpe_lock, flags); + + unlock_and_exit: + (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); + exit: + if (ACPI_FAILURE(status)) + ACPI_EXCEPTION((AE_INFO, status, + "Installing notify handler failed")); + return_ACPI_STATUS(status); } +ACPI_EXPORT_SYMBOL(acpi_install_gpe_handler) /******************************************************************************* * * FUNCTION: acpi_remove_gpe_handler * - * PARAMETERS: gpe_number - The event to remove a handler - * gpe_block - GPE block (NULL == FADT GPEs) - * Handler - Address of the handler + * PARAMETERS: gpe_device - Namespace node for the GPE (NULL for FADT + * defined GPEs) + * gpe_number - The event to remove a handler + * Address - Address of the handler * * RETURN: Status * * DESCRIPTION: Remove a handler for a General Purpose acpi_event. * ******************************************************************************/ - acpi_status -acpi_remove_gpe_handler ( - acpi_handle gpe_device, - u32 gpe_number, - acpi_gpe_handler handler) +acpi_remove_gpe_handler(acpi_handle gpe_device, + u32 gpe_number, acpi_event_handler address) { - acpi_status status; - struct acpi_gpe_event_info *gpe_event_info; - - - ACPI_FUNCTION_TRACE ("acpi_remove_gpe_handler"); + struct acpi_gpe_event_info *gpe_event_info; + struct acpi_handler_info *handler; + acpi_status status; + acpi_cpu_flags flags; + ACPI_FUNCTION_TRACE(acpi_remove_gpe_handler); /* Parameter validation */ - if (!handler) { - return_ACPI_STATUS (AE_BAD_PARAMETER); + if (!address) { + return_ACPI_STATUS(AE_BAD_PARAMETER); } - status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS); - if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); + status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); } /* Ensure that we have a valid GPE number */ - gpe_event_info = acpi_ev_get_gpe_event_info (gpe_device, gpe_number); + gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); if (!gpe_event_info) { status = AE_BAD_PARAMETER; goto unlock_and_exit; } - /* Disable the GPE before removing the handler */ + /* Make sure that a handler is indeed installed */ - status = acpi_hw_disable_gpe (gpe_event_info); - if (ACPI_FAILURE (status)) { + if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) != + ACPI_GPE_DISPATCH_HANDLER) { + status = AE_NOT_EXIST; goto unlock_and_exit; } /* Make sure that the installed handler is the same */ - if (gpe_event_info->handler != handler) { - (void) acpi_hw_enable_gpe (gpe_event_info); + if (gpe_event_info->dispatch.handler->address != address) { status = AE_BAD_PARAMETER; goto unlock_and_exit; } + /* Disable the GPE before removing the handler */ + + status = acpi_ev_disable_gpe(gpe_event_info); + if (ACPI_FAILURE(status)) { + goto unlock_and_exit; + } + + /* Make sure all deferred tasks are completed */ + + (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); + acpi_os_wait_events_complete(NULL); + status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + /* Remove the handler */ - acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR); - gpe_event_info->handler = NULL; - gpe_event_info->context = NULL; - acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR); + flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); + handler = gpe_event_info->dispatch.handler; + + /* Restore Method node (if any), set dispatch flags */ + + gpe_event_info->dispatch.method_node = handler->method_node; + gpe_event_info->flags &= ~ACPI_GPE_DISPATCH_MASK; /* Clear bits */ + if (handler->method_node) { + gpe_event_info->flags |= ACPI_GPE_DISPATCH_METHOD; + } + acpi_os_release_lock(acpi_gbl_gpe_lock, flags); + + /* Now we can free the handler object */ + ACPI_FREE(handler); -unlock_and_exit: - (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS); - return_ACPI_STATUS (status); + unlock_and_exit: + (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); + return_ACPI_STATUS(status); } +ACPI_EXPORT_SYMBOL(acpi_remove_gpe_handler) /******************************************************************************* * * FUNCTION: acpi_acquire_global_lock * * PARAMETERS: Timeout - How long the caller is willing to wait - * out_handle - A handle to the lock if acquired + * Handle - Where the handle to the lock is returned + * (if acquired) * * RETURN: Status * * DESCRIPTION: Acquire the ACPI Global Lock * ******************************************************************************/ - -acpi_status -acpi_acquire_global_lock ( - u16 timeout, - u32 *handle) +acpi_status acpi_acquire_global_lock(u16 timeout, u32 * handle) { - acpi_status status; - + acpi_status status; if (!handle) { return (AE_BAD_PARAMETER); } - status = acpi_ex_enter_interpreter (); - if (ACPI_FAILURE (status)) { + status = acpi_ex_enter_interpreter(); + if (ACPI_FAILURE(status)) { return (status); } - status = acpi_ev_acquire_global_lock (timeout); - acpi_ex_exit_interpreter (); + status = acpi_ev_acquire_global_lock(timeout); + acpi_ex_exit_interpreter(); - if (ACPI_SUCCESS (status)) { + if (ACPI_SUCCESS(status)) { acpi_gbl_global_lock_handle++; *handle = acpi_gbl_global_lock_handle; } @@ -669,6 +784,7 @@ acpi_acquire_global_lock ( return (status); } +ACPI_EXPORT_SYMBOL(acpi_acquire_global_lock) /******************************************************************************* * @@ -678,23 +794,19 @@ acpi_acquire_global_lock ( * * RETURN: Status * - * DESCRIPTION: Release the ACPI Global Lock + * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid. * ******************************************************************************/ - -acpi_status -acpi_release_global_lock ( - u32 handle) +acpi_status acpi_release_global_lock(u32 handle) { - acpi_status status; - + acpi_status status; if (handle != acpi_gbl_global_lock_handle) { return (AE_NOT_ACQUIRED); } - status = acpi_ev_release_global_lock (); + status = acpi_ev_release_global_lock(); return (status); } - +ACPI_EXPORT_SYMBOL(acpi_release_global_lock)