ACPICA: Events: Introduce acpi_set_gpe()/acpi_finish_gpe() to reduce divergences
This can help to reduce source code differences between Linux and ACPICA upstream. Further driver cleanups also require these APIs to eliminate GPE storms. 1. acpi_set_gpe(): An API that driver should invoke in the case it wants to disable/enable IRQ without honoring the reference count implemented in the acpi_disable_gpe() and acpi_enable_gpe(). Note that this API should only be invoked inside a acpi_enable_gpe()/acpi_disable_gpe() pair. 2. acpi_finish_gpe(): Drivers returned ACPI_REENABLE_GPE unset from the GPE handler should use this API instead of invoking acpi_set_gpe()/acpi_enable_gpe() to re-enable the GPE. The GPE APIs can be invoked inside of a GPE handler or in the task context with a driver provided lock held. This driver provided lock is safe to be held in the GPE handler by the driver. Signed-off-by: Lv Zheng <lv.zheng@intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
parent
0d0988af81
commit
eb3d80f729
|
@ -183,6 +183,68 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number)
|
|||
|
||||
ACPI_EXPORT_SYMBOL(acpi_disable_gpe)
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_set_gpe
|
||||
*
|
||||
* PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
|
||||
* gpe_number - GPE level within the GPE block
|
||||
* action - ACPI_GPE_ENABLE or ACPI_GPE_DISABLE
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Enable or disable an individual GPE. This function bypasses
|
||||
* the reference count mechanism used in the acpi_enable_gpe and
|
||||
* acpi_disable_gpe interfaces -- and should be used with care.
|
||||
*
|
||||
* Note: Typically used to disable a runtime GPE for short period of time,
|
||||
* then re-enable it, without disturbing the existing reference counts. This
|
||||
* is useful, for example, in the Embedded Controller (EC) driver.
|
||||
*
|
||||
******************************************************************************/
|
||||
acpi_status acpi_set_gpe(acpi_handle gpe_device, u32 gpe_number, u8 action)
|
||||
{
|
||||
struct acpi_gpe_event_info *gpe_event_info;
|
||||
acpi_status status;
|
||||
acpi_cpu_flags flags;
|
||||
|
||||
ACPI_FUNCTION_TRACE(acpi_set_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 = AE_BAD_PARAMETER;
|
||||
goto unlock_and_exit;
|
||||
}
|
||||
|
||||
/* Perform the action */
|
||||
|
||||
switch (action) {
|
||||
case ACPI_GPE_ENABLE:
|
||||
|
||||
status = acpi_ev_enable_gpe(gpe_event_info);
|
||||
break;
|
||||
|
||||
case ACPI_GPE_DISABLE:
|
||||
|
||||
status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
status = AE_BAD_PARAMETER;
|
||||
break;
|
||||
}
|
||||
|
||||
unlock_and_exit:
|
||||
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
ACPI_EXPORT_SYMBOL(acpi_set_gpe)
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
|
@ -530,6 +592,49 @@ unlock_and_exit:
|
|||
|
||||
ACPI_EXPORT_SYMBOL(acpi_get_gpe_status)
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_finish_gpe
|
||||
*
|
||||
* PARAMETERS: gpe_device - Namespace node for the GPE Block
|
||||
* (NULL for FADT defined GPEs)
|
||||
* gpe_number - GPE level within the GPE block
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Clear and conditionally reenable a GPE. This completes the GPE
|
||||
* processing. Intended for use by asynchronous host-installed
|
||||
* GPE handlers. The GPE is only reenabled if the enable_for_run bit
|
||||
* is set in the GPE info.
|
||||
*
|
||||
******************************************************************************/
|
||||
acpi_status acpi_finish_gpe(acpi_handle gpe_device, u32 gpe_number)
|
||||
{
|
||||
struct acpi_gpe_event_info *gpe_event_info;
|
||||
acpi_status status;
|
||||
acpi_cpu_flags flags;
|
||||
|
||||
ACPI_FUNCTION_TRACE(acpi_finish_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 = AE_BAD_PARAMETER;
|
||||
goto unlock_and_exit;
|
||||
}
|
||||
|
||||
status = acpi_ev_finish_gpe(gpe_event_info);
|
||||
|
||||
unlock_and_exit:
|
||||
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
ACPI_EXPORT_SYMBOL(acpi_finish_gpe)
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_disable_all_gpes
|
||||
|
|
Loading…
Reference in New Issue