summaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/time.c
diff options
context:
space:
mode:
authorShaohua Li2005-09-04 00:57:07 +0200
committerLinus Torvalds2005-09-05 09:06:18 +0200
commitc3c433e4f33afe255389ba3b1a003dc8deb3de9a (patch)
tree071304e15e21e0a93c17050000a682f4ae1a98c1 /arch/i386/kernel/time.c
parent[PATCH] pm: clean up /sys/power/disk (diff)
downloadkernel-qcow2-linux-c3c433e4f33afe255389ba3b1a003dc8deb3de9a.tar.gz
kernel-qcow2-linux-c3c433e4f33afe255389ba3b1a003dc8deb3de9a.tar.xz
kernel-qcow2-linux-c3c433e4f33afe255389ba3b1a003dc8deb3de9a.zip
[PATCH] add suspend/resume for timer
The timers lack .suspend/.resume methods. Because of this, jiffies got a big compensation after a S3 resume. And then softlockup watchdog reports an oops. This occured with HPET enabled, but it's also possible for other timers. Signed-off-by: Shaohua Li <shaohua.li@intel.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/i386/kernel/time.c')
-rw-r--r--arch/i386/kernel/time.c10
1 files changed, 10 insertions, 0 deletions
diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c
index 0ee9dee8af06..6f794a78ee1e 100644
--- a/arch/i386/kernel/time.c
+++ b/arch/i386/kernel/time.c
@@ -383,6 +383,7 @@ void notify_arch_cmos_timer(void)
static long clock_cmos_diff, sleep_start;
+static struct timer_opts *last_timer;
static int timer_suspend(struct sys_device *dev, pm_message_t state)
{
/*
@@ -391,6 +392,10 @@ static int timer_suspend(struct sys_device *dev, pm_message_t state)
clock_cmos_diff = -get_cmos_time();
clock_cmos_diff += get_seconds();
sleep_start = get_cmos_time();
+ last_timer = cur_timer;
+ cur_timer = &timer_none;
+ if (last_timer->suspend)
+ last_timer->suspend(state);
return 0;
}
@@ -404,6 +409,7 @@ static int timer_resume(struct sys_device *dev)
if (is_hpet_enabled())
hpet_reenable();
#endif
+ setup_pit_timer();
sec = get_cmos_time() + clock_cmos_diff;
sleep_length = (get_cmos_time() - sleep_start) * HZ;
write_seqlock_irqsave(&xtime_lock, flags);
@@ -412,6 +418,10 @@ static int timer_resume(struct sys_device *dev)
write_sequnlock_irqrestore(&xtime_lock, flags);
jiffies += sleep_length;
wall_jiffies += sleep_length;
+ if (last_timer->resume)
+ last_timer->resume();
+ cur_timer = last_timer;
+ last_timer = NULL;
return 0;
}