Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 56026645 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki
Browse files

cpufreq: governor: Ensure sufficiently large sampling intervals



After commit aa7519af (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: aa7519af (cpufreq: Use transition_delay_us for legacy governors as well)
Reported-by: default avatarAndy Tang <andy.tang@nxp.com>
Reported-by: default avatarDoug Smythies <dsmythies@telus.net>
Tested-by: default avatarAndy Tang <andy.tang@nxp.com>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: default avatarViresh Kumar <viresh.kumar@linaro.org>
parent ccc153a6
Loading
Loading
Loading
Loading
+16 −3
Original line number Diff line number Diff line
@@ -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);
@@ -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.
@@ -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;