clockevents: check broadcast device not tick device
authorThomas Gleixner <tglx@linutronix.de>
Mon, 22 Sep 2008 17:02:25 +0000 (19:02 +0200)
committerThomas Gleixner <tglx@linutronix.de>
Tue, 23 Sep 2008 09:38:53 +0000 (11:38 +0200)
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>
kernel/time/tick-broadcast.c

index f1f3eee28113f010492a9e7757d4f5b8ef651714..e2b66d1c8ca587bb30bfb6a11e90828a6103a5e6 100644 (file)
@@ -235,7 +235,7 @@ static void tick_do_broadcast_on_off(void *why)
        case CLOCK_EVT_NOTIFY_BROADCAST_FORCE:
                if (!cpu_isset(cpu, tick_broadcast_mask)) {
                        cpu_set(cpu, tick_broadcast_mask);
-                       if (td->mode == TICKDEV_MODE_PERIODIC)
+                       if (bc->mode == TICKDEV_MODE_PERIODIC)
                                clockevents_shutdown(dev);
                }
                if (*reason == CLOCK_EVT_NOTIFY_BROADCAST_FORCE)
@@ -245,7 +245,7 @@ static void tick_do_broadcast_on_off(void *why)
                if (!tick_broadcast_force &&
                    cpu_isset(cpu, tick_broadcast_mask)) {
                        cpu_clear(cpu, tick_broadcast_mask);
-                       if (td->mode == TICKDEV_MODE_PERIODIC)
+                       if (bc->mode == TICKDEV_MODE_PERIODIC)
                                tick_setup_periodic(dev, 0);
                }
                break;