* 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
*
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) &&
+ 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) {
+ 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 */ {
+
+ if (handler_type & ACPI_DEVICE_NOTIFY) {
acpi_gbl_device_notify.node = node;
acpi_gbl_device_notify.handler = handler;
acpi_gbl_device_notify.context = context;
if (obj_desc) {
/* Object exists - make sure there's no handler */
- if (((handler_type == ACPI_SYSTEM_NOTIFY) &&
+ if (((handler_type & ACPI_SYSTEM_NOTIFY) &&
obj_desc->common_notify.system_notify) ||
- ((handler_type == ACPI_DEVICE_NOTIFY) &&
+ ((handler_type & ACPI_DEVICE_NOTIFY) &&
obj_desc->common_notify.device_notify)) {
status = AE_ALREADY_EXISTS;
goto unlock_and_exit;
/* Remove local reference to the object */
acpi_ut_remove_reference (obj_desc);
-
if (ACPI_FAILURE (status)) {
goto unlock_and_exit;
}
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);
+ }
}
* 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
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"));
- if (((handler_type == ACPI_SYSTEM_NOTIFY) &&
- !acpi_gbl_system_notify.handler) ||
- ((handler_type == ACPI_DEVICE_NOTIFY) &&
+ 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;
return_ACPI_STATUS (status);
}
- if (handler_type == ACPI_SYSTEM_NOTIFY) {
+ 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 {
+
+ 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? */
/* 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) ||
+ (notify_obj->notify.handler != handler)) {
+ status = AE_BAD_PARAMETER;
+ goto unlock_and_exit;
+ }
+ /* Make sure all deferred tasks are completed */
- if ((!notify_obj) ||
- (notify_obj->notify.handler != handler)) {
- status = AE_BAD_PARAMETER;
- goto unlock_and_exit;
- }
+ (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)) {
+ return_ACPI_STATUS (status);
+ }
- /* Make sure all deferred tasks are completed */
+ /* Remove the handler */
+ obj_desc->common_notify.system_notify = NULL;
+ acpi_ut_remove_reference (notify_obj);
+ }
- (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)) {
- return_ACPI_STATUS (status);
- }
+ if (handler_type & ACPI_DEVICE_NOTIFY) {
+ notify_obj = obj_desc->common_notify.device_notify;
+ if ((!notify_obj) ||
+ (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)) {
+ return_ACPI_STATUS (status);
+ }
- if (handler_type == ACPI_SYSTEM_NOTIFY) {
- obj_desc->common_notify.system_notify = NULL;
- }
- else {
+ /* Remove the handler */
obj_desc->common_notify.device_notify = NULL;
+ acpi_ut_remove_reference (notify_obj);
}
-
- acpi_ut_remove_reference (notify_obj);
}
* gpe_block - GPE block (NULL == FADT GPEs)
* 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
acpi_handle gpe_device,
u32 gpe_number,
u32 type,
- acpi_gpe_handler handler,
+ acpi_event_handler address,
void *context)
{
- acpi_status status;
struct acpi_gpe_event_info *gpe_event_info;
+ struct acpi_handler_info *handler;
+ acpi_status status;
ACPI_FUNCTION_TRACE ("acpi_install_gpe_handler");
/* Parameter validation */
- if (!handler) {
+ if ((!address) || (type > ACPI_GPE_XRUPT_TYPE_MASK)) {
return_ACPI_STATUS (AE_BAD_PARAMETER);
}
/* 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 */
- 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 = ACPI_MEM_CALLOCATE (sizeof (struct acpi_handler_info));
+ if (!handler) {
+ status = AE_NO_MEMORY;
+ goto unlock_and_exit;
+ }
- /* Clear the GPE (of stale events), the enable it */
+ handler->address = address;
+ handler->context = context;
+ handler->method_node = gpe_event_info->dispatch.method_node;
- status = acpi_hw_clear_gpe (gpe_event_info);
+ /* Disable the GPE before installing the handler */
+
+ 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 */
+
+ acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
+ 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);
+
+ acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
unlock_and_exit:
*
* PARAMETERS: gpe_number - The event to remove a handler
* gpe_block - GPE block (NULL == FADT GPEs)
- * Handler - Address of the handler
+ * Address - Address of the handler
*
* RETURN: Status
*
acpi_remove_gpe_handler (
acpi_handle gpe_device,
u32 gpe_number,
- acpi_gpe_handler handler)
+ acpi_event_handler address)
{
- acpi_status status;
struct acpi_gpe_event_info *gpe_event_info;
+ struct acpi_handler_info *handler;
+ acpi_status status;
ACPI_FUNCTION_TRACE ("acpi_remove_gpe_handler");
/* Parameter validation */
- if (!handler) {
+ if (!address) {
return_ACPI_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);
/* Remove the handler */
acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
- gpe_event_info->handler = NULL;
- gpe_event_info->context = NULL;
+ 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, ACPI_NOT_ISR);
+ /* Now we can free the handler object */
+
+ ACPI_MEM_FREE (handler);
+
unlock_and_exit:
(void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);