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 /* if we are already at full speed then break out early */ 107 if (requested_freq == policy->max) 108 goto out; 109 110 requested_freq += freq_step; 111 if (requested_freq > policy->max) 112 requested_freq = policy->max; 113 114 __cpufreq_driver_target(policy, requested_freq, 115 CPUFREQ_RELATION_HE); 116 dbs_info->requested_freq = requested_freq; 117 goto out; 118 } 119 120 /* if sampling_down_factor is active break out early */ 121 if (++dbs_info->down_skip < dbs_data->sampling_down_factor) 122 goto out; 123 dbs_info->down_skip = 0; 124 125 /* Check for frequency decrease */ 126 if (load < cs_tuners->down_threshold) { 127 /* 128 * if we cannot reduce the frequency anymore, break out early 129 */ 130 if (requested_freq == policy->min) 131 goto out; 132 133 if (requested_freq > freq_step) 134 requested_freq -= freq_step; 135 else 136 requested_freq = policy->min; 137 138 __cpufreq_driver_target(policy, requested_freq, 139 CPUFREQ_RELATION_LE); 140 dbs_info->requested_freq = requested_freq; 141 } 142 143 out: 144 return dbs_data->sampling_rate; 145 } 146 147 /************************** sysfs interface ************************/ 148 149 static ssize_t sampling_down_factor_store(struct gov_attr_set *attr_set, 150 const char *buf, size_t count) 151 { 152 struct dbs_data *dbs_data = to_dbs_data(attr_set); 153 unsigned int input; 154 int ret; 155 ret = sscanf(buf, "%u", &input); 156 157 if (ret != 1 || input > MAX_SAMPLING_DOWN_FACTOR || input < 1) 158 return -EINVAL; 159 160 dbs_data->sampling_down_factor = input; 161 return count; 162 } 163 164 static ssize_t up_threshold_store(struct gov_attr_set *attr_set, 165 const char *buf, size_t count) 166 { 167 struct dbs_data *dbs_data = to_dbs_data(attr_set); 168 struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; 169 unsigned int input; 170 int ret; 171 ret = sscanf(buf, "%u", &input); 172 173 if (ret != 1 || input > 100 || input <= cs_tuners->down_threshold) 174 return -EINVAL; 175 176 dbs_data->up_threshold = input; 177 return count; 178 } 179 180 static ssize_t down_threshold_store(struct gov_attr_set *attr_set, 181 const char *buf, size_t count) 182 { 183 struct dbs_data *dbs_data = to_dbs_data(attr_set); 184 struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; 185 unsigned int input; 186 int ret; 187 ret = sscanf(buf, "%u", &input); 188 189 /* cannot be lower than 1 otherwise freq will not fall */ 190 if (ret != 1 || input < 1 || input >= dbs_data->up_threshold) 191 return -EINVAL; 192 193 cs_tuners->down_threshold = input; 194 return count; 195 } 196 197 static ssize_t ignore_nice_load_store(struct gov_attr_set *attr_set, 198 const char *buf, size_t count) 199 { 200 struct dbs_data *dbs_data = to_dbs_data(attr_set); 201 unsigned int input; 202 int ret; 203 204 ret = sscanf(buf, "%u", &input); 205 if (ret != 1) 206 return -EINVAL; 207 208 if (input > 1) 209 input = 1; 210 211 if (input == dbs_data->ignore_nice_load) /* nothing to do */ 212 return count; 213 214 dbs_data->ignore_nice_load = input; 215 216 /* we need to re-evaluate prev_cpu_idle */ 217 gov_update_cpu_data(dbs_data); 218 219 return count; 220 } 221 222 static ssize_t freq_step_store(struct gov_attr_set *attr_set, const char *buf, 223 size_t count) 224 { 225 struct dbs_data *dbs_data = to_dbs_data(attr_set); 226 struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; 227 unsigned int input; 228 int ret; 229 ret = sscanf(buf, "%u", &input); 230 231 if (ret != 1) 232 return -EINVAL; 233 234 if (input > 100) 235 input = 100; 236 237 /* 238 * no need to test here if freq_step is zero as the user might actually 239 * want this, they would be crazy though :) 240 */ 241 cs_tuners->freq_step = input; 242 return count; 243 } 244 245 gov_show_one_common(sampling_rate); 246 gov_show_one_common(sampling_down_factor); 247 gov_show_one_common(up_threshold); 248 gov_show_one_common(ignore_nice_load); 249 gov_show_one(cs, down_threshold); 250 gov_show_one(cs, freq_step); 251 252 gov_attr_rw(sampling_rate); 253 gov_attr_rw(sampling_down_factor); 254 gov_attr_rw(up_threshold); 255 gov_attr_rw(ignore_nice_load); 256 gov_attr_rw(down_threshold); 257 gov_attr_rw(freq_step); 258 259 static struct attribute *cs_attrs[] = { 260 &sampling_rate.attr, 261 &sampling_down_factor.attr, 262 &up_threshold.attr, 263 &down_threshold.attr, 264 &ignore_nice_load.attr, 265 &freq_step.attr, 266 NULL 267 }; 268 ATTRIBUTE_GROUPS(cs); 269 270 /************************** sysfs end ************************/ 271 272 static struct policy_dbs_info *cs_alloc(void) 273 { 274 struct cs_policy_dbs_info *dbs_info; 275 276 dbs_info = kzalloc(sizeof(*dbs_info), GFP_KERNEL); 277 return dbs_info ? &dbs_info->policy_dbs : NULL; 278 } 279 280 static void cs_free(struct policy_dbs_info *policy_dbs) 281 { 282 kfree(to_dbs_info(policy_dbs)); 283 } 284 285 static int cs_init(struct dbs_data *dbs_data) 286 { 287 struct cs_dbs_tuners *tuners; 288 289 tuners = kzalloc(sizeof(*tuners), GFP_KERNEL); 290 if (!tuners) 291 return -ENOMEM; 292 293 tuners->down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD; 294 tuners->freq_step = DEF_FREQUENCY_STEP; 295 dbs_data->up_threshold = DEF_FREQUENCY_UP_THRESHOLD; 296 dbs_data->sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR; 297 dbs_data->ignore_nice_load = 0; 298 dbs_data->tuners = tuners; 299 300 return 0; 301 } 302 303 static void cs_exit(struct dbs_data *dbs_data) 304 { 305 kfree(dbs_data->tuners); 306 } 307 308 static void cs_start(struct cpufreq_policy *policy) 309 { 310 struct cs_policy_dbs_info *dbs_info = to_dbs_info(policy->governor_data); 311 312 dbs_info->down_skip = 0; 313 dbs_info->requested_freq = policy->cur; 314 } 315 316 static struct dbs_governor cs_governor = { 317 .gov = CPUFREQ_DBS_GOVERNOR_INITIALIZER("conservative"), 318 .kobj_type = { .default_groups = cs_groups }, 319 .gov_dbs_update = cs_dbs_update, 320 .alloc = cs_alloc, 321 .free = cs_free, 322 .init = cs_init, 323 .exit = cs_exit, 324 .start = cs_start, 325 }; 326 327 #define CPU_FREQ_GOV_CONSERVATIVE (cs_governor.gov) 328 329 MODULE_AUTHOR("Alexander Clouter <alex@digriz.org.uk>"); 330 MODULE_DESCRIPTION("'cpufreq_conservative' - A dynamic cpufreq governor for " 331 "Low Latency Frequency Transition capable processors " 332 "optimised for use in a battery environment"); 333 MODULE_LICENSE("GPL"); 334 335 #ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE 336 struct cpufreq_governor *cpufreq_default_governor(void) 337 { 338 return &CPU_FREQ_GOV_CONSERVATIVE; 339 } 340 #endif 341 342 cpufreq_governor_init(CPU_FREQ_GOV_CONSERVATIVE); 343 cpufreq_governor_exit(CPU_FREQ_GOV_CONSERVATIVE); 344