cpufreq: conservative: Do not use transition notifications
The conservative governor registers a transition notifier so it can update its internal requested_freq value if it falls out of the policy->min...policy->max range, but requested_freq is not really necessary. That value is used to track the frequency requested by the governor previously, but policy->cur can be used instead of it and then the governor will not have to worry about updating the tracked value when the current frequency changes independently (for example, as a result of min or max changes). Accodringly, drop requested_freq from struct cs_policy_dbs_info and modify cs_dbs_timer() to use policy->cur instead of it. While at it, notice that __cpufreq_driver_target() clamps its target_freq argument between policy->min and policy->max, so the callers of it don't have to do that and make additional changes in cs_dbs_timer() in accordance with that. After these changes the transition notifier used by the conservative governor is not necessary any more, so drop it, which also makes it possible to drop the struct cs_governor definition and simplify the code accordingly. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
This commit is contained in:
parent
bb4b9933e2
commit
d352cf47d9
|
@ -17,7 +17,6 @@
|
|||
struct cs_policy_dbs_info {
|
||||
struct policy_dbs_info policy_dbs;
|
||||
unsigned int down_skip;
|
||||
unsigned int requested_freq;
|
||||
};
|
||||
|
||||
static inline struct cs_policy_dbs_info *to_dbs_info(struct policy_dbs_info *policy_dbs)
|
||||
|
@ -75,19 +74,17 @@ static unsigned int cs_dbs_timer(struct cpufreq_policy *policy)
|
|||
|
||||
/* Check for frequency increase */
|
||||
if (load > dbs_data->up_threshold) {
|
||||
unsigned int requested_freq = policy->cur;
|
||||
|
||||
dbs_info->down_skip = 0;
|
||||
|
||||
/* if we are already at full speed then break out early */
|
||||
if (dbs_info->requested_freq == policy->max)
|
||||
if (requested_freq == policy->max)
|
||||
goto out;
|
||||
|
||||
dbs_info->requested_freq += get_freq_target(cs_tuners, policy);
|
||||
requested_freq += get_freq_target(cs_tuners, policy);
|
||||
|
||||
if (dbs_info->requested_freq > policy->max)
|
||||
dbs_info->requested_freq = policy->max;
|
||||
|
||||
__cpufreq_driver_target(policy, dbs_info->requested_freq,
|
||||
CPUFREQ_RELATION_H);
|
||||
__cpufreq_driver_target(policy, requested_freq, CPUFREQ_RELATION_H);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -98,34 +95,26 @@ static unsigned int cs_dbs_timer(struct cpufreq_policy *policy)
|
|||
|
||||
/* Check for frequency decrease */
|
||||
if (load < cs_tuners->down_threshold) {
|
||||
unsigned int freq_target;
|
||||
unsigned int freq_target, requested_freq = policy->cur;
|
||||
/*
|
||||
* if we cannot reduce the frequency anymore, break out early
|
||||
*/
|
||||
if (policy->cur == policy->min)
|
||||
if (requested_freq == policy->min)
|
||||
goto out;
|
||||
|
||||
freq_target = get_freq_target(cs_tuners, policy);
|
||||
if (dbs_info->requested_freq > freq_target)
|
||||
dbs_info->requested_freq -= freq_target;
|
||||
if (requested_freq > freq_target)
|
||||
requested_freq -= freq_target;
|
||||
else
|
||||
dbs_info->requested_freq = policy->min;
|
||||
requested_freq = policy->min;
|
||||
|
||||
__cpufreq_driver_target(policy, dbs_info->requested_freq,
|
||||
CPUFREQ_RELATION_L);
|
||||
__cpufreq_driver_target(policy, requested_freq, CPUFREQ_RELATION_L);
|
||||
}
|
||||
|
||||
out:
|
||||
return dbs_data->sampling_rate;
|
||||
}
|
||||
|
||||
static int dbs_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
|
||||
void *data);
|
||||
|
||||
static struct notifier_block cs_cpufreq_notifier_block = {
|
||||
.notifier_call = dbs_cpufreq_notifier,
|
||||
};
|
||||
|
||||
/************************** sysfs interface ************************/
|
||||
|
||||
static ssize_t store_sampling_down_factor(struct gov_attr_set *attr_set,
|
||||
|
@ -254,13 +243,6 @@ static struct attribute *cs_attributes[] = {
|
|||
|
||||
/************************** sysfs end ************************/
|
||||
|
||||
struct cs_governor {
|
||||
struct dbs_governor dbs_gov;
|
||||
unsigned int usage_count;
|
||||
};
|
||||
|
||||
static struct cs_governor cs_gov;
|
||||
|
||||
static struct policy_dbs_info *cs_alloc(void)
|
||||
{
|
||||
struct cs_policy_dbs_info *dbs_info;
|
||||
|
@ -292,25 +274,11 @@ static int cs_init(struct dbs_data *dbs_data)
|
|||
dbs_data->min_sampling_rate = MIN_SAMPLING_RATE_RATIO *
|
||||
jiffies_to_usecs(10);
|
||||
|
||||
/*
|
||||
* This function and cs_exit() are only called under gov_dbs_data_mutex
|
||||
* which is global, so the cs_gov.usage_count accesses are guaranteed
|
||||
* to be serialized.
|
||||
*/
|
||||
if (!cs_gov.usage_count++)
|
||||
cpufreq_register_notifier(&cs_cpufreq_notifier_block,
|
||||
CPUFREQ_TRANSITION_NOTIFIER);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cs_exit(struct dbs_data *dbs_data)
|
||||
{
|
||||
/* Protected by gov_dbs_data_mutex - see the comment in cs_init(). */
|
||||
if (!--cs_gov.usage_count)
|
||||
cpufreq_unregister_notifier(&cs_cpufreq_notifier_block,
|
||||
CPUFREQ_TRANSITION_NOTIFIER);
|
||||
|
||||
kfree(dbs_data->tuners);
|
||||
}
|
||||
|
||||
|
@ -319,49 +287,20 @@ static void cs_start(struct cpufreq_policy *policy)
|
|||
struct cs_policy_dbs_info *dbs_info = to_dbs_info(policy->governor_data);
|
||||
|
||||
dbs_info->down_skip = 0;
|
||||
dbs_info->requested_freq = policy->cur;
|
||||
}
|
||||
|
||||
static struct cs_governor cs_gov = {
|
||||
.dbs_gov = {
|
||||
.gov = CPUFREQ_DBS_GOVERNOR_INITIALIZER("conservative"),
|
||||
.kobj_type = { .default_attrs = cs_attributes },
|
||||
.gov_dbs_timer = cs_dbs_timer,
|
||||
.alloc = cs_alloc,
|
||||
.free = cs_free,
|
||||
.init = cs_init,
|
||||
.exit = cs_exit,
|
||||
.start = cs_start,
|
||||
},
|
||||
static struct dbs_governor cs_governor = {
|
||||
.gov = CPUFREQ_DBS_GOVERNOR_INITIALIZER("conservative"),
|
||||
.kobj_type = { .default_attrs = cs_attributes },
|
||||
.gov_dbs_timer = cs_dbs_timer,
|
||||
.alloc = cs_alloc,
|
||||
.free = cs_free,
|
||||
.init = cs_init,
|
||||
.exit = cs_exit,
|
||||
.start = cs_start,
|
||||
};
|
||||
|
||||
#define CPU_FREQ_GOV_CONSERVATIVE (&cs_gov.dbs_gov.gov)
|
||||
|
||||
static int dbs_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
|
||||
void *data)
|
||||
{
|
||||
struct cpufreq_freqs *freq = data;
|
||||
struct cpufreq_policy *policy = cpufreq_cpu_get_raw(freq->cpu);
|
||||
struct cs_policy_dbs_info *dbs_info;
|
||||
|
||||
if (!policy)
|
||||
return 0;
|
||||
|
||||
/* policy isn't governed by conservative governor */
|
||||
if (policy->governor != CPU_FREQ_GOV_CONSERVATIVE)
|
||||
return 0;
|
||||
|
||||
dbs_info = to_dbs_info(policy->governor_data);
|
||||
/*
|
||||
* we only care if our internally tracked freq moves outside the 'valid'
|
||||
* ranges of frequency available to us otherwise we do not change it
|
||||
*/
|
||||
if (dbs_info->requested_freq > policy->max
|
||||
|| dbs_info->requested_freq < policy->min)
|
||||
dbs_info->requested_freq = freq->new;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#define CPU_FREQ_GOV_CONSERVATIVE (&cs_governor.gov)
|
||||
|
||||
static int __init cpufreq_gov_dbs_init(void)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue