|
@@ -17,7 +17,6 @@
|
|
struct cs_policy_dbs_info {
|
|
struct cs_policy_dbs_info {
|
|
struct policy_dbs_info policy_dbs;
|
|
struct policy_dbs_info policy_dbs;
|
|
unsigned int down_skip;
|
|
unsigned int down_skip;
|
|
- unsigned int requested_freq;
|
|
|
|
};
|
|
};
|
|
|
|
|
|
static inline struct cs_policy_dbs_info *to_dbs_info(struct policy_dbs_info *policy_dbs)
|
|
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 */
|
|
/* Check for frequency increase */
|
|
if (load > dbs_data->up_threshold) {
|
|
if (load > dbs_data->up_threshold) {
|
|
|
|
+ unsigned int requested_freq = policy->cur;
|
|
|
|
+
|
|
dbs_info->down_skip = 0;
|
|
dbs_info->down_skip = 0;
|
|
|
|
|
|
/* if we are already at full speed then break out early */
|
|
/* 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;
|
|
goto out;
|
|
|
|
|
|
- dbs_info->requested_freq += get_freq_target(cs_tuners, policy);
|
|
|
|
-
|
|
|
|
- if (dbs_info->requested_freq > policy->max)
|
|
|
|
- dbs_info->requested_freq = policy->max;
|
|
|
|
|
|
+ requested_freq += get_freq_target(cs_tuners, policy);
|
|
|
|
|
|
- __cpufreq_driver_target(policy, dbs_info->requested_freq,
|
|
|
|
- CPUFREQ_RELATION_H);
|
|
|
|
|
|
+ __cpufreq_driver_target(policy, requested_freq, CPUFREQ_RELATION_H);
|
|
goto out;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -98,34 +95,26 @@ static unsigned int cs_dbs_timer(struct cpufreq_policy *policy)
|
|
|
|
|
|
/* Check for frequency decrease */
|
|
/* Check for frequency decrease */
|
|
if (load < cs_tuners->down_threshold) {
|
|
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 we cannot reduce the frequency anymore, break out early
|
|
*/
|
|
*/
|
|
- if (policy->cur == policy->min)
|
|
|
|
|
|
+ if (requested_freq == policy->min)
|
|
goto out;
|
|
goto out;
|
|
|
|
|
|
freq_target = get_freq_target(cs_tuners, policy);
|
|
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
|
|
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:
|
|
out:
|
|
return dbs_data->sampling_rate;
|
|
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 ************************/
|
|
/************************** sysfs interface ************************/
|
|
|
|
|
|
static ssize_t store_sampling_down_factor(struct gov_attr_set *attr_set,
|
|
static ssize_t store_sampling_down_factor(struct gov_attr_set *attr_set,
|
|
@@ -254,13 +243,6 @@ static struct attribute *cs_attributes[] = {
|
|
|
|
|
|
/************************** sysfs end ************************/
|
|
/************************** 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)
|
|
static struct policy_dbs_info *cs_alloc(void)
|
|
{
|
|
{
|
|
struct cs_policy_dbs_info *dbs_info;
|
|
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 *
|
|
dbs_data->min_sampling_rate = MIN_SAMPLING_RATE_RATIO *
|
|
jiffies_to_usecs(10);
|
|
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;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
static void cs_exit(struct dbs_data *dbs_data)
|
|
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);
|
|
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);
|
|
struct cs_policy_dbs_info *dbs_info = to_dbs_info(policy->governor_data);
|
|
|
|
|
|
dbs_info->down_skip = 0;
|
|
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)
|
|
static int __init cpufreq_gov_dbs_init(void)
|
|
{
|
|
{
|