From f1be3a4538b750d063683e771cdea6657b58948a Mon Sep 17 00:00:00 2001 From: Ning Jiang Date: Fri, 29 Mar 2013 16:03:51 +0800 Subject: [PATCH] ARM: timer: Shutdown clock event device when stopping local timer Currently there are two problems when we try to stop local timer. First, it calls set_mode function directly so mode state is not updated for the clock event device. Second, it makes the device unused instead of shutdown. A subtle error will happen because of it. When a cpu is plugged out it will stop the local timer. It will call tick_nohz_idle_enter() in idle thread afterwards. It will cancel the sched timer and try to reprogram the next event. This is wrong since the local timer is supposed to be stopped. The right way to stop the local timer is to shutdown it by calling clockevents_set_mode(). Thus when we try to reprogram the clock event device, it will return directly without doing anything since the clock mode is CLOCK_EVT_MODE_SHUTDOWN. Signed-off-by: Ning Jiang --- arch/arm/kernel/smp_twd.c | 2 +- arch/arm/mach-exynos/mct.c | 2 +- arch/arm/mach-msm/timer.c | 2 +- drivers/clocksource/arm_arch_timer.c | 2 +- drivers/clocksource/time-armada-370-xp.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c index 3f25650..00fee36 100644 --- a/arch/arm/kernel/smp_twd.c +++ b/arch/arm/kernel/smp_twd.c @@ -92,7 +92,7 @@ static int twd_timer_ack(void) static void twd_timer_stop(struct clock_event_device *clk) { - twd_set_mode(CLOCK_EVT_MODE_UNUSED, clk); + clockevents_shutdown(clk); disable_percpu_irq(clk->irq); } diff --git a/arch/arm/mach-exynos/mct.c b/arch/arm/mach-exynos/mct.c index c9d6650..afc1d9b 100644 --- a/arch/arm/mach-exynos/mct.c +++ b/arch/arm/mach-exynos/mct.c @@ -429,7 +429,7 @@ static int __cpuinit exynos4_local_timer_setup(struct clock_event_device *evt) static void exynos4_local_timer_stop(struct clock_event_device *evt) { unsigned int cpu = smp_processor_id(); - evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt); + clockevents_shutdown(evt); if (mct_int_type == MCT_INT_SPI) if (cpu == 0) remove_irq(evt->irq, &mct_tick0_event_irq); diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c index 2969027..83d5381 100644 --- a/arch/arm/mach-msm/timer.c +++ b/arch/arm/mach-msm/timer.c @@ -152,7 +152,7 @@ static int __cpuinit msm_local_timer_setup(struct clock_event_device *evt) static void msm_local_timer_stop(struct clock_event_device *evt) { - evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt); + clockevents_shutdown(evt); disable_percpu_irq(evt->irq); } diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index d7ad425..12f186e 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -242,7 +242,7 @@ static void __cpuinit arch_timer_stop(struct clock_event_device *clk) disable_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI]); } - clk->set_mode(CLOCK_EVT_MODE_UNUSED, clk); + clockevents_shutdown(clk); } static int __cpuinit arch_timer_cpu_notify(struct notifier_block *self, diff --git a/drivers/clocksource/time-armada-370-xp.c b/drivers/clocksource/time-armada-370-xp.c index 47a6730..3da4861 100644 --- a/drivers/clocksource/time-armada-370-xp.c +++ b/drivers/clocksource/time-armada-370-xp.c @@ -201,7 +201,7 @@ static int __cpuinit armada_370_xp_timer_setup(struct clock_event_device *evt) static void armada_370_xp_timer_stop(struct clock_event_device *evt) { - evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt); + clockevents_shutdown(evt); disable_percpu_irq(evt->irq); } -- 1.7.1