aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/time/tick-broadcast.c
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2008-09-16 14:32:50 -0400
committerThomas Gleixner <tglx@linutronix.de>2008-09-16 16:47:02 -0400
commit2344abbcbdb82140050e8be29d3d55e4f6fe860b (patch)
tree46c1842fc2a47aa4d7ee0c2c558f54bc50772b69 /kernel/time/tick-broadcast.c
parentf1926ce63b996b42772b39e4b47bb4ef4ba748b4 (diff)
clockevents: make device shutdown robust
The device shut down does not cleanup the next_event variable of the clock event device. So when the device is reactivated the possible stale next_event value can prevent the device to be reprogrammed as it claims to wait on a event already. This is the root cause of the resurfacing suspend/resume problem, where systems need key press to come back to life. Fix this by setting next_event to KTIME_MAX when the device is shut down. Use a separate function for shutdown which takes care of that and only keep the direct set mode call in the broadcast code, where we can not touch the next_event value. Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'kernel/time/tick-broadcast.c')
-rw-r--r--kernel/time/tick-broadcast.c9
1 files changed, 4 insertions, 5 deletions
diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c
index 2f5a38294bf9..f1f3eee28113 100644
--- a/kernel/time/tick-broadcast.c
+++ b/kernel/time/tick-broadcast.c
@@ -236,8 +236,7 @@ static void tick_do_broadcast_on_off(void *why)
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 (td->mode == TICKDEV_MODE_PERIODIC)
239 clockevents_set_mode(dev, 239 clockevents_shutdown(dev);
240 CLOCK_EVT_MODE_SHUTDOWN);
241 } 240 }
242 if (*reason == CLOCK_EVT_NOTIFY_BROADCAST_FORCE) 241 if (*reason == CLOCK_EVT_NOTIFY_BROADCAST_FORCE)
243 tick_broadcast_force = 1; 242 tick_broadcast_force = 1;
@@ -254,7 +253,7 @@ static void tick_do_broadcast_on_off(void *why)
254 253
255 if (cpus_empty(tick_broadcast_mask)) { 254 if (cpus_empty(tick_broadcast_mask)) {
256 if (!bc_stopped) 255 if (!bc_stopped)
257 clockevents_set_mode(bc, CLOCK_EVT_MODE_SHUTDOWN); 256 clockevents_shutdown(bc);
258 } else if (bc_stopped) { 257 } else if (bc_stopped) {
259 if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC) 258 if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC)
260 tick_broadcast_start_periodic(bc); 259 tick_broadcast_start_periodic(bc);
@@ -306,7 +305,7 @@ void tick_shutdown_broadcast(unsigned int *cpup)
306 305
307 if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC) { 306 if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC) {
308 if (bc && cpus_empty(tick_broadcast_mask)) 307 if (bc && cpus_empty(tick_broadcast_mask))
309 clockevents_set_mode(bc, CLOCK_EVT_MODE_SHUTDOWN); 308 clockevents_shutdown(bc);
310 } 309 }
311 310
312 spin_unlock_irqrestore(&tick_broadcast_lock, flags); 311 spin_unlock_irqrestore(&tick_broadcast_lock, flags);
@@ -321,7 +320,7 @@ void tick_suspend_broadcast(void)
321 320
322 bc = tick_broadcast_device.evtdev; 321 bc = tick_broadcast_device.evtdev;
323 if (bc) 322 if (bc)
324 clockevents_set_mode(bc, CLOCK_EVT_MODE_SHUTDOWN); 323 clockevents_shutdown(bc);
325 324
326 spin_unlock_irqrestore(&tick_broadcast_lock, flags); 325 spin_unlock_irqrestore(&tick_broadcast_lock, flags);
327} 326}