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/cpufreq.h>
  15#include <linux/init.h>
  16#include <linux/kernel.h>
  17#include <linux/kernel_stat.h>
  18#include <linux/kobject.h>
  19#include <linux/module.h>
  20#include <linux/mutex.h>
  21#include <linux/notifier.h>
  22#include <linux/percpu-defs.h>
  23#include <linux/sysfs.h>
  24#include <linux/types.h>
  25
  26#include "cpufreq_governor.h"
  27
  28/* Conservative governor macors */
  29#define DEF_FREQUENCY_UP_THRESHOLD              (80)
  30#define DEF_FREQUENCY_DOWN_THRESHOLD            (20)
  31#define DEF_SAMPLING_DOWN_FACTOR                (1)
  32#define MAX_SAMPLING_DOWN_FACTOR                (10)
  33
  34static struct dbs_data cs_dbs_data;
  35static DEFINE_PER_CPU(struct cs_cpu_dbs_info_s, cs_cpu_dbs_info);
  36
  37static struct cs_dbs_tuners cs_tuners = {
  38        .up_threshold = DEF_FREQUENCY_UP_THRESHOLD,
  39        .down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD,
  40        .sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR,
  41        .ignore_nice = 0,
  42        .freq_step = 5,
  43};
  44
  45/*
  46 * Every sampling_rate, we check, if current idle time is less than 20%
  47 * (default), then we try to increase frequency Every sampling_rate *
  48 * sampling_down_factor, we check, if current idle time is more than 80%, then
  49 * we try to decrease frequency
  50 *
  51 * Any frequency increase takes it to the maximum frequency. Frequency reduction
  52 * happens at minimum steps of 5% (default) of maximum frequency
  53 */
  54static void cs_check_cpu(int cpu, unsigned int load)
  55{
  56        struct cs_cpu_dbs_info_s *dbs_info = &per_cpu(cs_cpu_dbs_info, cpu);
  57        struct cpufreq_policy *policy = dbs_info->cdbs.cur_policy;
  58        unsigned int freq_target;
  59
  60        /*
  61         * break out if we 'cannot' reduce the speed as the user might
  62         * want freq_step to be zero
  63         */
  64        if (cs_tuners.freq_step == 0)
  65                return;
  66
  67        /* Check for frequency increase */
  68        if (load > cs_tuners.up_threshold) {
  69                dbs_info->down_skip = 0;
  70
  71                /* if we are already at full speed then break out early */
  72                if (dbs_info->requested_freq == policy->max)
  73                        return;
  74
  75                freq_target = (cs_tuners.freq_step * policy->max) / 100;
  76
  77                /* max freq cannot be less than 100. But who knows.... */
  78                if (unlikely(freq_target == 0))
  79                        freq_target = 5;
  80
  81                dbs_info->requested_freq += freq_target;
  82                if (dbs_info->requested_freq > policy->max)
  83                        dbs_info->requested_freq = policy->max;
  84
  85                __cpufreq_driver_target(policy, dbs_info->requested_freq,
  86                        CPUFREQ_RELATION_H);
  87                return;
  88        }
  89
  90        /*
  91         * The optimal frequency is the frequency that is the lowest that can
  92         * support the current CPU usage without triggering the up policy. To be
  93         * safe, we focus 10 points under the threshold.
  94         */
  95        if (load < (cs_tuners.down_threshold - 10)) {
  96                freq_target = (cs_tuners.freq_step * policy->max) / 100;
  97
  98                dbs_info->requested_freq -= freq_target;
  99                if (dbs_info->requested_freq < policy->min)
 100                        dbs_info->requested_freq = policy->min;
 101
 102                /*
 103                 * if we cannot reduce the frequency anymore, break out early
 104                 */
 105                if (policy->cur == policy->min)
 106                        return;
 107
 108                __cpufreq_driver_target(policy, dbs_info->requested_freq,
 109                                CPUFREQ_RELATION_H);
 110                return;
 111        }
 112}
 113
 114static void cs_dbs_timer(struct work_struct *work)
 115{
 116        struct cs_cpu_dbs_info_s *dbs_info = container_of(work,
 117                        struct cs_cpu_dbs_info_s, cdbs.work.work);
 118        unsigned int cpu = dbs_info->cdbs.cpu;
 119        int delay = delay_for_sampling_rate(cs_tuners.sampling_rate);
 120
 121        mutex_lock(&dbs_info->cdbs.timer_mutex);
 122
 123        dbs_check_cpu(&cs_dbs_data, cpu);
 124
 125        schedule_delayed_work_on(cpu, &dbs_info->cdbs.work, delay);
 126        mutex_unlock(&dbs_info->cdbs.timer_mutex);
 127}
 128
 129static int dbs_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
 130                void *data)
 131{
 132        struct cpufreq_freqs *freq = data;
 133        struct cs_cpu_dbs_info_s *dbs_info =
 134                                        &per_cpu(cs_cpu_dbs_info, freq->cpu);
 135        struct cpufreq_policy *policy;
 136
 137        if (!dbs_info->enable)
 138                return 0;
 139
 140        policy = dbs_info->cdbs.cur_policy;
 141
 142        /*
 143         * we only care if our internally tracked freq moves outside the 'valid'
 144         * ranges of freqency available to us otherwise we do not change it
 145        */
 146        if (dbs_info->requested_freq > policy->max
 147                        || dbs_info->requested_freq < policy->min)
 148                dbs_info->requested_freq = freq->new;
 149
 150        return 0;
 151}
 152
 153/************************** sysfs interface ************************/
 154static ssize_t show_sampling_rate_min(struct kobject *kobj,
 155                                      struct attribute *attr, char *buf)
 156{
 157        return sprintf(buf, "%u\n", cs_dbs_data.min_sampling_rate);
 158}
 159
 160static ssize_t store_sampling_down_factor(struct kobject *a,
 161                                          struct attribute *b,
 162                                          const char *buf, size_t count)
 163{
 164        unsigned int input;
 165        int ret;
 166        ret = sscanf(buf, "%u", &input);
 167
 168        if (ret != 1 || input > MAX_SAMPLING_DOWN_FACTOR || input < 1)
 169                return -EINVAL;
 170
 171        cs_tuners.sampling_down_factor = input;
 172        return count;
 173}
 174
 175static ssize_t store_sampling_rate(struct kobject *a, struct attribute *b,
 176                                   const char *buf, size_t count)
 177{
 178        unsigned int input;
 179        int ret;
 180        ret = sscanf(buf, "%u", &input);
 181
 182        if (ret != 1)
 183                return -EINVAL;
 184
 185        cs_tuners.sampling_rate = max(input, cs_dbs_data.min_sampling_rate);
 186        return count;
 187}
 188
 189static ssize_t store_up_threshold(struct kobject *a, struct attribute *b,
 190                                  const char *buf, size_t count)
 191{
 192        unsigned int input;
 193        int ret;
 194        ret = sscanf(buf, "%u", &input);
 195
 196        if (ret != 1 || input > 100 || input <= cs_tuners.down_threshold)
 197                return -EINVAL;
 198
 199        cs_tuners.up_threshold = input;
 200        return count;
 201}
 202
 203static ssize_t store_down_threshold(struct kobject *a, struct attribute *b,
 204                                    const char *buf, size_t count)
 205{
 206        unsigned int input;
 207        int ret;
 208        ret = sscanf(buf, "%u", &input);
 209
 210        /* cannot be lower than 11 otherwise freq will not fall */
 211        if (ret != 1 || input < 11 || input > 100 ||
 212                        input >= cs_tuners.up_threshold)
 213                return -EINVAL;
 214
 215        cs_tuners.down_threshold = input;
 216        return count;
 217}
 218
 219static ssize_t store_ignore_nice_load(struct kobject *a, struct attribute *b,
 220                                      const char *buf, size_t count)
 221{
 222        unsigned int input, j;
 223        int ret;
 224
 225        ret = sscanf(buf, "%u", &input);
 226        if (ret != 1)
 227                return -EINVAL;
 228
 229        if (input > 1)
 230                input = 1;
 231
 232        if (input == cs_tuners.ignore_nice) /* nothing to do */
 233                return count;
 234
 235        cs_tuners.ignore_nice = input;
 236
 237        /* we need to re-evaluate prev_cpu_idle */
 238        for_each_online_cpu(j) {
 239                struct cs_cpu_dbs_info_s *dbs_info;
 240                dbs_info = &per_cpu(cs_cpu_dbs_info, j);
 241                dbs_info->cdbs.prev_cpu_idle = get_cpu_idle_time(j,
 242                                                &dbs_info->cdbs.prev_cpu_wall);
 243                if (cs_tuners.ignore_nice)
 244                        dbs_info->cdbs.prev_cpu_nice =
 245                                kcpustat_cpu(j).cpustat[CPUTIME_NICE];
 246        }
 247        return count;
 248}
 249
 250static ssize_t store_freq_step(struct kobject *a, struct attribute *b,
 251                               const char *buf, size_t count)
 252{
 253        unsigned int input;
 254        int ret;
 255        ret = sscanf(buf, "%u", &input);
 256
 257        if (ret != 1)
 258                return -EINVAL;
 259
 260        if (input > 100)
 261                input = 100;
 262
 263        /*
 264         * no need to test here if freq_step is zero as the user might actually
 265         * want this, they would be crazy though :)
 266         */
 267        cs_tuners.freq_step = input;
 268        return count;
 269}
 270
 271show_one(cs, sampling_rate, sampling_rate);
 272show_one(cs, sampling_down_factor, sampling_down_factor);
 273show_one(cs, up_threshold, up_threshold);
 274show_one(cs, down_threshold, down_threshold);
 275show_one(cs, ignore_nice_load, ignore_nice);
 276show_one(cs, freq_step, freq_step);
 277
 278define_one_global_rw(sampling_rate);
 279define_one_global_rw(sampling_down_factor);
 280define_one_global_rw(up_threshold);
 281define_one_global_rw(down_threshold);
 282define_one_global_rw(ignore_nice_load);
 283define_one_global_rw(freq_step);
 284define_one_global_ro(sampling_rate_min);
 285
 286static struct attribute *dbs_attributes[] = {
 287        &sampling_rate_min.attr,
 288        &sampling_rate.attr,
 289        &sampling_down_factor.attr,
 290        &up_threshold.attr,
 291        &down_threshold.attr,
 292        &ignore_nice_load.attr,
 293        &freq_step.attr,
 294        NULL
 295};
 296
 297static struct attribute_group cs_attr_group = {
 298        .attrs = dbs_attributes,
 299        .name = "conservative",
 300};
 301
 302/************************** sysfs end ************************/
 303
 304define_get_cpu_dbs_routines(cs_cpu_dbs_info);
 305
 306static struct notifier_block cs_cpufreq_notifier_block = {
 307        .notifier_call = dbs_cpufreq_notifier,
 308};
 309
 310static struct cs_ops cs_ops = {
 311        .notifier_block = &cs_cpufreq_notifier_block,
 312};
 313
 314static struct dbs_data cs_dbs_data = {
 315        .governor = GOV_CONSERVATIVE,
 316        .attr_group = &cs_attr_group,
 317        .tuners = &cs_tuners,
 318        .get_cpu_cdbs = get_cpu_cdbs,
 319        .get_cpu_dbs_info_s = get_cpu_dbs_info_s,
 320        .gov_dbs_timer = cs_dbs_timer,
 321        .gov_check_cpu = cs_check_cpu,
 322        .gov_ops = &cs_ops,
 323};
 324
 325static int cs_cpufreq_governor_dbs(struct cpufreq_policy *policy,
 326                                   unsigned int event)
 327{
 328        return cpufreq_governor_dbs(&cs_dbs_data, policy, event);
 329}
 330
 331#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE
 332static
 333#endif
 334struct cpufreq_governor cpufreq_gov_conservative = {
 335        .name                   = "conservative",
 336        .governor               = cs_cpufreq_governor_dbs,
 337        .max_transition_latency = TRANSITION_LATENCY_LIMIT,
 338        .owner                  = THIS_MODULE,
 339};
 340
 341static int __init cpufreq_gov_dbs_init(void)
 342{
 343        mutex_init(&cs_dbs_data.mutex);
 344        return cpufreq_register_governor(&cpufreq_gov_conservative);
 345}
 346
 347static void __exit cpufreq_gov_dbs_exit(void)
 348{
 349        cpufreq_unregister_governor(&cpufreq_gov_conservative);
 350}
 351
 352MODULE_AUTHOR("Alexander Clouter <alex@digriz.org.uk>");
 353MODULE_DESCRIPTION("'cpufreq_conservative' - A dynamic cpufreq governor for "
 354                "Low Latency Frequency Transition capable processors "
 355                "optimised for use in a battery environment");
 356MODULE_LICENSE("GPL");
 357
 358#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE
 359fs_initcall(cpufreq_gov_dbs_init);
 360#else
 361module_init(cpufreq_gov_dbs_init);
 362#endif
 363module_exit(cpufreq_gov_dbs_exit);
 364
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.