2001-03-19 07:51:05

by Ulrich Windl

[permalink] [raw]
Subject: 2.4.2: kernel patch for <asm-i386/delay.h>, nanosleep

Index: arch/i386/kernel/i386_ksyms.c
===================================================================
RCS file: /root/LinuxCVS/Kernel/arch/i386/kernel/i386_ksyms.c,v
retrieving revision 1.1.1.3
diff -u -r1.1.1.3 i386_ksyms.c
--- arch/i386/kernel/i386_ksyms.c 2001/03/11 13:51:19 1.1.1.3
+++ arch/i386/kernel/i386_ksyms.c 2001/03/17 18:08:20
@@ -82,9 +82,9 @@
/* Networking helper routines. */
EXPORT_SYMBOL(csum_partial_copy_generic);
/* Delay loops */
-EXPORT_SYMBOL(__udelay);
+EXPORT_SYMBOL(__ndelay);
EXPORT_SYMBOL(__delay);
-EXPORT_SYMBOL(__const_udelay);
+EXPORT_SYMBOL(__const_sndelay);

EXPORT_SYMBOL_NOVERS(__get_user_1);
EXPORT_SYMBOL_NOVERS(__get_user_2);
Index: arch/i386/lib/delay.c
===================================================================
RCS file: /root/LinuxCVS/Kernel/arch/i386/lib/delay.c,v
retrieving revision 1.1.1.2
diff -u -r1.1.1.2 delay.c
--- arch/i386/lib/delay.c 2001/01/08 20:17:36 1.1.1.2
+++ arch/i386/lib/delay.c 2001/03/17 18:12:36
@@ -64,16 +64,27 @@
__loop_delay(loops);
}

-inline void __const_udelay(unsigned long xloops)
+/* convert scaled nanoseconds to execution loops and delay */
+inline void __const_sndelay(unsigned long scaled_nsecs)
{
int d0;
__asm__("mull %0"
- :"=d" (xloops), "=&a" (d0)
- :"1" (xloops),"0" (current_cpu_data.loops_per_jiffy));
- __delay(xloops * HZ);
+ :"=d" (scaled_nsecs), "=&a" (d0)
+ :"1" (scaled_nsecs),"0" (current_cpu_data.loops_per_jiffy));
+ __delay(scaled_nsecs * HZ);
}

-void __udelay(unsigned long usecs)
+void __ndelay(unsigned long nsecs)
{
- __const_udelay(usecs * 0x000010c6); /* 2**32 / 1000000 */
+ /* 2**32 / 1000000000 == 4.2946... */
+ if (nsecs > NDELAY_LIMIT) {
+ static int complaints = 7;
+
+ if (complaints > 0) {
+ --complaints;
+ printk(KERN_ERR "__ndelay(%lu) exceeds limit\n", nsecs);
+ }
+ nsecs = NDELAY_LIMIT;
+ }
+ __const_sndelay((nsecs * 429) / 100);
}
Index: include/asm-i386/delay.h
===================================================================
RCS file: /root/LinuxCVS/Kernel/include/asm-i386/delay.h,v
retrieving revision 1.1.1.2
diff -u -r1.1.1.2 delay.h
--- include/asm-i386/delay.h 2001/01/08 20:22:29 1.1.1.2
+++ include/asm-i386/delay.h 2001/03/17 17:58:33
@@ -7,14 +7,19 @@
* Delay routines calling functions in arch/i386/lib/delay.c
*/

-extern void __bad_udelay(void);
+extern void __bad_ndelay(void);

-extern void __udelay(unsigned long usecs);
-extern void __const_udelay(unsigned long usecs);
-extern void __delay(unsigned long loops);
+extern void __ndelay(unsigned long nsecs);
+extern void __const_sndelay(unsigned long scaled_nsecs);
+extern void __delay(unsigned long xloops);

-#define udelay(n) (__builtin_constant_p(n) ? \
- ((n) > 20000 ? __bad_udelay() : __const_udelay((n) * 0x10c6ul)) : \
- __udelay(n))
+#define NDELAY_LIMIT 20000000 /* 20 ms (2 / HZ)? */
+
+#define ndelay(n) (__builtin_constant_p(n) ? \
+ ((n) > NDELAY_LIMIT ? \
+ __bad_ndelay() : __const_sndelay(((n) * 429ul) / 100)) : \
+ __ndelay(n))
+
+#define udelay(n) ndelay(n * 1000)

#endif /* defined(_I386_DELAY_H) */
Index: kernel/timer.c
===================================================================
RCS file: /root/LinuxCVS/Kernel/kernel/timer.c,v
retrieving revision 1.1.1.2.8.1
diff -u -r1.1.1.2.8.1 timer.c
--- kernel/timer.c 2001/03/11 15:29:17 1.1.1.2.8.1
+++ kernel/timer.c 2001/03/17 17:22:57
@@ -592,10 +592,11 @@
/*
* Short delay requests up to 2 ms will be handled with
* high precision by a busy wait for all real-time processes.
+ * Anything else will be delayed for at least 1/HZ.
*
* Its important on SMP not to do this holding locks.
*/
- udelay((t.tv_nsec + 999) / 1000);
+ ndelay(t.tv_nsec);
return 0;
}