summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2008-09-06 03:03:32 +0200
committerGreg Kroah-Hartman <gregkh@suse.de>2008-10-08 19:44:43 -0700
commit59ff733c6b6ef547bb09a9902020750dfbb2200f (patch)
treef21360929d4bea6d293afafc042d0e1eb46b0393
parent9d29a18def727d9e0d5c656cfc86a278988b7926 (diff)
downloadlwn-59ff733c6b6ef547bb09a9902020750dfbb2200f.tar.gz
lwn-59ff733c6b6ef547bb09a9902020750dfbb2200f.zip
x86: HPET fix moronic 32/64bit thinko
commit f7676254f179eac6b5244a80195ec8ae0e9d4606 upstream 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> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--arch/x86/kernel/hpet.c8
1 files changed, 4 insertions, 4 deletions
diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index 1cbbf7211164..791c369dd813 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -282,15 +282,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;
}
/*