ARM: SMP: Always enable clock event broadcast support
authorRussell King <rmk+kernel@arm.linux.org.uk>
Mon, 26 Jul 2010 12:19:43 +0000 (13:19 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Tue, 27 Jul 2010 09:48:42 +0000 (10:48 +0100)
The TWD local timers are unable to wake up the CPU when it is placed
into a low power mode, eg. C3.  Therefore, we need to adapt things
such that the TWD code can cope with this.

We do this by always providing a broadcast tick function, and marking
the fact that the TWD local timer will stop in low power modes.  This
means that when the CPU is placed into a low power mode, the core
timer code marks this fact, and allows an IPI to be given to the core.

Tested-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
arch/arm/Kconfig
arch/arm/kernel/smp.c
arch/arm/kernel/smp_twd.c

index 88b4f389ab35d73f8e522041d5f904fc0cb846bc..157b08aa03663ed744c24ee49f60df9937de1995 100644 (file)
@@ -56,7 +56,7 @@ config GENERIC_CLOCKEVENTS
 config GENERIC_CLOCKEVENTS_BROADCAST
        bool
        depends on GENERIC_CLOCKEVENTS
-       default y if SMP && !LOCAL_TIMERS
+       default y if SMP
 
 config HAVE_TCM
        bool
index b8c3d0f689d9560cc33a7e8ec06958ad216e7ef1..0170e248a1dd413829e1099a02762661a0d2ac87 100644 (file)
@@ -429,7 +429,11 @@ static void smp_timer_broadcast(const struct cpumask *mask)
 {
        send_ipi_message(mask, IPI_TIMER);
 }
+#else
+#define smp_timer_broadcast    NULL
+#endif
 
+#ifndef CONFIG_LOCAL_TIMERS
 static void broadcast_timer_set_mode(enum clock_event_mode mode,
        struct clock_event_device *evt)
 {
@@ -444,7 +448,6 @@ static void local_timer_setup(struct clock_event_device *evt)
        evt->rating     = 400;
        evt->mult       = 1;
        evt->set_mode   = broadcast_timer_set_mode;
-       evt->broadcast  = smp_timer_broadcast;
 
        clockevents_register_device(evt);
 }
@@ -456,6 +459,7 @@ void __cpuinit percpu_timer_setup(void)
        struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu);
 
        evt->cpumask = cpumask_of(cpu);
+       evt->broadcast = smp_timer_broadcast;
 
        local_timer_setup(evt);
 }
index 7c5f0c024db7e468aba3a185bded3bf3fde7073a..35882fbf37f90063723d3247352a3c05af480f99 100644 (file)
@@ -132,7 +132,8 @@ void __cpuinit twd_timer_setup(struct clock_event_device *clk)
        twd_calibrate_rate();
 
        clk->name = "local_timer";
-       clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
+       clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT |
+                       CLOCK_EVT_FEAT_C3STOP;
        clk->rating = 350;
        clk->set_mode = twd_set_mode;
        clk->set_next_event = twd_set_next_event;