diff options
author | danh-arm <dan.handley@arm.com> | 2016-07-26 14:35:07 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-07-26 14:35:07 +0100 |
commit | 422a40d9c6be03ed3508f0dd17a04227abcb70ce (patch) | |
tree | 6e745772276ccde6000ab1058e6abde6304b3e1a /lib/psci | |
parent | fabd0a864a09ab6024db2cac0a4929b443a72640 (diff) | |
parent | 61eae524b6e452fd1be931c6e1ff8f7cf3ae969c (diff) | |
download | arm-trusted-firmware-422a40d9c6be03ed3508f0dd17a04227abcb70ce.tar.gz |
Merge pull request #670 from achingupta/ag/psci_retention_fix
Fix use of stale power states in PSCI standby finisher
Diffstat (limited to 'lib/psci')
-rw-r--r-- | lib/psci/psci_common.c | 4 | ||||
-rw-r--r-- | lib/psci/psci_private.h | 2 | ||||
-rw-r--r-- | lib/psci/psci_suspend.c | 14 |
3 files changed, 15 insertions, 5 deletions
diff --git a/lib/psci/psci_common.c b/lib/psci/psci_common.c index c6fea5b04..e87e8c054 100644 --- a/lib/psci/psci_common.c +++ b/lib/psci/psci_common.c @@ -252,8 +252,8 @@ static plat_local_state_t *psci_get_req_local_pwr_states(unsigned int pwrlvl, * function will be called after a cpu is powered on to find the local state * each power domain has emerged from. *****************************************************************************/ -static void psci_get_target_local_pwr_states(unsigned int end_pwrlvl, - psci_power_state_t *target_state) +void psci_get_target_local_pwr_states(unsigned int end_pwrlvl, + psci_power_state_t *target_state) { unsigned int parent_idx, lvl; plat_local_state_t *pd_state = target_state->pwr_domain_state; diff --git a/lib/psci/psci_private.h b/lib/psci/psci_private.h index 493521443..b795c8e03 100644 --- a/lib/psci/psci_private.h +++ b/lib/psci/psci_private.h @@ -192,6 +192,8 @@ int psci_validate_power_state(unsigned int power_state, void psci_query_sys_suspend_pwrstate(psci_power_state_t *state_info); int psci_validate_mpidr(u_register_t mpidr); void psci_init_req_local_pwr_states(void); +void psci_get_target_local_pwr_states(unsigned int end_pwrlvl, + psci_power_state_t *target_state); int psci_validate_entry_point(entry_point_info_t *ep, uintptr_t entrypoint, u_register_t context_id); void psci_get_parent_pwr_domain_nodes(unsigned int cpu_idx, diff --git a/lib/psci/psci_suspend.c b/lib/psci/psci_suspend.c index 904a4e758..0887e3b2d 100644 --- a/lib/psci/psci_suspend.c +++ b/lib/psci/psci_suspend.c @@ -45,17 +45,25 @@ * from standby/retention states at multiple power levels. ******************************************************************************/ static void psci_suspend_to_standby_finisher(unsigned int cpu_idx, - psci_power_state_t *state_info, unsigned int end_pwrlvl) { + psci_power_state_t state_info; + psci_acquire_pwr_domain_locks(end_pwrlvl, cpu_idx); /* + * Find out which retention states this CPU has exited from until the + * 'end_pwrlvl'. The exit retention state could be deeper than the entry + * state as a result of state coordination amongst other CPUs post wfi. + */ + psci_get_target_local_pwr_states(end_pwrlvl, &state_info); + + /* * Plat. management: Allow the platform to do operations * on waking up from retention. */ - psci_plat_pm_ops->pwr_domain_suspend_finish(state_info); + psci_plat_pm_ops->pwr_domain_suspend_finish(&state_info); /* * Set the requested and target state of this CPU and all the higher @@ -222,7 +230,7 @@ exit: * After we wake up from context retaining suspend, call the * context retaining suspend finisher. */ - psci_suspend_to_standby_finisher(idx, state_info, end_pwrlvl); + psci_suspend_to_standby_finisher(idx, end_pwrlvl); } /******************************************************************************* |