[2.0.31-pre9] Patch to fix __delay weirdness for i386.

Gordon Oliver (gordo@telsur.cl)
Tue, 16 Sep 1997 16:57:29 -0400 (CST)


Hi,
The problem is that at varying offsets (mod 4096) on the Pentium, Pentium
Overdrive, and K6 (at a minimum) The __delay function can have delays that
differ by a factor of 3. If the delay is calibrated at the maximum value,
the delay may end up being 3 times less than requested. This could cause
severe unpredictibility.

The solution provided here is to make __delay a non-inline function, so
that it always has the same offset (that way, it shouldn't matter what it is).
In the future this will allow for the rdtsc version of delay as well.

Problems with the patch:
!!! This will kill backwards compatibility. If you compile a module under
2.0.31 (or whatever kernel has this patch), that module will not run on
earlier 2.0.xx series kernels. (Earlier modules will continue to work, but
with the possibly bad __delay that is compiled inline)

I hope that this gets into the mainline kernel, as it should improve stability
quite a lot, and is a relatively low risk change.

It creates a new file, because I couldn't find a useful place to put the
function. The copyright is copied from the header file...

--- linux/include/asm-i386/delay.h.orig Thu Sep 11 14:36:50 1997
+++ linux/include/asm-i386/delay.h Mon Sep 15 10:34:30 1997
@@ -11,14 +11,7 @@
#include <asm/smp.h>
#endif

-extern __inline__ void __delay(int loops)
-{
- __asm__ __volatile__(
- ".align 2,0x90\n1:\tdecl %0\n\tjns 1b"
- :/* no outputs */
- :"a" (loops)
- :"ax");
-}
+extern void __delay(int loops);

/*
* division by multiplication: you don't have to worry about
--- linux/arch/i386/kernel/delay.c.orig Mon Sep 15 10:43:00 1997
+++ linux/arch/i386/kernel/delay.c Mon Sep 15 10:47:15 1997
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 1993 Linus Torvalds
+ *
+ * Delay routines, using a pre-computed "loops_per_second" value.
+ */
+
+#include <linux/delay.h>
+#include <asm/delay.h>
+
+void __delay(int loops)
+{
+ __asm__ __volatile__(
+ ".align 4,0x90\n1:\tdecl %0\n\tjns 1b"
+ :/* no outputs */
+ :"a" (loops)
+ :"ax");
+}
--- linux/arch/i386/kernel/Makefile.orig Mon Sep 15 10:43:10 1997
+++ linux/arch/i386/kernel/Makefile Mon Sep 15 10:43:28 1997
@@ -22,7 +22,7 @@

O_TARGET := kernel.o
O_OBJS := process.o signal.o entry.o traps.o irq.o vm86.o bios32.o \
- ptrace.o ioport.o ldt.o setup.o time.o sys_i386.o ksyms.o
+ ptrace.o ioport.o ldt.o setup.o time.o sys_i386.o ksyms.o delay.o

ifdef SMP

--- linux/arch/i386/kernel/ksyms.c.orig Mon Sep 15 11:26:15 1997
+++ linux/arch/i386/kernel/ksyms.c Mon Sep 15 11:28:55 1997
@@ -2,6 +2,7 @@
#include <linux/smp.h>
#include <linux/user.h>
#include <linux/elfcore.h>
+#include <linux/delay.h>

#include <asm/semaphore.h>

@@ -13,6 +14,7 @@
/* platform dependent support */
X(dump_thread),
X(dump_fpu),
+ X(__delay),
XNOVERS(down_failed),
XNOVERS(down_failed_interruptible),
XNOVERS(up_wakeup),