From: john stultz 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); } _