aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2008-09-22 13:02:25 -0400
committerThomas Gleixner <tglx@linutronix.de>2008-09-23 05:38:53 -0400
commit302745699c1b675b5d2a1af87271de10e4d96b6a (patch)
tree4efc6c93c038e14021fa10b1eb358695f45f2130
parent49d670fb8dd62d3ed4e3ed2513538ea65b051aed (diff)
clockevents: check broadcast device not tick device
Impact: Possible hang on CPU online observed on AMD C1E machines. The broadcast setup code looks at the mode of the tick device to determine whether it needs to be shut down or setup. This is wrong when the broadcast mode is set to one shot already. This can happen when a CPU is brought online as it goes through the periodic setup first. The problem went unnoticed as sane systems do not call into that code before the switch to one shot for the clock event device happens. The AMD C1E idle routine switches over immediately and thereby shuts down the just setup device before the first interrupt happens. Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r--kernel/time/tick-broadcast.c4
1 files changed, 2 insertions, 2 deletions
diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c
index f1f3eee28113..e2b66d1c8ca5 100644
--- a/kernel/time/tick-broadcast.c
+++ b/kernel/time/tick-broadcast.c
@@ -235,7 +235,7 @@ static void tick_do_broadcast_on_off(void *why)
235 case CLOCK_EVT_NOTIFY_BROADCAST_FORCE: 235 case CLOCK_EVT_NOTIFY_BROADCAST_FORCE:
236 if (!cpu_isset(cpu, tick_broadcast_mask)) { 236 if (!cpu_isset(cpu, tick_broadcast_mask)) {
237 cpu_set(cpu, tick_broadcast_mask); 237 cpu_set(cpu, tick_broadcast_mask);
238 if (td->mode == TICKDEV_MODE_PERIODIC) 238 if (bc->mode == TICKDEV_MODE_PERIODIC)
239 clockevents_shutdown(dev); 239 clockevents_shutdown(dev);
240 } 240 }
241 if (*reason == CLOCK_EVT_NOTIFY_BROADCAST_FORCE) 241 if (*reason == CLOCK_EVT_NOTIFY_BROADCAST_FORCE)
@@ -245,7 +245,7 @@ static void tick_do_broadcast_on_off(void *why)
245 if (!tick_broadcast_force && 245 if (!tick_broadcast_force &&
246 cpu_isset(cpu, tick_broadcast_mask)) { 246 cpu_isset(cpu, tick_broadcast_mask)) {
247 cpu_clear(cpu, tick_broadcast_mask); 247 cpu_clear(cpu, tick_broadcast_mask);
248 if (td->mode == TICKDEV_MODE_PERIODIC) 248 if (bc->mode == TICKDEV_MODE_PERIODIC)
249 tick_setup_periodic(dev, 0); 249 tick_setup_periodic(dev, 0);
250 } 250 }
251 break; 251 break;