[PATCH] all-arch delay patch

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This one is for review only by arch maintainers.

Run tested on i386.

# size vmlinux.org vmlinux.delay
   text    data     bss     dec     hex filename
4345737 1607102  259296 6212135  5eca27 vmlinux.org
4345296 1604470  259296 6209062  5ebe26 vmlinux.delay

If someone from non-i386 land with a bit of time to spare
wants to test it, that will be appreciated.
Add #include <linux/delay.h> if you will get undefined refs to
[mun]delay(). (I already did in two files IIRC).

Vojtech, I did not read your mail when I worked on the patch,
thus your ndelay() concerns are not addressed.

find.out.bz2 has some less boring cases of delays grepped
from kernel source. Selected gems are:

aic79xx_osm.h:
ahd_delay(long usec)
{
        /*
         * udelay on Linux can have problems for
         * multi-millisecond waits.  Wait at most
         * 1024us per call.
         */
        while (usec > 0) {
                udelay(usec % 1024);
                usec -= 1024;
        }
}

arch/i386/kernel/traps.c:
        outb(reason, 0x61);
        i = 2000;
        while (--i) udelay(1000);
        reason &= ~8;
        outb(reason, 0x61);

sound/oss/ad1889.c:
//now 100ms
/* #define WAIT_10MS()  schedule_timeout(HZ/10) */
#define WAIT_10MS()     do { int __i; for (__i = 0; __i < 100; __i++) udelay(1000); } while(0)

drivers/isdn/hisax/hisax.h:
#define HZDELAY(jiffs) {int tout = jiffs; while (tout--) udelay(1000000/HZ);}

drivers/scsi/u14-34f.c:
while ((jiffies - time) < HZ && limit++ < 20000) udelay(100L);
...
while ((jiffies - time) < (10 * HZ) && limit++ < 200000) udelay(100L);

sound/isa/es18xx.c:
        udelay(100000);

drivers/scsi/aha152x.c:
        mdelay(10000);
--
vda
diff -U10 -urpN linux-2.6.12.org/arch/alpha/lib/udelay.c linux-2.6.12.delay/arch/alpha/lib/udelay.c
--- linux-2.6.12.org/arch/alpha/lib/udelay.c	Tue Oct 19 00:54:39 2004
+++ linux-2.6.12.delay/arch/alpha/lib/udelay.c	Thu Jun 30 22:48:06 2005
@@ -32,24 +32,24 @@ __delay(int loops)
 		: "=&r" (tmp), "=r" (loops) : "1"(loops));
 }
 
 #ifdef CONFIG_SMP
 #define LPJ	 cpu_data[smp_processor_id()].loops_per_jiffy
 #else
 #define LPJ	 loops_per_jiffy
 #endif
 
 void
-udelay(unsigned long usecs)
+__udelay(unsigned long usecs)
 {
 	usecs *= (((unsigned long)HZ << 32) / 1000000) * LPJ;
 	__delay((long)usecs >> 32);
 }
-EXPORT_SYMBOL(udelay);
+EXPORT_SYMBOL(__udelay);
 
 void
-ndelay(unsigned long nsecs)
+__ndelay(unsigned long nsecs)
 {
 	nsecs *= (((unsigned long)HZ << 32) / 1000000000) * LPJ;
 	__delay((long)nsecs >> 32);
 }
-EXPORT_SYMBOL(ndelay);
+EXPORT_SYMBOL(__ndelay);
diff -U10 -urpN linux-2.6.12.org/arch/arm/kernel/armksyms.c linux-2.6.12.delay/arch/arm/kernel/armksyms.c
--- linux-2.6.12.org/arch/arm/kernel/armksyms.c	Thu Feb  3 11:38:47 2005
+++ linux-2.6.12.delay/arch/arm/kernel/armksyms.c	Thu Jun 30 22:42:50 2005
@@ -54,21 +54,20 @@ extern void fp_enter(void);
  * These symbols will never change their calling convention...
  */
 EXPORT_SYMBOL_ALIAS(kern_fp_enter,fp_enter);
 EXPORT_SYMBOL_ALIAS(fp_printk,printk);
 EXPORT_SYMBOL_ALIAS(fp_send_sig,send_sig);
 
 EXPORT_SYMBOL(__backtrace);
 
 	/* platform dependent support */
 EXPORT_SYMBOL(__udelay);
-EXPORT_SYMBOL(__const_udelay);
 
 	/* networking */
 EXPORT_SYMBOL(csum_partial);
 EXPORT_SYMBOL(csum_partial_copy_nocheck);
 EXPORT_SYMBOL(__csum_ipv6_magic);
 
 	/* io */
 #ifndef __raw_readsb
 EXPORT_SYMBOL(__raw_readsb);
 #endif
diff -U10 -urpN linux-2.6.12.org/arch/arm/lib/delay.S linux-2.6.12.delay/arch/arm/lib/delay.S
--- linux-2.6.12.org/arch/arm/lib/delay.S	Thu Feb  3 11:38:48 2005
+++ linux-2.6.12.delay/arch/arm/lib/delay.S	Thu Jun 30 22:44:30 2005
@@ -13,21 +13,21 @@
 
 LC0:		.word	loops_per_jiffy
 
 /*
  * 0 <= r0 <= 2000
  */
 ENTRY(__udelay)
 		mov	r2,     #0x6800
 		orr	r2, r2, #0x00db
 		mul	r0, r2, r0
-ENTRY(__const_udelay)				@ 0 <= r0 <= 0x01ffffff
+						@ 0 <= r0 <= 0x01ffffff
 		ldr	r2, LC0
 		ldr	r2, [r2]		@ max = 0x0fffffff
 		mov	r0, r0, lsr #11		@ max = 0x00003fff
 		mov	r2, r2, lsr #11		@ max = 0x0003ffff
 		mul	r0, r2, r0		@ max = 2^32-1
 		movs	r0, r0, lsr #6
 		RETINSTR(moveq,pc,lr)
 
 /*
  * loops = (r0 * 0x10c6 * 100 * loops_per_jiffy) / 2^32
diff -U10 -urpN linux-2.6.12.org/arch/i386/kernel/i386_ksyms.c linux-2.6.12.delay/arch/i386/kernel/i386_ksyms.c
--- linux-2.6.12.org/arch/i386/kernel/i386_ksyms.c	Sun Jun 19 16:09:49 2005
+++ linux-2.6.12.delay/arch/i386/kernel/i386_ksyms.c	Thu Jun 30 20:33:42 2005
@@ -84,21 +84,20 @@ EXPORT_SYMBOL(apm_info);
 EXPORT_SYMBOL(__down_failed);
 EXPORT_SYMBOL(__down_failed_interruptible);
 EXPORT_SYMBOL(__down_failed_trylock);
 EXPORT_SYMBOL(__up_wakeup);
 /* Networking helper routines. */
 EXPORT_SYMBOL(csum_partial_copy_generic);
 /* Delay loops */
 EXPORT_SYMBOL(__ndelay);
 EXPORT_SYMBOL(__udelay);
 EXPORT_SYMBOL(__delay);
-EXPORT_SYMBOL(__const_udelay);
 
 EXPORT_SYMBOL(__get_user_1);
 EXPORT_SYMBOL(__get_user_2);
 EXPORT_SYMBOL(__get_user_4);
 
 EXPORT_SYMBOL(__put_user_1);
 EXPORT_SYMBOL(__put_user_2);
 EXPORT_SYMBOL(__put_user_4);
 EXPORT_SYMBOL(__put_user_8);
 
diff -U10 -urpN linux-2.6.12.org/arch/i386/kernel/i8259.c linux-2.6.12.delay/arch/i386/kernel/i8259.c
--- linux-2.6.12.org/arch/i386/kernel/i8259.c	Sun Jun 19 16:09:49 2005
+++ linux-2.6.12.delay/arch/i386/kernel/i8259.c	Fri Jul  1 00:18:40 2005
@@ -4,20 +4,21 @@
 #include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
 #include <linux/slab.h>
 #include <linux/random.h>
 #include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/kernel_stat.h>
 #include <linux/sysdev.h>
 #include <linux/bitops.h>
+#include <linux/delay.h>
 
 #include <asm/8253pit.h>
 #include <asm/atomic.h>
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/timer.h>
 #include <asm/pgtable.h>
 #include <asm/delay.h>
 #include <asm/desc.h>
diff -U10 -urpN linux-2.6.12.org/arch/i386/kernel/timers/timer_pit.c linux-2.6.12.delay/arch/i386/kernel/timers/timer_pit.c
--- linux-2.6.12.org/arch/i386/kernel/timers/timer_pit.c	Thu Feb  3 11:38:53 2005
+++ linux-2.6.12.delay/arch/i386/kernel/timers/timer_pit.c	Fri Jul  1 00:20:04 2005
@@ -2,21 +2,21 @@
  * This code largely moved from arch/i386/kernel/time.c.
  * See comments there for proper credits.
  */
 
 #include <linux/spinlock.h>
 #include <linux/module.h>
 #include <linux/device.h>
 #include <linux/irq.h>
 #include <linux/sysdev.h>
 #include <linux/timex.h>
-#include <asm/delay.h>
+#include <linux/delay.h>
 #include <asm/mpspec.h>
 #include <asm/timer.h>
 #include <asm/smp.h>
 #include <asm/io.h>
 #include <asm/arch_hooks.h>
 
 extern spinlock_t i8259A_lock;
 extern spinlock_t i8253_lock;
 #include "do_timer.h"
 #include "io_ports.h"
diff -U10 -urpN linux-2.6.12.org/arch/i386/lib/delay.c linux-2.6.12.delay/arch/i386/lib/delay.c
--- linux-2.6.12.org/arch/i386/lib/delay.c	Thu Mar  3 09:30:10 2005
+++ linux-2.6.12.delay/arch/i386/lib/delay.c	Thu Jun 30 20:33:54 2005
@@ -21,21 +21,21 @@
 #include <asm/smp.h>
 #endif
 
 extern struct timer_opts* timer;
 
 void __delay(unsigned long loops)
 {
 	cur_timer->delay(loops);
 }
 
-inline void __const_udelay(unsigned long xloops)
+static inline void __const_udelay(unsigned long xloops)
 {
 	int d0;
 	xloops *= 4;
 	__asm__("mull %0"
 		:"=d" (xloops), "=&a" (d0)
 		:"1" (xloops),"0" (cpu_data[_smp_processor_id()].loops_per_jiffy * (HZ/4)));
         __delay(++xloops);
 }
 
 void __udelay(unsigned long usecs)
diff -U10 -urpN linux-2.6.12.org/arch/m32r/kernel/m32r_ksyms.c linux-2.6.12.delay/arch/m32r/kernel/m32r_ksyms.c
--- linux-2.6.12.org/arch/m32r/kernel/m32r_ksyms.c	Sun Jun 19 16:09:52 2005
+++ linux-2.6.12.delay/arch/m32r/kernel/m32r_ksyms.c	Thu Jun 30 20:31:44 2005
@@ -37,21 +37,20 @@ EXPORT_SYMBOL(disable_irq_nosync);
 EXPORT_SYMBOL(kernel_thread);
 EXPORT_SYMBOL(__down);
 EXPORT_SYMBOL(__down_interruptible);
 EXPORT_SYMBOL(__up);
 EXPORT_SYMBOL(__down_trylock);
 
 /* Networking helper routines. */
 /* Delay loops */
 EXPORT_SYMBOL(__udelay);
 EXPORT_SYMBOL(__delay);
-EXPORT_SYMBOL(__const_udelay);
 
 EXPORT_SYMBOL(__get_user_1);
 EXPORT_SYMBOL(__get_user_2);
 EXPORT_SYMBOL(__get_user_4);
 
 EXPORT_SYMBOL(strpbrk);
 EXPORT_SYMBOL(strstr);
 
 EXPORT_SYMBOL(strncpy_from_user);
 EXPORT_SYMBOL(__strncpy_from_user);
diff -U10 -urpN linux-2.6.12.org/arch/m32r/lib/delay.c linux-2.6.12.delay/arch/m32r/lib/delay.c
--- linux-2.6.12.org/arch/m32r/lib/delay.c	Thu Feb  3 11:38:55 2005
+++ linux-2.6.12.delay/arch/m32r/lib/delay.c	Thu Jun 30 20:31:36 2005
@@ -51,21 +51,21 @@ void __delay(unsigned long loops)
 		"addi	%0, #-1			\n\t"
 		"bgtz	%0, 1b			\n\t"
 		" .fillinsn			\n\t"
 		"2:				\n\t"
 		: "+r" (loops)
 		: "r" (0)
 	);
 #endif
 }
 
-void __const_udelay(unsigned long xloops)
+static void __const_udelay(unsigned long xloops)
 {
 #if defined(CONFIG_ISA_M32R2) && defined(CONFIG_ISA_DSP_LEVEL2)
 	/*
 	 * loops [1] = (xloops >> 32) [sec] * loops_per_jiffy [1/jiffy]
 	 *            * HZ [jiffy/sec]
 	 *          = (xloops >> 32) [sec] * (loops_per_jiffy * HZ) [1/sec]
 	 *          = (((xloops * loops_per_jiffy) >> 32) * HZ) [1]
 	 *
 	 * NOTE:
 	 *   - '[]' depicts variable's dimension in the above equation.
diff -U10 -urpN linux-2.6.12.org/arch/m68knommu/lib/delay.c linux-2.6.12.delay/arch/m68knommu/lib/delay.c
--- linux-2.6.12.org/arch/m68knommu/lib/delay.c	Thu Mar  3 09:30:14 2005
+++ linux-2.6.12.delay/arch/m68knommu/lib/delay.c	Thu Jun 30 20:29:49 2005
@@ -5,17 +5,69 @@
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
 
 #include <linux/module.h>
 #include <asm/param.h>
 #include <asm/delay.h>
 
-EXPORT_SYMBOL(udelay);
+extern unsigned long loops_per_jiffy;
 
-void udelay(unsigned long usecs)
+extern __inline__ void __delay(unsigned long loops)
 {
-	_udelay(usecs);
+#if defined(CONFIG_COLDFIRE)
+	/* The coldfire runs this loop at significantly different speeds
+	 * depending upon long word alignment or not.  We'll pad it to
+	 * long word alignment which is the faster version.
+	 * The 0x4a8e is of course a 'tstl %fp' instruction.  This is better
+	 * than using a NOP (0x4e71) instruction because it executes in one
+	 * cycle not three and doesn't allow for an arbitary delay waiting
+	 * for bus cycles to finish.  Also fp/a6 isn't likely to cause a
+	 * stall waiting for the register to become valid if such is added
+	 * to the coldfire at some stage.
+	 */
+	__asm__ __volatile__ (	".balignw 4, 0x4a8e\n\t"
+				"1: subql #1, %0\n\t"
+				"jcc 1b"
+		: "=d" (loops) : "0" (loops));
+#else
+	__asm__ __volatile__ (	"1: subql #1, %0\n\t"
+				"jcc 1b"
+		: "=d" (loops) : "0" (loops));
+#endif
+}
+
+/*
+ *	Ideally we use a 32*32->64 multiply to calculate the number of
+ *	loop iterations, but the older standard 68k and ColdFire do not
+ *	have this instruction. So for them we have a clsoe approximation
+ *	loop using 32*32->32 multiplies only. This calculation based on
+ *	the ARM version of delay.
+ *
+ *	We want to implement:
+ *
+ *	loops = (usecs * 0x10c6 * HZ * loops_per_jiffy) / 2^32
+ */
+
+#define	HZSCALE		(268435456 / (1000000/HZ))
+
+EXPORT_SYMBOL(__udelay);
+
+void __udelay(unsigned long usecs)
+{
+#if defined(CONFIG_M68328) || defined(CONFIG_M68EZ328) || \
+    defined(CONFIG_M68VZ328) || defined(CONFIG_M68360) || \
+    defined(CONFIG_COLDFIRE)
+	__delay((((usecs * HZSCALE) >> 11) * (loops_per_jiffy >> 11)) >> 6);
+#else
+	unsigned long tmp;
+
+	usecs *= 4295;		/* 2**32 / 1000000 */
+	__asm__ ("mulul %2,%0:%1"
+		: "=d" (usecs), "=d" (tmp)
+		: "d" (usecs), "1" (loops_per_jiffy*HZ));
+	__delay(usecs);
+#endif
 }
 
diff -U10 -urpN linux-2.6.12.org/arch/sh/kernel/sh_ksyms.c linux-2.6.12.delay/arch/sh/kernel/sh_ksyms.c
--- linux-2.6.12.org/arch/sh/kernel/sh_ksyms.c	Sun Jun 19 16:09:58 2005
+++ linux-2.6.12.delay/arch/sh/kernel/sh_ksyms.c	Thu Jun 30 20:32:27 2005
@@ -70,21 +70,20 @@ EXPORT_SYMBOL(boot_cpu_data);
 EXPORT_SYMBOL(get_vm_area);
 #endif
 
 /* semaphore exports */
 EXPORT_SYMBOL(__up);
 EXPORT_SYMBOL(__down);
 EXPORT_SYMBOL(__down_interruptible);
 
 EXPORT_SYMBOL(__udelay);
 EXPORT_SYMBOL(__ndelay);
-EXPORT_SYMBOL(__const_udelay);
 
 EXPORT_SYMBOL(__div64_32);
 
 #define DECLARE_EXPORT(name) extern void name(void);EXPORT_SYMBOL(name)
 
 /* These symbols are generated by the compiler itself */
 DECLARE_EXPORT(__udivsi3);
 DECLARE_EXPORT(__udivdi3);
 DECLARE_EXPORT(__sdivsi3);
 DECLARE_EXPORT(__ashrdi3);
diff -U10 -urpN linux-2.6.12.org/arch/sh/lib/delay.c linux-2.6.12.delay/arch/sh/lib/delay.c
--- linux-2.6.12.org/arch/sh/lib/delay.c	Thu Mar  3 09:30:22 2005
+++ linux-2.6.12.delay/arch/sh/lib/delay.c	Thu Jun 30 20:32:33 2005
@@ -12,21 +12,21 @@ void __delay(unsigned long loops)
 	__asm__ __volatile__(
 		"tst	%0, %0\n\t"
 		"1:\t"
 		"bf/s	1b\n\t"
 		" dt	%0"
 		: "=r" (loops)
 		: "0" (loops)
 		: "t");
 }
 
-inline void __const_udelay(unsigned long xloops)
+static inline void __const_udelay(unsigned long xloops)
 {
 	__asm__("dmulu.l	%0, %2\n\t"
 		"sts	mach, %0"
 		: "=r" (xloops)
 		: "0" (xloops), "r" (cpu_data[_smp_processor_id()].loops_per_jiffy)
 		: "macl", "mach");
 	__delay(xloops * HZ);
 }
 
 void __udelay(unsigned long usecs)
diff -U10 -urpN linux-2.6.12.org/arch/sh64/lib/udelay.c linux-2.6.12.delay/arch/sh64/lib/udelay.c
--- linux-2.6.12.org/arch/sh64/lib/udelay.c	Tue Oct 19 00:53:46 2004
+++ linux-2.6.12.delay/arch/sh64/lib/udelay.c	Thu Jun 30 22:46:11 2005
@@ -29,32 +29,21 @@ void __delay(int loops)
 	long long dummy;
 	__asm__ __volatile__("gettr	tr0, %1\n\t"
 			     "pta	$+4, tr0\n\t"
 			     "addi	%0, -1, %0\n\t"
 			     "bne	%0, r63, tr0\n\t"
 			     "ptabs	%1, tr0\n\t":"=r"(loops),
 			     "=r"(dummy)
 			     :"0"(loops));
 }
 
-void __udelay(unsigned long long usecs, unsigned long lpj)
+void __udelay(unsigned long long usecs)
 {
-	usecs *= (((unsigned long long) HZ << 32) / 1000000) * lpj;
+	usecs *= (((unsigned long long) HZ << 32) / 1000000) * loops_per_jiffy;
 	__delay((long long) usecs >> 32);
 }
 
-void __ndelay(unsigned long long nsecs, unsigned long lpj)
+void __ndelay(unsigned long long nsecs)
 {
-	nsecs *= (((unsigned long long) HZ << 32) / 1000000000) * lpj;
+	nsecs *= (((unsigned long long) HZ << 32) / 1000000000) * loops_per_jiffy;
 	__delay((long long) nsecs >> 32);
 }
-
-void udelay(unsigned long usecs)
-{
-	__udelay(usecs, loops_per_jiffy);
-}
-
-void ndelay(unsigned long nsecs)
-{
-	__ndelay(nsecs, loops_per_jiffy);
-}
-
diff -U10 -urpN linux-2.6.12.org/arch/sparc/kernel/entry.S linux-2.6.12.delay/arch/sparc/kernel/entry.S
--- linux-2.6.12.org/arch/sparc/kernel/entry.S	Thu Feb  3 11:39:08 2005
+++ linux-2.6.12.delay/arch/sparc/kernel/entry.S	Thu Jun 30 19:56:48 2005
@@ -1789,40 +1789,40 @@ fpload:
 	ldd	[%o0 + 0x50], %f20
 	ldd	[%o0 + 0x58], %f22
 	ldd	[%o0 + 0x60], %f24
 	ldd	[%o0 + 0x68], %f26
 	ldd	[%o0 + 0x70], %f28
 	ldd	[%o0 + 0x78], %f30
 	ld	[%o1], %fsr
 	retl
 	 nop
 
-	/* __ndelay and __udelay take two arguments:
+	/* ___ndelay and ___udelay take two arguments:
 	 * 0 - nsecs or usecs to delay
 	 * 1 - per_cpu udelay_val (loops per jiffy)
 	 *
 	 * Note that ndelay gives HZ times higher resolution but has a 10ms
 	 * limit.  udelay can handle up to 1s.
 	 */
-	.globl	__ndelay
-__ndelay:
+	.globl	___ndelay
+___ndelay:
 	save	%sp, -STACKFRAME_SZ, %sp
 	mov	%i0, %o0
 	call	.umul
 	 mov	0x1ad, %o1		! 2**32 / (1 000 000 000 / HZ)
 	call	.umul
 	 mov	%i1, %o1		! udelay_val
 	ba	delay_continue
 	 mov	%o1, %o0		! >>32 later for better resolution
 
-	.globl	__udelay
-__udelay:
+	.globl	___udelay
+___udelay:
 	save	%sp, -STACKFRAME_SZ, %sp
 	mov	%i0, %o0
 	sethi	%hi(0x10c6), %o1
 	call	.umul
 	 or	%o1, %lo(0x10c6), %o1	! 2**32 / 1 000 000
 	call	.umul
 	 mov	%i1, %o1		! udelay_val
 	call	.umul
 	 mov	HZ, %o0			! >>32 earlier for wider range
 
diff -U10 -urpN linux-2.6.12.org/arch/sparc/kernel/sparc_ksyms.c linux-2.6.12.delay/arch/sparc/kernel/sparc_ksyms.c
--- linux-2.6.12.org/arch/sparc/kernel/sparc_ksyms.c	Sun Jun 19 16:09:59 2005
+++ linux-2.6.12.delay/arch/sparc/kernel/sparc_ksyms.c	Thu Jun 30 19:57:13 2005
@@ -157,22 +157,22 @@ EXPORT_SYMBOL(synchronize_irq);
 
 /* Misc SMP information */
 EXPORT_SYMBOL(__cpu_number_map);
 EXPORT_SYMBOL(__cpu_logical_map);
 
 /* CPU online map and active count. */
 EXPORT_SYMBOL(cpu_online_map);
 EXPORT_SYMBOL(phys_cpu_present_map);
 #endif
 
-EXPORT_SYMBOL(__udelay);
-EXPORT_SYMBOL(__ndelay);
+EXPORT_SYMBOL(___udelay);
+EXPORT_SYMBOL(___ndelay);
 EXPORT_SYMBOL(rtc_lock);
 EXPORT_SYMBOL(mostek_lock);
 EXPORT_SYMBOL(mstk48t02_regs);
 #ifdef CONFIG_SUN_AUXIO
 EXPORT_SYMBOL(set_auxio);
 EXPORT_SYMBOL(get_auxio);
 #endif
 EXPORT_SYMBOL(request_fast_irq);
 EXPORT_SYMBOL(io_remap_page_range);
 EXPORT_SYMBOL(io_remap_pfn_range);
diff -U10 -urpN linux-2.6.12.org/arch/sparc64/kernel/sparc64_ksyms.c linux-2.6.12.delay/arch/sparc64/kernel/sparc64_ksyms.c
--- linux-2.6.12.org/arch/sparc64/kernel/sparc64_ksyms.c	Sun Jun 19 16:10:00 2005
+++ linux-2.6.12.delay/arch/sparc64/kernel/sparc64_ksyms.c	Thu Jun 30 20:35:43 2005
@@ -393,21 +393,20 @@ EXPORT_SYMBOL(__ret_efault);
 /* No version information on these, as gcc produces such symbols. */
 EXPORT_SYMBOL(memcmp);
 EXPORT_SYMBOL(memcpy);
 EXPORT_SYMBOL(memset);
 EXPORT_SYMBOL(memmove);
 EXPORT_SYMBOL(strncmp);
 
 /* Delay routines. */
 EXPORT_SYMBOL(__udelay);
 EXPORT_SYMBOL(__ndelay);
-EXPORT_SYMBOL(__const_udelay);
 EXPORT_SYMBOL(__delay);
 
 void VISenter(void);
 /* RAID code needs this */
 EXPORT_SYMBOL(VISenter);
 
 /* for input/keybdev */
 EXPORT_SYMBOL(sun_do_break);
 EXPORT_SYMBOL(serial_console);
 EXPORT_SYMBOL(stop_a_enabled);
diff -U10 -urpN linux-2.6.12.org/arch/sparc64/lib/delay.c linux-2.6.12.delay/arch/sparc64/lib/delay.c
--- linux-2.6.12.org/arch/sparc64/lib/delay.c	Thu Mar  3 09:30:22 2005
+++ linux-2.6.12.delay/arch/sparc64/lib/delay.c	Thu Jun 30 20:35:40 2005
@@ -20,21 +20,21 @@ void __delay(unsigned long loops)
 "	 subcc	%0, 1, %0\n"
 	: "=&r" (loops)
 	: "0" (loops)
 	: "cc");
 }
 
 /* We used to multiply by HZ after shifting down by 32 bits
  * but that runs into problems for higher values of HZ and
  * slow cpus.
  */
-void __const_udelay(unsigned long n)
+static void __const_udelay(unsigned long n)
 {
 	n *= 4;
 
 	n *= (cpu_data(_smp_processor_id()).udelay_val * (HZ/4));
 	n >>= 32;
 
 	__delay(n + 1);
 }
 
 void __udelay(unsigned long n)
diff -U10 -urpN linux-2.6.12.org/arch/um/sys-i386/delay.c linux-2.6.12.delay/arch/um/sys-i386/delay.c
--- linux-2.6.12.org/arch/um/sys-i386/delay.c	Sun Jun 19 16:10:01 2005
+++ linux-2.6.12.delay/arch/um/sys-i386/delay.c	Thu Jun 30 22:43:14 2005
@@ -20,21 +20,10 @@ void __delay(unsigned long time)
 void __udelay(unsigned long usecs)
 {
 	int i, n;
 
 	n = (loops_per_jiffy * HZ * usecs) / MILLION;
         for(i=0;i<n;i++)
                 cpu_relax();
 }
 
 EXPORT_SYMBOL(__udelay);
-
-void __const_udelay(unsigned long usecs)
-{
-	int i, n;
-
-	n = (loops_per_jiffy * HZ * usecs) / MILLION;
-        for(i=0;i<n;i++)
-                cpu_relax();
-}
-
-EXPORT_SYMBOL(__const_udelay);
diff -U10 -urpN linux-2.6.12.org/arch/um/sys-i386/ksyms.c linux-2.6.12.delay/arch/um/sys-i386/ksyms.c
--- linux-2.6.12.org/arch/um/sys-i386/ksyms.c	Sun Jun 19 16:10:01 2005
+++ linux-2.6.12.delay/arch/um/sys-i386/ksyms.c	Thu Jun 30 22:43:50 2005
@@ -10,12 +10,11 @@
 
 EXPORT_SYMBOL(__down_failed);
 EXPORT_SYMBOL(__down_failed_interruptible);
 EXPORT_SYMBOL(__down_failed_trylock);
 EXPORT_SYMBOL(__up_wakeup);
 
 /* Networking helper routines. */
 EXPORT_SYMBOL(csum_partial);
 
 /* delay core functions */
-EXPORT_SYMBOL(__const_udelay);
 EXPORT_SYMBOL(__udelay);
diff -U10 -urpN linux-2.6.12.org/arch/um/sys-x86_64/delay.c linux-2.6.12.delay/arch/um/sys-x86_64/delay.c
--- linux-2.6.12.org/arch/um/sys-x86_64/delay.c	Sun Jun 19 16:10:01 2005
+++ linux-2.6.12.delay/arch/um/sys-x86_64/delay.c	Thu Jun 30 22:43:27 2005
@@ -21,21 +21,10 @@ void __delay(unsigned long loops)
 void __udelay(unsigned long usecs)
 {
 	unsigned long i, n;
 
 	n = (loops_per_jiffy * HZ * usecs) / MILLION;
         for(i=0;i<n;i++)
                 cpu_relax();
 }
 
 EXPORT_SYMBOL(__udelay);
-
-void __const_udelay(unsigned long usecs)
-{
-	unsigned long i, n;
-
-	n = (loops_per_jiffy * HZ * usecs) / MILLION;
-        for(i=0;i<n;i++)
-                cpu_relax();
-}
-
-EXPORT_SYMBOL(__const_udelay);
diff -U10 -urpN linux-2.6.12.org/arch/x86_64/kernel/x8664_ksyms.c linux-2.6.12.delay/arch/x86_64/kernel/x8664_ksyms.c
--- linux-2.6.12.org/arch/x86_64/kernel/x8664_ksyms.c	Sun Jun 19 16:10:03 2005
+++ linux-2.6.12.delay/arch/x86_64/kernel/x8664_ksyms.c	Thu Jun 30 20:37:34 2005
@@ -66,21 +66,20 @@ EXPORT_SYMBOL(__down_failed);
 EXPORT_SYMBOL(__down_failed_interruptible);
 EXPORT_SYMBOL(__down_failed_trylock);
 EXPORT_SYMBOL(__up_wakeup);
 /* Networking helper routines. */
 EXPORT_SYMBOL(csum_partial_copy_nocheck);
 EXPORT_SYMBOL(ip_compute_csum);
 /* Delay loops */
 EXPORT_SYMBOL(__udelay);
 EXPORT_SYMBOL(__ndelay);
 EXPORT_SYMBOL(__delay);
-EXPORT_SYMBOL(__const_udelay);
 
 EXPORT_SYMBOL(__get_user_1);
 EXPORT_SYMBOL(__get_user_2);
 EXPORT_SYMBOL(__get_user_4);
 EXPORT_SYMBOL(__get_user_8);
 EXPORT_SYMBOL(__put_user_1);
 EXPORT_SYMBOL(__put_user_2);
 EXPORT_SYMBOL(__put_user_4);
 EXPORT_SYMBOL(__put_user_8);
 
diff -U10 -urpN linux-2.6.12.org/arch/x86_64/lib/delay.c linux-2.6.12.delay/arch/x86_64/lib/delay.c
--- linux-2.6.12.org/arch/x86_64/lib/delay.c	Sun Jun 19 16:10:03 2005
+++ linux-2.6.12.delay/arch/x86_64/lib/delay.c	Thu Jun 30 20:35:15 2005
@@ -25,21 +25,21 @@ void __delay(unsigned long loops)
 	
 	rdtscl(bclock);
 	do
 	{
 		rep_nop(); 
 		rdtscl(now);
 	}
 	while((now-bclock) < loops);
 }
 
-inline void __const_udelay(unsigned long xloops)
+static inline void __const_udelay(unsigned long xloops)
 {
 	__delay(((xloops * cpu_data[_smp_processor_id()].loops_per_jiffy) >> 32) * HZ);
 }
 
 void __udelay(unsigned long usecs)
 {
 	__const_udelay(usecs * 0x000010c6);  /* 2**32 / 1000000 */
 }
 
 void __ndelay(unsigned long nsecs)
diff -U10 -urpN linux-2.6.12.org/include/asm-alpha/delay.h linux-2.6.12.delay/include/asm-alpha/delay.h
--- linux-2.6.12.org/include/asm-alpha/delay.h	Tue Oct 19 00:53:51 2004
+++ linux-2.6.12.delay/include/asm-alpha/delay.h	Thu Jun 30 19:58:07 2005
@@ -1,10 +1,9 @@
 #ifndef __ALPHA_DELAY_H
 #define __ALPHA_DELAY_H
 
 extern void __delay(int loops);
-extern void udelay(unsigned long usecs);
-
-extern void ndelay(unsigned long nsecs);
-#define ndelay ndelay
+extern void __udelay(unsigned long usecs);
+extern void __ndelay(unsigned long nsecs);
+#define __ndelay(n) __ndelay(n)
 
 #endif /* defined(__ALPHA_DELAY_H) */
diff -U10 -urpN linux-2.6.12.org/include/asm-arm/delay.h linux-2.6.12.delay/include/asm-arm/delay.h
--- linux-2.6.12.org/include/asm-arm/delay.h	Thu Feb  3 11:40:05 2005
+++ linux-2.6.12.delay/include/asm-arm/delay.h	Thu Jun 30 20:24:49 2005
@@ -1,42 +1,16 @@
 /*
  * Copyright (C) 1995-2004 Russell King
  *
  * Delay routines, using a pre-computed "loops_per_second" value.
  */
 #ifndef __ASM_ARM_DELAY_H
 #define __ASM_ARM_DELAY_H
 
 extern void __delay(int loops);
 
-/*
- * This function intentionally does not exist; if you see references to
- * it, it means that you're calling udelay() with an out of range value.
- *
- * With currently imposed limits, this means that we support a max delay
- * of 2000us and 671 bogomips
- */
-extern void __bad_udelay(void);
-
-/*
- * division by multiplication: you don't have to worry about
- * loss of precision.
- *
- * Use only for very small delays ( < 1 msec).  Should probably use a
- * lookup table, really, as the multiplications take much too long with
- * short delays.  This is a "reasonable" implementation, though (and the
- * first constant multiplications gets optimized away if the delay is
- * a constant)
- */
 extern void __udelay(unsigned long usecs);
-extern void __const_udelay(unsigned long);
 
 #define MAX_UDELAY_MS 2
-
-#define udelay(n)						\
-	(__builtin_constant_p(n) ?				\
-	  ((n) > (MAX_UDELAY_MS * 1000) ? __bad_udelay() :	\
-			__const_udelay((n) * 0x68dbul)) :	\
-	  __udelay(n))
 
 #endif /* defined(_ARM_DELAY_H) */
 
diff -U10 -urpN linux-2.6.12.org/include/asm-arm26/delay.h linux-2.6.12.delay/include/asm-arm26/delay.h
--- linux-2.6.12.org/include/asm-arm26/delay.h	Tue Oct 19 00:53:06 2004
+++ linux-2.6.12.delay/include/asm-arm26/delay.h	Thu Jun 30 19:38:27 2005
@@ -14,21 +14,21 @@ extern void __delay(int loops);
  * loss of precision.
  *
  * Use only for very small delays ( < 1 msec).  Should probably use a
  * lookup table, really, as the multiplications take much too long with
  * short delays.  This is a "reasonable" implementation, though (and the
  * first constant multiplications gets optimized away if the delay is
  * a constant)
  *
  * FIXME - lets improve it then...
  */
-extern void udelay(unsigned long usecs);
+extern void __udelay(unsigned long usecs);
 
 static inline unsigned long muldiv(unsigned long a, unsigned long b, unsigned long c)
 {
 	return a * b / c;
 }
 
 	
 
 #endif /* defined(_ARM_DELAY_H) */
 
diff -U10 -urpN linux-2.6.12.org/include/asm-cris/delay.h linux-2.6.12.delay/include/asm-cris/delay.h
--- linux-2.6.12.org/include/asm-cris/delay.h	Tue Oct 19 00:55:23 2004
+++ linux-2.6.12.delay/include/asm-cris/delay.h	Thu Jun 30 19:33:41 2005
@@ -6,19 +6,19 @@
  *
  * Delay routines, using a pre-computed "loops_per_second" value.
  */
 
 #include <asm/arch/delay.h>
 
 /* Use only for very small delays ( < 1 msec).  */
 
 extern unsigned long loops_per_usec; /* arch/cris/mm/init.c */
 
-extern __inline__ void udelay(unsigned long usecs)
+extern __inline__ void __udelay(unsigned long usecs)
 {
 	__delay(usecs * loops_per_usec);
 }
 
 #endif /* defined(_CRIS_DELAY_H) */
 
 
 
diff -U10 -urpN linux-2.6.12.org/include/asm-frv/delay.h linux-2.6.12.delay/include/asm-frv/delay.h
--- linux-2.6.12.org/include/asm-frv/delay.h	Thu Mar  3 09:31:07 2005
+++ linux-2.6.12.delay/include/asm-frv/delay.h	Thu Jun 30 19:22:31 2005
@@ -33,18 +33,18 @@ static inline void __delay(unsigned long
 /*
  * Use only for very small delays ( < 1 msec).  Should probably use a
  * lookup table, really, as the multiplications take much too long with
  * short delays.  This is a "reasonable" implementation, though (and the
  * first constant multiplications gets optimized away if the delay is
  * a constant)
  */
 
 extern unsigned long loops_per_jiffy;
 
-static inline void udelay(unsigned long usecs)
+static inline void __udelay(unsigned long usecs)
 {
 	__delay(usecs * __delay_loops_MHz);
 }
 
-#define ndelay(n)	udelay((n) * 5)
+//BOGUS! #define ndelay(n)	udelay((n) * 5)
 
 #endif /* _ASM_DELAY_H */
diff -U10 -urpN linux-2.6.12.org/include/asm-h8300/delay.h linux-2.6.12.delay/include/asm-h8300/delay.h
--- linux-2.6.12.org/include/asm-h8300/delay.h	Thu Feb  3 11:40:05 2005
+++ linux-2.6.12.delay/include/asm-h8300/delay.h	Thu Jun 30 19:38:09 2005
@@ -20,19 +20,19 @@ extern __inline__ void __delay(unsigned 
 /*
  * Use only for very small delays ( < 1 msec).  Should probably use a
  * lookup table, really, as the multiplications take much too long with
  * short delays.  This is a "reasonable" implementation, though (and the
  * first constant multiplications gets optimized away if the delay is
  * a constant)  
  */
 
 extern unsigned long loops_per_jiffy;
 
-extern __inline__ void udelay(unsigned long usecs)
+extern __inline__ void __udelay(unsigned long usecs)
 {
 	usecs *= 4295;		/* 2**32 / 1000000 */
 	usecs /= (loops_per_jiffy*HZ);
 	if (usecs)
 		__delay(usecs);
 }
 
 #endif /* _H8300_DELAY_H */
diff -U10 -urpN linux-2.6.12.org/include/asm-i386/delay.h linux-2.6.12.delay/include/asm-i386/delay.h
--- linux-2.6.12.org/include/asm-i386/delay.h	Tue Oct 19 00:53:05 2004
+++ linux-2.6.12.delay/include/asm-i386/delay.h	Thu Jun 30 20:34:21 2005
@@ -1,26 +1,15 @@
 #ifndef _I386_DELAY_H
 #define _I386_DELAY_H
 
 /*
  * Copyright (C) 1993 Linus Torvalds
  *
  * 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 __ndelay(unsigned long nsecs);
-extern void __const_udelay(unsigned long usecs);
+#define __ndelay(n) __ndelay(n)
 extern void __delay(unsigned long loops);
-
-#define udelay(n) (__builtin_constant_p(n) ? \
-	((n) > 20000 ? __bad_udelay() : __const_udelay((n) * 0x10c7ul)) : \
-	__udelay(n))
-	
-#define ndelay(n) (__builtin_constant_p(n) ? \
-	((n) > 20000 ? __bad_ndelay() : __const_udelay((n) * 5ul)) : \
-	__ndelay(n))
 
 #endif /* defined(_I386_DELAY_H) */
diff -U10 -urpN linux-2.6.12.org/include/asm-m32r/delay.h linux-2.6.12.delay/include/asm-m32r/delay.h
--- linux-2.6.12.org/include/asm-m32r/delay.h	Tue Oct 19 00:53:45 2004
+++ linux-2.6.12.delay/include/asm-m32r/delay.h	Thu Jun 30 20:32:48 2005
@@ -2,27 +2,16 @@
 #define _ASM_M32R_DELAY_H
 
 /* $Id$ */
 
 /*
  * Copyright (C) 1993 Linus Torvalds
  *
  * Delay routines calling functions in arch/m32r/lib/delay.c
  */
 
-extern void __bad_udelay(void);
-extern void __bad_ndelay(void);
-
 extern void __udelay(unsigned long usecs);
 extern void __ndelay(unsigned long nsecs);
-extern void __const_udelay(unsigned long usecs);
+#define __ndelay(n) __ndelay(n)
 extern void __delay(unsigned long loops);
-
-#define udelay(n) (__builtin_constant_p(n) ? \
-	((n) > 20000 ? __bad_udelay() : __const_udelay((n) * 0x10c7ul)) : \
-	__udelay(n))
-
-#define ndelay(n) (__builtin_constant_p(n) ? \
-	((n) > 20000 ? __bad_ndelay() : __const_udelay((n) * 5ul)) : \
-	__ndelay(n))
 
 #endif /* _ASM_M32R_DELAY_H */
diff -U10 -urpN linux-2.6.12.org/include/asm-m68k/delay.h linux-2.6.12.delay/include/asm-m68k/delay.h
--- linux-2.6.12.org/include/asm-m68k/delay.h	Tue Oct 19 00:55:28 2004
+++ linux-2.6.12.delay/include/asm-m68k/delay.h	Thu Jun 30 20:29:04 2005
@@ -8,22 +8,20 @@
  *
  * Delay routines, using a pre-computed "loops_per_jiffy" value.
  */
 
 static inline void __delay(unsigned long loops)
 {
 	__asm__ __volatile__ ("1: subql #1,%0; jcc 1b"
 		: "=d" (loops) : "0" (loops));
 }
 
-extern void __bad_udelay(void);
-
 /*
  * Use only for very small delays ( < 1 msec).  Should probably use a
  * lookup table, really, as the multiplications take much too long with
  * short delays.  This is a "reasonable" implementation, though (and the
  * first constant multiplications gets optimized away if the delay is
  * a constant)
  */
 static inline void __const_udelay(unsigned long xloops)
 {
 	unsigned long tmp;
@@ -31,24 +29,20 @@ static inline void __const_udelay(unsign
 	__asm__ ("mulul %2,%0:%1"
 		: "=d" (xloops), "=d" (tmp)
 		: "d" (xloops), "1" (loops_per_jiffy));
 	__delay(xloops * HZ);
 }
 
 static inline void __udelay(unsigned long usecs)
 {
 	__const_udelay(usecs * 4295);	/* 2**32 / 1000000 */
 }
-
-#define udelay(n) (__builtin_constant_p(n) ? \
-	((n) > 20000 ? __bad_udelay() : __const_udelay((n) * 4295)) : \
-	__udelay(n))
 
 static inline unsigned long muldiv(unsigned long a, unsigned long b,
 				   unsigned long c)
 {
 	unsigned long tmp;
 
 	__asm__ ("mulul %2,%0:%1; divul %3,%0:%1"
 		: "=d" (tmp), "=d" (a)
 		: "d" (b), "d" (c), "1" (a));
 	return a;
diff -U10 -urpN linux-2.6.12.org/include/asm-m68knommu/delay.h linux-2.6.12.delay/include/asm-m68knommu/delay.h
--- linux-2.6.12.org/include/asm-m68knommu/delay.h	Thu Feb  3 11:40:08 2005
+++ linux-2.6.12.delay/include/asm-m68knommu/delay.h	Thu Jun 30 20:27:54 2005
@@ -1,76 +1,13 @@
 #ifndef _M68KNOMMU_DELAY_H
 #define _M68KNOMMU_DELAY_H
 
 /*
  * Copyright (C) 1994 Hamish Macdonald
  * Copyright (C) 2004 Greg Ungerer <[email protected]>
  */
 
 #include <asm/param.h>
 
-extern __inline__ void __delay(unsigned long loops)
-{
-#if defined(CONFIG_COLDFIRE)
-	/* The coldfire runs this loop at significantly different speeds
-	 * depending upon long word alignment or not.  We'll pad it to
-	 * long word alignment which is the faster version.
-	 * The 0x4a8e is of course a 'tstl %fp' instruction.  This is better
-	 * than using a NOP (0x4e71) instruction because it executes in one
-	 * cycle not three and doesn't allow for an arbitary delay waiting
-	 * for bus cycles to finish.  Also fp/a6 isn't likely to cause a
-	 * stall waiting for the register to become valid if such is added
-	 * to the coldfire at some stage.
-	 */
-	__asm__ __volatile__ (	".balignw 4, 0x4a8e\n\t"
-				"1: subql #1, %0\n\t"
-				"jcc 1b"
-		: "=d" (loops) : "0" (loops));
-#else
-	__asm__ __volatile__ (	"1: subql #1, %0\n\t"
-				"jcc 1b"
-		: "=d" (loops) : "0" (loops));
-#endif
-}
-
-/*
- *	Ideally we use a 32*32->64 multiply to calculate the number of
- *	loop iterations, but the older standard 68k and ColdFire do not
- *	have this instruction. So for them we have a clsoe approximation
- *	loop using 32*32->32 multiplies only. This calculation based on
- *	the ARM version of delay.
- *
- *	We want to implement:
- *
- *	loops = (usecs * 0x10c6 * HZ * loops_per_jiffy) / 2^32
- */
-
-#define	HZSCALE		(268435456 / (1000000/HZ))
-
-extern unsigned long loops_per_jiffy;
-
-extern __inline__ void _udelay(unsigned long usecs)
-{
-#if defined(CONFIG_M68328) || defined(CONFIG_M68EZ328) || \
-    defined(CONFIG_M68VZ328) || defined(CONFIG_M68360) || \
-    defined(CONFIG_COLDFIRE)
-	__delay((((usecs * HZSCALE) >> 11) * (loops_per_jiffy >> 11)) >> 6);
-#else
-	unsigned long tmp;
-
-	usecs *= 4295;		/* 2**32 / 1000000 */
-	__asm__ ("mulul %2,%0:%1"
-		: "=d" (usecs), "=d" (tmp)
-		: "d" (usecs), "1" (loops_per_jiffy*HZ));
-	__delay(usecs);
-#endif
-}
-
-/*
- *	Moved the udelay() function into library code, no longer inlined.
- *	I had to change the algorithm because we are overflowing now on
- *	the faster ColdFire parts. The code is a little biger, so it makes
- *	sense to library it.
- */
-extern void udelay(unsigned long usecs);
+extern void __udelay(unsigned long usecs);
 
 #endif /* defined(_M68KNOMMU_DELAY_H) */
diff -U10 -urpN linux-2.6.12.org/include/asm-mips/delay.h linux-2.6.12.delay/include/asm-mips/delay.h
--- linux-2.6.12.org/include/asm-mips/delay.h	Thu Feb  3 11:40:09 2005
+++ linux-2.6.12.delay/include/asm-mips/delay.h	Thu Jun 30 20:29:34 2005
@@ -42,52 +42,50 @@ static inline void __delay(unsigned long
  * Division by multiplication: you don't have to worry about
  * loss of precision.
  *
  * Use only for very small delays ( < 1 msec).  Should probably use a
  * lookup table, really, as the multiplications take much too long with
  * short delays.  This is a "reasonable" implementation, though (and the
  * first constant multiplications gets optimized away if the delay is
  * a constant)
  */
 
-static inline void __udelay(unsigned long usecs, unsigned long lpj)
+static inline void __udelay(unsigned long usecs)
 {
 	unsigned long lo;
 
+#ifdef CONFIG_SMP
+	unsigned long loops_per_jiffy = cpu_data[smp_processor_id()].udelay_val;
+#else
+	/* using global one */
+#endif
+
 	/*
 	 * The common rates of 1000 and 128 are rounded wrongly by the
 	 * catchall case for 64-bit.  Excessive precission?  Probably ...
 	 */
 #if defined(CONFIG_MIPS64) && (HZ == 128)
 	usecs *= 0x0008637bd05af6c7UL;		/* 2**64 / (1000000 / HZ) */
 #elif defined(CONFIG_MIPS64) && (HZ == 1000)
 	usecs *= 0x004189374BC6A7f0UL;		/* 2**64 / (1000000 / HZ) */
 #elif defined(CONFIG_MIPS64)
 	usecs *= (0x8000000000000000UL / (500000 / HZ));
 #else /* 32-bit junk follows here */
 	usecs *= (unsigned long) (((0x8000000000000000ULL / (500000 / HZ)) +
 	                           0x80000000ULL) >> 32);
 #endif
 
 	if (sizeof(long) == 4)
 		__asm__("multu\t%2, %3"
 		: "=h" (usecs), "=l" (lo)
-		: "r" (usecs), "r" (lpj)
+		: "r" (usecs), "r" (loops_per_jiffy)
 		: GCC_REG_ACCUM);
 	else if (sizeof(long) == 8)
 		__asm__("dmultu\t%2, %3"
 		: "=h" (usecs), "=l" (lo)
-		: "r" (usecs), "r" (lpj)
+		: "r" (usecs), "r" (loops_per_jiffy)
 		: GCC_REG_ACCUM);
 
 	__delay(usecs);
 }
-
-#ifdef CONFIG_SMP
-#define __udelay_val cpu_data[smp_processor_id()].udelay_val
-#else
-#define __udelay_val loops_per_jiffy
-#endif
-
-#define udelay(usecs) __udelay((usecs),__udelay_val)
 
 #endif /* _ASM_DELAY_H */
diff -U10 -urpN linux-2.6.12.org/include/asm-parisc/delay.h linux-2.6.12.delay/include/asm-parisc/delay.h
--- linux-2.6.12.org/include/asm-parisc/delay.h	Tue Oct 19 00:54:08 2004
+++ linux-2.6.12.delay/include/asm-parisc/delay.h	Thu Jun 30 20:28:18 2005
@@ -31,13 +31,11 @@ static __inline__ void __cr16_delay(unsi
 
 	start = mfctl(16);
 	while ((mfctl(16) - start) < clocks)
 	    ;
 }
 
 static __inline__ void __udelay(unsigned long usecs) {
 	__cr16_delay(usecs * ((unsigned long)boot_cpu_data.cpu_hz / 1000000UL));
 }
 
-#define udelay(n) __udelay(n)
-
 #endif /* defined(_PARISC_DELAY_H) */
diff -U10 -urpN linux-2.6.12.org/include/asm-ppc/delay.h linux-2.6.12.delay/include/asm-ppc/delay.h
--- linux-2.6.12.org/include/asm-ppc/delay.h	Tue Oct 19 00:54:39 2004
+++ linux-2.6.12.delay/include/asm-ppc/delay.h	Thu Jun 30 20:22:55 2005
@@ -43,24 +43,14 @@ extern __inline__ void __udelay(unsigned
 }
 
 extern __inline__ void __ndelay(unsigned int x)
 {
 	unsigned int loops;
 
 	__asm__("mulhwu %0,%1,%2" : "=r" (loops) :
 		"r" (x), "r" (loops_per_jiffy * 5));
 	__delay(loops);
 }
-
-extern void __bad_udelay(void);		/* deliberately undefined */
-extern void __bad_ndelay(void);		/* deliberately undefined */
-
-#define udelay(n) (__builtin_constant_p(n)? \
-	((n) > __MAX_UDELAY? __bad_udelay(): __udelay((n) * (19 * HZ))) : \
-	__udelay((n) * (19 * HZ)))
-
-#define ndelay(n) (__builtin_constant_p(n)? \
-	((n) > __MAX_NDELAY? __bad_ndelay(): __ndelay((n) * HZ)) : \
-	__ndelay((n) * HZ))
+#define __ndelay(n) __ndelay(n)
 
 #endif /* defined(_PPC_DELAY_H) */
 #endif /* __KERNEL__ */
diff -U10 -urpN linux-2.6.12.org/include/asm-ppc64/delay.h linux-2.6.12.delay/include/asm-ppc64/delay.h
--- linux-2.6.12.org/include/asm-ppc64/delay.h	Tue Oct 19 00:53:06 2004
+++ linux-2.6.12.delay/include/asm-ppc64/delay.h	Thu Jun 30 19:37:43 2005
@@ -31,18 +31,18 @@ static inline unsigned long __get_tb(voi
 static inline void __delay(unsigned long loops)
 {
 	unsigned long start = __get_tb();
 
 	while((__get_tb()-start) < loops)
 		__HMT_low();
 	__HMT_medium();
 	__barrier();
 }
 
-static inline void udelay(unsigned long usecs)
+static inline void __udelay(unsigned long usecs)
 {
 	unsigned long loops = tb_ticks_per_usec * usecs;
 
 	__delay(loops);
 }
 
 #endif /* _PPC64_DELAY_H */
diff -U10 -urpN linux-2.6.12.org/include/asm-s390/delay.h linux-2.6.12.delay/include/asm-s390/delay.h
--- linux-2.6.12.org/include/asm-s390/delay.h	Tue Oct 19 00:54:39 2004
+++ linux-2.6.12.delay/include/asm-s390/delay.h	Thu Jun 30 20:25:11 2005
@@ -10,13 +10,11 @@
  *
  *  Delay routines calling functions in arch/s390/lib/delay.c
  */
  
 #ifndef _S390_DELAY_H
 #define _S390_DELAY_H
 
 extern void __udelay(unsigned long usecs);
 extern void __delay(unsigned long loops);
 
-#define udelay(n) __udelay(n)
-
 #endif /* defined(_S390_DELAY_H) */
diff -U10 -urpN linux-2.6.12.org/include/asm-sh/delay.h linux-2.6.12.delay/include/asm-sh/delay.h
--- linux-2.6.12.org/include/asm-sh/delay.h	Tue Oct 19 00:55:24 2004
+++ linux-2.6.12.delay/include/asm-sh/delay.h	Thu Jun 30 20:37:05 2005
@@ -1,27 +1,15 @@
 #ifndef __ASM_SH_DELAY_H
 #define __ASM_SH_DELAY_H
 
 /*
  * Copyright (C) 1993 Linus Torvalds
  *
  * Delay routines calling functions in arch/sh/lib/delay.c
  */
  
-extern void __bad_udelay(void);
-extern void __bad_ndelay(void);
-
 extern void __udelay(unsigned long usecs);
 extern void __ndelay(unsigned long nsecs);
-extern void __const_udelay(unsigned long usecs);
+#define __ndelay(n) __ndelay(n)
 extern void __delay(unsigned long loops);
-
-#define udelay(n) (__builtin_constant_p(n) ? \
-	((n) > 20000 ? __bad_udelay() : __const_udelay((n) * 0x10c6ul)) : \
-	__udelay(n))
-
-
-#define ndelay(n) (__builtin_constant_p(n) ? \
-	((n) > 20000 ? __bad_ndelay() : __const_udelay((n) * 5ul)) : \
-	__ndelay(n))
 
 #endif /* __ASM_SH_DELAY_H */
diff -U10 -urpN linux-2.6.12.org/include/asm-sh64/delay.h linux-2.6.12.delay/include/asm-sh64/delay.h
--- linux-2.6.12.org/include/asm-sh64/delay.h	Tue Oct 19 00:54:37 2004
+++ linux-2.6.12.delay/include/asm-sh64/delay.h	Thu Jun 30 20:25:04 2005
@@ -1,11 +1,10 @@
 #ifndef __ASM_SH64_DELAY_H
 #define __ASM_SH64_DELAY_H
 
 extern void __delay(int loops);
-extern void __udelay(unsigned long long usecs, unsigned long lpj);
-extern void __ndelay(unsigned long long nsecs, unsigned long lpj);
-extern void udelay(unsigned long usecs);
-extern void ndelay(unsigned long nsecs);
+extern void __udelay(unsigned long long usecs);
+extern void __ndelay(unsigned long long nsecs);
+#define __ndelay(n) __ndelay(n)
 
 #endif /* __ASM_SH64_DELAY_H */
 
diff -U10 -urpN linux-2.6.12.org/include/asm-sparc/delay.h linux-2.6.12.delay/include/asm-sparc/delay.h
--- linux-2.6.12.org/include/asm-sparc/delay.h	Tue Oct 19 00:53:45 2004
+++ linux-2.6.12.delay/include/asm-sparc/delay.h	Thu Jun 30 19:57:52 2005
@@ -14,22 +14,22 @@ extern __inline__ void __delay(unsigned 
 {
 	__asm__ __volatile__("cmp %0, 0\n\t"
 			     "1: bne 1b\n\t"
 			     "subcc %0, 1, %0\n" :
 			     "=&r" (loops) :
 			     "0" (loops) :
 			     "cc");
 }
 
 /* This is too messy with inline asm on the Sparc. */
-extern void __udelay(unsigned long usecs, unsigned long lpj);
-extern void __ndelay(unsigned long nsecs, unsigned long lpj);
+extern void ___udelay(unsigned long usecs, unsigned long lpj);
+extern void ___ndelay(unsigned long nsecs, unsigned long lpj);
 
 #ifdef CONFIG_SMP
 #define __udelay_val	cpu_data(smp_processor_id()).udelay_val
 #else /* SMP */
 #define __udelay_val	loops_per_jiffy
 #endif /* SMP */
-#define udelay(__usecs)	__udelay(__usecs, __udelay_val)
-#define ndelay(__nsecs)	__ndelay(__nsecs, __udelay_val)
+#define __udelay(__usecs)	___udelay(__usecs, __udelay_val)
+#define __ndelay(__nsecs)	___ndelay(__nsecs, __udelay_val)
 
 #endif /* defined(__SPARC_DELAY_H) */
diff -U10 -urpN linux-2.6.12.org/include/asm-sparc64/delay.h linux-2.6.12.delay/include/asm-sparc64/delay.h
--- linux-2.6.12.org/include/asm-sparc64/delay.h	Tue Oct 19 00:54:38 2004
+++ linux-2.6.12.delay/include/asm-sparc64/delay.h	Thu Jun 30 20:22:45 2005
@@ -10,29 +10,17 @@
 
 #ifndef __SPARC64_DELAY_H
 #define __SPARC64_DELAY_H
 
 #include <linux/config.h>
 #include <linux/param.h>
 #include <asm/cpudata.h>
 
 #ifndef __ASSEMBLY__
 
-extern void __bad_udelay(void);
-extern void __bad_ndelay(void);
-
 extern void __udelay(unsigned long usecs);
 extern void __ndelay(unsigned long nsecs);
-extern void __const_udelay(unsigned long usecs);
-extern void __delay(unsigned long loops);
-
-#define udelay(n) (__builtin_constant_p(n) ? \
-	((n) > 20000 ? __bad_udelay() : __const_udelay((n) * 0x10c7ul)) : \
-	__udelay(n))
-	
-#define ndelay(n) (__builtin_constant_p(n) ? \
-	((n) > 20000 ? __bad_ndelay() : __const_udelay((n) * 5ul)) : \
-	__ndelay(n))
+#define __ndelay(n) __ndelay(n)
 
 #endif /* !__ASSEMBLY__ */
 
 #endif /* defined(__SPARC64_DELAY_H) */
diff -U10 -urpN linux-2.6.12.org/include/asm-v850/delay.h linux-2.6.12.delay/include/asm-v850/delay.h
--- linux-2.6.12.org/include/asm-v850/delay.h	Tue Oct 19 00:55:24 2004
+++ linux-2.6.12.delay/include/asm-v850/delay.h	Thu Jun 30 19:24:39 2005
@@ -26,21 +26,21 @@ extern __inline__ void __delay(unsigned 
 /*
  * Use only for very small delays ( < 1 msec).  Should probably use a
  * lookup table, really, as the multiplications take much too long with
  * short delays.  This is a "reasonable" implementation, though (and the
  * first constant multiplications gets optimized away if the delay is
  * a constant)  
  */
 
 extern unsigned long loops_per_jiffy;
 
-extern __inline__ void udelay(unsigned long usecs)
+extern __inline__ void __udelay(unsigned long usecs)
 {
 	register unsigned long full_loops, part_loops;
 
 	full_loops = ((usecs * HZ) / 1000000) * loops_per_jiffy;
 	usecs %= (1000000 / HZ);
 	part_loops = (usecs * HZ * loops_per_jiffy) / 1000000;
 
 	__delay(full_loops + part_loops);
 }
 
diff -U10 -urpN linux-2.6.12.org/include/asm-x86_64/delay.h linux-2.6.12.delay/include/asm-x86_64/delay.h
--- linux-2.6.12.org/include/asm-x86_64/delay.h	Tue Oct 19 00:54:32 2004
+++ linux-2.6.12.delay/include/asm-x86_64/delay.h	Thu Jun 30 20:35:55 2005
@@ -1,27 +1,16 @@
 #ifndef _X8664_DELAY_H
 #define _X8664_DELAY_H
 
 /*
  * Copyright (C) 1993 Linus Torvalds
  *
  * Delay routines calling functions in arch/x86_64/lib/delay.c
  */
  
-extern void __bad_udelay(void);
-extern void __bad_ndelay(void);
 
 extern void __udelay(unsigned long usecs);
 extern void __ndelay(unsigned long usecs);
-extern void __const_udelay(unsigned long usecs);
+#define __ndelay(n) __ndelay(n)
 extern void __delay(unsigned long loops);
-
-#define udelay(n) (__builtin_constant_p(n) ? \
-	((n) > 20000 ? __bad_udelay() : __const_udelay((n) * 0x10c6ul)) : \
-	__udelay(n))
-
-#define ndelay(n) (__builtin_constant_p(n) ? \
-       ((n) > 20000 ? __bad_ndelay() : __const_udelay((n) * 5ul)) : \
-       __ndelay(n))
-
 
 #endif /* defined(_X8664_DELAY_H) */
diff -U10 -urpN linux-2.6.12.org/include/linux/delay.h linux-2.6.12.delay/include/linux/delay.h
--- linux-2.6.12.org/include/linux/delay.h	Thu Mar  3 09:31:14 2005
+++ linux-2.6.12.delay/include/linux/delay.h	Fri Jul  1 00:32:09 2005
@@ -5,46 +5,67 @@
  * Copyright (C) 1993 Linus Torvalds
  *
  * Delay routines, using a pre-computed "loops_per_jiffy" value.
  */
 
 extern unsigned long loops_per_jiffy;
 
 #include <asm/delay.h>
 
 /*
- * Using udelay() for intervals greater than a few milliseconds can
- * risk overflow for high loops_per_jiffy (high bogomips) machines. The
- * mdelay() provides a wrapper to prevent this.  For delays greater
- * than MAX_UDELAY_MS milliseconds, the wrapper is used.  Architecture
- * specific values can be defined in asm-???/delay.h as an override.
- * The 2nd mdelay() definition ensures GCC will optimize away the 
- * while loop for the common cases where n <= MAX_UDELAY_MS  --  Paul G.
+ * Milli, micro and nanosecond delay loops.
+ *
+ * Duration is artificially capped by MAX_MDELAY_MS,
+ * MAX_UDELAY_MS*1000 and MAX_UDELAY_MS*1000*1000 respectively
+ * in order to catch math underflows etc.
+ * At compile time you get link failure, if you slip through
+ * __builtin_constant_p check, ar run time you get a message and
+ * dump_stack in the log and delay is capped.
+ *
+ * Arch has to provide __udelay(n).
+ * It is guaranteed that __udelay(n) is never called with n > 1024.
+ *
+ * Arch may provide a macro __ndelay(n), else ndelay is 'emulated'
+ * by udelay(n/1000). It is guaranteed that __ndelay() is never
+ * called with n > 64*1024.
+ *
+ * Arch may also override default MAX_MDELAY_MS and MAX_UDELAY_MS.
  */
+#ifndef MAX_MDELAY_MS
+#define MAX_MDELAY_MS	5000
+#endif
 
 #ifndef MAX_UDELAY_MS
-#define MAX_UDELAY_MS	5
+#define MAX_UDELAY_MS	20
 #endif
 
-#ifdef notdef
-#define mdelay(n) (\
-	{unsigned long __ms=(n); while (__ms--) udelay(1000);})
-#else
-#define mdelay(n) (\
-	(__builtin_constant_p(n) && (n)<=MAX_UDELAY_MS) ? udelay((n)*1000) : \
-	({unsigned long __ms=(n); while (__ms--) udelay(1000);}))
-#endif
+/* defined nowhere */
+void BUG_overlong_mdelay(void);
+void BUG_overlong_udelay(void);
+void BUG_overlong_ndelay(void);
+
+void _mdelay(unsigned int msecs);
+void _udelay(unsigned int usecs);
+void _ndelay(unsigned int nsecs);
+
+#define mdelay(n) ( \
+	(__builtin_constant_p(n) && (unsigned int)(n)>MAX_MDELAY_MS) ? \
+	BUG_overlong_mdelay() : _mdelay(n))
 
-#ifndef ndelay
-#define ndelay(x)	udelay(((x)+999)/1000)
+#define udelay(n) ( \
+	(__builtin_constant_p(n) && (unsigned int)(n)>MAX_UDELAY_MS*1000) ? \
+	BUG_overlong_udelay() : _udelay(n))
+
+#ifndef __ndelay
+#define __ndelay(x)	__udelay(((x)+999)/1000)
 #endif
 
+#define ndelay(n) ( \
+	(__builtin_constant_p(n) && (unsigned int)(n)>MAX_UDELAY_MS*1000*1000) ? \
+	BUG_overlong_ndelay() : _ndelay(n))
+
 void calibrate_delay(void);
+void ssleep(unsigned int secs);
 void msleep(unsigned int msecs);
 unsigned long msleep_interruptible(unsigned int msecs);
-
-static inline void ssleep(unsigned int seconds)
-{
-	msleep(seconds * 1000);
-}
 
 #endif /* defined(_LINUX_DELAY_H) */
diff -U10 -urpN linux-2.6.12.org/kernel/timer.c linux-2.6.12.delay/kernel/timer.c
--- linux-2.6.12.org/kernel/timer.c	Sun Jun 19 16:11:00 2005
+++ linux-2.6.12.delay/kernel/timer.c	Fri Jul  1 00:05:52 2005
@@ -26,20 +26,21 @@
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/swap.h>
 #include <linux/notifier.h>
 #include <linux/thread_info.h>
 #include <linux/time.h>
 #include <linux/jiffies.h>
 #include <linux/posix-timers.h>
 #include <linux/cpu.h>
 #include <linux/syscalls.h>
+#include <linux/delay.h>
 
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
 #include <asm/div64.h>
 #include <asm/timex.h>
 #include <asm/io.h>
 
 #ifdef CONFIG_TIME_INTERPOLATION
 static void time_interpolator_update(long delta_nsec);
 #else
@@ -82,20 +83,70 @@ static inline void set_running_timer(tve
 					struct timer_list *timer)
 {
 #ifdef CONFIG_SMP
 	base->running_timer = timer;
 #endif
 }
 
 /* Fake initialization */
 static DEFINE_PER_CPU(tvec_base_t, tvec_bases) = { SPIN_LOCK_UNLOCKED };
 
+/***
+ * Arch __udelay() for intervals greater than a few milliseconds can
+ * risk overflow for high loops_per_jiffy (high bogomips) machines. The
+ * _mdelay() and _udelay() provide wrappers to prevent this.
+ *
+ * It's not inlined because we do not optimize delays for speed,
+ * but for code size at mdelay/udelay callsite
+ */
+void _mdelay(unsigned int msecs)
+{
+	if (msecs > MAX_MDELAY_MS) {
+		printk("BUG: delay too large: mdelay(%u)\n", msecs);
+		dump_stack();
+		msecs = MAX_MDELAY_MS;
+	}
+	while (msecs--)
+		__udelay(1000);
+}
+EXPORT_SYMBOL(_mdelay);
+
+void _udelay(unsigned int usecs)
+{
+	unsigned int k;
+	if (usecs > MAX_UDELAY_MS*1000) {
+		printk("BUG: delay too large: udelay(%u)\n", usecs);
+		dump_stack();
+		usecs = MAX_UDELAY_MS*1000;
+	}
+	k = usecs / 1024;
+	while (k--)
+		__udelay(1024);
+	__udelay(usecs % 1024);
+}
+EXPORT_SYMBOL(_udelay);
+
+void _ndelay(unsigned int nsecs)
+{
+	unsigned int k;
+	if (nsecs > MAX_UDELAY_MS*1000*1000) {
+		printk("BUG: delay too large: ndelay(%u)\n", nsecs);
+		dump_stack();
+		nsecs = MAX_UDELAY_MS*1000*1000;
+	}
+	k = nsecs / (64*1024);
+	while (k--)
+		__ndelay(64*1024);
+	__ndelay(nsecs % (64*1024));
+}
+EXPORT_SYMBOL(_ndelay);
+
 static void check_timer_failed(struct timer_list *timer)
 {
 	static int whine_count;
 	if (whine_count < 16) {
 		whine_count++;
 		printk("Uninitialised timer!\n");
 		printk("This is just a warning.  Your computer is OK\n");
 		printk("function=0x%p, data=0x%lx\n",
 			timer->function, timer->data);
 		dump_stack();
@@ -1583,22 +1634,27 @@ unregister_time_interpolator(struct time
  */
 void msleep(unsigned int msecs)
 {
 	unsigned long timeout = msecs_to_jiffies(msecs) + 1;
 
 	while (timeout) {
 		set_current_state(TASK_UNINTERRUPTIBLE);
 		timeout = schedule_timeout(timeout);
 	}
 }
-
 EXPORT_SYMBOL(msleep);
+
+void ssleep(unsigned int secs)
+{
+	msleep(secs * 1000);
+}
+EXPORT_SYMBOL(ssleep);
 
 /**
  * msleep_interruptible - sleep waiting for waitqueue interruptions
  * @msecs: Time in milliseconds to sleep for
  */
 unsigned long msleep_interruptible(unsigned int msecs)
 {
 	unsigned long timeout = msecs_to_jiffies(msecs) + 1;
 
 	while (timeout && !signal_pending(current)) {

Attachment: find.out.bz2
Description: BZip2 compressed data


[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]
  Powered by Linux