X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;ds=sidebyside;f=arch%2Fi386%2Fkernel%2Ftime.c;h=22d38b3a66b6488f7344584598cfa892df77d12b;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=a9711fc3500eec5f3dea4cd31dd35e15dad494ff;hpb=87fc8d1bb10cd459024a742c6a10961fefcef18f;p=linux-2.6.git diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c index a9711fc35..22d38b3a6 100644 --- a/arch/i386/kernel/time.c +++ b/arch/i386/kernel/time.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include @@ -80,9 +81,9 @@ unsigned long cpu_khz; /* Detected as we calibrate the TSC */ extern unsigned long wall_jiffies; -spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED; +DEFINE_SPINLOCK(rtc_lock); -spinlock_t i8253_lock = SPIN_LOCK_UNLOCKED; +DEFINE_SPINLOCK(i8253_lock); EXPORT_SYMBOL(i8253_lock); struct timer_opts *cur_timer = &timer_none; @@ -261,8 +262,7 @@ static inline void do_timer_interrupt(int irq, void *dev_id, last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */ } -#ifdef CONFIG_MCA - if( MCA_bus ) { + if (MCA_bus) { /* The PS/2 uses level-triggered interrupts. You can't turn them off, nor would you want to (any attempt to enable edge-triggered interrupts usually gets intercepted by a @@ -275,7 +275,6 @@ static inline void do_timer_interrupt(int irq, void *dev_id, irq = inb_p( 0x61 ); /* read the current state */ outb_p( irq|0x80, 0x61 ); /* reset the IRQ */ } -#endif } /* @@ -319,47 +318,58 @@ unsigned long get_cmos_time(void) return retval; } -static long clock_cmos_diff; +static long clock_cmos_diff, sleep_start; -static int time_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 */ clock_cmos_diff = -get_cmos_time(); clock_cmos_diff += get_seconds(); + sleep_start = get_cmos_time(); return 0; } -static int time_resume(struct sys_device *dev) +static int timer_resume(struct sys_device *dev) { unsigned long flags; - unsigned long sec = get_cmos_time() + clock_cmos_diff; + unsigned long sec; + unsigned long sleep_length; + +#ifdef CONFIG_HPET_TIMER + if (is_hpet_enabled()) + hpet_reenable(); +#endif + sec = get_cmos_time() + clock_cmos_diff; + sleep_length = (get_cmos_time() - sleep_start) * HZ; write_seqlock_irqsave(&xtime_lock, flags); xtime.tv_sec = sec; xtime.tv_nsec = 0; write_sequnlock_irqrestore(&xtime_lock, flags); + jiffies += sleep_length; + wall_jiffies += sleep_length; return 0; } -static struct sysdev_class pit_sysclass = { - .resume = time_resume, - .suspend = time_suspend, - set_kset_name("pit"), +static struct sysdev_class timer_sysclass = { + .resume = timer_resume, + .suspend = timer_suspend, + set_kset_name("timer"), }; /* XXX this driverfs stuff should probably go elsewhere later -john */ -static struct sys_device device_i8253 = { +static struct sys_device device_timer = { .id = 0, - .cls = &pit_sysclass, + .cls = &timer_sysclass, }; static int time_init_device(void) { - int error = sysdev_class_register(&pit_sysclass); + int error = sysdev_class_register(&timer_sysclass); if (!error) - error = sysdev_register(&device_i8253); + error = sysdev_register(&device_timer); return error; } @@ -371,9 +381,9 @@ extern void (*late_time_init)(void); void __init hpet_time_init(void) { xtime.tv_sec = get_cmos_time(); - wall_to_monotonic.tv_sec = -xtime.tv_sec; xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); - wall_to_monotonic.tv_nsec = -xtime.tv_nsec; + set_normalized_timespec(&wall_to_monotonic, + -xtime.tv_sec, -xtime.tv_nsec); if (hpet_enable() >= 0) { printk("Using HPET for base-timer\n"); @@ -399,9 +409,9 @@ void __init time_init(void) } #endif xtime.tv_sec = get_cmos_time(); - wall_to_monotonic.tv_sec = -xtime.tv_sec; xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); - wall_to_monotonic.tv_nsec = -xtime.tv_nsec; + set_normalized_timespec(&wall_to_monotonic, + -xtime.tv_sec, -xtime.tv_nsec); cur_timer = select_timer(); printk(KERN_INFO "Using %s for high-res timesource\n",cur_timer->name);