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
This commit is contained in:
parent
539dcedb7d
commit
22f08973f3
|
@ -270,6 +270,8 @@ DEFINE_SYSREG_RW_FUNCS(cntvoff_el2)
|
|||
DEFINE_SYSREG_RW_FUNCS(vpidr_el2)
|
||||
DEFINE_SYSREG_RW_FUNCS(vmpidr_el2)
|
||||
|
||||
DEFINE_SYSREG_READ_FUNC(isr_el1)
|
||||
|
||||
/* GICv3 System Registers */
|
||||
|
||||
DEFINE_RENAME_SYSREG_RW_FUNCS(icc_sre_el1, ICC_SRE_EL1)
|
||||
|
|
|
@ -236,5 +236,13 @@ exit:
|
|||
end_afflvl,
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -257,6 +257,7 @@ void psci_afflvl_suspend(entry_point_info_t *ep,
|
|||
int start_afflvl,
|
||||
int end_afflvl)
|
||||
{
|
||||
int skip_wfi = 0;
|
||||
mpidr_aff_map_nodes_t mpidr_nodes;
|
||||
unsigned int max_phys_off_afflvl;
|
||||
|
||||
|
@ -280,6 +281,16 @@ void psci_afflvl_suspend(entry_point_info_t *ep,
|
|||
end_afflvl,
|
||||
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
|
||||
* 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,
|
|||
*/
|
||||
psci_set_max_phys_off_afflvl(PSCI_INVALID_DATA);
|
||||
|
||||
exit:
|
||||
/*
|
||||
* Release the locks corresponding to each affinity level in the
|
||||
* reverse order to which they were acquired.
|
||||
|
@ -330,6 +342,8 @@ void psci_afflvl_suspend(entry_point_info_t *ep,
|
|||
psci_release_afflvl_locks(start_afflvl,
|
||||
end_afflvl,
|
||||
mpidr_nodes);
|
||||
if (!skip_wfi)
|
||||
psci_power_down_wfi();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
|
|
@ -161,8 +161,6 @@ int psci_cpu_suspend(unsigned int power_state,
|
|||
MPIDR_AFFLVL0,
|
||||
target_afflvl);
|
||||
|
||||
psci_power_down_wfi();
|
||||
|
||||
/* Reset PSCI power state parameter for the core. */
|
||||
psci_set_suspend_power_state(PSCI_INVALID_DATA);
|
||||
return PSCI_E_SUCCESS;
|
||||
|
@ -181,14 +179,6 @@ int psci_cpu_off(void)
|
|||
*/
|
||||
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
|
||||
* indeed the case.
|
||||
|
|
Loading…
Reference in New Issue