acpi_status acpi_remove_gpe_handler ( u32 gpe_number, acpi_gpe_handler handler) { acpi_status status = AE_OK; FUNCTION_TRACE ("Acpi_remove_gpe_handler"); /* Parameter validation */ if (!handler || (gpe_number > ACPI_GPE_MAX)) { return_ACPI_STATUS (AE_BAD_PARAMETER); } /* Ensure that we have a valid GPE number */ if (acpi_gbl_gpe_valid[gpe_number] == ACPI_GPE_INVALID) { return_ACPI_STATUS (AE_BAD_PARAMETER); } /* Disable the GPE before removing the handler */ acpi_hw_disable_gpe (gpe_number); acpi_ut_acquire_mutex (ACPI_MTX_EVENTS); /* Make sure that the installed handler is the same */ if (acpi_gbl_gpe_info[gpe_number].handler != handler) { acpi_hw_enable_gpe (gpe_number); status = AE_BAD_PARAMETER; goto cleanup; } /* Remove the handler */ acpi_gbl_gpe_info[gpe_number].handler = NULL; acpi_gbl_gpe_info[gpe_number].context = NULL; cleanup: acpi_ut_release_mutex (ACPI_MTX_EVENTS); return_ACPI_STATUS (status); }
u32 acpi_ev_gpe_dispatch ( struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number) { acpi_status status; ACPI_FUNCTION_TRACE ("ev_gpe_dispatch"); /* * If edge-triggered, clear the GPE status bit now. Note that * level-triggered events are cleared after the GPE is serviced. */ if (gpe_event_info->flags & ACPI_EVENT_EDGE_TRIGGERED) { status = acpi_hw_clear_gpe (gpe_event_info); if (ACPI_FAILURE (status)) { ACPI_REPORT_ERROR (("acpi_ev_gpe_dispatch: Unable to clear GPE[%2X]\n", gpe_number)); return_VALUE (ACPI_INTERRUPT_NOT_HANDLED); } } /* * Dispatch the GPE to either an installed handler, or the control * method associated with this GPE (_Lxx or _Exx). * If a handler exists, we invoke it and do not attempt to run the method. * If there is neither a handler nor a method, we disable the level to * prevent further events from coming in here. */ if (gpe_event_info->handler) { /* Invoke the installed handler (at interrupt level) */ gpe_event_info->handler (gpe_event_info->context); } else if (gpe_event_info->method_node) { /* * Disable GPE, so it doesn't keep firing before the method has a * chance to run. */ status = acpi_hw_disable_gpe (gpe_event_info); if (ACPI_FAILURE (status)) { ACPI_REPORT_ERROR (("acpi_ev_gpe_dispatch: Unable to disable GPE[%2X]\n", gpe_number)); return_VALUE (ACPI_INTERRUPT_NOT_HANDLED); } /* Execute the method associated with the GPE. */ if (ACPI_FAILURE (acpi_os_queue_for_execution (OSD_PRIORITY_GPE, acpi_ev_asynch_execute_gpe_method, gpe_event_info))) { ACPI_REPORT_ERROR (( "acpi_ev_gpe_dispatch: Unable to queue handler for GPE[%2X], event is disabled\n", gpe_number)); } } else { /* No handler or method to run! */ ACPI_REPORT_ERROR (( "acpi_ev_gpe_dispatch: No handler or method for GPE[%2X], disabling event\n", gpe_number)); /* * Disable the GPE. The GPE will remain disabled until the ACPI * Core Subsystem is restarted, or the handler is reinstalled. */ status = acpi_hw_disable_gpe (gpe_event_info); if (ACPI_FAILURE (status)) { ACPI_REPORT_ERROR (("acpi_ev_gpe_dispatch: Unable to disable GPE[%2X]\n", gpe_number)); return_VALUE (ACPI_INTERRUPT_NOT_HANDLED); } } /* It is now safe to clear level-triggered events. */ if (gpe_event_info->flags & ACPI_EVENT_LEVEL_TRIGGERED) { status = acpi_hw_clear_gpe (gpe_event_info); if (ACPI_FAILURE (status)) { ACPI_REPORT_ERROR (("acpi_ev_gpe_dispatch: Unable to clear GPE[%2X]\n", gpe_number)); return_VALUE (ACPI_INTERRUPT_NOT_HANDLED); } } return_VALUE (ACPI_INTERRUPT_HANDLED); }
u32 acpi_ev_gpe_dispatch ( u32 gpe_number) { acpi_gpe_level_info gpe_info; FUNCTION_TRACE ("Ev_gpe_dispatch"); /* * Valid GPE number? */ if (acpi_gbl_gpe_valid[gpe_number] == ACPI_GPE_INVALID) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid GPE bit [%X].\n", gpe_number)); return_VALUE (INTERRUPT_NOT_HANDLED); } /* * Disable the GPE. */ acpi_hw_disable_gpe (gpe_number); gpe_info = acpi_gbl_gpe_info [gpe_number]; /* * Edge-Triggered? * --------------- * If edge-triggered, clear the GPE status bit now. Note that * level-triggered events are cleared after the GPE is serviced. */ if (gpe_info.type & ACPI_EVENT_EDGE_TRIGGERED) { acpi_hw_clear_gpe (gpe_number); } /* * Function Handler (e.g. EC)? */ if (gpe_info.handler) { /* Invoke function handler (at interrupt level). */ gpe_info.handler (gpe_info.context); /* Level-Triggered? */ if (gpe_info.type & ACPI_EVENT_LEVEL_TRIGGERED) { acpi_hw_clear_gpe (gpe_number); } /* Enable GPE */ acpi_hw_enable_gpe (gpe_number); } /* * Method Handler (e.g. _Exx/_Lxx)? */ else if (gpe_info.method_handle) { if (ACPI_FAILURE(acpi_os_queue_for_execution (OSD_PRIORITY_GPE, acpi_ev_asynch_execute_gpe_method, (void*) (u64)gpe_number))) { /* * Shoudn't occur, but if it does report an error. Note that * the GPE will remain disabled until the ACPI Core Subsystem * is restarted, or the handler is removed/reinstalled. */ REPORT_ERROR (("Acpi_ev_gpe_dispatch: Unable to queue handler for GPE bit [%X]\n", gpe_number)); } } /* * No Handler? Report an error and leave the GPE disabled. */ else { REPORT_ERROR (("Acpi_ev_gpe_dispatch: No installed handler for GPE [%X]\n", gpe_number)); /* Level-Triggered? */ if (gpe_info.type & ACPI_EVENT_LEVEL_TRIGGERED) { acpi_hw_clear_gpe (gpe_number); } } return_VALUE (INTERRUPT_HANDLED); }