aboutsummaryrefslogtreecommitdiffstats
path: root/lib/psci/psci_off.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/psci/psci_off.c')
-rw-r--r--lib/psci/psci_off.c14
1 files changed, 12 insertions, 2 deletions
diff --git a/lib/psci/psci_off.c b/lib/psci/psci_off.c
index ac03e0596..e8cd8feb0 100644
--- a/lib/psci/psci_off.c
+++ b/lib/psci/psci_off.c
@@ -45,6 +45,7 @@ int psci_do_cpu_off(unsigned int end_pwrlvl)
int rc = PSCI_E_SUCCESS;
int idx = (int) plat_my_core_pos();
psci_power_state_t state_info;
+ unsigned int parent_nodes[PLAT_MAX_PWR_LVL] = {0};
/*
* This function must only be called on platforms where the
@@ -56,11 +57,20 @@ int psci_do_cpu_off(unsigned int end_pwrlvl)
psci_set_power_off_state(&state_info);
/*
+ * Get the parent nodes here, this is important to do before we
+ * initiate the power down sequence as after that point the core may
+ * have exited coherency and its cache may be disabled, any access to
+ * shared memory after that (such as the parent node lookup in
+ * psci_cpu_pd_nodes) can cause coherency issues on some platforms.
+ */
+ psci_get_parent_pwr_domain_nodes(idx, end_pwrlvl, parent_nodes);
+
+ /*
* This function acquires the lock corresponding to each power
* level so that by the time all locks are taken, the system topology
* is snapshot and state management can be done safely.
*/
- psci_acquire_pwr_domain_locks(end_pwrlvl, idx);
+ psci_acquire_pwr_domain_locks(end_pwrlvl, parent_nodes);
/*
* Call the cpu off handler registered by the Secure Payload Dispatcher
@@ -122,7 +132,7 @@ exit:
* Release the locks corresponding to each power level in the
* reverse order to which they were acquired.
*/
- psci_release_pwr_domain_locks(end_pwrlvl, idx);
+ psci_release_pwr_domain_locks(end_pwrlvl, parent_nodes);
/*
* Check if all actions needed to safely power down this cpu have