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
- Prev by Date: Re: FUSE merging?
- Next by Date: Re: setitimer expire too early (Kernel 2.4)
- Previous by thread: include/asm-frv/delay.h: bogus ndelay() definition?
- Next by thread: Re: [patch 1/1] sizeof(*dev) : arch/arm/common/sa1111.c
- Index(es):