Commit e0eabf37 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki Committed by Linus Torvalds

[PATCH] Fix a bug in timer_suspend() on x86_64

This patch is intended to fix a bug in timer_suspend() on x86_64 that
causes hard lockups on suspend with swsusp and provide some optimizations. 
It is based on the Nigel Cunningham's patches to to reduce delay in
arch/kernel/time.c.
Signed-off-by: default avatarRafael J. Wysocki <rjw@sisk.pl>
Acked-by: default avatarPavel Machek <pavel@suse.cz>
Acked-by: default avatarNigel Cunningham <ncunningham@linuxmail.org>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent ba6d1ee6
...@@ -955,16 +955,19 @@ void __init time_init_smp(void) ...@@ -955,16 +955,19 @@ void __init time_init_smp(void)
__setup("report_lost_ticks", time_setup); __setup("report_lost_ticks", time_setup);
static long clock_cmos_diff, sleep_start; static long clock_cmos_diff;
static unsigned long sleep_start;
static int timer_suspend(struct sys_device *dev, u32 state) static int timer_suspend(struct sys_device *dev, u32 state)
{ {
/* /*
* Estimate time zone so that set_time can update the clock * Estimate time zone so that set_time can update the clock
*/ */
clock_cmos_diff = -get_cmos_time(); long cmos_time = get_cmos_time();
clock_cmos_diff = -cmos_time;
clock_cmos_diff += get_seconds(); clock_cmos_diff += get_seconds();
sleep_start = jiffies; sleep_start = cmos_time;
return 0; return 0;
} }
...@@ -973,7 +976,7 @@ static int timer_resume(struct sys_device *dev) ...@@ -973,7 +976,7 @@ static int timer_resume(struct sys_device *dev)
unsigned long flags; unsigned long flags;
unsigned long sec; unsigned long sec;
unsigned long ctime = get_cmos_time(); unsigned long ctime = get_cmos_time();
unsigned long sleep_length = ctime - sleep_start; unsigned long sleep_length = (ctime - sleep_start) * HZ;
if (vxtime.hpet_address) if (vxtime.hpet_address)
hpet_reenable(); hpet_reenable();
...@@ -983,7 +986,8 @@ static int timer_resume(struct sys_device *dev) ...@@ -983,7 +986,8 @@ static int timer_resume(struct sys_device *dev)
xtime.tv_sec = sec; xtime.tv_sec = sec;
xtime.tv_nsec = 0; xtime.tv_nsec = 0;
write_sequnlock_irqrestore(&xtime_lock,flags); write_sequnlock_irqrestore(&xtime_lock,flags);
jiffies += sleep_length * HZ; jiffies += sleep_length;
wall_jiffies += sleep_length;
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment