I have a strange problem with the musb driver in host mode on AM3358 (beaglebone) hardware. If I connect a multi-port serial adapter and open two or more of the ttys, then unplug the device, an interrupt storm ensues that makes the system completely unresponsive until the watchdog resets it. Enabling some debug messages, I get this repeated endlessly: musb-hdrc musb-hdrc.1: usbintr (0) epintr(1c0000) musb-hdrc musb-hdrc.1: end 2 RX proto error musb-hdrc musb-hdrc.1: ... next ep2 RX urb 72aabc13 musb-hdrc musb-hdrc.1: <-- hw2 urb 72aabc13 spd3 dev4 ep3in h_addr02 h_port00 bytes 4096 musb-hdrc musb-hdrc.1: RXCSR2 := 2020 musb-hdrc musb-hdrc.1: end 3 RX proto error musb-hdrc musb-hdrc.1: ... next ep3 RX urb 94c2cc43 musb-hdrc musb-hdrc.1: <-- hw3 urb 94c2cc43 spd3 dev4 ep2in h_addr02 h_port00 bytes 4096 musb-hdrc musb-hdrc.1: RXCSR3 := 2020 musb-hdrc musb-hdrc.1: end 4 RX proto error musb-hdrc musb-hdrc.1: ... next ep4 RX urb cbdc39c6 musb-hdrc musb-hdrc.1: <-- hw4 urb cbdc39c6 spd3 dev4 ep5in h_addr02 h_port00 bytes 4096 musb-hdrc musb-hdrc.1: RXCSR4 := 2020 This happens with both a two-port FTDI serial adapter and a Simcom GSM modem (Qualcomm based) using the "option" driver. In both cases, the problem occurs only if two or more of the ttys are opened when the device is unplugged. Applying the patch below makes this problem go away, though it most likely breaks something else. I'm only posting it here in case it helps identify the cause of the error. diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index b59ce9ad14ce..addf9197689c 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -337,6 +337,7 @@ static void musb_advance_schedule(struct musb *musb, struct urb *urb, qh->is_ready = 0; musb_giveback(musb, urb, status); + if (status != -EPROTO) qh->is_ready = ready; /* reclaim resources (and bandwidth) ASAP; deschedule it, and @@ -2465,12 +2466,14 @@ musb_h_disable(struct usb_hcd *hcd, struct usb_host_endpoint *hep) if (musb_ep_get_qh(qh->hw_ep, is_in) == qh) { urb = next_urb(qh); + if (urb) { /* make software (then hardware) stop ASAP */ if (!urb->unlinked) urb->status = -ESHUTDOWN; /* cleanup */ musb_cleanup_urb(urb, qh); + } /* Then nuke all the others ... and advance the * queue on hw_ep (e.g. bulk ring) when we're done. -- Måns Rullgård