ARM: tegra: power: Tune Tegra3 hotplug algorithm
Alex Frid [Wed, 24 Aug 2011 05:52:42 +0000 (22:52 -0700)]
- 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

arch/arm/mach-tegra/cpu-tegra.c
arch/arm/mach-tegra/cpu-tegra.h
arch/arm/mach-tegra/cpu-tegra3.c

index 902c515..b87e795 100644 (file)
@@ -177,6 +177,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)
 {
index 4ffdfb9..348d138 100644 (file)
@@ -63,4 +63,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 */
index 3c46b1f..38c1748 100644 (file)
@@ -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;
 }