Browse Source

refactor(psci): unify psci_is_last_on_cpu and psci_is_last_on_cpu_safe

"psci_is_last_on_cpu" and "psci_is_last_on_cpu_safe" modules perform
mostly similar functionalities, verifying whether the current CPU
is the only active core and other cores have been turned off.

However, psci_is_last_on_cpu_safe function differs from the other with:
1. Safe API locks the power domain

This patch removes the section duplicating the functionality
and ensures that "psci_is_last_on_cpu api",is reused in
"psci_is_last_on_cpu_safe" procedure.

Signed-off-by: Jayanth Dodderi Chidanand <jayanthdodderi.chidanand@arm.com>
Change-Id: Ie372519e423898d7afa5427cdd77a7f9d3369587
pull/1988/merge
Jayanth Dodderi Chidanand 2 years ago
parent
commit
b41b082464
  1. 61
      lib/psci/psci_common.c
  2. 4
      lib/psci/psci_main.c
  3. 2
      lib/psci/psci_private.h

61
lib/psci/psci_common.c

@ -156,25 +156,26 @@ void psci_query_sys_suspend_pwrstate(psci_power_state_t *state_info)
/*******************************************************************************
* This function verifies that the all the other cores in the system have been
* turned OFF and the current CPU is the last running CPU in the system.
* Returns 1 (true) if the current CPU is the last ON CPU or 0 (false)
* otherwise.
* Returns true, if the current CPU is the last ON CPU or false otherwise.
******************************************************************************/
unsigned int psci_is_last_on_cpu(void)
bool psci_is_last_on_cpu(void)
{
unsigned int cpu_idx, my_idx = plat_my_core_pos();
for (cpu_idx = 0; cpu_idx < psci_plat_core_count;
cpu_idx++) {
for (cpu_idx = 0; cpu_idx < psci_plat_core_count; cpu_idx++) {
if (cpu_idx == my_idx) {
assert(psci_get_aff_info_state() == AFF_STATE_ON);
continue;
}
if (psci_get_aff_info_state_by_idx(cpu_idx) != AFF_STATE_OFF)
return 0;
if (psci_get_aff_info_state_by_idx(cpu_idx) != AFF_STATE_OFF) {
VERBOSE("core=%u other than current core=%u %s\n",
cpu_idx, my_idx, "running in the system");
return false;
}
}
return 1;
return true;
}
/*******************************************************************************
@ -1009,11 +1010,11 @@ int psci_stop_other_cores(unsigned int wait_ms,
/* Need to wait for other cores to shutdown */
if (wait_ms != 0U) {
while ((wait_ms-- != 0U) && (psci_is_last_on_cpu() != 0U)) {
while ((wait_ms-- != 0U) && (!psci_is_last_on_cpu())) {
mdelay(1U);
}
if (psci_is_last_on_cpu() != 0U) {
if (!psci_is_last_on_cpu()) {
WARN("Failed to stop all cores!\n");
psci_print_power_domain_map();
return PSCI_E_DENIED;
@ -1030,48 +1031,22 @@ int psci_stop_other_cores(unsigned int wait_ms,
*
* This API has following differences with psci_is_last_on_cpu
* 1. PSCI states are locked
* 2. It caters for "forest" topology instead of just "tree"
* TODO : Revisit both API's and unify them
******************************************************************************/
bool psci_is_last_on_cpu_safe(void)
{
unsigned int this_core = plat_my_core_pos();
unsigned int parent_nodes[PLAT_MAX_PWR_LVL] = {0};
unsigned int i = 0;
/*
* Traverse the forest of PSCI nodes, nodes with no parents
* (invalid-nodes) are the root nodes.
*/
while ((i < PSCI_NUM_NON_CPU_PWR_DOMAINS) &&
(psci_non_cpu_pd_nodes[i].parent_node ==
PSCI_PARENT_NODE_INVALID)) {
psci_get_parent_pwr_domain_nodes(
psci_non_cpu_pd_nodes[i].cpu_start_idx,
PLAT_MAX_PWR_LVL, parent_nodes);
psci_acquire_pwr_domain_locks(PLAT_MAX_PWR_LVL, parent_nodes);
for (unsigned int core = 0U;
core < psci_non_cpu_pd_nodes[i].ncpus; core++) {
if (core == this_core) {
continue;
}
if (psci_get_aff_info_state_by_idx(core) !=
AFF_STATE_OFF) {
psci_release_pwr_domain_locks(PLAT_MAX_PWR_LVL,
parent_nodes);
VERBOSE("core=%u other than boot core=%u %s\n",
core, this_core, "running in the system");
return false;
}
}
psci_get_parent_pwr_domain_nodes(this_core, PLAT_MAX_PWR_LVL, parent_nodes);
psci_acquire_pwr_domain_locks(PLAT_MAX_PWR_LVL, parent_nodes);
if (!psci_is_last_on_cpu()) {
psci_release_pwr_domain_locks(PLAT_MAX_PWR_LVL, parent_nodes);
i++;
return false;
}
psci_release_pwr_domain_locks(PLAT_MAX_PWR_LVL, parent_nodes);
return true;
}

4
lib/psci/psci_main.c

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2013-2022, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@ -158,7 +158,7 @@ int psci_system_suspend(uintptr_t entrypoint, u_register_t context_id)
entry_point_info_t ep;
/* Check if the current CPU is the last ON CPU in the system */
if (psci_is_last_on_cpu() == 0U)
if (!psci_is_last_on_cpu())
return PSCI_E_DENIED;
/* Validate the entry point and get the entry_point_info */

2
lib/psci/psci_private.h

@ -294,7 +294,7 @@ unsigned int psci_find_max_off_lvl(const psci_power_state_t *state_info);
unsigned int psci_find_target_suspend_lvl(const psci_power_state_t *state_info);
void psci_set_pwr_domains_to_run(unsigned int end_pwrlvl);
void psci_print_power_domain_map(void);
unsigned int psci_is_last_on_cpu(void);
bool psci_is_last_on_cpu(void);
int psci_spd_migrate_info(u_register_t *mpidr);
/*

Loading…
Cancel
Save