i386: HPET, check if the counter works
authorThomas Gleixner <tglx@linutronix.de>
Sat, 21 Jul 2007 15:11:12 +0000 (17:11 +0200)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Sun, 22 Jul 2007 01:37:12 +0000 (18:37 -0700)
Some systems have a HPET which is not incrementing, which leads to a
complete hang.  Detect it during HPET setup.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: john stultz <johnstul@us.ibm.com>
Cc: <stable@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Andi Kleen <ak@suse.de>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
arch/i386/kernel/hpet.c

index 662d7976a9ea48bdb4ebdda762d5031bad24415c..b93310d119505bf8b356005841676b9860ef2848 100644 (file)
@@ -232,7 +232,8 @@ int __init hpet_enable(void)
 {
        unsigned long id;
        uint64_t hpet_freq;
-       u64 tmp;
+       u64 tmp, start, now;
+       cycle_t t1;
 
        if (!is_hpet_capable())
                return 0;
@@ -279,6 +280,27 @@ int __init hpet_enable(void)
        /* Start the counter */
        hpet_start_counter();
 
+       /* Verify whether hpet counter works */
+       t1 = read_hpet();
+       rdtscll(start);
+
+       /*
+        * We don't know the TSC frequency yet, but waiting for
+        * 200000 TSC cycles is safe:
+        * 4 GHz == 50us
+        * 1 GHz == 200us
+        */
+       do {
+               rep_nop();
+               rdtscll(now);
+       } while ((now - start) < 200000UL);
+
+       if (t1 == read_hpet()) {
+               printk(KERN_WARNING
+                      "HPET counter not counting. HPET disabled\n");
+               goto out_nohpet;
+       }
+
        /* Initialize and register HPET clocksource
         *
         * hpet period is in femto seconds per cycle