From: john stultz <johnstul@us.ibm.com>

This patch replaces the loop based delay_pmtmr with a TSC based
delay_pmtmr, which resolves a number of issues caused by the loop based
delay.  Unsynced TSCs as well frequency changing TSCs will effect the
length of __delay(), but it seems this method works best.



---

 25-akpm/arch/i386/kernel/timers/timer_pm.c |   24 ++++++++++++------------
 1 files changed, 12 insertions(+), 12 deletions(-)

diff -puN arch/i386/kernel/timers/timer_pm.c~use-TSC-for-delay_pmtmr-2 arch/i386/kernel/timers/timer_pm.c
--- 25/arch/i386/kernel/timers/timer_pm.c~use-TSC-for-delay_pmtmr-2	Wed Jan 28 16:28:20 2004
+++ 25-akpm/arch/i386/kernel/timers/timer_pm.c	Wed Jan 28 16:28:20 2004
@@ -68,6 +68,10 @@ static int init_pmtmr(char* override)
 	if (!pmtmr_ioport)
 		return -ENODEV;
 
+	/* we use the TSC for delay_pmtmr, so make sure it exists */
+	if (!cpu_has_tsc)
+		return -ENODEV;
+
 	/* "verify" this timing source */
 	value1 = read_pmtmr();
 	for (i = 0; i < 10000; i++) {
@@ -168,20 +172,16 @@ static unsigned long long monotonic_cloc
 	return ret;
 }
 
-/*
- * copied from delay_pit
- */
 static void delay_pmtmr(unsigned long loops)
 {
-	int d0;
-	__asm__ __volatile__(
-		"\tjmp 1f\n"
-		".align 16\n"
-		"1:\tjmp 2f\n"
-		".align 16\n"
-		"2:\tdecl %0\n\tjns 2b"
-		:"=&a" (d0)
-		:"0" (loops));
+	unsigned long bclock, now;
+
+	rdtscl(bclock);
+	do
+	{
+		rep_nop();
+		rdtscl(now);
+	} while ((now-bclock) < loops);
 }
 
 

_