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 > 100 || 191 input >= dbs_data->up_threshold) 192 return -EINVAL; 193 194 cs_tuners->down_threshold = input; 195 return count; 196 } 197 198 static ssize_t ignore_nice_load_store(struct gov_attr_set *attr_set, 199 const char *buf, size_t count) 200 { 201 struct dbs_data *dbs_data = to_dbs_data(attr_set); 202 unsigned int input; 203 int ret; 204 205 ret = sscanf(buf, "%u", &input); 206 if (ret != 1) 207 return -EINVAL; 208 209 if (input > 1) 210 input = 1; 211 212 if (input == dbs_data->ignore_nice_load) /* nothing to do */ 213 return count; 214 215 dbs_data->ignore_nice_load = input; 216 217 /* we need to re-evaluate prev_cpu_idle */ 218 gov_update_cpu_data(dbs_data); 219 220 return count; 221 } 222 223 static ssize_t freq_step_store(struct gov_attr_set *attr_set, const char *buf, 224 size_t count) 225 { 226 struct dbs_data *dbs_data = to_dbs_data(attr_set); 227 struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; 228 unsigned int input; 229 int ret; 230 ret = sscanf(buf, "%u", &input); 231 232 if (ret != 1) 233 return -EINVAL; 234 235 if (input > 100) 236 input = 100; 237 238 /* 239 * no need to test here if freq_step is zero as the user might actually 240 * want this, they would be crazy though :) 241 */ 242 cs_tuners->freq_step = input; 243 return count; 244 } 245 246 gov_show_one_common(sampling_rate); 247 gov_show_one_common(sampling_down_factor); 248 gov_show_one_common(up_threshold); 249 gov_show_one_common(ignore_nice_load); 250 gov_show_one(cs, down_threshold); 251 gov_show_one(cs, freq_step); 252 253 gov_attr_rw(sampling_rate); 254 gov_attr_rw(sampling_down_factor); 255 gov_attr_rw(up_threshold); 256 gov_attr_rw(ignore_nice_load); 257 gov_attr_rw(down_threshold); 258 gov_attr_rw(freq_step); 259 260 static struct attribute *cs_attrs[] = { 261 &sampling_rate.attr, 262 &sampling_down_factor.attr, 263 &up_threshold.attr, 264 &down_threshold.attr, 265 &ignore_nice_load.attr, 266 &freq_step.attr, 267 NULL 268 }; 269 ATTRIBUTE_GROUPS(cs); 270 271 /************************** sysfs end ************************/ 272 273 static struct policy_dbs_info *cs_alloc(void) 274 { 275 struct cs_policy_dbs_info *dbs_info; 276 277 dbs_info = kzalloc(sizeof(*dbs_info), GFP_KERNEL); 278 return dbs_info ? &dbs_info->policy_dbs : NULL; 279 } 280 281 static void cs_free(struct policy_dbs_info *policy_dbs) 282 { 283 kfree(to_dbs_info(policy_dbs)); 284 } 285 286 static int cs_init(struct dbs_data *dbs_data) 287 { 288 struct cs_dbs_tuners *tuners; 289 290 tuners = kzalloc(sizeof(*tuners), GFP_KERNEL); 291 if (!tuners) 292 return -ENOMEM; 293 294 tuners->down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD; 295 tuners->freq_step = DEF_FREQUENCY_STEP; 296 dbs_data->up_threshold = DEF_FREQUENCY_UP_THRESHOLD; 297 dbs_data->sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR; 298 dbs_data->ignore_nice_load = 0; 299 dbs_data->tuners = tuners; 300 301 return 0; 302 } 303 304 static void cs_exit(struct dbs_data *dbs_data) 305 { 306 kfree(dbs_data->tuners); 307 } 308 309 static void cs_start(struct cpufreq_policy *policy) 310 { 311 struct cs_policy_dbs_info *dbs_info = to_dbs_info(policy->governor_data); 312 313 dbs_info->down_skip = 0; 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 }; 327 328 #define CPU_FREQ_GOV_CONSERVATIVE (cs_governor.gov) 329 330 MODULE_AUTHOR("Alexander Clouter <alex@digriz.org.uk>"); 331 MODULE_DESCRIPTION("'cpufreq_conservative' - A dynamic cpufreq governor for " 332 "Low Latency Frequency Transition capable processors " 333 "optimised for use in a battery environment"); 334 MODULE_LICENSE("GPL"); 335 336 #ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE 337 struct cpufreq_governor *cpufreq_default_governor(void) 338 { 339 return &CPU_FREQ_GOV_CONSERVATIVE; 340 } 341 #endif 342 343 cpufreq_governor_init(CPU_FREQ_GOV_CONSERVATIVE); 344 cpufreq_governor_exit(CPU_FREQ_GOV_CONSERVATIVE); 345