From: Dmitry Torokhov <dtor_core@ameritech.net>

It needs at least the patch below to handle timer wrap-arounds.



 arch/i386/kernel/timers/timer_pm.c |   16 +++++++---------
 1 files changed, 7 insertions(+), 9 deletions(-)

diff -puN arch/i386/kernel/timers/timer_pm.c~timer_pm-wraparound-fixes arch/i386/kernel/timers/timer_pm.c
--- 25/arch/i386/kernel/timers/timer_pm.c~timer_pm-wraparound-fixes	2003-12-29 12:27:35.000000000 -0800
+++ 25-akpm/arch/i386/kernel/timers/timer_pm.c	2003-12-29 12:27:35.000000000 -0800
@@ -92,28 +92,28 @@ static void mark_offset_pmtmr(void)
 {
 	u32 lost, delta, last_offset;
 	static int first_run = 1;
-	last_offset = offset_tick;
 
 	write_seqlock(&monotonic_lock);
 
+	last_offset = offset_tick;
 	offset_tick = inl(pmtmr_ioport);
 	offset_tick &= ACPI_PM_MASK; /* limit it to 24 bits */
 
 	/* calculate tick interval */
-	delta = (offset_tick - last_offset) & ACPI_PM_MASK;
+	delta = likely(last_offset < offset_tick) ?
+		offset_tick - last_offset : ACPI_PM_MASK - last_offset + offset_tick;
 
 	/* convert to usecs */
 	delta = cyc2us(delta);
 
 	/* update the monotonic base value */
-	monotonic_base += delta*NSEC_PER_USEC;
+	monotonic_base += delta * NSEC_PER_USEC;
 	write_sequnlock(&monotonic_lock);
 
 	/* convert to ticks */
 	delta += offset_delay;
-	lost = delta/(USEC_PER_SEC/HZ);
-	offset_delay = delta%(USEC_PER_SEC/HZ);
-
+	lost = delta / (USEC_PER_SEC / HZ);
+	offset_delay = delta % (USEC_PER_SEC / HZ);
 
 	/* compensate for lost ticks */
 	if (lost >= 2)
@@ -125,8 +125,6 @@ static void mark_offset_pmtmr(void)
 		first_run = 0;
 		offset_delay = 0;
 	}
-
-	return;
 }
 
 
@@ -181,7 +179,7 @@ static unsigned long get_offset_pmtmr(vo
 	offset = offset_tick;
 	now = inl(pmtmr_ioport);
 	now &= ACPI_PM_MASK;
-	delta = (now - offset)&ACPI_PM_MASK;
+	delta = likely(offset < now) ? now - offset : ACPI_PM_MASK - offset + now;
 
 	return (unsigned long) offset_delay + cyc2us(delta);
 }

_