Merge branch 'sched-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[sfrench/cifs-2.6.git] / arch / x86 / kernel / tsc.c
index b0597ad02c93e85bb46c17ce15a89cc78641926d..6e1a368d21d4d9214feda8eb6fcabe9c043708e1 100644 (file)
@@ -590,22 +590,26 @@ EXPORT_SYMBOL(recalibrate_cpu_khz);
  */
 
 DEFINE_PER_CPU(unsigned long, cyc2ns);
+DEFINE_PER_CPU(unsigned long long, cyc2ns_offset);
 
 static void set_cyc2ns_scale(unsigned long cpu_khz, int cpu)
 {
-       unsigned long long tsc_now, ns_now;
+       unsigned long long tsc_now, ns_now, *offset;
        unsigned long flags, *scale;
 
        local_irq_save(flags);
        sched_clock_idle_sleep_event();
 
        scale = &per_cpu(cyc2ns, cpu);
+       offset = &per_cpu(cyc2ns_offset, cpu);
 
        rdtscll(tsc_now);
        ns_now = __cycles_2_ns(tsc_now);
 
-       if (cpu_khz)
+       if (cpu_khz) {
                *scale = (NSEC_PER_MSEC << CYC2NS_SCALE_FACTOR)/cpu_khz;
+               *offset = ns_now - (tsc_now * *scale >> CYC2NS_SCALE_FACTOR);
+       }
 
        sched_clock_idle_wakeup_event(0);
        local_irq_restore(flags);