diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2017-12-17 20:15:32 -0500 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2017-12-18 06:09:39 -0500 |
commit | 56026645e2b6f11ede34a5e6ab69d3eb56f9c8fc (patch) | |
tree | 4cf4a458d91fe51a6a2d41b05354776bdb0e0933 | |
parent | ccc153a6de1f7741b5ef7c996f9be133772b2092 (diff) |
cpufreq: governor: Ensure sufficiently large sampling intervals
After commit aa7519af450d (cpufreq: Use transition_delay_us for legacy
governors as well) the sampling_rate field of struct dbs_data may be
less than the tick period which causes dbs_update() to produce
incorrect results, so make the code ensure that the value of that
field will always be sufficiently large.
Fixes: aa7519af450d (cpufreq: Use transition_delay_us for legacy governors as well)
Reported-by: Andy Tang <andy.tang@nxp.com>
Reported-by: Doug Smythies <dsmythies@telus.net>
Tested-by: Andy Tang <andy.tang@nxp.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
-rw-r--r-- | drivers/cpufreq/cpufreq_governor.c | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c index 58d4f4e1ad6a..ca38229b045a 100644 --- a/drivers/cpufreq/cpufreq_governor.c +++ b/drivers/cpufreq/cpufreq_governor.c | |||
@@ -22,6 +22,8 @@ | |||
22 | 22 | ||
23 | #include "cpufreq_governor.h" | 23 | #include "cpufreq_governor.h" |
24 | 24 | ||
25 | #define CPUFREQ_DBS_MIN_SAMPLING_INTERVAL (2 * TICK_NSEC / NSEC_PER_USEC) | ||
26 | |||
25 | static DEFINE_PER_CPU(struct cpu_dbs_info, cpu_dbs); | 27 | static DEFINE_PER_CPU(struct cpu_dbs_info, cpu_dbs); |
26 | 28 | ||
27 | static DEFINE_MUTEX(gov_dbs_data_mutex); | 29 | static DEFINE_MUTEX(gov_dbs_data_mutex); |
@@ -47,11 +49,15 @@ ssize_t store_sampling_rate(struct gov_attr_set *attr_set, const char *buf, | |||
47 | { | 49 | { |
48 | struct dbs_data *dbs_data = to_dbs_data(attr_set); | 50 | struct dbs_data *dbs_data = to_dbs_data(attr_set); |
49 | struct policy_dbs_info *policy_dbs; | 51 | struct policy_dbs_info *policy_dbs; |
52 | unsigned int sampling_interval; | ||
50 | int ret; | 53 | int ret; |
51 | ret = sscanf(buf, "%u", &dbs_data->sampling_rate); | 54 | |
52 | if (ret != 1) | 55 | ret = sscanf(buf, "%u", &sampling_interval); |
56 | if (ret != 1 || sampling_interval < CPUFREQ_DBS_MIN_SAMPLING_INTERVAL) | ||
53 | return -EINVAL; | 57 | return -EINVAL; |
54 | 58 | ||
59 | dbs_data->sampling_rate = sampling_interval; | ||
60 | |||
55 | /* | 61 | /* |
56 | * We are operating under dbs_data->mutex and so the list and its | 62 | * We are operating under dbs_data->mutex and so the list and its |
57 | * entries can't be freed concurrently. | 63 | * entries can't be freed concurrently. |
@@ -430,7 +436,14 @@ int cpufreq_dbs_governor_init(struct cpufreq_policy *policy) | |||
430 | if (ret) | 436 | if (ret) |
431 | goto free_policy_dbs_info; | 437 | goto free_policy_dbs_info; |
432 | 438 | ||
433 | dbs_data->sampling_rate = cpufreq_policy_transition_delay_us(policy); | 439 | /* |
440 | * The sampling interval should not be less than the transition latency | ||
441 | * of the CPU and it also cannot be too small for dbs_update() to work | ||
442 | * correctly. | ||
443 | */ | ||
444 | dbs_data->sampling_rate = max_t(unsigned int, | ||
445 | CPUFREQ_DBS_MIN_SAMPLING_INTERVAL, | ||
446 | cpufreq_policy_transition_delay_us(policy)); | ||
434 | 447 | ||
435 | if (!have_governor_per_policy()) | 448 | if (!have_governor_per_policy()) |
436 | gov->gdbs_data = dbs_data; | 449 | gov->gdbs_data = dbs_data; |