1 /* 2 * drivers/cpufreq/cpufreq_conservative.c 3 * 4 * Copyright (C) 2001 Russell King 5 * (C) 2003 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>. 6 * Jun Nakajima <jun.nakajima@intel.com> 7 * (C) 2009 Alexander Clouter <alex@digriz.org.uk> 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License version 2 as 11 * published by the Free Software Foundation. 12 */ 13 14 #include <linux/slab.h> 15 #include "cpufreq_governor.h" 16 17 /* Conservative governor macros */ 18 #define DEF_FREQUENCY_UP_THRESHOLD (80) 19 #define DEF_FREQUENCY_DOWN_THRESHOLD (20) 20 #define DEF_FREQUENCY_STEP (5) 21 #define DEF_SAMPLING_DOWN_FACTOR (1) 22 #define MAX_SAMPLING_DOWN_FACTOR (10) 23 24 static DEFINE_PER_CPU(struct cs_cpu_dbs_info_s, cs_cpu_dbs_info); 25 26 static struct dbs_governor cs_dbs_gov; 27 28 static inline unsigned int get_freq_target(struct cs_dbs_tuners *cs_tuners, 29 struct cpufreq_policy *policy) 30 { 31 unsigned int freq_target = (cs_tuners->freq_step * policy->max) / 100; 32 33 /* max freq cannot be less than 100. But who knows... */ 34 if (unlikely(freq_target == 0)) 35 freq_target = DEF_FREQUENCY_STEP; 36 37 return freq_target; 38 } 39 40 /* 41 * Every sampling_rate, we check, if current idle time is less than 20% 42 * (default), then we try to increase frequency. Every sampling_rate * 43 * sampling_down_factor, we check, if current idle time is more than 80% 44 * (default), then we try to decrease frequency 45 * 46 * Any frequency increase takes it to the maximum frequency. Frequency reduction 47 * happens at minimum steps of 5% (default) of maximum frequency 48 */ 49 static unsigned int cs_dbs_timer(struct cpufreq_policy *policy) 50 { 51 struct cs_cpu_dbs_info_s *dbs_info = &per_cpu(cs_cpu_dbs_info, policy->cpu); 52 struct policy_dbs_info *policy_dbs = policy->governor_data; 53 struct dbs_data *dbs_data = policy_dbs->dbs_data; 54 struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; 55 unsigned int load = dbs_update(policy); 56 57 /* 58 * break out if we 'cannot' reduce the speed as the user might 59 * want freq_step to be zero 60 */ 61 if (cs_tuners->freq_step == 0) 62 goto out; 63 64 /* Check for frequency increase */ 65 if (load > dbs_data->up_threshold) { 66 dbs_info->down_skip = 0; 67 68 /* if we are already at full speed then break out early */ 69 if (dbs_info->requested_freq == policy->max) 70 goto out; 71 72 dbs_info->requested_freq += get_freq_target(cs_tuners, policy); 73 74 if (dbs_info->requested_freq > policy->max) 75 dbs_info->requested_freq = policy->max; 76 77 __cpufreq_driver_target(policy, dbs_info->requested_freq, 78 CPUFREQ_RELATION_H); 79 goto out; 80 } 81 82 /* if sampling_down_factor is active break out early */ 83 if (++dbs_info->down_skip < dbs_data->sampling_down_factor) 84 goto out; 85 dbs_info->down_skip = 0; 86 87 /* Check for frequency decrease */ 88 if (load < cs_tuners->down_threshold) { 89 unsigned int freq_target; 90 /* 91 * if we cannot reduce the frequency anymore, break out early 92 */ 93 if (policy->cur == policy->min) 94 goto out; 95 96 freq_target = get_freq_target(cs_tuners, policy); 97 if (dbs_info->requested_freq > freq_target) 98 dbs_info->requested_freq -= freq_target; 99 else 100 dbs_info->requested_freq = policy->min; 101 102 __cpufreq_driver_target(policy, dbs_info->requested_freq, 103 CPUFREQ_RELATION_L); 104 } 105 106 out: 107 return dbs_data->sampling_rate; 108 } 109 110 static int dbs_cpufreq_notifier(struct notifier_block *nb, unsigned long val, 111 void *data); 112 113 static struct notifier_block cs_cpufreq_notifier_block = { 114 .notifier_call = dbs_cpufreq_notifier, 115 }; 116 117 /************************** sysfs interface ************************/ 118 static struct dbs_governor cs_dbs_gov; 119 120 static ssize_t store_sampling_down_factor(struct dbs_data *dbs_data, 121 const char *buf, size_t count) 122 { 123 unsigned int input; 124 int ret; 125 ret = sscanf(buf, "%u", &input); 126 127 if (ret != 1 || input > MAX_SAMPLING_DOWN_FACTOR || input < 1) 128 return -EINVAL; 129 130 dbs_data->sampling_down_factor = input; 131 return count; 132 } 133 134 static ssize_t store_up_threshold(struct dbs_data *dbs_data, const char *buf, 135 size_t count) 136 { 137 struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; 138 unsigned int input; 139 int ret; 140 ret = sscanf(buf, "%u", &input); 141 142 if (ret != 1 || input > 100 || input <= cs_tuners->down_threshold) 143 return -EINVAL; 144 145 dbs_data->up_threshold = input; 146 return count; 147 } 148 149 static ssize_t store_down_threshold(struct dbs_data *dbs_data, const char *buf, 150 size_t count) 151 { 152 struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; 153 unsigned int input; 154 int ret; 155 ret = sscanf(buf, "%u", &input); 156 157 /* cannot be lower than 11 otherwise freq will not fall */ 158 if (ret != 1 || input < 11 || input > 100 || 159 input >= dbs_data->up_threshold) 160 return -EINVAL; 161 162 cs_tuners->down_threshold = input; 163 return count; 164 } 165 166 static ssize_t store_ignore_nice_load(struct dbs_data *dbs_data, 167 const char *buf, size_t count) 168 { 169 unsigned int input; 170 int ret; 171 172 ret = sscanf(buf, "%u", &input); 173 if (ret != 1) 174 return -EINVAL; 175 176 if (input > 1) 177 input = 1; 178 179 if (input == dbs_data->ignore_nice_load) /* nothing to do */ 180 return count; 181 182 dbs_data->ignore_nice_load = input; 183 184 /* we need to re-evaluate prev_cpu_idle */ 185 gov_update_cpu_data(&cs_dbs_gov, dbs_data); 186 187 return count; 188 } 189 190 static ssize_t store_freq_step(struct dbs_data *dbs_data, const char *buf, 191 size_t count) 192 { 193 struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; 194 unsigned int input; 195 int ret; 196 ret = sscanf(buf, "%u", &input); 197 198 if (ret != 1) 199 return -EINVAL; 200 201 if (input > 100) 202 input = 100; 203 204 /* 205 * no need to test here if freq_step is zero as the user might actually 206 * want this, they would be crazy though :) 207 */ 208 cs_tuners->freq_step = input; 209 return count; 210 } 211 212 gov_show_one_common(sampling_rate); 213 gov_show_one_common(sampling_down_factor); 214 gov_show_one_common(up_threshold); 215 gov_show_one_common(ignore_nice_load); 216 gov_show_one_common(min_sampling_rate); 217 gov_show_one(cs, down_threshold); 218 gov_show_one(cs, freq_step); 219 220 gov_attr_rw(sampling_rate); 221 gov_attr_rw(sampling_down_factor); 222 gov_attr_rw(up_threshold); 223 gov_attr_rw(ignore_nice_load); 224 gov_attr_ro(min_sampling_rate); 225 gov_attr_rw(down_threshold); 226 gov_attr_rw(freq_step); 227 228 static struct attribute *cs_attributes[] = { 229 &min_sampling_rate.attr, 230 &sampling_rate.attr, 231 &sampling_down_factor.attr, 232 &up_threshold.attr, 233 &down_threshold.attr, 234 &ignore_nice_load.attr, 235 &freq_step.attr, 236 NULL 237 }; 238 239 /************************** sysfs end ************************/ 240 241 static int cs_init(struct dbs_data *dbs_data, bool notify) 242 { 243 struct cs_dbs_tuners *tuners; 244 245 tuners = kzalloc(sizeof(*tuners), GFP_KERNEL); 246 if (!tuners) { 247 pr_err("%s: kzalloc failed\n", __func__); 248 return -ENOMEM; 249 } 250 251 tuners->down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD; 252 tuners->freq_step = DEF_FREQUENCY_STEP; 253 dbs_data->up_threshold = DEF_FREQUENCY_UP_THRESHOLD; 254 dbs_data->sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR; 255 dbs_data->ignore_nice_load = 0; 256 257 dbs_data->tuners = tuners; 258 dbs_data->min_sampling_rate = MIN_SAMPLING_RATE_RATIO * 259 jiffies_to_usecs(10); 260 261 if (notify) 262 cpufreq_register_notifier(&cs_cpufreq_notifier_block, 263 CPUFREQ_TRANSITION_NOTIFIER); 264 265 return 0; 266 } 267 268 static void cs_exit(struct dbs_data *dbs_data, bool notify) 269 { 270 if (notify) 271 cpufreq_unregister_notifier(&cs_cpufreq_notifier_block, 272 CPUFREQ_TRANSITION_NOTIFIER); 273 274 kfree(dbs_data->tuners); 275 } 276 277 static void cs_start(struct cpufreq_policy *policy) 278 { 279 struct cs_cpu_dbs_info_s *dbs_info = &per_cpu(cs_cpu_dbs_info, policy->cpu); 280 281 dbs_info->down_skip = 0; 282 dbs_info->requested_freq = policy->cur; 283 } 284 285 define_get_cpu_dbs_routines(cs_cpu_dbs_info); 286 287 static struct dbs_governor cs_dbs_gov = { 288 .gov = { 289 .name = "conservative", 290 .governor = cpufreq_governor_dbs, 291 .max_transition_latency = TRANSITION_LATENCY_LIMIT, 292 .owner = THIS_MODULE, 293 }, 294 .kobj_type = { .default_attrs = cs_attributes }, 295 .get_cpu_cdbs = get_cpu_cdbs, 296 .gov_dbs_timer = cs_dbs_timer, 297 .init = cs_init, 298 .exit = cs_exit, 299 .start = cs_start, 300 }; 301 302 #define CPU_FREQ_GOV_CONSERVATIVE (&cs_dbs_gov.gov) 303 304 static int dbs_cpufreq_notifier(struct notifier_block *nb, unsigned long val, 305 void *data) 306 { 307 struct cpufreq_freqs *freq = data; 308 struct cs_cpu_dbs_info_s *dbs_info = 309 &per_cpu(cs_cpu_dbs_info, freq->cpu); 310 struct cpufreq_policy *policy = cpufreq_cpu_get_raw(freq->cpu); 311 312 if (!policy) 313 return 0; 314 315 /* policy isn't governed by conservative governor */ 316 if (policy->governor != CPU_FREQ_GOV_CONSERVATIVE) 317 return 0; 318 319 /* 320 * we only care if our internally tracked freq moves outside the 'valid' 321 * ranges of frequency available to us otherwise we do not change it 322 */ 323 if (dbs_info->requested_freq > policy->max 324 || dbs_info->requested_freq < policy->min) 325 dbs_info->requested_freq = freq->new; 326 327 return 0; 328 } 329 330 static int __init cpufreq_gov_dbs_init(void) 331 { 332 return cpufreq_register_governor(CPU_FREQ_GOV_CONSERVATIVE); 333 } 334 335 static void __exit cpufreq_gov_dbs_exit(void) 336 { 337 cpufreq_unregister_governor(CPU_FREQ_GOV_CONSERVATIVE); 338 } 339 340 MODULE_AUTHOR("Alexander Clouter <alex@digriz.org.uk>"); 341 MODULE_DESCRIPTION("'cpufreq_conservative' - A dynamic cpufreq governor for " 342 "Low Latency Frequency Transition capable processors " 343 "optimised for use in a battery environment"); 344 MODULE_LICENSE("GPL"); 345 346 #ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE 347 struct cpufreq_governor *cpufreq_default_governor(void) 348 { 349 return CPU_FREQ_GOV_CONSERVATIVE; 350 } 351 352 fs_initcall(cpufreq_gov_dbs_init); 353 #else 354 module_init(cpufreq_gov_dbs_init); 355 #endif 356 module_exit(cpufreq_gov_dbs_exit); 357