Пример #1
0
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);
}
Пример #2
0
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);
}
Пример #3
0
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);
}