>From 95d830ad8765d6c35fb9e91d5028bf3cf1ff2451 Mon Sep 17 00:00:00 2001 Message-Id: <95d830ad8765d6c35fb9e91d5028bf3cf1ff2451.1501049147.git.viresh.kumar@linaro.org> From: Viresh Kumar Date: Fri, 2 Jun 2017 15:00:58 +0530 Subject: [PATCH] cpufreq: Find transition latency dynamically Test patch to find latency dynamically. Signed-off-by: Viresh Kumar --- drivers/cpufreq/cpufreq.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 0d6fbb3099b4..e62d670dffd2 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1076,6 +1076,62 @@ __weak struct cpufreq_governor *cpufreq_default_governor(void) return NULL; } +static int find_dvfs_latency(struct cpufreq_policy *policy, unsigned long freq, + unsigned int *latency_ns) +{ + u64 time; + int ret; + + time = local_clock(); + ret = __cpufreq_driver_target(policy, freq, CPUFREQ_RELATION_L); + *latency_ns = local_clock() - time; + + return ret; +} + +/* + * Find the transition latency dynamically by: + * - Switching to min freq first. + * - Then switching to max freq. + * - And finally switching back to the initial freq. + * + * The maximum duration of the above three freq changes should be good enough to + * find the maximum transition latency for a platform. + */ +static void cpufreq_find_target_latency(struct cpufreq_policy *policy) +{ + unsigned long initial_freq = policy->cur; + unsigned int latency_ns, latency_max_ns; + int ret; + + if (!has_target()) + return; + + /* Go to min frequency first */ + ret = find_dvfs_latency(policy, policy->cpuinfo.min_freq, &latency_ns); + if (ret) + return; + + latency_max_ns = latency_ns; + + /* Go to max frequency then.. */ + ret = find_dvfs_latency(policy, policy->cpuinfo.max_freq, &latency_ns); + if (ret) + return; + + latency_max_ns = max(latency_max_ns, latency_ns); + + /* And finally switch back to where we started from */ + ret = find_dvfs_latency(policy, initial_freq, &latency_ns); + if (ret) + return; + + policy->cpuinfo.transition_latency = max(latency_max_ns, latency_ns); + + pr_info("%s: Setting transition latency to %u ns for policy of CPU%d\n", + __func__, policy->cpuinfo.transition_latency, policy->cpu); +} + static int cpufreq_init_policy(struct cpufreq_policy *policy) { struct cpufreq_governor *gov = NULL; @@ -1345,6 +1401,8 @@ static int cpufreq_online(unsigned int cpu) } if (new_policy) { + cpufreq_find_target_latency(policy); + ret = cpufreq_add_dev_interface(policy); if (ret) goto out_exit_policy; -- 2.13.0.71.gd7076ec9c9cb