summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra
diff options
context:
space:
mode:
authorScott Williams <scwilliams@nvidia.com>2011-08-23 11:00:41 -0700
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:48:30 -0800
commitebfe732c0f6f6f34900d1ce00c97aa15201408a5 (patch)
tree66f66bd431cd41997f19aa36f83bb4c7dd53fdb5 /arch/arm/mach-tegra
parentf9c7da35d00782b79d63b62fac71b00ea980b157 (diff)
ARM: tegra: power: Fix premature clock event broadcast mode
Do not switch to clock event broadcast mode until the final CPU is going into LP2. Switching into broadcast mode on the secondary CPUs can cause double ticking and/or kernel panics on the primary. Change-Id: I92076f053bdae7de57e5d7453170b43558b094cc Signed-off-by: Scott Williams <scwilliams@nvidia.com> Reviewed-on: http://git-master/r/48743 Reviewed-by: Jin Qian <jqian@nvidia.com> Tested-by: Jin Qian <jqian@nvidia.com> Reviewed-by: Daniel Willemsen <dwillemsen@nvidia.com> Rebase-Id: R18bd87d171133d210a5edf732960d1c011e1e9a5
Diffstat (limited to 'arch/arm/mach-tegra')
-rw-r--r--arch/arm/mach-tegra/cpuidle-t2.c4
-rw-r--r--arch/arm/mach-tegra/cpuidle-t3.c3
-rw-r--r--arch/arm/mach-tegra/cpuidle.c6
3 files changed, 7 insertions, 6 deletions
diff --git a/arch/arm/mach-tegra/cpuidle-t2.c b/arch/arm/mach-tegra/cpuidle-t2.c
index 947a0038fb8e..8428bc4cfd3e 100644
--- a/arch/arm/mach-tegra/cpuidle-t2.c
+++ b/arch/arm/mach-tegra/cpuidle-t2.c
@@ -221,12 +221,16 @@ static int tegra2_idle_lp2_cpu_0(struct cpuidle_device *dev,
idle_stats.lp2_count++;
idle_stats.lp2_count_bin[bin]++;
+ clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu);
+
if (tegra_idle_lp2_last(sleep_time, 0) == 0)
sleep_completed = true;
else {
int irq = tegra_gic_pending_interrupt();
idle_stats.lp2_int_count[irq]++;
}
+
+ clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
}
for_each_online_cpu(i) {
diff --git a/arch/arm/mach-tegra/cpuidle-t3.c b/arch/arm/mach-tegra/cpuidle-t3.c
index 34bb3d0b13c7..9393ea3a51da 100644
--- a/arch/arm/mach-tegra/cpuidle-t3.c
+++ b/arch/arm/mach-tegra/cpuidle-t3.c
@@ -214,6 +214,7 @@ static void tegra3_idle_enter_lp2_cpu_0(struct cpuidle_device *dev,
idle_stats.lp2_count_bin[bin]++;
trace_power_start(POWER_CSTATE, 2, dev->cpu);
+ clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu);
if (tegra_idle_lp2_last(sleep_time, 0) == 0)
sleep_completed = true;
@@ -221,6 +222,8 @@ static void tegra3_idle_enter_lp2_cpu_0(struct cpuidle_device *dev,
int irq = tegra_gic_pending_interrupt();
idle_stats.lp2_int_count[irq]++;
}
+
+ clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
}
#ifdef CONFIG_SMP
diff --git a/arch/arm/mach-tegra/cpuidle.c b/arch/arm/mach-tegra/cpuidle.c
index 92fbc61f469d..3a2452104f46 100644
--- a/arch/arm/mach-tegra/cpuidle.c
+++ b/arch/arm/mach-tegra/cpuidle.c
@@ -116,13 +116,7 @@ static int tegra_idle_enter_lp2(struct cpuidle_device *dev,
enter = ktime_get();
tegra_cpu_idle_stats_lp2_ready(dev->cpu);
-
- /* Shut down the CPU local timer and switch timekeeping to the
- global system timer. */
- clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu);
tegra_idle_lp2(dev, state);
- /* Switch timekeeping back to the CPU local timer. */
- clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
exit = ktime_sub(ktime_get(), enter);
us = ktime_to_us(exit);