aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/timers/timer_tsc.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386/kernel/timers/timer_tsc.c')
-rw-r--r--arch/i386/kernel/timers/timer_tsc.c19
1 files changed, 17 insertions, 2 deletions
diff --git a/arch/i386/kernel/timers/timer_tsc.c b/arch/i386/kernel/timers/timer_tsc.c
index 47675bbbb316..a7f5a2aceba2 100644
--- a/arch/i386/kernel/timers/timer_tsc.c
+++ b/arch/i386/kernel/timers/timer_tsc.c
@@ -45,6 +45,15 @@ static unsigned long last_tsc_high; /* msb 32 bits of Time Stamp Counter */
45static unsigned long long monotonic_base; 45static unsigned long long monotonic_base;
46static seqlock_t monotonic_lock = SEQLOCK_UNLOCKED; 46static seqlock_t monotonic_lock = SEQLOCK_UNLOCKED;
47 47
48/* Avoid compensating for lost ticks before TSCs are synched */
49static int detect_lost_ticks;
50static int __init start_lost_tick_compensation(void)
51{
52 detect_lost_ticks = 1;
53 return 0;
54}
55late_initcall(start_lost_tick_compensation);
56
48/* convert from cycles(64bits) => nanoseconds (64bits) 57/* convert from cycles(64bits) => nanoseconds (64bits)
49 * basic equation: 58 * basic equation:
50 * ns = cycles / (freq / ns_per_sec) 59 * ns = cycles / (freq / ns_per_sec)
@@ -196,7 +205,8 @@ static void mark_offset_tsc_hpet(void)
196 205
197 /* lost tick compensation */ 206 /* lost tick compensation */
198 offset = hpet_readl(HPET_T0_CMP) - hpet_tick; 207 offset = hpet_readl(HPET_T0_CMP) - hpet_tick;
199 if (unlikely(((offset - hpet_last) > hpet_tick) && (hpet_last != 0))) { 208 if (unlikely(((offset - hpet_last) > hpet_tick) && (hpet_last != 0))
209 && detect_lost_ticks) {
200 int lost_ticks = (offset - hpet_last) / hpet_tick; 210 int lost_ticks = (offset - hpet_last) / hpet_tick;
201 jiffies_64 += lost_ticks; 211 jiffies_64 += lost_ticks;
202 } 212 }
@@ -272,6 +282,10 @@ time_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
272 if (val != CPUFREQ_RESUMECHANGE) 282 if (val != CPUFREQ_RESUMECHANGE)
273 write_seqlock_irq(&xtime_lock); 283 write_seqlock_irq(&xtime_lock);
274 if (!ref_freq) { 284 if (!ref_freq) {
285 if (!freq->old){
286 ref_freq = freq->new;
287 goto end;
288 }
275 ref_freq = freq->old; 289 ref_freq = freq->old;
276 loops_per_jiffy_ref = cpu_data[freq->cpu].loops_per_jiffy; 290 loops_per_jiffy_ref = cpu_data[freq->cpu].loops_per_jiffy;
277#ifndef CONFIG_SMP 291#ifndef CONFIG_SMP
@@ -297,6 +311,7 @@ time_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
297#endif 311#endif
298 } 312 }
299 313
314end:
300 if (val != CPUFREQ_RESUMECHANGE) 315 if (val != CPUFREQ_RESUMECHANGE)
301 write_sequnlock_irq(&xtime_lock); 316 write_sequnlock_irq(&xtime_lock);
302 317
@@ -421,7 +436,7 @@ static void mark_offset_tsc(void)
421 delta += delay_at_last_interrupt; 436 delta += delay_at_last_interrupt;
422 lost = delta/(1000000/HZ); 437 lost = delta/(1000000/HZ);
423 delay = delta%(1000000/HZ); 438 delay = delta%(1000000/HZ);
424 if (lost >= 2) { 439 if (lost >= 2 && detect_lost_ticks) {
425 jiffies_64 += lost-1; 440 jiffies_64 += lost-1;
426 441
427 /* sanity check to ensure we're not always losing ticks */ 442 /* sanity check to ensure we're not always losing ticks */