summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/cpuquiet/governors/balanced.c53
1 files changed, 44 insertions, 9 deletions
diff --git a/drivers/cpuquiet/governors/balanced.c b/drivers/cpuquiet/governors/balanced.c
index 270bbf5d1f28..968344e220d9 100644
--- a/drivers/cpuquiet/governors/balanced.c
+++ b/drivers/cpuquiet/governors/balanced.c
@@ -72,12 +72,13 @@ struct balanced_attribute {
}
/* configurable parameters */
-static unsigned long balance_level = 75;
+static unsigned long balance_level = 60;
static unsigned long idle_bottom_freq;
static unsigned long idle_top_freq;
static unsigned long up_delay;
static unsigned long down_delay;
-
+static unsigned long last_change_time;
+static unsigned long load_sample_rate = 20; // msec
static struct workqueue_struct *balanced_wq;
static struct delayed_work balanced_work;
static BALANCED_STATE balanced_state;
@@ -106,7 +107,7 @@ static void calculate_load_timer(unsigned long data)
do_div(idle_time, elapsed_time);
*load = 100 - idle_time;
}
- mod_timer(&load_timer, jiffies + msecs_to_jiffies(100));
+ mod_timer(&load_timer, jiffies + msecs_to_jiffies(load_sample_rate));
}
static void start_load_timer(void)
@@ -183,6 +184,14 @@ static unsigned int count_slow_cpus(unsigned int limit)
return cnt;
}
+#define NR_FSHIFT 2
+static unsigned int nr_run_thresholds[] = {
+/* 1, 2, 3, 4 - on-line cpus target */
+ 5, 9, 10, UINT_MAX /* avg run threads * 4 (e.g., 9 = 2.25 threads) */
+};
+static unsigned int nr_run_hysteresis = 2; /* 0.5 thread */
+static unsigned int nr_run_last;
+
static CPU_SPEED_BALANCE balanced_speed_balance(void)
{
unsigned long highest_speed = cpu_highest_speed();
@@ -190,14 +199,27 @@ static CPU_SPEED_BALANCE balanced_speed_balance(void)
unsigned long skewed_speed = balanced_speed / 2;
unsigned int nr_cpus = num_online_cpus();
unsigned int max_cpus = pm_qos_request(PM_QOS_MAX_ONLINE_CPUS) ? : 4;
+ unsigned int avg_nr_run = avg_nr_running();
+ unsigned int nr_run;
/* balanced: freq targets for all CPUs are above 50% of highest speed
biased: freq target for at least one CPU is below 50% threshold
skewed: freq targets for at least 2 CPUs are below 25% threshold */
- if (count_slow_cpus(skewed_speed) >= 2 || nr_cpus > max_cpus)
+ for (nr_run = 1; nr_run < ARRAY_SIZE(nr_run_thresholds); nr_run++) {
+ unsigned int nr_threshold = nr_run_thresholds[nr_run - 1];
+ if (nr_run_last <= nr_run)
+ nr_threshold += nr_run_hysteresis;
+ if (avg_nr_run <= (nr_threshold << (FSHIFT - NR_FSHIFT)))
+ break;
+ }
+ nr_run_last = nr_run;
+
+ if (count_slow_cpus(skewed_speed) >= 2 || nr_cpus > max_cpus ||
+ nr_run < nr_cpus)
return CPU_SPEED_SKEWED;
- if (count_slow_cpus(balanced_speed) >= 1 || nr_cpus == max_cpus)
+ if (count_slow_cpus(balanced_speed) >= 1 || nr_cpus == max_cpus ||
+ nr_run <= nr_cpus)
return CPU_SPEED_BIASED;
return CPU_SPEED_BALANCED;
@@ -207,6 +229,8 @@ static void balanced_work_func(struct work_struct *work)
{
bool up = false;
unsigned int cpu = nr_cpu_ids;
+ unsigned long now = jiffies;
+
CPU_SPEED_BALANCE balance;
switch (balanced_state) {
@@ -217,7 +241,7 @@ static void balanced_work_func(struct work_struct *work)
if (cpu < nr_cpu_ids) {
up = false;
queue_delayed_work(balanced_wq,
- &balanced_work, down_delay);
+ &balanced_work, up_delay);
} else
stop_load_timer();
break;
@@ -250,7 +274,11 @@ static void balanced_work_func(struct work_struct *work)
__func__, balanced_state);
}
+ if (!up && ((now - last_change_time) < down_delay))
+ cpu = nr_cpu_ids;
+
if (cpu < nr_cpu_ids) {
+ last_change_time = now;
if (up)
cpuquiet_wake_cpu(cpu);
else
@@ -294,7 +322,7 @@ static int balanced_cpufreq_transition(struct notifier_block *nb,
if (cpu_freq <= idle_bottom_freq) {
balanced_state = DOWN;
queue_delayed_work(balanced_wq,
- &balanced_work, down_delay);
+ &balanced_work, up_delay);
start_load_timer();
}
break;
@@ -357,6 +385,7 @@ BALANCED_ATTRIBUTE(idle_bottom_freq, 0644);
BALANCED_ATTRIBUTE(idle_top_freq, 0644);
BALANCED_ATTRIBUTE(up_delay, 0644);
BALANCED_ATTRIBUTE(down_delay, 0644);
+BALANCED_ATTRIBUTE(load_sample_rate, 0644);
static struct attribute *balanced_attributes[] = {
&balance_level_attr.attr,
@@ -419,6 +448,7 @@ static int balanced_start(void)
{
int err, count;
struct cpufreq_frequency_table *table;
+ struct cpufreq_freqs initial_freq;
err = balanced_sysfs();
if (err)
@@ -431,8 +461,8 @@ static int balanced_start(void)
INIT_DELAYED_WORK(&balanced_work, balanced_work_func);
- up_delay = msecs_to_jiffies(1000);
- down_delay = msecs_to_jiffies(2000);
+ up_delay = msecs_to_jiffies(100);
+ down_delay = msecs_to_jiffies(500);
table = cpufreq_frequency_get_table(0);
for (count = 0; table[count].frequency != CPUFREQ_TABLE_END; count++)
@@ -447,6 +477,11 @@ static int balanced_start(void)
init_timer(&load_timer);
load_timer.function = calculate_load_timer;
+ /*FIXME: Kick start the state machine by faking a freq notification*/
+ initial_freq.new = cpufreq_get(0);
+ if (initial_freq.new != 0)
+ balanced_cpufreq_transition(NULL, CPUFREQ_RESUMECHANGE,
+ &initial_freq);
return 0;
}