summaryrefslogtreecommitdiffstats
path: root/kernel/time/clockevents.c
diff options
context:
space:
mode:
authorThomas Gleixner2008-09-16 20:32:50 +0200
committerThomas Gleixner2008-09-16 22:47:02 +0200
commit2344abbcbdb82140050e8be29d3d55e4f6fe860b (patch)
tree46c1842fc2a47aa4d7ee0c2c558f54bc50772b69 /kernel/time/clockevents.c
parentclocksource, acpi_pm.c: fix check for monotonicity (diff)
downloadkernel-qcow2-linux-2344abbcbdb82140050e8be29d3d55e4f6fe860b.tar.gz
kernel-qcow2-linux-2344abbcbdb82140050e8be29d3d55e4f6fe860b.tar.xz
kernel-qcow2-linux-2344abbcbdb82140050e8be29d3d55e4f6fe860b.zip
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/clockevents.c')
-rw-r--r--kernel/time/clockevents.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c
index 1876b526c778..f8d968063cea 100644
--- a/kernel/time/clockevents.c
+++ b/kernel/time/clockevents.c
@@ -72,6 +72,16 @@ void clockevents_set_mode(struct clock_event_device *dev,
}
/**
+ * clockevents_shutdown - shutdown the device and clear next_event
+ * @dev: device to shutdown
+ */
+void clockevents_shutdown(struct clock_event_device *dev)
+{
+ clockevents_set_mode(dev, CLOCK_EVT_MODE_SHUTDOWN);
+ dev->next_event.tv64 = KTIME_MAX;
+}
+
+/**
* clockevents_program_event - Reprogram the clock event device.
* @expires: absolute expiry time (monotonic clock)
*
@@ -206,7 +216,7 @@ void clockevents_exchange_device(struct clock_event_device *old,
if (new) {
BUG_ON(new->mode != CLOCK_EVT_MODE_UNUSED);
- clockevents_set_mode(new, CLOCK_EVT_MODE_SHUTDOWN);
+ clockevents_shutdown(new);
}
local_irq_restore(flags);
}