aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Walmsley <paul@pwsan.com>2009-12-08 18:33:16 -0500
committerpaul <paul@twilight.(none)>2009-12-11 19:00:43 -0500
commit6f8b7ff5b01e16a65c3b17865ce047faeca40907 (patch)
treeae5ecb4b377588b157c23176cf95a5c9631206ba
parent3863c74b512c1afd3ce6b2f81d8dea9f1d860968 (diff)
OMAP clock/hwmod: fix off-by-one errors
Fix loop bailout off-by-one bugs reported by Juha Leppänen <juha_motorsportcom@luukku.com>. This second version incorporates comments from Russell King <linux@arm.linux.org.uk>. A new macro, 'omap_test_timeout', has been created, with cleaner code, and existing code has been converted to use it. Signed-off-by: Paul Walmsley <paul@pwsan.com> Cc: Juha Leppänen <juha_motorsportcom@luukku.com> Cc: Russell King <linux@arm.linux.org.uk>
-rw-r--r--arch/arm/mach-omap2/cm.c7
-rw-r--r--arch/arm/mach-omap2/omap_hwmod.c13
-rw-r--r--arch/arm/mach-omap2/prcm.c5
-rw-r--r--arch/arm/plat-omap/include/plat/common.h20
4 files changed, 31 insertions, 14 deletions
diff --git a/arch/arm/mach-omap2/cm.c b/arch/arm/mach-omap2/cm.c
index 8eb2dab8c7db..58e4a1c557d8 100644
--- a/arch/arm/mach-omap2/cm.c
+++ b/arch/arm/mach-omap2/cm.c
@@ -21,6 +21,8 @@
21 21
22#include <asm/atomic.h> 22#include <asm/atomic.h>
23 23
24#include <plat/common.h>
25
24#include "cm.h" 26#include "cm.h"
25#include "cm-regbits-24xx.h" 27#include "cm-regbits-24xx.h"
26#include "cm-regbits-34xx.h" 28#include "cm-regbits-34xx.h"
@@ -61,9 +63,8 @@ int omap2_cm_wait_module_ready(s16 prcm_mod, u8 idlest_id, u8 idlest_shift)
61 mask = 1 << idlest_shift; 63 mask = 1 << idlest_shift;
62 64
63 /* XXX should be OMAP2 CM */ 65 /* XXX should be OMAP2 CM */
64 while (((cm_read_mod_reg(prcm_mod, cm_idlest_reg) & mask) != ena) && 66 omap_test_timeout(((cm_read_mod_reg(prcm_mod, cm_idlest_reg) & mask) == ena),
65 (i++ < MAX_MODULE_READY_TIME)) 67 MAX_MODULE_READY_TIME, i);
66 udelay(1);
67 68
68 return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY; 69 return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY;
69} 70}
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 633b216a8b26..7aaf5f1eea7a 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -45,6 +45,7 @@
45#include <linux/mutex.h> 45#include <linux/mutex.h>
46#include <linux/bootmem.h> 46#include <linux/bootmem.h>
47 47
48#include <plat/common.h>
48#include <plat/cpu.h> 49#include <plat/cpu.h>
49#include <plat/clockdomain.h> 50#include <plat/clockdomain.h>
50#include <plat/powerdomain.h> 51#include <plat/powerdomain.h>
@@ -736,7 +737,7 @@ static int _wait_target_ready(struct omap_hwmod *oh)
736static int _reset(struct omap_hwmod *oh) 737static int _reset(struct omap_hwmod *oh)
737{ 738{
738 u32 r, v; 739 u32 r, v;
739 int c; 740 int c = 0;
740 741
741 if (!oh->sysconfig || 742 if (!oh->sysconfig ||
742 !(oh->sysconfig->sysc_flags & SYSC_HAS_SOFTRESET) || 743 !(oh->sysconfig->sysc_flags & SYSC_HAS_SOFTRESET) ||
@@ -758,13 +759,9 @@ static int _reset(struct omap_hwmod *oh)
758 return r; 759 return r;
759 _write_sysconfig(v, oh); 760 _write_sysconfig(v, oh);
760 761
761 c = 0; 762 omap_test_timeout((omap_hwmod_readl(oh, oh->sysconfig->syss_offs) &
762 while (c < MAX_MODULE_RESET_WAIT && 763 SYSS_RESETDONE_MASK),
763 !(omap_hwmod_readl(oh, oh->sysconfig->syss_offs) & 764 MAX_MODULE_RESET_WAIT, c);
764 SYSS_RESETDONE_MASK)) {
765 udelay(1);
766 c++;
767 }
768 765
769 if (c == MAX_MODULE_RESET_WAIT) 766 if (c == MAX_MODULE_RESET_WAIT)
770 WARN(1, "omap_hwmod: %s: failed to reset in %d usec\n", 767 WARN(1, "omap_hwmod: %s: failed to reset in %d usec\n",
diff --git a/arch/arm/mach-omap2/prcm.c b/arch/arm/mach-omap2/prcm.c
index 9208b6e873ae..79637c2eaf64 100644
--- a/arch/arm/mach-omap2/prcm.c
+++ b/arch/arm/mach-omap2/prcm.c
@@ -241,9 +241,8 @@ int omap2_cm_wait_idlest(void __iomem *reg, u32 mask, const char *name)
241 BUG(); 241 BUG();
242 242
243 /* Wait for lock */ 243 /* Wait for lock */
244 while (((__raw_readl(reg) & mask) != ena) && 244 omap_test_timeout(((__raw_readl(reg) & mask) == ena),
245 (i++ < MAX_MODULE_ENABLE_WAIT)) 245 MAX_MODULE_ENABLE_WAIT, i);
246 udelay(1);
247 246
248 if (i < MAX_MODULE_ENABLE_WAIT) 247 if (i < MAX_MODULE_ENABLE_WAIT)
249 pr_debug("cm: Module associated with clock %s ready after %d " 248 pr_debug("cm: Module associated with clock %s ready after %d "
diff --git a/arch/arm/plat-omap/include/plat/common.h b/arch/arm/plat-omap/include/plat/common.h
index 064f1730f43b..e9779676448b 100644
--- a/arch/arm/plat-omap/include/plat/common.h
+++ b/arch/arm/plat-omap/include/plat/common.h
@@ -71,4 +71,24 @@ void omap2_set_globals_sdrc(struct omap_globals *);
71void omap2_set_globals_control(struct omap_globals *); 71void omap2_set_globals_control(struct omap_globals *);
72void omap2_set_globals_prcm(struct omap_globals *); 72void omap2_set_globals_prcm(struct omap_globals *);
73 73
74/**
75 * omap_test_timeout - busy-loop, testing a condition
76 * @cond: condition to test until it evaluates to true
77 * @timeout: maximum number of microseconds in the timeout
78 * @index: loop index (integer)
79 *
80 * Loop waiting for @cond to become true or until at least @timeout
81 * microseconds have passed. To use, define some integer @index in the
82 * calling code. After running, if @index == @timeout, then the loop has
83 * timed out.
84 */
85#define omap_test_timeout(cond, timeout, index) \
86({ \
87 for (index = 0; index < timeout; index++) { \
88 if (cond) \
89 break; \
90 udelay(1); \
91 } \
92})
93
74#endif /* __ARCH_ARM_MACH_OMAP_COMMON_H */ 94#endif /* __ARCH_ARM_MACH_OMAP_COMMON_H */