diff options
author | Vikram Kanigiri <vikram.kanigiri@arm.com> | 2015-08-13 11:45:25 +0100 |
---|---|---|
committer | Sandrine Bailleux <sandrine.bailleux@arm.com> | 2015-08-26 09:23:25 +0100 |
commit | fa26eb13138dea72c7f3ea01e4288c6782993d6e (patch) | |
tree | c2cb5c9370634ea0251c9b633656f7b6120c3375 /lib/power_management/hotplug | |
parent | 76ab6999e95320c523da7ed397e8861619509f4c (diff) |
Add a simple CPU_ON API in framework
Currently, tftf_cpu_on() has the capability to handle the race
conditions arising due to powering off and powering on a CPU
between different tests. This capability stops the testcases
from seeing the real return value provided by EL3 firmware
and validating the firmware against the race conditions.
Hence, this patch provides a new API tftf_try_cpu_on() which
just does the CPU_ON call and passes the return value to the
test case.
It also adds and calls a new api tftf_init_cpus_status_map(), for
initialising the CPUs status map which sets the primary CPU as online.
Additionally, it also detects spurious wakeups in tftf_set_cpu_online()
by explicitly checking CPU is powered up by a CPU_ON call which means
CPU status should be ON_PENDING.
Change-Id: I571bbb7e8173764e1d35d4b625e3691f6e9faf2f
Diffstat (limited to 'lib/power_management/hotplug')
-rw-r--r-- | lib/power_management/hotplug/hotplug.c | 68 |
1 files changed, 60 insertions, 8 deletions
diff --git a/lib/power_management/hotplug/hotplug.c b/lib/power_management/hotplug/hotplug.c index 7bc4420..a855174 100644 --- a/lib/power_management/hotplug/hotplug.c +++ b/lib/power_management/hotplug/hotplug.c @@ -54,6 +54,7 @@ * as OFF. */ static tftf_cpu_state_t cpus_status_map[PLATFORM_CORE_COUNT]; +static int cpus_status_init_done; /* * Reference count keeping track of the number of CPUs participating in @@ -100,13 +101,32 @@ unsigned int tftf_get_ref_cnt(void) return ACCESS(ref_cnt); } +void tftf_init_cpus_status_map(void) +{ + unsigned int mpid = read_mpidr_el1(); + unsigned int core_pos = platform_get_core_pos(mpid); + + /* Check only primary does the initialisation */ + assert ((mpid & MPID_MASK) == platform_get_primary_core_mpid()); + /* Check init is done only once */ + assert(!cpus_status_init_done); + + cpus_status_init_done = 1; + + /* + * cpus_status_map already initialised to zero as part of BSS init, + * just set the primary to ON state + */ + cpus_status_map[core_pos].state = TFTF_AFFINITY_STATE_ON; +} + void tftf_set_cpu_online(void) { unsigned int mpid = read_mpidr_el1(); unsigned int core_pos = platform_get_core_pos(mpid); spin_lock(&cpus_status_map[core_pos].lock); - assert(!tftf_is_cpu_online(mpid)); + assert(cpus_status_map[core_pos].state == TFTF_AFFINITY_STATE_ON_PENDING); cpus_status_map[core_pos].state = TFTF_AFFINITY_STATE_ON; spin_unlock(&cpus_status_map[core_pos].lock); } @@ -152,13 +172,6 @@ int32_t tftf_cpu_on(uint64_t target_cpu, assert(cpu_state == TFTF_AFFINITY_STATE_OFF); - /* - * Populate the test entry point for this core. - * This is the address where the core will jump to once the framework - * has finished initialising it. - */ - test_entrypoint[core_pos] = (test_function_t) entrypoint; - do { ret = tftf_psci_cpu_on(target_cpu, (uint64_t) tftf_hotplug_entry, @@ -169,7 +182,46 @@ int32_t tftf_cpu_on(uint64_t target_cpu, } while (ret == PSCI_E_ALREADY_ON); if (ret == PSCI_E_SUCCESS) { + /* + * Populate the test entry point for this core. + * This is the address where the core will jump to once the framework + * has finished initialising it. + */ + test_entrypoint[core_pos] = (test_function_t) entrypoint; + + cpus_status_map[core_pos].state = TFTF_AFFINITY_STATE_ON_PENDING; + spin_unlock(&cpus_status_map[core_pos].lock); + } else { + spin_unlock(&cpus_status_map[core_pos].lock); + ERROR("Failed to boot CPU 0x%lx (%d)\n", target_cpu, ret); + } + + return ret; +} + +int32_t tftf_try_cpu_on(uint64_t target_cpu, + uint64_t entrypoint, + uint64_t context_id) +{ + int32_t ret; + unsigned int core_pos = platform_get_core_pos(target_cpu); + + spin_lock(&cpus_status_map[core_pos].lock); + + ret = tftf_psci_cpu_on(target_cpu, + (uint64_t) tftf_hotplug_entry, + context_id); + + if (ret == PSCI_E_SUCCESS) { + assert(cpus_status_map[core_pos].state == TFTF_AFFINITY_STATE_OFF); cpus_status_map[core_pos].state = TFTF_AFFINITY_STATE_ON_PENDING; + + /* + * Populate the test entry point for this core. + * This is the address where the core will jump to once the framework + * has finished initialising it. + */ + test_entrypoint[core_pos] = (test_function_t) entrypoint; spin_unlock(&cpus_status_map[core_pos].lock); } else { spin_unlock(&cpus_status_map[core_pos].lock); |