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 struct cs_policy_dbs_info { 18 struct policy_dbs_info policy_dbs; 19 unsigned int down_skip; 20 }; 21 22 static inline struct cs_policy_dbs_info *to_dbs_info(struct policy_dbs_info *policy_dbs) 23 { 24 return container_of(policy_dbs, struct cs_policy_dbs_info, policy_dbs); 25 } 26 27 struct cs_dbs_tuners { 28 unsigned int down_threshold; 29 unsigned int freq_step; 30 }; 31 32 /* Conservative governor macros */ 33 #define DEF_FREQUENCY_UP_THRESHOLD (80) 34 #define DEF_FREQUENCY_DOWN_THRESHOLD (20) 35 #define DEF_FREQUENCY_STEP (5) 36 #define DEF_SAMPLING_DOWN_FACTOR (1) 37 #define MAX_SAMPLING_DOWN_FACTOR (10) 38 39 static inline unsigned int get_freq_target(struct cs_dbs_tuners *cs_tuners, 40 struct cpufreq_policy *policy) 41 { 42 unsigned int freq_target = (cs_tuners->freq_step * policy->max) / 100; 43 44 /* max freq cannot be less than 100. But who knows... */ 45 if (unlikely(freq_target == 0)) 46 freq_target = DEF_FREQUENCY_STEP; 47 48 return freq_target; 49 } 50 51 /* 52 * Every sampling_rate, we check, if current idle time is less than 20% 53 * (default), then we try to increase frequency. Every sampling_rate * 54 * sampling_down_factor, we check, if current idle time is more than 80% 55 * (default), then we try to decrease frequency 56 * 57 * Any frequency increase takes it to the maximum frequency. Frequency reduction 58 * happens at minimum steps of 5% (default) of maximum frequency 59 */ 60 static unsigned int cs_dbs_timer(struct cpufreq_policy *policy) 61 { 62 struct policy_dbs_info *policy_dbs = policy->governor_data; 63 struct cs_policy_dbs_info *dbs_info = to_dbs_info(policy_dbs); 64 struct dbs_data *dbs_data = policy_dbs->dbs_data; 65 struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; 66 unsigned int load = dbs_update(policy); 67 68 /* 69 * break out if we 'cannot' reduce the speed as the user might 70 * want freq_step to be zero 71 */ 72 if (cs_tuners->freq_step == 0) 73 goto out; 74 75 /* Check for frequency increase */ 76 if (load > dbs_data->up_threshold) { 77 unsigned int requested_freq = policy->cur; 78 79 dbs_info->down_skip = 0; 80 81 /* if we are already at full speed then break out early */ 82 if (requested_freq == policy->max) 83 goto out; 84 85 requested_freq += get_freq_target(cs_tuners, policy); 86 87 __cpufreq_driver_target(policy, requested_freq, CPUFREQ_RELATION_H); 88 goto out; 89 } 90 91 /* if sampling_down_factor is active break out early */ 92 if (++dbs_info->down_skip < dbs_data->sampling_down_factor) 93 goto out; 94 dbs_info->down_skip = 0; 95 96 /* Check for frequency decrease */ 97 if (load < cs_tuners->down_threshold) { 98 unsigned int freq_target, requested_freq = policy->cur; 99 /* 100 * if we cannot reduce the frequency anymore, break out early 101 */ 102 if (requested_freq == policy->min) 103 goto out; 104 105 freq_target = get_freq_target(cs_tuners, policy); 106 if (requested_freq > freq_target) 107 requested_freq -= freq_target; 108 else 109 requested_freq = policy->min; 110 111 __cpufreq_driver_target(policy, requested_freq, CPUFREQ_RELATION_L); 112 } 113 114 out: 115 return dbs_data->sampling_rate; 116 } 117 118 /************************** sysfs interface ************************/ 119 120 static ssize_t store_sampling_down_factor(struct gov_attr_set *attr_set, 121 const char *buf, size_t count) 122 { 123 struct dbs_data *dbs_data = to_dbs_data(attr_set); 124 unsigned int input; 125 int ret; 126 ret = sscanf(buf, "%u", &input); 127 128 if (ret != 1 || input > MAX_SAMPLING_DOWN_FACTOR || input < 1) 129 return -EINVAL; 130 131 dbs_data->sampling_down_factor = input; 132 return count; 133 } 134 135 static ssize_t store_up_threshold(struct gov_attr_set *attr_set, 136 const char *buf, size_t count) 137 { 138 struct dbs_data *dbs_data = to_dbs_data(attr_set); 139 struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; 140 unsigned int input; 141 int ret; 142 ret = sscanf(buf, "%u", &input); 143 144 if (ret != 1 || input > 100 || input <= cs_tuners->down_threshold) 145 return -EINVAL; 146 147 dbs_data->up_threshold = input; 148 return count; 149 } 150 151 static ssize_t store_down_threshold(struct gov_attr_set *attr_set, 152 const char *buf, size_t count) 153 { 154 struct dbs_data *dbs_data = to_dbs_data(attr_set); 155 struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; 156 unsigned int input; 157 int ret; 158 ret = sscanf(buf, "%u", &input); 159 160 /* cannot be lower than 11 otherwise freq will not fall */ 161 if (ret != 1 || input < 11 || input > 100 || 162 input >= dbs_data->up_threshold) 163 return -EINVAL; 164 165 cs_tuners->down_threshold = input; 166 return count; 167 } 168 169 static ssize_t store_ignore_nice_load(struct gov_attr_set *attr_set, 170 const char *buf, size_t count) 171 { 172 struct dbs_data *dbs_data = to_dbs_data(attr_set); 173 unsigned int input; 174 int ret; 175 176 ret = sscanf(buf, "%u", &input); 177 if (ret != 1) 178 return -EINVAL; 179 180 if (input > 1) 181 input = 1; 182 183 if (input == dbs_data->ignore_nice_load) /* nothing to do */ 184 return count; 185 186 dbs_data->ignore_nice_load = input; 187 188 /* we need to re-evaluate prev_cpu_idle */ 189 gov_update_cpu_data(dbs_data); 190 191 return count; 192 } 193 194 static ssize_t store_freq_step(struct gov_attr_set *attr_set, const char *buf, 195 size_t count) 196 { 197 struct dbs_data *dbs_data = to_dbs_data(attr_set); 198 struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; 199 unsigned int input; 200 int ret; 201 ret = sscanf(buf, "%u", &input); 202 203 if (ret != 1) 204 return -EINVAL; 205 206 if (input > 100) 207 input = 100; 208 209 /* 210 * no need to test here if freq_step is zero as the user might actually 211 * want this, they would be crazy though :) 212 */ 213 cs_tuners->freq_step = input; 214 return count; 215 } 216 217 gov_show_one_common(sampling_rate); 218 gov_show_one_common(sampling_down_factor); 219 gov_show_one_common(up_threshold); 220 gov_show_one_common(ignore_nice_load); 221 gov_show_one_common(min_sampling_rate); 222 gov_show_one(cs, down_threshold); 223 gov_show_one(cs, freq_step); 224 225 gov_attr_rw(sampling_rate); 226 gov_attr_rw(sampling_down_factor); 227 gov_attr_rw(up_threshold); 228 gov_attr_rw(ignore_nice_load); 229 gov_attr_ro(min_sampling_rate); 230 gov_attr_rw(down_threshold); 231 gov_attr_rw(freq_step); 232 233 static struct attribute *cs_attributes[] = { 234 &min_sampling_rate.attr, 235 &sampling_rate.attr, 236 &sampling_down_factor.attr, 237 &up_threshold.attr, 238 &down_threshold.attr, 239 &ignore_nice_load.attr, 240 &freq_step.attr, 241 NULL 242 }; 243 244 /************************** sysfs end ************************/ 245 246 static struct policy_dbs_info *cs_alloc(void) 247 { 248 struct cs_policy_dbs_info *dbs_info; 249 250 dbs_info = kzalloc(sizeof(*dbs_info), GFP_KERNEL); 251 return dbs_info ? &dbs_info->policy_dbs : NULL; 252 } 253 254 static void cs_free(struct policy_dbs_info *policy_dbs) 255 { 256 kfree(to_dbs_info(policy_dbs)); 257 } 258 259 static int cs_init(struct dbs_data *dbs_data) 260 { 261 struct cs_dbs_tuners *tuners; 262 263 tuners = kzalloc(sizeof(*tuners), GFP_KERNEL); 264 if (!tuners) 265 return -ENOMEM; 266 267 tuners->down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD; 268 tuners->freq_step = DEF_FREQUENCY_STEP; 269 dbs_data->up_threshold = DEF_FREQUENCY_UP_THRESHOLD; 270 dbs_data->sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR; 271 dbs_data->ignore_nice_load = 0; 272 273 dbs_data->tuners = tuners; 274 dbs_data->min_sampling_rate = MIN_SAMPLING_RATE_RATIO * 275 jiffies_to_usecs(10); 276 277 return 0; 278 } 279 280 static void cs_exit(struct dbs_data *dbs_data) 281 { 282 kfree(dbs_data->tuners); 283 } 284 285 static void cs_start(struct cpufreq_policy *policy) 286 { 287 struct cs_policy_dbs_info *dbs_info = to_dbs_info(policy->governor_data); 288 289 dbs_info->down_skip = 0; 290 } 291 292 static struct dbs_governor cs_governor = { 293 .gov = CPUFREQ_DBS_GOVERNOR_INITIALIZER("conservative"), 294 .kobj_type = { .default_attrs = cs_attributes }, 295 .gov_dbs_timer = cs_dbs_timer, 296 .alloc = cs_alloc, 297 .free = cs_free, 298 .init = cs_init, 299 .exit = cs_exit, 300 .start = cs_start, 301 }; 302 303 #define CPU_FREQ_GOV_CONSERVATIVE (&cs_governor.gov) 304 305 static int __init cpufreq_gov_dbs_init(void) 306 { 307 return cpufreq_register_governor(CPU_FREQ_GOV_CONSERVATIVE); 308 } 309 310 static void __exit cpufreq_gov_dbs_exit(void) 311 { 312 cpufreq_unregister_governor(CPU_FREQ_GOV_CONSERVATIVE); 313 } 314 315 MODULE_AUTHOR("Alexander Clouter <alex@digriz.org.uk>"); 316 MODULE_DESCRIPTION("'cpufreq_conservative' - A dynamic cpufreq governor for " 317 "Low Latency Frequency Transition capable processors " 318 "optimised for use in a battery environment"); 319 MODULE_LICENSE("GPL"); 320 321 #ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE 322 struct cpufreq_governor *cpufreq_default_governor(void) 323 { 324 return CPU_FREQ_GOV_CONSERVATIVE; 325 } 326 327 fs_initcall(cpufreq_gov_dbs_init); 328 #else 329 module_init(cpufreq_gov_dbs_init); 330 #endif 331 module_exit(cpufreq_gov_dbs_exit); 332