diff options
author | NeilBrown <neilb@suse.de> | 2012-08-13 12:32:58 +1000 |
---|---|---|
committer | Felipe Balbi <balbi@ti.com> | 2012-08-14 11:03:00 +0300 |
commit | 12a19b5f836c1a1b838e668f9aa804d017d8c58b (patch) | |
tree | d57cc77e5cb43656d9388b70d53b0628c8406c1a /drivers/usb/musb | |
parent | 07a67bbb95ea7977846bd851dab5f4f2be8e488c (diff) |
usb: musb: omap2430: don't loop indefinitely in interrupt.
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>
Diffstat (limited to 'drivers/usb/musb')
-rw-r--r-- | drivers/usb/musb/omap2430.c | 6 |
1 files changed, 5 insertions, 1 deletions
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index e32aff9920f..af5f4214673 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -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; |