aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/time.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386/kernel/time.c')
-rw-r--r--arch/i386/kernel/time.c50
1 files changed, 33 insertions, 17 deletions
diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c
index 5af802ef00b2..86944acfb647 100644
--- a/arch/i386/kernel/time.c
+++ b/arch/i386/kernel/time.c
@@ -285,16 +285,19 @@ void notify_arch_cmos_timer(void)
285 mod_timer(&sync_cmos_timer, jiffies + 1); 285 mod_timer(&sync_cmos_timer, jiffies + 1);
286} 286}
287 287
288static long clock_cmos_diff, sleep_start; 288static long clock_cmos_diff;
289static unsigned long sleep_start;
289 290
290static int timer_suspend(struct sys_device *dev, pm_message_t state) 291static int timer_suspend(struct sys_device *dev, pm_message_t state)
291{ 292{
292 /* 293 /*
293 * Estimate time zone so that set_time can update the clock 294 * Estimate time zone so that set_time can update the clock
294 */ 295 */
295 clock_cmos_diff = -get_cmos_time(); 296 unsigned long ctime = get_cmos_time();
297
298 clock_cmos_diff = -ctime;
296 clock_cmos_diff += get_seconds(); 299 clock_cmos_diff += get_seconds();
297 sleep_start = get_cmos_time(); 300 sleep_start = ctime;
298 return 0; 301 return 0;
299} 302}
300 303
@@ -302,18 +305,29 @@ static int timer_resume(struct sys_device *dev)
302{ 305{
303 unsigned long flags; 306 unsigned long flags;
304 unsigned long sec; 307 unsigned long sec;
305 unsigned long sleep_length; 308 unsigned long ctime = get_cmos_time();
306 309 long sleep_length = (ctime - sleep_start) * HZ;
310 struct timespec ts;
311
312 if (sleep_length < 0) {
313 printk(KERN_WARNING "CMOS clock skew detected in timer resume!\n");
314 /* The time after the resume must not be earlier than the time
315 * before the suspend or some nasty things will happen
316 */
317 sleep_length = 0;
318 ctime = sleep_start;
319 }
307#ifdef CONFIG_HPET_TIMER 320#ifdef CONFIG_HPET_TIMER
308 if (is_hpet_enabled()) 321 if (is_hpet_enabled())
309 hpet_reenable(); 322 hpet_reenable();
310#endif 323#endif
311 setup_pit_timer(); 324 setup_pit_timer();
312 sec = get_cmos_time() + clock_cmos_diff; 325
313 sleep_length = (get_cmos_time() - sleep_start) * HZ; 326 sec = ctime + clock_cmos_diff;
327 ts.tv_sec = sec;
328 ts.tv_nsec = 0;
329 do_settimeofday(&ts);
314 write_seqlock_irqsave(&xtime_lock, flags); 330 write_seqlock_irqsave(&xtime_lock, flags);
315 xtime.tv_sec = sec;
316 xtime.tv_nsec = 0;
317 jiffies_64 += sleep_length; 331 jiffies_64 += sleep_length;
318 wall_jiffies += sleep_length; 332 wall_jiffies += sleep_length;
319 write_sequnlock_irqrestore(&xtime_lock, flags); 333 write_sequnlock_irqrestore(&xtime_lock, flags);
@@ -349,10 +363,11 @@ extern void (*late_time_init)(void);
349/* Duplicate of time_init() below, with hpet_enable part added */ 363/* Duplicate of time_init() below, with hpet_enable part added */
350static void __init hpet_time_init(void) 364static void __init hpet_time_init(void)
351{ 365{
352 xtime.tv_sec = get_cmos_time(); 366 struct timespec ts;
353 xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); 367 ts.tv_sec = get_cmos_time();
354 set_normalized_timespec(&wall_to_monotonic, 368 ts.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
355 -xtime.tv_sec, -xtime.tv_nsec); 369
370 do_settimeofday(&ts);
356 371
357 if ((hpet_enable() >= 0) && hpet_use_timer) { 372 if ((hpet_enable() >= 0) && hpet_use_timer) {
358 printk("Using HPET for base-timer\n"); 373 printk("Using HPET for base-timer\n");
@@ -364,6 +379,7 @@ static void __init hpet_time_init(void)
364 379
365void __init time_init(void) 380void __init time_init(void)
366{ 381{
382 struct timespec ts;
367#ifdef CONFIG_HPET_TIMER 383#ifdef CONFIG_HPET_TIMER
368 if (is_hpet_capable()) { 384 if (is_hpet_capable()) {
369 /* 385 /*
@@ -374,10 +390,10 @@ void __init time_init(void)
374 return; 390 return;
375 } 391 }
376#endif 392#endif
377 xtime.tv_sec = get_cmos_time(); 393 ts.tv_sec = get_cmos_time();
378 xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); 394 ts.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
379 set_normalized_timespec(&wall_to_monotonic, 395
380 -xtime.tv_sec, -xtime.tv_nsec); 396 do_settimeofday(&ts);
381 397
382 time_init_hook(); 398 time_init_hook();
383} 399}