/******************************************************************************* * * FUNCTION: acpi_enable_gpe * * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 * gpe_number - GPE level within the GPE block * * RETURN: Status * * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is * hardware-enabled. * ******************************************************************************/ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number) { acpi_status status = AE_BAD_PARAMETER; struct acpi_gpe_event_info *gpe_event_info; acpi_cpu_flags flags; ACPI_FUNCTION_TRACE(acpi_enable_gpe); flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); /* * Ensure that we have a valid GPE number and that there is some way * of handling the GPE (handler or a GPE method). In other words, we * won't allow a valid GPE to be enabled if there is no way to handle it. */ gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); if (gpe_event_info) { if (ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) != ACPI_GPE_DISPATCH_NONE) { status = acpi_ev_add_gpe_reference(gpe_event_info); } else { status = AE_NO_HANDLER; } } acpi_os_release_lock(acpi_gbl_gpe_lock, flags); return_ACPI_STATUS(status); }
acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number) { acpi_status status = AE_BAD_PARAMETER; struct acpi_gpe_event_info *gpe_event_info; acpi_cpu_flags flags; ACPI_FUNCTION_TRACE(acpi_enable_gpe); flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); /* Ensure that we have a valid GPE number */ gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); if (gpe_event_info) { status = acpi_ev_add_gpe_reference(gpe_event_info); } acpi_os_release_lock(acpi_gbl_gpe_lock, flags); return_ACPI_STATUS(status); }
acpi_status acpi_ev_initialize_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, struct acpi_gpe_block_info *gpe_block, void *ignored) { acpi_status status; struct acpi_gpe_event_info *gpe_event_info; u32 gpe_enabled_count; u32 gpe_index; u32 i; u32 j; ACPI_FUNCTION_TRACE(ev_initialize_gpe_block); /* * Ignore a null GPE block (e.g., if no GPE block 1 exists), and * any GPE blocks that have been initialized already. */ if (!gpe_block || gpe_block->initialized) { return_ACPI_STATUS(AE_OK); } /* * Enable all GPEs that have a corresponding method and have the * ACPI_GPE_CAN_WAKE flag unset. Any other GPEs within this block * must be enabled via the acpi_enable_gpe() interface. */ gpe_enabled_count = 0; for (i = 0; i < gpe_block->register_count; i++) { for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) { /* Get the info block for this particular GPE */ gpe_index = (i * ACPI_GPE_REGISTER_WIDTH) + j; gpe_event_info = &gpe_block->event_info[gpe_index]; /* * Ignore GPEs that have no corresponding _Lxx/_Exx method * and GPEs that are used to wake the system */ if (((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_NONE) || ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_HANDLER) || (gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) { continue; } status = acpi_ev_add_gpe_reference(gpe_event_info); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Could not enable GPE 0x%02X", gpe_index + gpe_block->block_base_number)); continue; } gpe_enabled_count++; } } if (gpe_enabled_count) { ACPI_DEBUG_PRINT((ACPI_DB_INIT, "Enabled %u GPEs in this block\n", gpe_enabled_count)); } gpe_block->initialized = TRUE; return_ACPI_STATUS(AE_OK); }
/******************************************************************************* * * FUNCTION: acpi_remove_gpe_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 address) { struct acpi_gpe_event_info *gpe_event_info; struct acpi_gpe_handler_info *handler; acpi_status status; acpi_cpu_flags flags; ACPI_FUNCTION_TRACE(acpi_remove_gpe_handler); /* Parameter validation */ if (!address) { return_ACPI_STATUS(AE_BAD_PARAMETER); } /* Make sure all deferred tasks are completed */ acpi_os_wait_events_complete(NULL); status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); /* Ensure that we have a valid 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; } /* Make sure that a handler is indeed installed */ 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->dispatch.handler->address != address) { status = AE_BAD_PARAMETER; goto unlock_and_exit; } /* Remove the handler */ 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_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); gpe_event_info->flags |= handler->original_flags; /* * If the GPE was previously associated with a method and it was * enabled, it should be enabled at this point to restore the * post-initialization configuration. */ if ((handler->original_flags & ACPI_GPE_DISPATCH_METHOD) && handler->originally_enabled) (void)acpi_ev_add_gpe_reference(gpe_event_info); /* Now we can free the handler object */ ACPI_FREE(handler); unlock_and_exit: acpi_os_release_lock(acpi_gbl_gpe_lock, flags); (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); return_ACPI_STATUS(status); }