Branch data Line data Source code
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 : 0 : unsigned int freq_step = (cs_tuners->freq_step * policy->max) / 100; 41 : : 42 : : /* max freq cannot be less than 100. But who knows... */ 43 : 0 : 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 : 0 : static unsigned int cs_dbs_update(struct cpufreq_policy *policy) 59 : : { 60 : 0 : struct policy_dbs_info *policy_dbs = policy->governor_data; 61 : : struct cs_policy_dbs_info *dbs_info = to_dbs_info(policy_dbs); 62 : 0 : unsigned int requested_freq = dbs_info->requested_freq; 63 : 0 : struct dbs_data *dbs_data = policy_dbs->dbs_data; 64 : 0 : struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; 65 : 0 : 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 : 0 : 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 : 0 : if (requested_freq > policy->max || requested_freq < policy->min) { 81 : 0 : requested_freq = policy->cur; 82 : 0 : 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 : 0 : if (policy_dbs->idle_periods < UINT_MAX) { 92 : 0 : unsigned int freq_steps = policy_dbs->idle_periods * freq_step; 93 : : 94 : 0 : if (requested_freq > policy->min + freq_steps) 95 : 0 : requested_freq -= freq_steps; 96 : : else 97 : : requested_freq = policy->min; 98 : : 99 : 0 : policy_dbs->idle_periods = UINT_MAX; 100 : : } 101 : : 102 : : /* Check for frequency increase */ 103 : 0 : if (load > dbs_data->up_threshold) { 104 : 0 : dbs_info->down_skip = 0; 105 : : 106 : : /* if we are already at full speed then break out early */ 107 : 0 : if (requested_freq == policy->max) 108 : : goto out; 109 : : 110 : 0 : requested_freq += freq_step; 111 : 0 : if (requested_freq > policy->max) 112 : : requested_freq = policy->max; 113 : : 114 : 0 : __cpufreq_driver_target(policy, requested_freq, CPUFREQ_RELATION_H); 115 : 0 : dbs_info->requested_freq = requested_freq; 116 : 0 : goto out; 117 : : } 118 : : 119 : : /* if sampling_down_factor is active break out early */ 120 : 0 : if (++dbs_info->down_skip < dbs_data->sampling_down_factor) 121 : : goto out; 122 : 0 : dbs_info->down_skip = 0; 123 : : 124 : : /* Check for frequency decrease */ 125 : 0 : if (load < cs_tuners->down_threshold) { 126 : : /* 127 : : * if we cannot reduce the frequency anymore, break out early 128 : : */ 129 : 0 : if (requested_freq == policy->min) 130 : : goto out; 131 : : 132 : 0 : if (requested_freq > freq_step) 133 : 0 : requested_freq -= freq_step; 134 : : else 135 : : requested_freq = policy->min; 136 : : 137 : 0 : __cpufreq_driver_target(policy, requested_freq, CPUFREQ_RELATION_L); 138 : 0 : dbs_info->requested_freq = requested_freq; 139 : : } 140 : : 141 : : out: 142 : 0 : return dbs_data->sampling_rate; 143 : : } 144 : : 145 : : /************************** sysfs interface ************************/ 146 : : 147 : 0 : 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 : 0 : ret = sscanf(buf, "%u", &input); 154 : : 155 : 0 : if (ret != 1 || input > MAX_SAMPLING_DOWN_FACTOR || input < 1) 156 : : return -EINVAL; 157 : : 158 : 0 : dbs_data->sampling_down_factor = input; 159 : 0 : return count; 160 : : } 161 : : 162 : 0 : 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 : 0 : struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; 167 : : unsigned int input; 168 : : int ret; 169 : 0 : ret = sscanf(buf, "%u", &input); 170 : : 171 : 0 : if (ret != 1 || input > 100 || input <= cs_tuners->down_threshold) 172 : : return -EINVAL; 173 : : 174 : 0 : dbs_data->up_threshold = input; 175 : 0 : return count; 176 : : } 177 : : 178 : 0 : 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 : 0 : struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; 183 : : unsigned int input; 184 : : int ret; 185 : 0 : ret = sscanf(buf, "%u", &input); 186 : : 187 : : /* cannot be lower than 1 otherwise freq will not fall */ 188 : 0 : if (ret != 1 || input < 1 || input > 100 || 189 : 0 : input >= dbs_data->up_threshold) 190 : : return -EINVAL; 191 : : 192 : 0 : cs_tuners->down_threshold = input; 193 : 0 : return count; 194 : : } 195 : : 196 : 0 : 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 : 0 : ret = sscanf(buf, "%u", &input); 204 : 0 : if (ret != 1) 205 : : return -EINVAL; 206 : : 207 : 0 : if (input > 1) 208 : 0 : input = 1; 209 : : 210 : 0 : if (input == dbs_data->ignore_nice_load) /* nothing to do */ 211 : 0 : return count; 212 : : 213 : 0 : dbs_data->ignore_nice_load = input; 214 : : 215 : : /* we need to re-evaluate prev_cpu_idle */ 216 : 0 : gov_update_cpu_data(dbs_data); 217 : : 218 : 0 : return count; 219 : : } 220 : : 221 : 0 : 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 : 0 : struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; 226 : : unsigned int input; 227 : : int ret; 228 : 0 : ret = sscanf(buf, "%u", &input); 229 : : 230 : 0 : if (ret != 1) 231 : : return -EINVAL; 232 : : 233 : 0 : if (input > 100) 234 : 0 : 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 : 0 : cs_tuners->freq_step = input; 241 : 0 : return count; 242 : : } 243 : : 244 : 0 : gov_show_one_common(sampling_rate); 245 : 0 : gov_show_one_common(sampling_down_factor); 246 : 0 : gov_show_one_common(up_threshold); 247 : 0 : gov_show_one_common(ignore_nice_load); 248 : 0 : gov_show_one(cs, down_threshold); 249 : 0 : 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 : 0 : static struct policy_dbs_info *cs_alloc(void) 271 : : { 272 : : struct cs_policy_dbs_info *dbs_info; 273 : : 274 : 0 : dbs_info = kzalloc(sizeof(*dbs_info), GFP_KERNEL); 275 : 0 : return dbs_info ? &dbs_info->policy_dbs : NULL; 276 : : } 277 : : 278 : 0 : static void cs_free(struct policy_dbs_info *policy_dbs) 279 : : { 280 : 0 : kfree(to_dbs_info(policy_dbs)); 281 : 0 : } 282 : : 283 : 0 : static int cs_init(struct dbs_data *dbs_data) 284 : : { 285 : : struct cs_dbs_tuners *tuners; 286 : : 287 : 0 : tuners = kzalloc(sizeof(*tuners), GFP_KERNEL); 288 : 0 : if (!tuners) 289 : : return -ENOMEM; 290 : : 291 : 0 : tuners->down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD; 292 : 0 : tuners->freq_step = DEF_FREQUENCY_STEP; 293 : 0 : dbs_data->up_threshold = DEF_FREQUENCY_UP_THRESHOLD; 294 : 0 : dbs_data->sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR; 295 : 0 : dbs_data->ignore_nice_load = 0; 296 : 0 : dbs_data->tuners = tuners; 297 : : 298 : 0 : return 0; 299 : : } 300 : : 301 : 0 : static void cs_exit(struct dbs_data *dbs_data) 302 : : { 303 : 0 : kfree(dbs_data->tuners); 304 : 0 : } 305 : : 306 : 0 : static void cs_start(struct cpufreq_policy *policy) 307 : : { 308 : 0 : struct cs_policy_dbs_info *dbs_info = to_dbs_info(policy->governor_data); 309 : : 310 : 0 : dbs_info->down_skip = 0; 311 : 0 : dbs_info->requested_freq = policy->cur; 312 : 0 : } 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 : 3 : static int __init cpufreq_gov_dbs_init(void) 328 : : { 329 : 3 : return cpufreq_register_governor(CPU_FREQ_GOV_CONSERVATIVE); 330 : : } 331 : : 332 : 0 : static void __exit cpufreq_gov_dbs_exit(void) 333 : : { 334 : 0 : cpufreq_unregister_governor(CPU_FREQ_GOV_CONSERVATIVE); 335 : 0 : } 336 : : 337 : : MODULE_AUTHOR("Alexander Clouter <alex@digriz.org.uk>"); 338 : : MODULE_DESCRIPTION("'cpufreq_conservative' - A dynamic cpufreq governor for " 339 : : "Low Latency Frequency Transition capable processors " 340 : : "optimised for use in a battery environment"); 341 : : MODULE_LICENSE("GPL"); 342 : : 343 : : #ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE 344 : : struct cpufreq_governor *cpufreq_default_governor(void) 345 : : { 346 : : return CPU_FREQ_GOV_CONSERVATIVE; 347 : : } 348 : : 349 : : fs_initcall(cpufreq_gov_dbs_init); 350 : : #else 351 : : module_init(cpufreq_gov_dbs_init); 352 : : #endif 353 : : module_exit(cpufreq_gov_dbs_exit);