Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

cpufreq: qcom-cpufreq-hw: Use new thermal pressure update function

Thermal pressure provides a new API, which allows to use CPU frequency
as an argument. That removes the need of local conversion to capacity.
Use this new API and remove old local conversion code.

The new arch_update_thermal_pressure() also accepts boost frequencies,
which solves issue in the driver code with wrong reduced capacity
calculation. The reduced capacity was calculated wrongly due to
'policy->cpuinfo.max_freq' used as a divider. The value present there was
actually the boost frequency. Thus, even a normal maximum frequency value
which corresponds to max CPU capacity (arch_scale_cpu_capacity(cpu_id))
is not able to remove the capping.

The second side effect which is solved is that the reduced frequency wasn't
properly translated into the right reduced capacity,
e.g.
boost frequency = 3000MHz (stored in policy->cpuinfo.max_freq)
max normal frequency = 2500MHz (which is 1024 capacity)
2nd highest frequency = 2000MHz (which translates to 819 capacity)

Then in a scenario when the 'throttled_freq' max allowed frequency was
2000MHz the driver translated it into 682 capacity:
capacity = 1024 * 2000 / 3000 = 682
Then set the pressure value bigger than actually applied by the HW:
max_capacity - capacity => 1024 - 682 = 342 (<- thermal pressure)
Which was causing higher throttling and misleading task scheduler
about available CPU capacity.
A proper calculation in such case should be:
capacity = 1024 * 2000 / 2500 = 819
1024 - 819 = 205 (<- thermal pressure)

This patch relies on the new arch_update_thermal_pressure() handling
correctly such use case (with boost frequencies).

Signed-off-by: Lukasz Luba <lukasz.luba@arm.com>
Reviewed-by: Thara Gopinath <thara.gopinath@linaro.org>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>

authored by

Lukasz Luba and committed by
Viresh Kumar
0258cb19 93d9e6f9

+3 -12
+3 -12
drivers/cpufreq/qcom-cpufreq-hw.c
··· 275 275 276 276 static void qcom_lmh_dcvs_notify(struct qcom_cpufreq_data *data) 277 277 { 278 - unsigned long max_capacity, capacity, freq_hz, throttled_freq; 279 278 struct cpufreq_policy *policy = data->policy; 280 279 int cpu = cpumask_first(policy->cpus); 281 280 struct device *dev = get_cpu_device(cpu); 281 + unsigned long freq_hz, throttled_freq; 282 282 struct dev_pm_opp *opp; 283 283 unsigned int freq; 284 284 ··· 295 295 296 296 throttled_freq = freq_hz / HZ_PER_KHZ; 297 297 298 - /* Update thermal pressure */ 299 - 300 - max_capacity = arch_scale_cpu_capacity(cpu); 301 - capacity = mult_frac(max_capacity, throttled_freq, policy->cpuinfo.max_freq); 302 - 303 - /* Don't pass boost capacity to scheduler */ 304 - if (capacity > max_capacity) 305 - capacity = max_capacity; 306 - 307 - arch_set_thermal_pressure(policy->related_cpus, 308 - max_capacity - capacity); 298 + /* Update thermal pressure (the boost frequencies are accepted) */ 299 + arch_update_thermal_pressure(policy->related_cpus, throttled_freq); 309 300 310 301 /* 311 302 * In the unlikely case policy is unregistered do not enable