|
@@ -589,22 +589,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);
|