diff options
Diffstat (limited to 'arch/i386/kernel/timers/timer_tsc.c')
-rw-r--r-- | arch/i386/kernel/timers/timer_tsc.c | 19 |
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 */ | |||
45 | static unsigned long long monotonic_base; | 45 | static unsigned long long monotonic_base; |
46 | static seqlock_t monotonic_lock = SEQLOCK_UNLOCKED; | 46 | static seqlock_t monotonic_lock = SEQLOCK_UNLOCKED; |
47 | 47 | ||
48 | /* Avoid compensating for lost ticks before TSCs are synched */ | ||
49 | static int detect_lost_ticks; | ||
50 | static int __init start_lost_tick_compensation(void) | ||
51 | { | ||
52 | detect_lost_ticks = 1; | ||
53 | return 0; | ||
54 | } | ||
55 | late_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 | ||
314 | end: | ||
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 */ |