Merge git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6
[pandora-kernel.git] / drivers / cpufreq / cpufreq_ondemand.c
index 7b50936..c631f27 100644 (file)
@@ -30,6 +30,8 @@
 
 #define DEF_FREQUENCY_DOWN_DIFFERENTIAL                (10)
 #define DEF_FREQUENCY_UP_THRESHOLD             (80)
+#define DEF_SAMPLING_DOWN_FACTOR               (1)
+#define MAX_SAMPLING_DOWN_FACTOR               (100000)
 #define MICRO_FREQUENCY_DOWN_DIFFERENTIAL      (3)
 #define MICRO_FREQUENCY_UP_THRESHOLD           (95)
 #define MICRO_FREQUENCY_MIN_SAMPLE_RATE                (10000)
@@ -82,6 +84,7 @@ struct cpu_dbs_info_s {
        unsigned int freq_lo;
        unsigned int freq_lo_jiffies;
        unsigned int freq_hi_jiffies;
+       unsigned int rate_mult;
        int cpu;
        unsigned int sample_type:1;
        /*
@@ -108,10 +111,12 @@ static struct dbs_tuners {
        unsigned int up_threshold;
        unsigned int down_differential;
        unsigned int ignore_nice;
+       unsigned int sampling_down_factor;
        unsigned int powersave_bias;
        unsigned int io_is_busy;
 } dbs_tuners_ins = {
        .up_threshold = DEF_FREQUENCY_UP_THRESHOLD,
+       .sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR,
        .down_differential = DEF_FREQUENCY_DOWN_DIFFERENTIAL,
        .ignore_nice = 0,
        .powersave_bias = 0,
@@ -259,6 +264,7 @@ static ssize_t show_##file_name                                             \
 show_one(sampling_rate, sampling_rate);
 show_one(io_is_busy, io_is_busy);
 show_one(up_threshold, up_threshold);
+show_one(sampling_down_factor, sampling_down_factor);
 show_one(ignore_nice_load, ignore_nice);
 show_one(powersave_bias, powersave_bias);
 
@@ -340,6 +346,29 @@ static ssize_t store_up_threshold(struct kobject *a, struct attribute *b,
        return count;
 }
 
+static ssize_t store_sampling_down_factor(struct kobject *a,
+                       struct attribute *b, const char *buf, size_t count)
+{
+       unsigned int input, j;
+       int ret;
+       ret = sscanf(buf, "%u", &input);
+
+       if (ret != 1 || input > MAX_SAMPLING_DOWN_FACTOR || input < 1)
+               return -EINVAL;
+       mutex_lock(&dbs_mutex);
+       dbs_tuners_ins.sampling_down_factor = input;
+
+       /* Reset down sampling multiplier in case it was active */
+       for_each_online_cpu(j) {
+               struct cpu_dbs_info_s *dbs_info;
+               dbs_info = &per_cpu(od_cpu_dbs_info, j);
+               dbs_info->rate_mult = 1;
+       }
+       mutex_unlock(&dbs_mutex);
+
+       return count;
+}
+
 static ssize_t store_ignore_nice_load(struct kobject *a, struct attribute *b,
                                      const char *buf, size_t count)
 {
@@ -401,6 +430,7 @@ static ssize_t store_powersave_bias(struct kobject *a, struct attribute *b,
 define_one_global_rw(sampling_rate);
 define_one_global_rw(io_is_busy);
 define_one_global_rw(up_threshold);
+define_one_global_rw(sampling_down_factor);
 define_one_global_rw(ignore_nice_load);
 define_one_global_rw(powersave_bias);
 
@@ -409,6 +439,7 @@ static struct attribute *dbs_attributes[] = {
        &sampling_rate_min.attr,
        &sampling_rate.attr,
        &up_threshold.attr,
+       &sampling_down_factor.attr,
        &ignore_nice_load.attr,
        &powersave_bias.attr,
        &io_is_busy.attr,
@@ -562,6 +593,10 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
 
        /* Check for frequency increase */
        if (max_load_freq > dbs_tuners_ins.up_threshold * policy->cur) {
+               /* If switching to max speed, apply sampling_down_factor */
+               if (policy->cur < policy->max)
+                       this_dbs_info->rate_mult =
+                               dbs_tuners_ins.sampling_down_factor;
                dbs_freq_increase(policy, policy->max);
                return;
        }
@@ -584,6 +619,9 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
                                (dbs_tuners_ins.up_threshold -
                                 dbs_tuners_ins.down_differential);
 
+               /* No longer fully busy, reset rate_mult */
+               this_dbs_info->rate_mult = 1;
+
                if (freq_next < policy->min)
                        freq_next = policy->min;
 
@@ -607,7 +645,8 @@ static void do_dbs_timer(struct work_struct *work)
        int sample_type = dbs_info->sample_type;
 
        /* We want all CPUs to do sampling nearly on same jiffy */
-       int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
+       int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate
+               * dbs_info->rate_mult);
 
        if (num_online_cpus() > 1)
                delay -= jiffies % delay;
@@ -711,6 +750,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
                        }
                }
                this_dbs_info->cpu = cpu;
+               this_dbs_info->rate_mult = 1;
                ondemand_powersave_bias_init_cpu(cpu);
                /*
                 * Start the timerschedule work, when this governor