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 edd00f6cee37..1302e4ab3c4f 100644
--- a/arch/i386/kernel/time.c
+++ b/arch/i386/kernel/time.c
@@ -270,16 +270,19 @@ void notify_arch_cmos_timer(void)
270 mod_timer(&sync_cmos_timer, jiffies + 1); 270 mod_timer(&sync_cmos_timer, jiffies + 1);
271} 271}
272 272
273static long clock_cmos_diff, sleep_start; 273static long clock_cmos_diff;
274static unsigned long sleep_start;
274 275
275static int timer_suspend(struct sys_device *dev, pm_message_t state) 276static int timer_suspend(struct sys_device *dev, pm_message_t state)
276{ 277{
277 /* 278 /*
278 * Estimate time zone so that set_time can update the clock 279 * Estimate time zone so that set_time can update the clock
279 */ 280 */
280 clock_cmos_diff = -get_cmos_time(); 281 unsigned long ctime = get_cmos_time();
282
283 clock_cmos_diff = -ctime;
281 clock_cmos_diff += get_seconds(); 284 clock_cmos_diff += get_seconds();
282 sleep_start = get_cmos_time(); 285 sleep_start = ctime;
283 return 0; 286 return 0;
284} 287}
285 288
@@ -287,18 +290,29 @@ static int timer_resume(struct sys_device *dev)
287{ 290{
288 unsigned long flags; 291 unsigned long flags;
289 unsigned long sec; 292 unsigned long sec;
290 unsigned long sleep_length; 293 unsigned long ctime = get_cmos_time();
291 294 long sleep_length = (ctime - sleep_start) * HZ;
295 struct timespec ts;
296
297 if (sleep_length < 0) {
298 printk(KERN_WARNING "CMOS clock skew detected in timer resume!\n");
299 /* The time after the resume must not be earlier than the time
300 * before the suspend or some nasty things will happen
301 */
302 sleep_length = 0;
303 ctime = sleep_start;
304 }
292#ifdef CONFIG_HPET_TIMER 305#ifdef CONFIG_HPET_TIMER
293 if (is_hpet_enabled()) 306 if (is_hpet_enabled())
294 hpet_reenable(); 307 hpet_reenable();
295#endif 308#endif
296 setup_pit_timer(); 309 setup_pit_timer();
297 sec = get_cmos_time() + clock_cmos_diff; 310
298 sleep_length = (get_cmos_time() - sleep_start) * HZ; 311 sec = ctime + clock_cmos_diff;
312 ts.tv_sec = sec;
313 ts.tv_nsec = 0;
314 do_settimeofday(&ts);
299 write_seqlock_irqsave(&xtime_lock, flags); 315 write_seqlock_irqsave(&xtime_lock, flags);
300 xtime.tv_sec = sec;
301 xtime.tv_nsec = 0;
302 jiffies_64 += sleep_length; 316 jiffies_64 += sleep_length;
303 wall_jiffies += sleep_length; 317 wall_jiffies += sleep_length;
304 write_sequnlock_irqrestore(&xtime_lock, flags); 318 write_sequnlock_irqrestore(&xtime_lock, flags);
@@ -334,10 +348,11 @@ extern void (*late_time_init)(void);
334/* Duplicate of time_init() below, with hpet_enable part added */ 348/* Duplicate of time_init() below, with hpet_enable part added */
335static void __init hpet_time_init(void) 349static void __init hpet_time_init(void)
336{ 350{
337 xtime.tv_sec = get_cmos_time(); 351 struct timespec ts;
338 xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); 352 ts.tv_sec = get_cmos_time();
339 set_normalized_timespec(&wall_to_monotonic, 353 ts.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
340 -xtime.tv_sec, -xtime.tv_nsec); 354
355 do_settimeofday(&ts);
341 356
342 if ((hpet_enable() >= 0) && hpet_use_timer) { 357 if ((hpet_enable() >= 0) && hpet_use_timer) {
343 printk("Using HPET for base-timer\n"); 358 printk("Using HPET for base-timer\n");
@@ -349,6 +364,7 @@ static void __init hpet_time_init(void)
349 364
350void __init time_init(void) 365void __init time_init(void)
351{ 366{
367 struct timespec ts;
352#ifdef CONFIG_HPET_TIMER 368#ifdef CONFIG_HPET_TIMER
353 if (is_hpet_capable()) { 369 if (is_hpet_capable()) {
354 /* 370 /*
@@ -359,10 +375,10 @@ void __init time_init(void)
359 return; 375 return;
360 } 376 }
361#endif 377#endif
362 xtime.tv_sec = get_cmos_time(); 378 ts.tv_sec = get_cmos_time();
363 xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); 379 ts.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
364 set_normalized_timespec(&wall_to_monotonic, 380
365 -xtime.tv_sec, -xtime.tv_nsec); 381 do_settimeofday(&ts);
366 382
367 time_init_hook(); 383 time_init_hook();
368} 384}