diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2008-09-06 03:03:32 +0200 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2008-09-06 07:21:17 +0200 |
commit | f7676254f179eac6b5244a80195ec8ae0e9d4606 (patch) | |
tree | 23074b023b683fa9940ff6543192eff2b6019350 /arch | |
parent | 7300711e8c6824fcfbd42a126980ff50439d8dd0 (diff) | |
download | blackbird-op-linux-f7676254f179eac6b5244a80195ec8ae0e9d4606.tar.gz blackbird-op-linux-f7676254f179eac6b5244a80195ec8ae0e9d4606.zip |
x86: HPET fix moronic 32/64bit thinko
We use the HPET only in 32bit mode because:
1) some HPETs are 32bit only
2) on i386 there is no way to read/write the HPET atomic 64bit wide
The HPET code unification done by the "moron of the year" did
not take into account that unsigned long is different on 32 and
64 bit.
This thinko results in a possible endless loop in the clockevents
code, when the return comparison fails due to the 64bit/332bit
unawareness.
unsigned long cnt = (u32) hpet_read() + delta can wrap over 32bit.
but the final compare will fail and return -ETIME causing endless
loops.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kernel/hpet.c | 8 |
1 files changed, 4 insertions, 4 deletions
diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index 2256315416d8..801497a16e0e 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c @@ -270,15 +270,15 @@ static void hpet_legacy_set_mode(enum clock_event_mode mode, } static int hpet_legacy_next_event(unsigned long delta, - struct clock_event_device *evt) + struct clock_event_device *evt) { - unsigned long cnt; + u32 cnt; cnt = hpet_readl(HPET_COUNTER); - cnt += delta; + cnt += (u32) delta; hpet_writel(cnt, HPET_T0_CMP); - return ((long)(hpet_readl(HPET_COUNTER) - cnt ) > 0) ? -ETIME : 0; + return (s32)((u32)hpet_readl(HPET_COUNTER) - cnt) >= 0 ? -ETIME : 0; } /* |