aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cpufreq/cppc_cpufreq.c
diff options
context:
space:
mode:
authorPrashanth Prakash <pprakash@codeaurora.org>2018-04-27 13:35:27 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2018-04-30 04:14:08 -0400
commitd4f3388afd488ed15368fa7413b8bd6d1f98bb1d (patch)
tree56ff9c746d4c2b75502d000204f4c20d6fafc78e /drivers/cpufreq/cppc_cpufreq.c
parent6da6c0db5316275015e8cc2959f12a17584aeb64 (diff)
cpufreq / CPPC: Set platform specific transition_delay_us
Add support to specify platform specific transition_delay_us instead of using the transition delay derived from PCC. With commit 3d41386d556d (cpufreq: CPPC: Use transition_delay_us depending transition_latency) we are setting transition_delay_us directly and not applying the LATENCY_MULTIPLIER. Because of that, on Qualcomm Centriq we can end up with a very high rate of frequency change requests when using the schedutil governor (default rate_limit_us=10 compared to an earlier value of 10000). The PCC subspace describes the rate at which the platform can accept commands on the CPPC's PCC channel. This includes read and write command on the PCC channel that can be used for reasons other than frequency transitions. Moreover the same PCC subspace can be used by multiple freq domains and deriving transition_delay_us from it as we do now can be sub-optimal. Moreover if a platform does not use PCC for desired_perf register then there is no way to compute the transition latency or the delay_us. CPPC does not have a standard defined mechanism to get the transition rate or the latency at the moment. Given the above limitations, it is simpler to have a platform specific transition_delay_us and rely on PCC derived value only if a platform specific value is not available. Signed-off-by: Prashanth Prakash <pprakash@codeaurora.org> Cc: 4.14+ <stable@vger.kernel.org> # 4.14+ Fixes: 3d41386d556d (cpufreq: CPPC: Use transition_delay_us depending transition_latency) Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/cpufreq/cppc_cpufreq.c')
-rw-r--r--drivers/cpufreq/cppc_cpufreq.c46
1 files changed, 44 insertions, 2 deletions
diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c
index bc5fc1630876..b15115a48775 100644
--- a/drivers/cpufreq/cppc_cpufreq.c
+++ b/drivers/cpufreq/cppc_cpufreq.c
@@ -126,6 +126,49 @@ static void cppc_cpufreq_stop_cpu(struct cpufreq_policy *policy)
126 cpu->perf_caps.lowest_perf, cpu_num, ret); 126 cpu->perf_caps.lowest_perf, cpu_num, ret);
127} 127}
128 128
129/*
130 * The PCC subspace describes the rate at which platform can accept commands
131 * on the shared PCC channel (including READs which do not count towards freq
132 * trasition requests), so ideally we need to use the PCC values as a fallback
133 * if we don't have a platform specific transition_delay_us
134 */
135#ifdef CONFIG_ARM64
136#include <asm/cputype.h>
137
138static unsigned int cppc_cpufreq_get_transition_delay_us(int cpu)
139{
140 unsigned long implementor = read_cpuid_implementor();
141 unsigned long part_num = read_cpuid_part_number();
142 unsigned int delay_us = 0;
143
144 switch (implementor) {
145 case ARM_CPU_IMP_QCOM:
146 switch (part_num) {
147 case QCOM_CPU_PART_FALKOR_V1:
148 case QCOM_CPU_PART_FALKOR:
149 delay_us = 10000;
150 break;
151 default:
152 delay_us = cppc_get_transition_latency(cpu) / NSEC_PER_USEC;
153 break;
154 }
155 break;
156 default:
157 delay_us = cppc_get_transition_latency(cpu) / NSEC_PER_USEC;
158 break;
159 }
160
161 return delay_us;
162}
163
164#else
165
166static unsigned int cppc_cpufreq_get_transition_delay_us(int cpu)
167{
168 return cppc_get_transition_latency(cpu) / NSEC_PER_USEC;
169}
170#endif
171
129static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy) 172static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy)
130{ 173{
131 struct cppc_cpudata *cpu; 174 struct cppc_cpudata *cpu;
@@ -162,8 +205,7 @@ static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy)
162 cpu->perf_caps.highest_perf; 205 cpu->perf_caps.highest_perf;
163 policy->cpuinfo.max_freq = cppc_dmi_max_khz; 206 policy->cpuinfo.max_freq = cppc_dmi_max_khz;
164 207
165 policy->transition_delay_us = cppc_get_transition_latency(cpu_num) / 208 policy->transition_delay_us = cppc_cpufreq_get_transition_delay_us(cpu_num);
166 NSEC_PER_USEC;
167 policy->shared_type = cpu->shared_type; 209 policy->shared_type = cpu->shared_type;
168 210
169 if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) { 211 if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) {