linux/drivers/cpufreq/cpufreq_conservative.c
<<
>>
Prefs
   1/*
   2 *  drivers/cpufreq/cpufreq_conservative.c
   3 *
   4 *  Copyright (C)  2001 Russell King
   5 *            (C)  2003 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>.
   6 *                      Jun Nakajima <jun.nakajima@intel.com>
   7 *            (C)  2009 Alexander Clouter <alex@digriz.org.uk>
   8 *
   9 * This program is free software; you can redistribute it and/or modify
  10 * it under the terms of the GNU General Public License version 2 as
  11 * published by the Free Software Foundation.
  12 */
  13
  14#include <linux/slab.h>
  15#include "cpufreq_governor.h"
  16
  17struct cs_policy_dbs_info {
  18        struct policy_dbs_info policy_dbs;
  19        unsigned int down_skip;
  20        unsigned int requested_freq;
  21};
  22
  23static inline struct cs_policy_dbs_info *to_dbs_info(struct policy_dbs_info *policy_dbs)
  24{
  25        return container_of(policy_dbs, struct cs_policy_dbs_info, policy_dbs);
  26}
  27
  28struct cs_dbs_tuners {
  29        unsigned int down_threshold;
  30        unsigned int freq_step;
  31};
  32
  33/* Conservative governor macros */
  34#define DEF_FREQUENCY_UP_THRESHOLD              (80)
  35#define DEF_FREQUENCY_DOWN_THRESHOLD            (20)
  36#define DEF_FREQUENCY_STEP                      (5)
  37#define DEF_SAMPLING_DOWN_FACTOR                (1)
  38#define MAX_SAMPLING_DOWN_FACTOR                (10)
  39
  40static inline unsigned int get_freq_step(struct cs_dbs_tuners *cs_tuners,
  41                                         struct cpufreq_policy *policy)
  42{
  43        unsigned int freq_step = (cs_tuners->freq_step * policy->max) / 100;
  44
  45        /* max freq cannot be less than 100. But who knows... */
  46        if (unlikely(freq_step == 0))
  47                freq_step = DEF_FREQUENCY_STEP;
  48
  49        return freq_step;
  50}
  51
  52/*
  53 * Every sampling_rate, we check, if current idle time is less than 20%
  54 * (default), then we try to increase frequency. Every sampling_rate *
  55 * sampling_down_factor, we check, if current idle time is more than 80%
  56 * (default), then we try to decrease frequency
  57 *
  58 * Frequency updates happen at minimum steps of 5% (default) of maximum
  59 * frequency
  60 */
  61static unsigned int cs_dbs_update(struct cpufreq_policy *policy)
  62{
  63        struct policy_dbs_info *policy_dbs = policy->governor_data;
  64        struct cs_policy_dbs_info *dbs_info = to_dbs_info(policy_dbs);
  65        unsigned int requested_freq = dbs_info->requested_freq;
  66        struct dbs_data *dbs_data = policy_dbs->dbs_data;
  67        struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
  68        unsigned int load = dbs_update(policy);
  69        unsigned int freq_step;
  70
  71        /*
  72         * break out if we 'cannot' reduce the speed as the user might
  73         * want freq_step to be zero
  74         */
  75        if (cs_tuners->freq_step == 0)
  76                goto out;
  77
  78        /*
  79         * If requested_freq is out of range, it is likely that the limits
  80         * changed in the meantime, so fall back to current frequency in that
  81         * case.
  82         */
  83        if (requested_freq > policy->max || requested_freq < policy->min)
  84                requested_freq = policy->cur;
  85
  86        freq_step = get_freq_step(cs_tuners, policy);
  87
  88        /*
  89         * Decrease requested_freq one freq_step for each idle period that
  90         * we didn't update the frequency.
  91         */
  92        if (policy_dbs->idle_periods < UINT_MAX) {
  93                unsigned int freq_steps = policy_dbs->idle_periods * freq_step;
  94
  95                if (requested_freq > freq_steps)
  96                        requested_freq -= freq_steps;
  97                else
  98                        requested_freq = policy->min;
  99
 100                policy_dbs->idle_periods = UINT_MAX;
 101        }
 102
 103        /* Check for frequency increase */
 104        if (load > dbs_data->up_threshold) {
 105                dbs_info->down_skip = 0;
 106
 107                /* if we are already at full speed then break out early */
 108                if (requested_freq == policy->max)
 109                        goto out;
 110
 111                requested_freq += freq_step;
 112                if (requested_freq > policy->max)
 113                        requested_freq = policy->max;
 114
 115                __cpufreq_driver_target(policy, requested_freq, CPUFREQ_RELATION_H);
 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, CPUFREQ_RELATION_L);
 139                dbs_info->requested_freq = requested_freq;
 140        }
 141
 142 out:
 143        return dbs_data->sampling_rate;
 144}
 145
 146/************************** sysfs interface ************************/
 147
 148static ssize_t store_sampling_down_factor(struct gov_attr_set *attr_set,
 149                                          const char *buf, size_t count)
 150{
 151        struct dbs_data *dbs_data = to_dbs_data(attr_set);
 152        unsigned int input;
 153        int ret;
 154        ret = sscanf(buf, "%u", &input);
 155
 156        if (ret != 1 || input > MAX_SAMPLING_DOWN_FACTOR || input < 1)
 157                return -EINVAL;
 158
 159        dbs_data->sampling_down_factor = input;
 160        return count;
 161}
 162
 163static ssize_t store_up_threshold(struct gov_attr_set *attr_set,
 164                                  const char *buf, size_t count)
 165{
 166        struct dbs_data *dbs_data = to_dbs_data(attr_set);
 167        struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
 168        unsigned int input;
 169        int ret;
 170        ret = sscanf(buf, "%u", &input);
 171
 172        if (ret != 1 || input > 100 || input <= cs_tuners->down_threshold)
 173                return -EINVAL;
 174
 175        dbs_data->up_threshold = input;
 176        return count;
 177}
 178
 179static ssize_t store_down_threshold(struct gov_attr_set *attr_set,
 180                                    const char *buf, size_t count)
 181{
 182        struct dbs_data *dbs_data = to_dbs_data(attr_set);
 183        struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
 184        unsigned int input;
 185        int ret;
 186        ret = sscanf(buf, "%u", &input);
 187
 188        /* cannot be lower than 1 otherwise freq will not fall */
 189        if (ret != 1 || input < 1 || input > 100 ||
 190                        input >= dbs_data->up_threshold)
 191                return -EINVAL;
 192
 193        cs_tuners->down_threshold = input;
 194        return count;
 195}
 196
 197static ssize_t store_ignore_nice_load(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
 222static ssize_t store_freq_step(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
 245gov_show_one_common(sampling_rate);
 246gov_show_one_common(sampling_down_factor);
 247gov_show_one_common(up_threshold);
 248gov_show_one_common(ignore_nice_load);
 249gov_show_one(cs, down_threshold);
 250gov_show_one(cs, freq_step);
 251
 252gov_attr_rw(sampling_rate);
 253gov_attr_rw(sampling_down_factor);
 254gov_attr_rw(up_threshold);
 255gov_attr_rw(ignore_nice_load);
 256gov_attr_rw(down_threshold);
 257gov_attr_rw(freq_step);
 258
 259static struct attribute *cs_attributes[] = {
 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
 269/************************** sysfs end ************************/
 270
 271static struct policy_dbs_info *cs_alloc(void)
 272{
 273        struct cs_policy_dbs_info *dbs_info;
 274
 275        dbs_info = kzalloc(sizeof(*dbs_info), GFP_KERNEL);
 276        return dbs_info ? &dbs_info->policy_dbs : NULL;
 277}
 278
 279static void cs_free(struct policy_dbs_info *policy_dbs)
 280{
 281        kfree(to_dbs_info(policy_dbs));
 282}
 283
 284static int cs_init(struct dbs_data *dbs_data)
 285{
 286        struct cs_dbs_tuners *tuners;
 287
 288        tuners = kzalloc(sizeof(*tuners), GFP_KERNEL);
 289        if (!tuners)
 290                return -ENOMEM;
 291
 292        tuners->down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD;
 293        tuners->freq_step = DEF_FREQUENCY_STEP;
 294        dbs_data->up_threshold = DEF_FREQUENCY_UP_THRESHOLD;
 295        dbs_data->sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR;
 296        dbs_data->ignore_nice_load = 0;
 297        dbs_data->tuners = tuners;
 298
 299        return 0;
 300}
 301
 302static void cs_exit(struct dbs_data *dbs_data)
 303{
 304        kfree(dbs_data->tuners);
 305}
 306
 307static void cs_start(struct cpufreq_policy *policy)
 308{
 309        struct cs_policy_dbs_info *dbs_info = to_dbs_info(policy->governor_data);
 310
 311        dbs_info->down_skip = 0;
 312        dbs_info->requested_freq = policy->cur;
 313}
 314
 315static struct dbs_governor cs_governor = {
 316        .gov = CPUFREQ_DBS_GOVERNOR_INITIALIZER("conservative"),
 317        .kobj_type = { .default_attrs = cs_attributes },
 318        .gov_dbs_update = cs_dbs_update,
 319        .alloc = cs_alloc,
 320        .free = cs_free,
 321        .init = cs_init,
 322        .exit = cs_exit,
 323        .start = cs_start,
 324};
 325
 326#define CPU_FREQ_GOV_CONSERVATIVE       (&cs_governor.gov)
 327
 328static int __init cpufreq_gov_dbs_init(void)
 329{
 330        return cpufreq_register_governor(CPU_FREQ_GOV_CONSERVATIVE);
 331}
 332
 333static void __exit cpufreq_gov_dbs_exit(void)
 334{
 335        cpufreq_unregister_governor(CPU_FREQ_GOV_CONSERVATIVE);
 336}
 337
 338MODULE_AUTHOR("Alexander Clouter <alex@digriz.org.uk>");
 339MODULE_DESCRIPTION("'cpufreq_conservative' - A dynamic cpufreq governor for "
 340                "Low Latency Frequency Transition capable processors "
 341                "optimised for use in a battery environment");
 342MODULE_LICENSE("GPL");
 343
 344#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE
 345struct cpufreq_governor *cpufreq_default_governor(void)
 346{
 347        return CPU_FREQ_GOV_CONSERVATIVE;
 348}
 349
 350fs_initcall(cpufreq_gov_dbs_init);
 351#else
 352module_init(cpufreq_gov_dbs_init);
 353#endif
 354module_exit(cpufreq_gov_dbs_exit);
 355