diff options
Diffstat (limited to 'lib/psci/psci_off.c')
-rw-r--r-- | lib/psci/psci_off.c | 14 |
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 |