0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/slab.h>
0012 #include "cpufreq_governor.h"
0013
0014 struct cs_policy_dbs_info {
0015 struct policy_dbs_info policy_dbs;
0016 unsigned int down_skip;
0017 unsigned int requested_freq;
0018 };
0019
0020 static inline struct cs_policy_dbs_info *to_dbs_info(struct policy_dbs_info *policy_dbs)
0021 {
0022 return container_of(policy_dbs, struct cs_policy_dbs_info, policy_dbs);
0023 }
0024
0025 struct cs_dbs_tuners {
0026 unsigned int down_threshold;
0027 unsigned int freq_step;
0028 };
0029
0030
0031 #define DEF_FREQUENCY_UP_THRESHOLD (80)
0032 #define DEF_FREQUENCY_DOWN_THRESHOLD (20)
0033 #define DEF_FREQUENCY_STEP (5)
0034 #define DEF_SAMPLING_DOWN_FACTOR (1)
0035 #define MAX_SAMPLING_DOWN_FACTOR (10)
0036
0037 static inline unsigned int get_freq_step(struct cs_dbs_tuners *cs_tuners,
0038 struct cpufreq_policy *policy)
0039 {
0040 unsigned int freq_step = (cs_tuners->freq_step * policy->max) / 100;
0041
0042
0043 if (unlikely(freq_step == 0))
0044 freq_step = DEF_FREQUENCY_STEP;
0045
0046 return freq_step;
0047 }
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058 static unsigned int cs_dbs_update(struct cpufreq_policy *policy)
0059 {
0060 struct policy_dbs_info *policy_dbs = policy->governor_data;
0061 struct cs_policy_dbs_info *dbs_info = to_dbs_info(policy_dbs);
0062 unsigned int requested_freq = dbs_info->requested_freq;
0063 struct dbs_data *dbs_data = policy_dbs->dbs_data;
0064 struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
0065 unsigned int load = dbs_update(policy);
0066 unsigned int freq_step;
0067
0068
0069
0070
0071
0072 if (cs_tuners->freq_step == 0)
0073 goto out;
0074
0075
0076
0077
0078
0079
0080 if (requested_freq > policy->max || requested_freq < policy->min) {
0081 requested_freq = policy->cur;
0082 dbs_info->requested_freq = requested_freq;
0083 }
0084
0085 freq_step = get_freq_step(cs_tuners, policy);
0086
0087
0088
0089
0090
0091 if (policy_dbs->idle_periods < UINT_MAX) {
0092 unsigned int freq_steps = policy_dbs->idle_periods * freq_step;
0093
0094 if (requested_freq > policy->min + freq_steps)
0095 requested_freq -= freq_steps;
0096 else
0097 requested_freq = policy->min;
0098
0099 policy_dbs->idle_periods = UINT_MAX;
0100 }
0101
0102
0103 if (load > dbs_data->up_threshold) {
0104 dbs_info->down_skip = 0;
0105
0106
0107 if (requested_freq == policy->max)
0108 goto out;
0109
0110 requested_freq += freq_step;
0111 if (requested_freq > policy->max)
0112 requested_freq = policy->max;
0113
0114 __cpufreq_driver_target(policy, requested_freq,
0115 CPUFREQ_RELATION_HE);
0116 dbs_info->requested_freq = requested_freq;
0117 goto out;
0118 }
0119
0120
0121 if (++dbs_info->down_skip < dbs_data->sampling_down_factor)
0122 goto out;
0123 dbs_info->down_skip = 0;
0124
0125
0126 if (load < cs_tuners->down_threshold) {
0127
0128
0129
0130 if (requested_freq == policy->min)
0131 goto out;
0132
0133 if (requested_freq > freq_step)
0134 requested_freq -= freq_step;
0135 else
0136 requested_freq = policy->min;
0137
0138 __cpufreq_driver_target(policy, requested_freq,
0139 CPUFREQ_RELATION_LE);
0140 dbs_info->requested_freq = requested_freq;
0141 }
0142
0143 out:
0144 return dbs_data->sampling_rate;
0145 }
0146
0147
0148
0149 static ssize_t sampling_down_factor_store(struct gov_attr_set *attr_set,
0150 const char *buf, size_t count)
0151 {
0152 struct dbs_data *dbs_data = to_dbs_data(attr_set);
0153 unsigned int input;
0154 int ret;
0155 ret = sscanf(buf, "%u", &input);
0156
0157 if (ret != 1 || input > MAX_SAMPLING_DOWN_FACTOR || input < 1)
0158 return -EINVAL;
0159
0160 dbs_data->sampling_down_factor = input;
0161 return count;
0162 }
0163
0164 static ssize_t up_threshold_store(struct gov_attr_set *attr_set,
0165 const char *buf, size_t count)
0166 {
0167 struct dbs_data *dbs_data = to_dbs_data(attr_set);
0168 struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
0169 unsigned int input;
0170 int ret;
0171 ret = sscanf(buf, "%u", &input);
0172
0173 if (ret != 1 || input > 100 || input <= cs_tuners->down_threshold)
0174 return -EINVAL;
0175
0176 dbs_data->up_threshold = input;
0177 return count;
0178 }
0179
0180 static ssize_t down_threshold_store(struct gov_attr_set *attr_set,
0181 const char *buf, size_t count)
0182 {
0183 struct dbs_data *dbs_data = to_dbs_data(attr_set);
0184 struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
0185 unsigned int input;
0186 int ret;
0187 ret = sscanf(buf, "%u", &input);
0188
0189
0190 if (ret != 1 || input < 1 || input > 100 ||
0191 input >= dbs_data->up_threshold)
0192 return -EINVAL;
0193
0194 cs_tuners->down_threshold = input;
0195 return count;
0196 }
0197
0198 static ssize_t ignore_nice_load_store(struct gov_attr_set *attr_set,
0199 const char *buf, size_t count)
0200 {
0201 struct dbs_data *dbs_data = to_dbs_data(attr_set);
0202 unsigned int input;
0203 int ret;
0204
0205 ret = sscanf(buf, "%u", &input);
0206 if (ret != 1)
0207 return -EINVAL;
0208
0209 if (input > 1)
0210 input = 1;
0211
0212 if (input == dbs_data->ignore_nice_load)
0213 return count;
0214
0215 dbs_data->ignore_nice_load = input;
0216
0217
0218 gov_update_cpu_data(dbs_data);
0219
0220 return count;
0221 }
0222
0223 static ssize_t freq_step_store(struct gov_attr_set *attr_set, const char *buf,
0224 size_t count)
0225 {
0226 struct dbs_data *dbs_data = to_dbs_data(attr_set);
0227 struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
0228 unsigned int input;
0229 int ret;
0230 ret = sscanf(buf, "%u", &input);
0231
0232 if (ret != 1)
0233 return -EINVAL;
0234
0235 if (input > 100)
0236 input = 100;
0237
0238
0239
0240
0241
0242 cs_tuners->freq_step = input;
0243 return count;
0244 }
0245
0246 gov_show_one_common(sampling_rate);
0247 gov_show_one_common(sampling_down_factor);
0248 gov_show_one_common(up_threshold);
0249 gov_show_one_common(ignore_nice_load);
0250 gov_show_one(cs, down_threshold);
0251 gov_show_one(cs, freq_step);
0252
0253 gov_attr_rw(sampling_rate);
0254 gov_attr_rw(sampling_down_factor);
0255 gov_attr_rw(up_threshold);
0256 gov_attr_rw(ignore_nice_load);
0257 gov_attr_rw(down_threshold);
0258 gov_attr_rw(freq_step);
0259
0260 static struct attribute *cs_attrs[] = {
0261 &sampling_rate.attr,
0262 &sampling_down_factor.attr,
0263 &up_threshold.attr,
0264 &down_threshold.attr,
0265 &ignore_nice_load.attr,
0266 &freq_step.attr,
0267 NULL
0268 };
0269 ATTRIBUTE_GROUPS(cs);
0270
0271
0272
0273 static struct policy_dbs_info *cs_alloc(void)
0274 {
0275 struct cs_policy_dbs_info *dbs_info;
0276
0277 dbs_info = kzalloc(sizeof(*dbs_info), GFP_KERNEL);
0278 return dbs_info ? &dbs_info->policy_dbs : NULL;
0279 }
0280
0281 static void cs_free(struct policy_dbs_info *policy_dbs)
0282 {
0283 kfree(to_dbs_info(policy_dbs));
0284 }
0285
0286 static int cs_init(struct dbs_data *dbs_data)
0287 {
0288 struct cs_dbs_tuners *tuners;
0289
0290 tuners = kzalloc(sizeof(*tuners), GFP_KERNEL);
0291 if (!tuners)
0292 return -ENOMEM;
0293
0294 tuners->down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD;
0295 tuners->freq_step = DEF_FREQUENCY_STEP;
0296 dbs_data->up_threshold = DEF_FREQUENCY_UP_THRESHOLD;
0297 dbs_data->sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR;
0298 dbs_data->ignore_nice_load = 0;
0299 dbs_data->tuners = tuners;
0300
0301 return 0;
0302 }
0303
0304 static void cs_exit(struct dbs_data *dbs_data)
0305 {
0306 kfree(dbs_data->tuners);
0307 }
0308
0309 static void cs_start(struct cpufreq_policy *policy)
0310 {
0311 struct cs_policy_dbs_info *dbs_info = to_dbs_info(policy->governor_data);
0312
0313 dbs_info->down_skip = 0;
0314 dbs_info->requested_freq = policy->cur;
0315 }
0316
0317 static struct dbs_governor cs_governor = {
0318 .gov = CPUFREQ_DBS_GOVERNOR_INITIALIZER("conservative"),
0319 .kobj_type = { .default_groups = cs_groups },
0320 .gov_dbs_update = cs_dbs_update,
0321 .alloc = cs_alloc,
0322 .free = cs_free,
0323 .init = cs_init,
0324 .exit = cs_exit,
0325 .start = cs_start,
0326 };
0327
0328 #define CPU_FREQ_GOV_CONSERVATIVE (cs_governor.gov)
0329
0330 MODULE_AUTHOR("Alexander Clouter <alex@digriz.org.uk>");
0331 MODULE_DESCRIPTION("'cpufreq_conservative' - A dynamic cpufreq governor for "
0332 "Low Latency Frequency Transition capable processors "
0333 "optimised for use in a battery environment");
0334 MODULE_LICENSE("GPL");
0335
0336 #ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE
0337 struct cpufreq_governor *cpufreq_default_governor(void)
0338 {
0339 return &CPU_FREQ_GOV_CONSERVATIVE;
0340 }
0341 #endif
0342
0343 cpufreq_governor_init(CPU_FREQ_GOV_CONSERVATIVE);
0344 cpufreq_governor_exit(CPU_FREQ_GOV_CONSERVATIVE);