|
@@ -112,22 +112,32 @@ static void musb_h_tx_flush_fifo(struct musb_hw_ep *ep)
|
|
struct musb *musb = ep->musb;
|
|
struct musb *musb = ep->musb;
|
|
void __iomem *epio = ep->regs;
|
|
void __iomem *epio = ep->regs;
|
|
u16 csr;
|
|
u16 csr;
|
|
- u16 lastcsr = 0;
|
|
|
|
int retries = 1000;
|
|
int retries = 1000;
|
|
|
|
|
|
csr = musb_readw(epio, MUSB_TXCSR);
|
|
csr = musb_readw(epio, MUSB_TXCSR);
|
|
while (csr & MUSB_TXCSR_FIFONOTEMPTY) {
|
|
while (csr & MUSB_TXCSR_FIFONOTEMPTY) {
|
|
- if (csr != lastcsr)
|
|
|
|
- dev_dbg(musb->controller, "Host TX FIFONOTEMPTY csr: %02x\n", csr);
|
|
|
|
- lastcsr = csr;
|
|
|
|
csr |= MUSB_TXCSR_FLUSHFIFO | MUSB_TXCSR_TXPKTRDY;
|
|
csr |= MUSB_TXCSR_FLUSHFIFO | MUSB_TXCSR_TXPKTRDY;
|
|
musb_writew(epio, MUSB_TXCSR, csr);
|
|
musb_writew(epio, MUSB_TXCSR, csr);
|
|
csr = musb_readw(epio, MUSB_TXCSR);
|
|
csr = musb_readw(epio, MUSB_TXCSR);
|
|
- if (WARN(retries-- < 1,
|
|
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * FIXME: sometimes the tx fifo flush failed, it has been
|
|
|
|
+ * observed during device disconnect on AM335x.
|
|
|
|
+ *
|
|
|
|
+ * To reproduce the issue, ensure tx urb(s) are queued when
|
|
|
|
+ * unplug the usb device which is connected to AM335x usb
|
|
|
|
+ * host port.
|
|
|
|
+ *
|
|
|
|
+ * I found using a usb-ethernet device and running iperf
|
|
|
|
+ * (client on AM335x) has very high chance to trigger it.
|
|
|
|
+ *
|
|
|
|
+ * Better to turn on dev_dbg() in musb_cleanup_urb() with
|
|
|
|
+ * CPPI enabled to see the issue when aborting the tx channel.
|
|
|
|
+ */
|
|
|
|
+ if (dev_WARN_ONCE(musb->controller, retries-- < 1,
|
|
"Could not flush host TX%d fifo: csr: %04x\n",
|
|
"Could not flush host TX%d fifo: csr: %04x\n",
|
|
ep->epnum, csr))
|
|
ep->epnum, csr))
|
|
return;
|
|
return;
|
|
- mdelay(1);
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|