diff options
-rw-r--r-- | arch/arm/mach-tegra/cpu-tegra.c | 34 | ||||
-rw-r--r-- | arch/arm/mach-tegra/cpu-tegra.h | 10 | ||||
-rw-r--r-- | arch/arm/mach-tegra/cpu-tegra3.c | 17 |
3 files changed, 58 insertions, 3 deletions
diff --git a/arch/arm/mach-tegra/cpu-tegra.c b/arch/arm/mach-tegra/cpu-tegra.c index af505aae9ff3..dc6d36738379 100644 --- a/arch/arm/mach-tegra/cpu-tegra.c +++ b/arch/arm/mach-tegra/cpu-tegra.c @@ -182,6 +182,40 @@ int tegra_edp_update_thermal_zone(int temperature) } EXPORT_SYMBOL_GPL(tegra_edp_update_thermal_zone); +bool tegra_cpu_edp_favor_up(unsigned int n, int mp_overhead) +{ + unsigned int current_limit, next_limit; + + if (n == 0) + return true; + + if (n >= ARRAY_SIZE(cpu_edp_limits->freq_limits)) + return false; + + current_limit = cpu_edp_limits[edp_thermal_index].freq_limits[n-1]; + next_limit = cpu_edp_limits[edp_thermal_index].freq_limits[n]; + + return ((next_limit * (n + 1)) > + (current_limit * n * (100 + mp_overhead) / 100)); +} + +bool tegra_cpu_edp_favor_down(unsigned int n, int mp_overhead) +{ + unsigned int current_limit, next_limit; + + if (n <= 1) + return false; + + if (n > ARRAY_SIZE(cpu_edp_limits->freq_limits)) + return true; + + current_limit = cpu_edp_limits[edp_thermal_index].freq_limits[n-1]; + next_limit = cpu_edp_limits[edp_thermal_index].freq_limits[n-2]; + + return ((next_limit * (n - 1) * (100 + mp_overhead) / 100)) > + (current_limit * n); +} + static int tegra_cpu_edp_notify( struct notifier_block *nb, unsigned long event, void *hcpu) { diff --git a/arch/arm/mach-tegra/cpu-tegra.h b/arch/arm/mach-tegra/cpu-tegra.h index b47828f3c7b9..9a1c05d27ff6 100644 --- a/arch/arm/mach-tegra/cpu-tegra.h +++ b/arch/arm/mach-tegra/cpu-tegra.h @@ -65,4 +65,14 @@ static inline void tegra_auto_hotplug_governor(unsigned int cpu_freq, { } #endif +#ifdef CONFIG_TEGRA_EDP_LIMITS +bool tegra_cpu_edp_favor_up(unsigned int n, int mp_overhead); +bool tegra_cpu_edp_favor_down(unsigned int n, int mp_overhead); +#else +static inline bool tegra_cpu_edp_favor_up(unsigned int n, int mp_overhead) +{ return true; } +static inline bool tegra_cpu_edp_favor_down(unsigned int n, int mp_overhead) +{ return false; } +#endif + #endif /* __MACH_TEGRA_CPU_TEGRA_H */ diff --git a/arch/arm/mach-tegra/cpu-tegra3.c b/arch/arm/mach-tegra/cpu-tegra3.c index e24be2b08510..490ccfbbad00 100644 --- a/arch/arm/mach-tegra/cpu-tegra3.c +++ b/arch/arm/mach-tegra/cpu-tegra3.c @@ -62,6 +62,12 @@ static unsigned int idle_bottom_freq; module_param(idle_top_freq, uint, 0644); module_param(idle_bottom_freq, uint, 0644); +static int mp_overhead = 10; +module_param(mp_overhead, int, 0644); + +static int balance_level = 75; +module_param(balance_level, int, 0644); + static struct clk *cpu_clk; static struct clk *cpu_g_clk; static struct clk *cpu_lp_clk; @@ -182,16 +188,21 @@ enum { TEGRA_CPU_SPEED_SKEWED, }; -static int tegra_cpu_speed_balance(void) +static noinline int tegra_cpu_speed_balance(void) { unsigned long highest_speed = tegra_cpu_highest_speed(); + unsigned long balanced_speed = highest_speed * balance_level / 100; + unsigned long skewed_speed = balanced_speed / 2; + unsigned int nr_cpus = num_online_cpus(); /* 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 (tegra_count_slow_cpus(highest_speed / 4) >= 2) + if ((tegra_count_slow_cpus(skewed_speed) >= 2) || + tegra_cpu_edp_favor_down(nr_cpus, mp_overhead)) return TEGRA_CPU_SPEED_SKEWED; - else if (tegra_count_slow_cpus(highest_speed / 2) >= 1) + else if ((tegra_count_slow_cpus(balanced_speed) >= 1) || + (!tegra_cpu_edp_favor_up(nr_cpus, mp_overhead))) return TEGRA_CPU_SPEED_BIASED; return TEGRA_CPU_SPEED_BALANCED; } |