summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authordanh-arm <dan.handley@arm.com>2016-07-26 14:35:07 +0100
committerGitHub <noreply@github.com>2016-07-26 14:35:07 +0100
commit422a40d9c6be03ed3508f0dd17a04227abcb70ce (patch)
tree6e745772276ccde6000ab1058e6abde6304b3e1a /lib
parentfabd0a864a09ab6024db2cac0a4929b443a72640 (diff)
parent61eae524b6e452fd1be931c6e1ff8f7cf3ae969c (diff)
Merge pull request #670 from achingupta/ag/psci_retention_fix
Fix use of stale power states in PSCI standby finisher
Diffstat (limited to 'lib')
-rw-r--r--lib/psci/psci_common.c4
-rw-r--r--lib/psci/psci_private.h2
-rw-r--r--lib/psci/psci_suspend.c14
3 files changed, 15 insertions, 5 deletions
diff --git a/lib/psci/psci_common.c b/lib/psci/psci_common.c
index c6fea5b0..e87e8c05 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 49352144..b795c8e0 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 904a4e75..0887e3b2 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);
}
/*******************************************************************************