[ath9k-devel] [PATCH 1/3] ath9k: Fix build error on ARM
From: joe@perches.com (Joe Perches)
Date: 2014-02-04 16:36:36
Also in:
linux-wireless
Subsystem:
arm port, the rest · Maintainers:
Russell King, Linus Torvalds
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);