1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * drivers/cpufreq/cpufreq_conservative.c 4 * 5 * Copyright (C) 2001 Russell King 6 * (C) 2003 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>. 7 * Jun Nakajima <jun.nakajima@intel.com> 8 * (C) 2009 Alexander Clouter <alex@digriz.org.uk> 9 */ 10 11 #include <linux/slab.h> 12 #include "cpufreq_governor.h" 13 14 struct cs_policy_dbs_info { 15 struct policy_dbs_info policy_dbs; 16 unsigned int down_skip; 17 unsigned int requested_freq; 18 }; 19 20 static inline struct cs_policy_dbs_info *to_dbs_info(struct policy_dbs_info *policy_dbs) 21 { 22 return container_of(policy_dbs, struct cs_policy_dbs_info, policy_dbs); 23 } 24 25 struct cs_dbs_tuners { 26 unsigned int down_threshold; 27 unsigned int freq_step; 28 }; 29 30 /* Conservative governor macros */ 31 #define DEF_FREQUENCY_UP_THRESHOLD (80) 32 #define DEF_FREQUENCY_DOWN_THRESHOLD (20) 33 #define DEF_FREQUENCY_STEP (5) 34 #define DEF_SAMPLING_DOWN_FACTOR (1) 35 #define MAX_SAMPLING_DOWN_FACTOR (10) 36 37 static inline unsigned int get_freq_step(struct cs_dbs_tuners *cs_tuners, 38 struct cpufreq_policy *policy) 39 { 40 unsigned int freq_step = (cs_tuners->freq_step * policy->max) / 100; 41 42 /* max freq cannot be less than 100. But who knows... */ 43 if (unlikely(freq_step == 0)) 44 freq_step = DEF_FREQUENCY_STEP; 45 46 return freq_step; 47 } 48 49 /* 50 * Every sampling_rate, we check, if current idle time is less than 20% 51 * (default), then we try to increase frequency. Every sampling_rate * 52 * sampling_down_factor, we check, if current idle time is more than 80% 53 * (default), then we try to decrease frequency 54 * 55 * Frequency updates happen at minimum steps of 5% (default) of maximum 56 * frequency 57 */ 58 static unsigned int cs_dbs_update(struct cpufreq_policy *policy) 59 { 60 struct policy_dbs_info *policy_dbs = policy->governor_data; 61 struct cs_policy_dbs_info *dbs_info = to_dbs_info(policy_dbs); 62 unsigned int requested_freq = dbs_info->requested_freq; 63 struct dbs_data *dbs_data = policy_dbs->dbs_data; 64 struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; 65 unsigned int load = dbs_update(policy); 66 unsigned int freq_step; 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 /* 76 * If requested_freq is out of range, it is likely that the limits 77 * changed in the meantime, so fall back to current frequency in that 78 * case. 79 */ 80 if (requested_freq > policy->max || requested_freq < policy->min) { 81 requested_freq = policy->cur; 82 dbs_info->requested_freq = requested_freq; 83 } 84 85 freq_step = get_freq_step(cs_tuners, policy); 86 87 /* 88 * Decrease requested_freq one freq_step for each idle period that 89 * we didn't update the frequency. 90 */ 91 if (policy_dbs->idle_periods < UINT_MAX) { 92 unsigned int freq_steps = policy_dbs->idle_periods * freq_step; 93 94 if (requested_freq > policy->min + freq_steps) 95 requested_freq -= freq_steps; 96 else 97 requested_freq = policy->min; 98 99 policy_dbs->idle_periods = UINT_MAX; 100 } 101 102 /* Check for frequency increase */ 103 if (load > dbs_data->up_threshold) { 104 dbs_info->down_skip = 0; 105 106 requested_freq += freq_step; 107 if (requested_freq > policy->max) 108 requested_freq = policy->max; 109 110 __cpufreq_driver_target(policy, requested_freq, 111 CPUFREQ_RELATION_HE); 112 dbs_info->requested_freq = requested_freq; 113 goto out; 114 } 115 116 /* if sampling_down_factor is active break out early */ 117 if (++dbs_info->down_skip < dbs_data->sampling_down_factor) 118 goto out; 119 dbs_info->down_skip = 0; 120 121 /* Check for frequency decrease */ 122 if (load < cs_tuners->down_threshold) { 123 if (requested_freq > policy->min + freq_step) 124 requested_freq -= freq_step; 125 else 126 requested_freq = policy->min; 127 128 __cpufreq_driver_target(policy, requested_freq, 129 CPUFREQ_RELATION_LE); 130 dbs_info->requested_freq = requested_freq; 131 } 132 133 out: 134 return dbs_data->sampling_rate; 135 } 136 137 /************************** sysfs interface ************************/ 138 139 static ssize_t sampling_down_factor_store(struct gov_attr_set *attr_set, 140 const char *buf, size_t count) 141 { 142 struct dbs_data *dbs_data = to_dbs_data(attr_set); 143 unsigned int input; 144 int ret; 145 ret = kstrtouint(buf, 0, &input); 146 147 if (ret || input > MAX_SAMPLING_DOWN_FACTOR || input < 1) 148 return -EINVAL; 149 150 dbs_data->sampling_down_factor = input; 151 return count; 152 } 153 154 static ssize_t up_threshold_store(struct gov_attr_set *attr_set, 155 const char *buf, size_t count) 156 { 157 struct dbs_data *dbs_data = to_dbs_data(attr_set); 158 struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; 159 unsigned int input; 160 int ret; 161 ret = kstrtouint(buf, 0, &input); 162 163 if (ret || input > 100 || input <= cs_tuners->down_threshold) 164 return -EINVAL; 165 166 dbs_data->up_threshold = input; 167 return count; 168 } 169 170 static ssize_t down_threshold_store(struct gov_attr_set *attr_set, 171 const char *buf, size_t count) 172 { 173 struct dbs_data *dbs_data = to_dbs_data(attr_set); 174 struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; 175 unsigned int input; 176 int ret; 177 ret = kstrtouint(buf, 0, &input); 178 179 /* cannot be lower than 1 otherwise freq will not fall */ 180 if (ret || input < 1 || input >= dbs_data->up_threshold) 181 return -EINVAL; 182 183 cs_tuners->down_threshold = input; 184 return count; 185 } 186 187 static ssize_t ignore_nice_load_store(struct gov_attr_set *attr_set, 188 const char *buf, size_t count) 189 { 190 struct dbs_data *dbs_data = to_dbs_data(attr_set); 191 unsigned int input; 192 int ret; 193 194 ret = kstrtouint(buf, 0, &input); 195 if (ret) 196 return ret; 197 198 if (input > 1) 199 input = 1; 200 201 if (input == dbs_data->ignore_nice_load) /* nothing to do */ 202 return count; 203 204 dbs_data->ignore_nice_load = input; 205 206 /* we need to re-evaluate prev_cpu_idle */ 207 gov_update_cpu_data(dbs_data); 208 209 return count; 210 } 211 212 static ssize_t freq_step_store(struct gov_attr_set *attr_set, const char *buf, 213 size_t count) 214 { 215 struct dbs_data *dbs_data = to_dbs_data(attr_set); 216 struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; 217 unsigned int input; 218 int ret; 219 ret = kstrtouint(buf, 0, &input); 220 221 if (ret) 222 return ret; 223 224 if (input > 100) 225 input = 100; 226 227 /* 228 * no need to test here if freq_step is zero as the user might actually 229 * want this, they would be crazy though :) 230 */ 231 cs_tuners->freq_step = input; 232 return count; 233 } 234 235 gov_show_one_common(sampling_rate); 236 gov_show_one_common(sampling_down_factor); 237 gov_show_one_common(up_threshold); 238 gov_show_one_common(ignore_nice_load); 239 gov_show_one(cs, down_threshold); 240 gov_show_one(cs, freq_step); 241 242 gov_attr_rw(sampling_rate); 243 gov_attr_rw(sampling_down_factor); 244 gov_attr_rw(up_threshold); 245 gov_attr_rw(ignore_nice_load); 246 gov_attr_rw(down_threshold); 247 gov_attr_rw(freq_step); 248 249 static struct attribute *cs_attrs[] = { 250 &sampling_rate.attr, 251 &sampling_down_factor.attr, 252 &up_threshold.attr, 253 &down_threshold.attr, 254 &ignore_nice_load.attr, 255 &freq_step.attr, 256 NULL 257 }; 258 ATTRIBUTE_GROUPS(cs); 259 260 /************************** sysfs end ************************/ 261 262 static struct policy_dbs_info *cs_alloc(void) 263 { 264 struct cs_policy_dbs_info *dbs_info; 265 266 dbs_info = kzalloc_obj(*dbs_info); 267 return dbs_info ? &dbs_info->policy_dbs : NULL; 268 } 269 270 static void cs_free(struct policy_dbs_info *policy_dbs) 271 { 272 kfree(to_dbs_info(policy_dbs)); 273 } 274 275 static int cs_init(struct dbs_data *dbs_data) 276 { 277 struct cs_dbs_tuners *tuners; 278 279 tuners = kzalloc_obj(*tuners); 280 if (!tuners) 281 return -ENOMEM; 282 283 tuners->down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD; 284 tuners->freq_step = DEF_FREQUENCY_STEP; 285 dbs_data->up_threshold = DEF_FREQUENCY_UP_THRESHOLD; 286 dbs_data->sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR; 287 dbs_data->ignore_nice_load = 0; 288 dbs_data->tuners = tuners; 289 290 return 0; 291 } 292 293 static void cs_exit(struct dbs_data *dbs_data) 294 { 295 kfree(dbs_data->tuners); 296 } 297 298 static void cs_start(struct cpufreq_policy *policy) 299 { 300 struct cs_policy_dbs_info *dbs_info = to_dbs_info(policy->governor_data); 301 302 dbs_info->down_skip = 0; 303 dbs_info->requested_freq = policy->cur; 304 } 305 306 static void cs_limits(struct cpufreq_policy *policy) 307 { 308 struct cs_policy_dbs_info *dbs_info = to_dbs_info(policy->governor_data); 309 310 /* 311 * The limits have changed, so may have the current frequency. Reset 312 * requested_freq to avoid any unintended outcomes due to the mismatch. 313 */ 314 dbs_info->requested_freq = policy->cur; 315 } 316 317 static struct dbs_governor cs_governor = { 318 .gov = CPUFREQ_DBS_GOVERNOR_INITIALIZER("conservative"), 319 .kobj_type = { .default_groups = cs_groups }, 320 .gov_dbs_update = cs_dbs_update, 321 .alloc = cs_alloc, 322 .free = cs_free, 323 .init = cs_init, 324 .exit = cs_exit, 325 .start = cs_start, 326 .limits = cs_limits, 327 }; 328 329 #define CPU_FREQ_GOV_CONSERVATIVE (cs_governor.gov) 330 331 MODULE_AUTHOR("Alexander Clouter <alex@digriz.org.uk>"); 332 MODULE_DESCRIPTION("'cpufreq_conservative' - A dynamic cpufreq governor for " 333 "Low Latency Frequency Transition capable processors " 334 "optimised for use in a battery environment"); 335 MODULE_LICENSE("GPL"); 336 337 #ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE 338 struct cpufreq_governor *cpufreq_default_governor(void) 339 { 340 return &CPU_FREQ_GOV_CONSERVATIVE; 341 } 342 #endif 343 344 cpufreq_governor_init(CPU_FREQ_GOV_CONSERVATIVE); 345 cpufreq_governor_exit(CPU_FREQ_GOV_CONSERVATIVE); 346