summaryrefslogtreecommitdiff
path: root/lib/power_management/hotplug
diff options
context:
space:
mode:
authorVikram Kanigiri <vikram.kanigiri@arm.com>2015-08-13 11:45:25 +0100
committerSandrine Bailleux <sandrine.bailleux@arm.com>2015-08-26 09:23:25 +0100
commitfa26eb13138dea72c7f3ea01e4288c6782993d6e (patch)
treec2cb5c9370634ea0251c9b633656f7b6120c3375 /lib/power_management/hotplug
parent76ab6999e95320c523da7ed397e8861619509f4c (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.c68
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);