Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[POWERPC] Fix mdelay badness on shared processor partitions

On partitioned PPC64 systems where a partition is given 1/10 of a
processor, we have seen mdelay() delaying for 10 times longer than it
should. The reason is that the generic mdelay(n) does n delays of 1
millisecond each. However, with 1/10 of a processor, we only get a
one-millisecond timeslice every 10ms. Thus each 1 millisecond delay
loop ends up taking 10ms elapsed time.

The solution is just to use the PPC64 udelay function, which uses the
timebase to ensure that the delay is based on elapsed time rather than
how much processing time the partition has been given. (Yes, the
generic mdelay uses the PPC64 udelay, but the problem is that the
start time gets reset every millisecond, and each time it gets reset
we lose another 9ms.)

Signed-off-by: Anton Blanchard <anton@samba.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Acked-by: Andrew Morton <akpm@osdl.org>

authored by

Anton Blanchard and committed by
Paul Mackerras
1e92a550 ddf5f75a

+14 -4
+13
include/asm-powerpc/delay.h
··· 17 17 extern void __delay(unsigned long loops); 18 18 extern void udelay(unsigned long usecs); 19 19 20 + /* 21 + * On shared processor machines the generic implementation of mdelay can 22 + * result in large errors. While each iteration of the loop inside mdelay 23 + * is supposed to take 1ms, the hypervisor could sleep our partition for 24 + * longer (eg 10ms). With the right timing these errors can add up. 25 + * 26 + * Since there is no 32bit overflow issue on 64bit kernels, just call 27 + * udelay directly. 28 + */ 29 + #ifdef CONFIG_PPC64 30 + #define mdelay(n) udelay((n) * 1000) 31 + #endif 32 + 20 33 #endif /* __KERNEL__ */ 21 34 #endif /* _ASM_POWERPC_DELAY_H */
+1 -4
include/linux/delay.h
··· 25 25 #define MAX_UDELAY_MS 5 26 26 #endif 27 27 28 - #ifdef notdef 29 - #define mdelay(n) (\ 30 - {unsigned long __ms=(n); while (__ms--) udelay(1000);}) 31 - #else 28 + #ifndef mdelay 32 29 #define mdelay(n) (\ 33 30 (__builtin_constant_p(n) && (n)<=MAX_UDELAY_MS) ? udelay((n)*1000) : \ 34 31 ({unsigned long __ms=(n); while (__ms--) udelay(1000);}))