diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2008-09-16 14:32:50 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2008-09-16 16:47:02 -0400 |
commit | 2344abbcbdb82140050e8be29d3d55e4f6fe860b (patch) | |
tree | 46c1842fc2a47aa4d7ee0c2c558f54bc50772b69 /kernel/time/tick-broadcast.c | |
parent | f1926ce63b996b42772b39e4b47bb4ef4ba748b4 (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.c | 9 |
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 | } |