/******************************************************************************* * This function is passed a cpu_index and the highest level in the topology * tree that the operation should be applied to. It releases the locks in order * of decreasing power domain level in the range specified. ******************************************************************************/ void psci_release_pwr_domain_locks(unsigned int end_pwrlvl, unsigned int cpu_idx) { unsigned int parent_idx, parent_nodes[PLAT_MAX_PWR_LVL] = {0}; int level; /* Get the parent nodes */ psci_get_parent_pwr_domain_nodes(cpu_idx, end_pwrlvl, parent_nodes); /* Unlock top down. No unlocking required for level 0. */ for (level = end_pwrlvl; level >= PSCI_CPU_PWR_LVL + 1; level--) { parent_idx = parent_nodes[level - 1]; psci_lock_release(&psci_non_cpu_pd_nodes[parent_idx]); } }
/******************************************************************************* * This functions updates cpu_start_idx and ncpus field for each of the node in * psci_non_cpu_pd_nodes[]. It does so by comparing the parent nodes of each of * the CPUs and check whether they match with the parent of the previous * CPU. The basic assumption for this work is that children of the same parent * are allocated adjacent indices. The platform should ensure this though proper * mapping of the CPUs to indices via plat_core_pos_by_mpidr() and * plat_my_core_pos() APIs. *******************************************************************************/ static void __init psci_update_pwrlvl_limits(void) { int j, cpu_idx; unsigned int nodes_idx[PLAT_MAX_PWR_LVL] = {0}; unsigned int temp_index[PLAT_MAX_PWR_LVL]; for (cpu_idx = 0; cpu_idx < PLATFORM_CORE_COUNT; cpu_idx++) { psci_get_parent_pwr_domain_nodes(cpu_idx, (unsigned int)PLAT_MAX_PWR_LVL, temp_index); for (j = (int) PLAT_MAX_PWR_LVL - 1; j >= 0; j--) { if (temp_index[j] != nodes_idx[j]) { nodes_idx[j] = temp_index[j]; psci_non_cpu_pd_nodes[nodes_idx[j]].cpu_start_idx = cpu_idx; } psci_non_cpu_pd_nodes[nodes_idx[j]].ncpus++; } } }