Skip to content

Commit

Permalink
cpufreq: governor: Ensure sufficiently large sampling intervals
Browse files Browse the repository at this point in the history
After commit aa7519a (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: aa7519a (cpufreq: Use transition_delay_us for legacy governors as well)
Reported-by: Andy Tang <[email protected]>
Reported-by: Doug Smythies <[email protected]>
Tested-by: Andy Tang <[email protected]>
Signed-off-by: Rafael J. Wysocki <[email protected]>
Acked-by: Viresh Kumar <[email protected]>
  • Loading branch information
rafaeljw committed Dec 18, 2017
1 parent ccc153a commit 5602664
Showing 1 changed file with 16 additions and 3 deletions.
19 changes: 16 additions & 3 deletions drivers/cpufreq/cpufreq_governor.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@

#include "cpufreq_governor.h"

#define CPUFREQ_DBS_MIN_SAMPLING_INTERVAL (2 * TICK_NSEC / NSEC_PER_USEC)

static DEFINE_PER_CPU(struct cpu_dbs_info, cpu_dbs);

static DEFINE_MUTEX(gov_dbs_data_mutex);
Expand All @@ -47,11 +49,15 @@ ssize_t store_sampling_rate(struct gov_attr_set *attr_set, const char *buf,
{
struct dbs_data *dbs_data = to_dbs_data(attr_set);
struct policy_dbs_info *policy_dbs;
unsigned int sampling_interval;
int ret;
ret = sscanf(buf, "%u", &dbs_data->sampling_rate);
if (ret != 1)

ret = sscanf(buf, "%u", &sampling_interval);
if (ret != 1 || sampling_interval < CPUFREQ_DBS_MIN_SAMPLING_INTERVAL)
return -EINVAL;

dbs_data->sampling_rate = sampling_interval;

/*
* We are operating under dbs_data->mutex and so the list and its
* entries can't be freed concurrently.
Expand Down Expand Up @@ -430,7 +436,14 @@ int cpufreq_dbs_governor_init(struct cpufreq_policy *policy)
if (ret)
goto free_policy_dbs_info;

dbs_data->sampling_rate = cpufreq_policy_transition_delay_us(policy);
/*
* The sampling interval should not be less than the transition latency
* of the CPU and it also cannot be too small for dbs_update() to work
* correctly.
*/
dbs_data->sampling_rate = max_t(unsigned int,
CPUFREQ_DBS_MIN_SAMPLING_INTERVAL,
cpufreq_policy_transition_delay_us(policy));

if (!have_governor_per_policy())
gov->gdbs_data = dbs_data;
Expand Down

0 comments on commit 5602664

Please sign in to comment.