The urb_dequeue() method "forgets" to unlink 'struct musb_qh' from the control/
bulk schedule list when an URB being cancelled is the only one queued to its
endpoint, which will cause musb_advance_schedule() to "block" once it reaches
'struct musb_qh' with now empty URB list, and so URBs queued for other control/
bulk endpoints after the one being dequeued will not be served. Hence add code
to unlink and free 'struct musb_qh' if its URB list emptied to this method and
remove now useless check from musb_advance_schedule().

The only exception case is when we're called from the driver's callback --
musb_giveback() doesn't expect us to pull out 'qh' from under it (it'll kill
this qh later anyway) and we want to keep around a qh with is_ready flag clear
because some drivers like usbaudio.c do submit a new URB after cancelling all
pending ones which leads to URB being started when it shouldn't be and started
all over again after the control returns to musb_giveback()...

Signed-off-by: Sergei Shtylyov <[email protected]>

---
The patch is against the recent Linus' kernel...

 drivers/usb/musb/musb_host.c |   16 ++++++++++++++--
 1 files changed, 14 insertions(+), 2 deletions(-)

Index: linux-2.6/drivers/usb/musb/musb_host.c
===================================================================
--- linux-2.6.orig/drivers/usb/musb/musb_host.c
+++ linux-2.6/drivers/usb/musb/musb_host.c
@@ -431,7 +431,7 @@ musb_advance_schedule(struct musb *musb,
        else
                qh = musb_giveback(qh, urb, urb->status);
 
-       if (qh && qh->is_ready && !list_empty(&qh->hep->urb_list)) {
+       if (qh != NULL && qh->is_ready) {
                DBG(4, "... next ep%d %cX urb %p\n",
                                hw_ep->epnum, is_in ? 'R' : 'T',
                                next_urb(qh));
@@ -2071,7 +2071,19 @@ static int musb_urb_dequeue(struct usb_h
                ret = 0;
                qh->is_ready = 0;
                __musb_giveback(musb, urb, 0);
-               qh->is_ready = ready;
+
+               /*
+                * If the URB list has emptied, it's time to kill this qh.
+                * However, if this was called from the driver callback,
+                * we don't really want to do it now, deferring it until
+                * we return to musb_giveback(), or bad things will happen...
+                */
+               if (ready && list_empty(&qh->hep->urb_list)) {
+                       qh->hep->hcpriv = NULL;
+                       list_del(&qh->ring);
+                       kfree(qh);
+               } else
+                       qh->is_ready = ready;
        } else
                ret = musb_cleanup_urb(urb, qh, urb->pipe & USB_DIR_IN);
 done:


_______________________________________________
Davinci-linux-open-source mailing list
[email protected]
http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source

Reply via email to