avr32: Fix theoretical race in udelay()
[platform/kernel/u-boot.git] / cpu / at32ap / interrupts.c
index c9e0499..160838e 100644 (file)
@@ -20,8 +20,8 @@
  * MA 02111-1307 USA
  */
 #include <common.h>
+#include <div64.h>
 
-#include <asm/div64.h>
 #include <asm/errno.h>
 #include <asm/io.h>
 #include <asm/processor.h>
@@ -98,18 +98,16 @@ void set_timer(unsigned long t)
  */
 void udelay(unsigned long usec)
 {
-       unsigned long now, end;
+       unsigned long cycles;
+       unsigned long base;
+       unsigned long now;
 
-       now = sysreg_read(COUNT);
+       base = sysreg_read(COUNT);
+       cycles = ((usec * (get_tbclk() / 10000)) + 50) / 100;
 
-       end = ((usec * (get_tbclk() / 10000)) + 50) / 100;
-       end += now;
-
-       while (now > end)
-               now = sysreg_read(COUNT);
-
-       while (now < end)
+       do {
                now = sysreg_read(COUNT);
+       } while ((now - base) < cycles);
 }
 
 static int set_interrupt_handler(unsigned int nr, void (*handler)(void),