diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2007-07-21 11:11:12 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-21 21:37:12 -0400 |
commit | 075bcd1f9726b8a1caff86eda06f29f71fb21235 (patch) | |
tree | 992a8717dbe7b17fa80cd10f47c3dc639f395aa2 /arch/i386 | |
parent | df2edcf3b6ba54d9ffa620e322583cd994a6e54a (diff) |
i386: HPET, check if the counter works
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>
Diffstat (limited to 'arch/i386')
-rw-r--r-- | arch/i386/kernel/hpet.c | 24 |
1 files changed, 23 insertions, 1 deletions
diff --git a/arch/i386/kernel/hpet.c b/arch/i386/kernel/hpet.c index 662d7976a9ea..b93310d11950 100644 --- a/arch/i386/kernel/hpet.c +++ b/arch/i386/kernel/hpet.c | |||
@@ -232,7 +232,8 @@ int __init hpet_enable(void) | |||
232 | { | 232 | { |
233 | unsigned long id; | 233 | unsigned long id; |
234 | uint64_t hpet_freq; | 234 | uint64_t hpet_freq; |
235 | u64 tmp; | 235 | u64 tmp, start, now; |
236 | cycle_t t1; | ||
236 | 237 | ||
237 | if (!is_hpet_capable()) | 238 | if (!is_hpet_capable()) |
238 | return 0; | 239 | return 0; |
@@ -279,6 +280,27 @@ int __init hpet_enable(void) | |||
279 | /* Start the counter */ | 280 | /* Start the counter */ |
280 | hpet_start_counter(); | 281 | hpet_start_counter(); |
281 | 282 | ||
283 | /* Verify whether hpet counter works */ | ||
284 | t1 = read_hpet(); | ||
285 | rdtscll(start); | ||
286 | |||
287 | /* | ||
288 | * We don't know the TSC frequency yet, but waiting for | ||
289 | * 200000 TSC cycles is safe: | ||
290 | * 4 GHz == 50us | ||
291 | * 1 GHz == 200us | ||
292 | */ | ||
293 | do { | ||
294 | rep_nop(); | ||
295 | rdtscll(now); | ||
296 | } while ((now - start) < 200000UL); | ||
297 | |||
298 | if (t1 == read_hpet()) { | ||
299 | printk(KERN_WARNING | ||
300 | "HPET counter not counting. HPET disabled\n"); | ||
301 | goto out_nohpet; | ||
302 | } | ||
303 | |||
282 | /* Initialize and register HPET clocksource | 304 | /* Initialize and register HPET clocksource |
283 | * | 305 | * |
284 | * hpet period is in femto seconds per cycle | 306 | * hpet period is in femto seconds per cycle |