diff --git a/src/kernel/drivers/cpufreq/cpufreq_interactivex.c b/src/kernel/drivers/cpufreq/cpufreq_interactivex.c index 82df1cbf..99b1f43d 100644 --- a/src/kernel/drivers/cpufreq/cpufreq_interactivex.c +++ b/src/kernel/drivers/cpufreq/cpufreq_interactivex.c @@ -52,15 +52,19 @@ static cpumask_t work_cpumask; static unsigned int suspended = 0; static unsigned int enabled = 0; +static unsigned int suspendfreq = 400000; + +static unsigned int samples = 0; + /* * The minimum ammount of time to spend at a frequency before we can ramp down, - * default is 80ms. + * default is 50ms. */ -#define DEFAULT_MIN_SAMPLE_TIME 80000; +#define DEFAULT_MIN_SAMPLE_TIME 50000; static unsigned long min_sample_time; -#define FREQ_THRESHOLD 1200000; -#define RESUME_SPEED 1200000; +static unsigned int freq_threshold = 1200000; +static unsigned int resume_speed = 1000000; static int cpufreq_governor_interactivex(struct cpufreq_policy *policy, unsigned int event); @@ -103,13 +107,22 @@ static void cpufreq_interactivex_timer(unsigned long data) if (nr_running() < 1) return; - target_freq = policy->max; + // imoseyon - when over 1.8Ghz jump less + if (policy->max > freq_threshold) { + if (samples > 0) { + target_freq = policy->max; + samples = 0; + } else { + samples++; + target_freq = freq_threshold; + } + } else target_freq = policy->max; cpumask_set_cpu(data, &work_cpumask); queue_work(up_wq, &freq_scale_work); return; } - + samples = 0; // reset sample counter /* * There is a window where if the cpu utlization can go from low to high * between the timer expiring, delta_idle will be > 0 and the cpu will @@ -182,8 +195,7 @@ static unsigned int cpufreq_interactivex_calc_freq(unsigned int cpu) cpu_load = 100 * (delta_time - idle_time) / delta_time; - if (cpu_load > 98) newfreq = policy->max; - else newfreq = policy->cur * cpu_load / 100; + newfreq = policy->cur * cpu_load / 100; return newfreq; } @@ -193,25 +205,33 @@ static unsigned int cpufreq_interactivex_calc_freq(unsigned int cpu) static void cpufreq_interactivex_freq_change_time_work(struct work_struct *work) { unsigned int cpu; - unsigned int newtarget; cpumask_t tmp_mask = work_cpumask; - newtarget = FREQ_THRESHOLD; for_each_cpu(cpu, tmp_mask) { - if (!suspended) { - if (target_freq == policy->max) { + if (!suspended && (target_freq >= freq_threshold || target_freq == policy->max) ) { + if (policy->cur < 400000) { + // avoid quick jump from lowest to highest + target_freq = resume_speed; + } if (nr_running() == 1) { cpumask_clear_cpu(cpu, &work_cpumask); return; } -// __cpufreq_driver_target(policy, target_freq, CPUFREQ_RELATION_H); - __cpufreq_driver_target(policy, newtarget, CPUFREQ_RELATION_H); + __cpufreq_driver_target(policy, target_freq, CPUFREQ_RELATION_H); } else { - target_freq = cpufreq_interactivex_calc_freq(cpu); - __cpufreq_driver_target(policy, target_freq, - CPUFREQ_RELATION_L); + if (!suspended) { + target_freq = cpufreq_interactivex_calc_freq(cpu); + __cpufreq_driver_target(policy, target_freq, CPUFREQ_RELATION_L); + } else { // special care when suspended + if (target_freq > suspendfreq) { + __cpufreq_driver_target(policy, suspendfreq, CPUFREQ_RELATION_H); + } else { + target_freq = cpufreq_interactivex_calc_freq(cpu); + if (target_freq < policy->cur) + __cpufreq_driver_target(policy, target_freq, CPUFREQ_RELATION_H); + } + } } - } freq_change_time_in_idle = get_cpu_idle_time_us(cpu, &freq_change_time); cpumask_clear_cpu(cpu, &work_cpumask); } @@ -248,7 +268,7 @@ static void interactivex_suspend(int suspend) { unsigned int max_speed; - max_speed = RESUME_SPEED; + max_speed = resume_speed; if (!enabled) return; if (!suspend) { // resume at max speed: @@ -257,7 +277,7 @@ static void interactivex_suspend(int suspend) pr_info("[imoseyon] interactiveX awake at %d\n", policy->cur); } else { suspended = 1; - __cpufreq_driver_target(policy, policy->min, CPUFREQ_RELATION_L); + __cpufreq_driver_target(policy, suspendfreq, CPUFREQ_RELATION_H); pr_info("[imoseyon] interactiveX suspended at %d\n", policy->cur); } } @@ -301,8 +321,9 @@ static int cpufreq_governor_interactivex(struct cpufreq_policy *new_policy, pm_idle = cpufreq_idle; policy = new_policy; enabled = 1; - register_early_suspend(&interactivex_power_suspend); - pr_info("[imoseyon] interactiveX active\n"); + + register_early_suspend(&interactivex_power_suspend); + pr_info("[imoseyon] interactiveX start - freq_threshold at %d, resume at %d\n", freq_threshold, resume_speed); break; case CPUFREQ_GOV_STOP: @@ -315,8 +336,8 @@ static int cpufreq_governor_interactivex(struct cpufreq_policy *new_policy, pm_idle = pm_idle_old; del_timer(&per_cpu(cpu_timer, new_policy->cpu)); enabled = 0; - unregister_early_suspend(&interactivex_power_suspend); - pr_info("[imoseyon] interactiveX inactive\n"); + unregister_early_suspend(&interactivex_power_suspend); + pr_info("[imoseyon] interactiveX inactive\n"); break; case CPUFREQ_GOV_LIMITS: @@ -346,12 +367,12 @@ static int __init cpufreq_interactivex_init(void) } /* Scale up is high priority */ - up_wq = create_workqueue("kinteractive_up"); + up_wq = create_rt_workqueue("kinteractive_up"); down_wq = create_workqueue("knteractive_down"); INIT_WORK(&freq_scale_work, cpufreq_interactivex_freq_change_time_work); - pr_info("[imoseyon] interactiveX enter\n"); + pr_info("[imoseyon] interactiveX enter\n"); return cpufreq_register_governor(&cpufreq_gov_interactivex); } @@ -375,4 +396,3 @@ MODULE_AUTHOR("Mike Chan "); MODULE_DESCRIPTION("'cpufreq_interactiveX' - A cpufreq governor for " "Latency sensitive workloads"); MODULE_LICENSE("GPL"); - diff --git a/src/kernel/drivers/cpufreq/cpufreq_ondemandx.c b/src/kernel/drivers/cpufreq/cpufreq_ondemandx.c index 95535540..bc84c43b 100644 --- a/src/kernel/drivers/cpufreq/cpufreq_ondemandx.c +++ b/src/kernel/drivers/cpufreq/cpufreq_ondemandx.c @@ -53,7 +53,7 @@ static unsigned int min_sampling_rate; -static unsigned int suspendfreq = 100000; //100mhz +static unsigned int suspendfreq = 400000; #define LATENCY_MULTIPLIER (1000) #define MIN_LATENCY_MULTIPLIER (100)