aboutsummaryrefslogtreecommitdiff
path: root/arch/x86_64/kernel/time.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.osdl.org>2007-01-10 18:06:14 -0800
committerLinus Torvalds <torvalds@woody.osdl.org>2007-01-10 18:06:14 -0800
commit0404f87f2e0a0aadbda47be0f54812671207492f (patch)
tree388ed26f2508aa0188d9435ee0e5a7a7786f8793 /arch/x86_64/kernel/time.c
parent2d9819e3473f3e2200a4942760fa1f3d41043b99 (diff)
parent7401969907594ac9632368ec53528fbd9b18f339 (diff)
Merge branch 'for-linus' of git://one.firstfloor.org/home/andi/git/linux-2.6
* 'for-linus' of git://one.firstfloor.org/home/andi/git/linux-2.6: [PATCH] x86-64: Fix warnings in ia32_aout.c [PATCH] i386: Convert some functions to __init to avoid MODPOST warnings [PATCH] i386: Fix memory hotplug related MODPOST generated warning [PATCH] x86-64: tighten up printks [PATCH] x86-64: - Ignore long SMI interrupts in clock calibration [PATCH] x86-64: pci quirks MODPOST warning fix [PATCH] x86-64: Modpost whitelist reference to more symbols (pattern 3) [PATCH] x86-64: modpost add more symbols to whitelist pattern2 [PATCH] i386: make apic probe function non-init [PATCH] i386: cpu hotplug/smpboot misc MODPOST warning fixes [PATCH] x86-64: Use different constraint for gcc < 4.1 in bitops.h [PATCH] x86-64: Make noirqdebug_setup function non init to fix modpost warning [PATCH] i386: Update defconfig [PATCH] x86-64: Update defconfig
Diffstat (limited to 'arch/x86_64/kernel/time.c')
-rw-r--r--arch/x86_64/kernel/time.c25
1 files changed, 21 insertions, 4 deletions
diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
index 9f05bc9b2da..5cc76d0d331 100644
--- a/arch/x86_64/kernel/time.c
+++ b/arch/x86_64/kernel/time.c
@@ -656,6 +656,25 @@ core_initcall(cpufreq_tsc);
*/
#define TICK_COUNT 100000000
+#define TICK_MIN 5000
+
+/*
+ * Some platforms take periodic SMI interrupts with 5ms duration. Make sure none
+ * occurs between the reads of the hpet & TSC.
+ */
+static void __init read_hpet_tsc(int *hpet, int *tsc)
+{
+ int tsc1, tsc2, hpet1;
+
+ do {
+ tsc1 = get_cycles_sync();
+ hpet1 = hpet_readl(HPET_COUNTER);
+ tsc2 = get_cycles_sync();
+ } while (tsc2 - tsc1 > TICK_MIN);
+ *hpet = hpet1;
+ *tsc = tsc2;
+}
+
static unsigned int __init hpet_calibrate_tsc(void)
{
@@ -666,13 +685,11 @@ static unsigned int __init hpet_calibrate_tsc(void)
local_irq_save(flags);
local_irq_disable();
- hpet_start = hpet_readl(HPET_COUNTER);
- rdtscl(tsc_start);
+ read_hpet_tsc(&hpet_start, &tsc_start);
do {
local_irq_disable();
- hpet_now = hpet_readl(HPET_COUNTER);
- tsc_now = get_cycles_sync();
+ read_hpet_tsc(&hpet_now, &tsc_now);
local_irq_restore(flags);
} while ((tsc_now - tsc_start) < TICK_COUNT &&
(hpet_now - hpet_start) < TICK_COUNT);