Fix use of stale power states in PSCI standby finisher

A PSCI CPU_SUSPEND request to place a CPU in retention states at power levels
higher than the CPU power level is subject to the same state coordination as a
power down state. A CPU could implement multiple retention states at a
particular power level. When exiting WFI, the non-CPU power levels may be in a
different retention state to what was initially requested, therefore each CPU
should refresh its view of the states of all power levels.

Previously, a CPU re-used the state of the power levels when it entered the
retention state. This patch fixes this issue by ensuring that a CPU upon exit
from retention reads the state of each power level afresh.

Change-Id: I93b5f5065c63400c6fd2598dbaafac385748f989
diff --git a/lib/psci/psci_suspend.c b/lib/psci/psci_suspend.c
index 904a4e7..0887e3b 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 @@
 	 * 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);
 }
 
 /*******************************************************************************