ARM: tegra: Prevent LP2 if request is less than target residency
Scott Williams [Fri, 22 Jul 2011 00:26:07 +0000 (17:26 -0700)]
Change-Id: Icc7409b611439ba94ec504579c00ab9227c9a857
Signed-off-by: Scott Williams <scwilliams@nvidia.com>
DW: Split into logical changes
Signed-off-by: Dan Willemsen <dwillemsen@nvidia.com>

Rebase-Id: R4b56e98c821627de480a67c241363608ebfc2f07

arch/arm/mach-tegra/cpuidle-t2.c
arch/arm/mach-tegra/cpuidle.c
arch/arm/mach-tegra/cpuidle.h

index 4666aec..c1f872c 100644 (file)
@@ -135,6 +135,19 @@ static int tegra2_reset_other_cpus(int cpu)
 }
 #endif
 
+bool tegra2_lp2_is_allowed(struct cpuidle_device *dev,
+                       struct cpuidle_state *state)
+{
+       s64 request = ktime_to_us(tick_nohz_get_sleep_length());
+
+       if (request < state->target_residency) {
+               /* Not enough time left to enter LP2 */
+               return false;
+       }
+
+       return true;
+}
+
 static int tegra2_idle_lp2_last(struct cpuidle_device *dev,
                        struct cpuidle_state *state, s64 request)
 {
@@ -146,6 +159,12 @@ static int tegra2_idle_lp2_last(struct cpuidle_device *dev,
        if (tegra2_reset_other_cpus(dev->cpu))
                return -EBUSY;
 
+       if (request < state->target_residency) {
+               /* Not enough time left to enter LP2 */
+               tegra_cpu_wfi();
+               return -EBUSY;
+       }
+
        tegra_idle_lp2_last(request, 0);
 
        for_each_online_cpu(i) {
index a638771..90a4b72 100644 (file)
@@ -130,7 +130,8 @@ static int tegra_idle_enter_lp2(struct cpuidle_device *dev,
        ktime_t enter, exit;
        s64 us;
 
-       if (!lp2_in_idle || lp2_disabled_by_suspend)
+       if (!lp2_in_idle || lp2_disabled_by_suspend ||
+           !tegra_lp2_is_allowed(dev, state))
                return tegra_idle_enter_lp3(dev, state);
 
        local_irq_disable();
index c0fbb45..8f17ba6 100644 (file)
@@ -27,6 +27,8 @@
 void tegra2_idle_lp2(struct cpuidle_device *dev, struct cpuidle_state *state);
 void tegra2_cpu_idle_stats_lp2_ready(unsigned int cpu);
 void tegra2_cpu_idle_stats_lp2_time(unsigned int cpu, s64 us);
+bool tegra2_lp2_is_allowed(struct cpuidle_device *dev,
+                       struct cpuidle_state *state);
 #ifdef CONFIG_DEBUG_FS
 int tegra2_lp2_debug_show(struct seq_file *s, void *data);
 #endif
@@ -54,6 +56,14 @@ static inline void tegra_idle_lp2(struct cpuidle_device *dev,
 #endif
 }
 
+static inline bool tegra_lp2_is_allowed(struct cpuidle_device *dev,
+                       struct cpuidle_state *state)
+{
+#ifdef CONFIG_ARCH_TEGRA_2x_SOC
+       return tegra2_lp2_is_allowed(dev, state);
+#endif
+}
+
 #ifdef CONFIG_DEBUG_FS
 static inline int tegra_lp2_debug_show(struct seq_file *s, void *data)
 {