MUSB interrupt storm on device removal

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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



[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux