urb->status is set when endpoint csr RXSTALL, H_ERROR, DATAERROR or
INCOMPRX bit is set. Those bits mean a broken pipe, so don't start next
urb when any of these bits is set by checking urb->status.

To minimize the risk of regression, only do so for RX, until we have a
test case to understand the behavior of TX.

The patch fixes system freeze issue caused by repeatedly invoking RX ISR
while removing a usb uart device connected to a hub, in which case the
hub has no chance to report the disconnect event due to the kernel is
busy in processing the RX interrupt flooding.

Fix checkpatch complaint (qh != NULL) as while.

Reported-by: Max Uvarov <muva...@gmail.com>
Tested-by: Yegor Yefremov <yegorsli...@googlemail.com>
Signed-off-by: Bin Liu <b-...@ti.com>
---
 drivers/usb/musb/musb_host.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index 931381c..dd1ebde 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -434,7 +434,13 @@ static void musb_advance_schedule(struct musb *musb, 
struct urb *urb,
                }
        }
 
-       if (qh != NULL && qh->is_ready) {
+       /*
+        * The pipe must be broken if current urb->status is set, so don't
+        * start next urb.
+        * TODO: to minimize the risk of regression, only check urb->status
+        * for RX, until we have a test case to understand the behavior of TX.
+        */
+       if ((!status || !is_in) && qh && qh->is_ready) {
                dev_dbg(musb->controller, "... next ep%d %cX urb %p\n",
                    hw_ep->epnum, is_in ? 'R' : 'T', next_urb(qh));
                musb_start_urb(musb, is_in, qh);
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to