Commit 22f08973 authored by Soby Mathew's avatar Soby Mathew
Browse files

Return success if an interrupt is seen during PSCI CPU_SUSPEND

This patch adds support to return SUCCESS if a pending interrupt is
detected during a CPU_SUSPEND call to a power down state. The check
is performed as late as possible without losing the ability to return
to the caller. This reduces the overhead incurred by a CPU in
undergoing a complete power cycle when a wakeup interrupt is already
pending.

Fixes ARM-Software/tf-issues#102

Change-Id: I1aff04a74b704a2f529734428030d1d10750fd4b
parent 539dcedb
...@@ -270,6 +270,8 @@ DEFINE_SYSREG_RW_FUNCS(cntvoff_el2) ...@@ -270,6 +270,8 @@ DEFINE_SYSREG_RW_FUNCS(cntvoff_el2)
DEFINE_SYSREG_RW_FUNCS(vpidr_el2) DEFINE_SYSREG_RW_FUNCS(vpidr_el2)
DEFINE_SYSREG_RW_FUNCS(vmpidr_el2) DEFINE_SYSREG_RW_FUNCS(vmpidr_el2)
DEFINE_SYSREG_READ_FUNC(isr_el1)
/* GICv3 System Registers */ /* GICv3 System Registers */
DEFINE_RENAME_SYSREG_RW_FUNCS(icc_sre_el1, ICC_SRE_EL1) DEFINE_RENAME_SYSREG_RW_FUNCS(icc_sre_el1, ICC_SRE_EL1)
......
...@@ -236,5 +236,13 @@ exit: ...@@ -236,5 +236,13 @@ exit:
end_afflvl, end_afflvl,
mpidr_nodes); mpidr_nodes);
/*
* Check if all actions needed to safely power down this cpu have
* successfully completed. Enter a wfi loop which will allow the
* power controller to physically power down this cpu.
*/
if (rc == PSCI_E_SUCCESS)
psci_power_down_wfi();
return rc; return rc;
} }
...@@ -257,6 +257,7 @@ void psci_afflvl_suspend(entry_point_info_t *ep, ...@@ -257,6 +257,7 @@ void psci_afflvl_suspend(entry_point_info_t *ep,
int start_afflvl, int start_afflvl,
int end_afflvl) int end_afflvl)
{ {
int skip_wfi = 0;
mpidr_aff_map_nodes_t mpidr_nodes; mpidr_aff_map_nodes_t mpidr_nodes;
unsigned int max_phys_off_afflvl; unsigned int max_phys_off_afflvl;
...@@ -280,6 +281,16 @@ void psci_afflvl_suspend(entry_point_info_t *ep, ...@@ -280,6 +281,16 @@ void psci_afflvl_suspend(entry_point_info_t *ep,
end_afflvl, end_afflvl,
mpidr_nodes); mpidr_nodes);
/*
* We check if there are any pending interrupts after the delay
* introduced by lock contention to increase the chances of early
* detection that a wake-up interrupt has fired.
*/
if (read_isr_el1()) {
skip_wfi = 1;
goto exit;
}
/* /*
* Call the cpu suspend handler registered by the Secure Payload * Call the cpu suspend handler registered by the Secure Payload
* Dispatcher to let it do any bookeeping. If the handler encounters an * Dispatcher to let it do any bookeeping. If the handler encounters an
...@@ -323,6 +334,7 @@ void psci_afflvl_suspend(entry_point_info_t *ep, ...@@ -323,6 +334,7 @@ void psci_afflvl_suspend(entry_point_info_t *ep,
*/ */
psci_set_max_phys_off_afflvl(PSCI_INVALID_DATA); psci_set_max_phys_off_afflvl(PSCI_INVALID_DATA);
exit:
/* /*
* Release the locks corresponding to each affinity level in the * Release the locks corresponding to each affinity level in the
* reverse order to which they were acquired. * reverse order to which they were acquired.
...@@ -330,6 +342,8 @@ void psci_afflvl_suspend(entry_point_info_t *ep, ...@@ -330,6 +342,8 @@ void psci_afflvl_suspend(entry_point_info_t *ep,
psci_release_afflvl_locks(start_afflvl, psci_release_afflvl_locks(start_afflvl,
end_afflvl, end_afflvl,
mpidr_nodes); mpidr_nodes);
if (!skip_wfi)
psci_power_down_wfi();
} }
/******************************************************************************* /*******************************************************************************
......
...@@ -161,8 +161,6 @@ int psci_cpu_suspend(unsigned int power_state, ...@@ -161,8 +161,6 @@ int psci_cpu_suspend(unsigned int power_state,
MPIDR_AFFLVL0, MPIDR_AFFLVL0,
target_afflvl); target_afflvl);
psci_power_down_wfi();
/* Reset PSCI power state parameter for the core. */ /* Reset PSCI power state parameter for the core. */
psci_set_suspend_power_state(PSCI_INVALID_DATA); psci_set_suspend_power_state(PSCI_INVALID_DATA);
return PSCI_E_SUCCESS; return PSCI_E_SUCCESS;
...@@ -181,14 +179,6 @@ int psci_cpu_off(void) ...@@ -181,14 +179,6 @@ int psci_cpu_off(void)
*/ */
rc = psci_afflvl_off(MPIDR_AFFLVL0, target_afflvl); rc = psci_afflvl_off(MPIDR_AFFLVL0, target_afflvl);
/*
* Check if all actions needed to safely power down this cpu have
* successfully completed. Enter a wfi loop which will allow the
* power controller to physically power down this cpu.
*/
if (rc == PSCI_E_SUCCESS)
psci_power_down_wfi();
/* /*
* The only error cpu_off can return is E_DENIED. So check if that's * The only error cpu_off can return is E_DENIED. So check if that's
* indeed the case. * indeed the case.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment