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