usb: musb: omap2430: don't loop indefinitely in interrupt.
authorNeilBrown <neilb@suse.de>
Mon, 13 Aug 2012 02:32:58 +0000 (12:32 +1000)
committerFelipe Balbi <balbi@ti.com>
Tue, 14 Aug 2012 08:03:00 +0000 (11:03 +0300)
When called during resume_irqs, omap2430_musb_set_vbus() is run with
interrupts disabled,  In that case 'jiffies' never changes so the loop
can loop forever.

So impose a maximum loop count and add an 'mdelay' to ensure we wait
a reasonable amount of time for bit to be cleared.

This fixes a hang on resume.

Signed-of-by: NeilBrown <neilb@suse.de>
Signed-off-by: Felipe Balbi <balbi@ti.com>
drivers/usb/musb/omap2430.c

index e32aff9920f2e780c040f925d61100f56511c04f..af5f4214673d761cd2c18d618cfc6357d3ced295 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/pm_runtime.h>
 #include <linux/err.h>
+#include <linux/delay.h>
 #include <linux/usb/musb-omap.h>
 
 #include "musb_core.h"
@@ -150,6 +151,7 @@ static void omap2430_musb_set_vbus(struct musb *musb, int is_on)
 
        if (is_on) {
                if (musb->xceiv->state == OTG_STATE_A_IDLE) {
+                       int loops = 100;
                        /* start the session */
                        devctl |= MUSB_DEVCTL_SESSION;
                        musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
@@ -159,9 +161,11 @@ static void omap2430_musb_set_vbus(struct musb *musb, int is_on)
                         */
                        while (musb_readb(musb->mregs, MUSB_DEVCTL) & 0x80) {
 
+                               mdelay(5);
                                cpu_relax();
 
-                               if (time_after(jiffies, timeout)) {
+                               if (time_after(jiffies, timeout)
+                                   || loops-- <= 0) {
                                        dev_err(musb->controller,
                                        "configured as A device timeout");
                                        ret = -EINVAL;