summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Fortescue <mark@mtfhpc.demon.co.uk>2007-08-30 06:07:11 +0200
committerAdrian Bunk <bunk@stusta.de>2007-08-30 06:07:11 +0200
commiteb845a0bad412b7caa04383715d59399de8b5c11 (patch)
treec76ed873c1a9f188d7a61b17c33328b16a7f3577
parent7380487e55320420da6277820f2825ec456406eb (diff)
downloadlinux-stable-eb845a0bad412b7caa04383715d59399de8b5c11.tar.gz
linux-stable-eb845a0bad412b7caa04383715d59399de8b5c11.tar.bz2
linux-stable-eb845a0bad412b7caa04383715d59399de8b5c11.zip
[SPARC32]: Fix rounding errors in ndelay/udelay implementation.
__ndelay and __udelay have not been delayung >= specified time. The problem with __ndelay has been tacked down to the rounding of the multiplier constant. By changing this, delays > app 18us are correctly calculated. The problem with __udelay has also been tracked down to rounding issues. Changing the multiplier constant (to match that used in sparc64) corrects for large delays and adding in a rounding constant corrects for trunctaion errors in the claculations. Many short delays will return without looping. This is not an error as there is the fixed delay of doing all the maths to calculate the loop count. Signed-off-by: Mark Fortescue <mark@mtfhpc.demon.co.uk> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Adrian Bunk <bunk@kernel.org>
-rw-r--r--arch/sparc/kernel/entry.S14
1 files changed, 10 insertions, 4 deletions
diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S
index 887f6a160c58..fbbae5d381d1 100644
--- a/arch/sparc/kernel/entry.S
+++ b/arch/sparc/kernel/entry.S
@@ -1751,8 +1751,8 @@ fpload:
__ndelay:
save %sp, -STACKFRAME_SZ, %sp
mov %i0, %o0
- call .umul
- mov 0x1ad, %o1 ! 2**32 / (1 000 000 000 / HZ)
+ call .umul ! round multiplier up so large ns ok
+ mov 0x1ae, %o1 ! 2**32 / (1 000 000 000 / HZ)
call .umul
mov %i1, %o1 ! udelay_val
ba delay_continue
@@ -1762,11 +1762,17 @@ __ndelay:
__udelay:
save %sp, -STACKFRAME_SZ, %sp
mov %i0, %o0
- sethi %hi(0x10c6), %o1
+ sethi %hi(0x10c7), %o1 ! round multiplier up so large us ok
call .umul
- or %o1, %lo(0x10c6), %o1 ! 2**32 / 1 000 000
+ or %o1, %lo(0x10c7), %o1 ! 2**32 / 1 000 000
call .umul
mov %i1, %o1 ! udelay_val
+ sethi %hi(0x028f4b62), %l0 ! Add in rounding constant * 2**32,
+ or %g0, %lo(0x028f4b62), %l0
+ addcc %o0, %l0, %o0 ! 2**32 * 0.009 999
+ bcs,a 3f
+ add %o1, 0x01, %o1
+3:
call .umul
mov HZ, %o0 ! >>32 earlier for wider range