summaryrefslogtreecommitdiff
path: root/arch/arm
diff options
context:
space:
mode:
authorAlex Frid <afrid@nvidia.com>2011-08-23 22:52:42 -0700
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:48:47 -0800
commit5a8cb95d768cfd40252cf3b1cd15a97f52db5143 (patch)
treed2b2c7f103e8ca0c189dbfe5d3adf355bd3912fb /arch/arm
parente06d79129a87936fc074afc1f3da3c9e5c4cf194 (diff)
ARM: tegra: power: Tune Tegra3 hotplug algorithm
- Account for EDP affect on total available MIPS when bringing on-line (removing off-line) new cpu core. Add multi-core overhead (in percent) as a parameter - set by default to 10%. - Add balance level parameter: level value (in percent) defines minimum speed ratio used by hotplug algorithm to determine if current CPU cores are balanced, so that another core may be brought on-line. By default set to 75% Added tunables: /sys/module/cpu_tegra3/parameters/mp_overhead /sys/module/cpu_tegra3/parameters/balance_level Bug 865176 Bug 867186 Original-Change-Id: I6f2e175e0b5ed14c4b85794949c1e65d0e7f4a36 Reviewed-on: http://git-master/r/49772 Reviewed-by: Scott Williams <scwilliams@nvidia.com> Reviewed-by: Peter Boonstoppel <pboonstoppel@nvidia.com> Tested-by: Peter Boonstoppel <pboonstoppel@nvidia.com> Tested-by: Aleksandr Frid <afrid@nvidia.com> Reviewed-by: Yu-Huan Hsu <yhsu@nvidia.com> Reviewed-by: Diwakar Tundlam <dtundlam@nvidia.com> Rebase-Id: Rcfefb570c30bf78f6eae155c3f3f7547ac64f128
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/mach-tegra/cpu-tegra.c34
-rw-r--r--arch/arm/mach-tegra/cpu-tegra.h10
-rw-r--r--arch/arm/mach-tegra/cpu-tegra3.c17
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 2f3fcc8de945..3711b9f2dc97 100644
--- a/arch/arm/mach-tegra/cpu-tegra.c
+++ b/arch/arm/mach-tegra/cpu-tegra.c
@@ -180,6 +180,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 9dfa40dcef67..c55cdcc748ed 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;
}