On Tue, 2014-02-04 at 08:03 +0100, Holger Schurig wrote:
> Joe, look in linux/arch/arm/include/asm/delay.h. The macro udelay
> cannot handle large values because of lost-of-precision.
> 
> IMHO udelay on ARM is broken, because it also cannot work with fast
> ARM processors (where bogomips >= 3355, which is in sight now). It's
> just not broken enought that someone did something against it ...   so
> the current kludge is good enought.

Maybe something like this would be better?

---
 arch/arm/include/asm/delay.h | 33 +++++++++++++++++++++++++++++----
 1 file changed, 29 insertions(+), 4 deletions(-)

diff --git a/arch/arm/include/asm/delay.h b/arch/arm/include/asm/delay.h
index dff714d..ac33c56 100644
--- a/arch/arm/include/asm/delay.h
+++ b/arch/arm/include/asm/delay.h
@@ -15,6 +15,8 @@
 
 #ifndef __ASSEMBLY__
 
+#include <linux/printk.h>
+
 struct delay_timer {
        unsigned long (*read_current_timer)(void);
        unsigned long freq;
@@ -51,11 +53,34 @@ extern void __bad_udelay(void);
 #define __udelay(n)            arm_delay_ops.udelay(n)
 #define __const_udelay(n)      arm_delay_ops.const_udelay(n)
 
+#ifdef DEBUG
+#define __udelay_debug_max_delay(n)                                    \
+do {                                                                   \
+       if (n > MAX_UDELAY_MS * 1000) {                                 \
+               pr_debug("udelay(%d) too large - Convert to mdelay\n", n); \
+               dump_stack();                                           \
+       }                                                               \
+} while (0)
+#else
+#define __udelay_debug_max_delay(n)                                    \
+       do {} while (0)
+#endif
+
 #define udelay(n)                                                      \
-       (__builtin_constant_p(n) ?                                      \
-         ((n) > (MAX_UDELAY_MS * 1000) ? __bad_udelay() :              \
-                       __const_udelay((n) * UDELAY_MULT)) :            \
-         __udelay(n))
+({                                                                     \
+       if (__builtin_constant_p(n)) {                                  \
+               typeof n _n = n;                                        \
+               while (_n > MAX_UDELAY_MS * 1000) {                     \
+                       __const_udelay(MAX_UDELAY_MS * 1000 * UDELAY_MULT); \
+                       _n -= MAX_UDELAY_MS * 1000;                     \
+               }                                                       \
+               if (_n)                                                 \
+                       __const_udelay(_n * 1000 * UDELAY_MULT);        \
+       } else {                                                        \
+               __udelay_debug_max_delay(n);                            \
+               __udelay(n);                                            \
+       }                                                               \
+})
 
 /* Loop-based definitions for assembly code. */
 extern void __loop_delay(unsigned long loops);


_______________________________________________
ath9k-devel mailing list
ath9k-devel@lists.ath9k.org
https://lists.ath9k.org/mailman/listinfo/ath9k-devel

Reply via email to