[PATCH] cpufreq: Find transition latency dynamically

From: Viresh Kumar
Date: Fri Jun 02 2017 - 05:30:58 EST


Test patch to find latency dynamically.

Signed-off-by: Viresh Kumar <viresh.kumar@xxxxxxxxxx>
---
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


--EVF5PPMfhYS0aIcm--