aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64
diff options
context:
space:
mode:
authorMathieu Desnoyers <mathieu.desnoyers@polymtl.ca>2005-10-30 14:59:25 -0800
committerLinus Torvalds <torvalds@g5.osdl.org>2005-10-30 17:37:11 -0800
commitdacb16b1a034fa7a0b868ee30758119fbfd90bc1 (patch)
treedaaa631c9c6fa2ad011647fb3acd219784faf2e2 /arch/x86_64
parentbfd51626cbf61cb23f787d8ff972ef0d5ddacc0b (diff)
downloadkernel_samsung_espresso10-dacb16b1a034fa7a0b868ee30758119fbfd90bc1.tar.gz
kernel_samsung_espresso10-dacb16b1a034fa7a0b868ee30758119fbfd90bc1.tar.bz2
kernel_samsung_espresso10-dacb16b1a034fa7a0b868ee30758119fbfd90bc1.zip
[PATCH] i386 and x86_64 TSC set_cyc2ns_scale imprecision
I just found out that some precision is unnecessarily lost in the arch/i386/kernel/timers/timer_tsc.c:set_cyc2ns_scale function. It uses a cpu_mhz parameter when it could use a cpu_khz. In the specific case of an Intel P4 running at 3001.171 Mhz, the truncation to 3001 Mhz leads to an imprecision of 19 microseconds per second : this is very sad for a timer with nearly nanosecond accuracy. Fix the x86_64 architecture too. Cc: george anzinger <george@mvista.com> Cc: john stultz <johnstul@us.ibm.com> Cc: Andi Kleen <ak@muc.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/x86_64')
-rw-r--r--arch/x86_64/kernel/time.c8
1 files changed, 4 insertions, 4 deletions
diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
index 703acde2a1a..47d25ad0816 100644
--- a/arch/x86_64/kernel/time.c
+++ b/arch/x86_64/kernel/time.c
@@ -481,9 +481,9 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
static unsigned int cyc2ns_scale;
#define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */
-static inline void set_cyc2ns_scale(unsigned long cpu_mhz)
+static inline void set_cyc2ns_scale(unsigned long cpu_khz)
{
- cyc2ns_scale = (1000 << CYC2NS_SCALE_FACTOR)/cpu_mhz;
+ cyc2ns_scale = (1000000 << CYC2NS_SCALE_FACTOR)/cpu_khz;
}
static inline unsigned long long cycles_2_ns(unsigned long long cyc)
@@ -655,7 +655,7 @@ static int time_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
vxtime.tsc_quot = (1000L << 32) / cpu_khz;
}
- set_cyc2ns_scale(cpu_khz_ref / 1000);
+ set_cyc2ns_scale(cpu_khz_ref);
return 0;
}
@@ -939,7 +939,7 @@ void __init time_init(void)
rdtscll_sync(&vxtime.last_tsc);
setup_irq(0, &irq0);
- set_cyc2ns_scale(cpu_khz / 1000);
+ set_cyc2ns_scale(cpu_khz);
#ifndef CONFIG_SMP
time_init_gtod();