Commit a2fd814e authored by Sergei Shtylyov's avatar Sergei Shtylyov Committed by Greg Kroah-Hartman

USB: musb: fix urb_dequeue() method

The urb_dequeue() method forgets to unlink 'struct musb_qh' from the
control or bulk schedules when the URB being cancelled is the only
one queued to its endpoint.  That will cause musb_advance_schedule()
to block once it reaches 'struct musb_qh' with now empty URB list, so
URBs queued for other endpoints after the one being dequeued will not
be served.

Fix by unlinking the QH from the list except when it's already being
handled (typically by musb_giveback).  Since a QH with an empty URB
list is now supposed to be freed, do that.  And remove a now-useless
check from musb_advance_schedule().

[ dbrownell@users.sourceforge.net: update patch description,
  and fold in a dequeue() comment patch ]
Signed-off-by: default avatarSergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: default avatarDavid Brownell <dbrownell@users.sourceforge.net>
Cc: Felipe Balbi <felipe.balbi@nokia.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent b7bdcb79
...@@ -432,7 +432,7 @@ musb_advance_schedule(struct musb *musb, struct urb *urb, ...@@ -432,7 +432,7 @@ musb_advance_schedule(struct musb *musb, struct urb *urb,
else else
qh = musb_giveback(qh, urb, urb->status); 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", DBG(4, "... next ep%d %cX urb %p\n",
hw_ep->epnum, is_in ? 'R' : 'T', hw_ep->epnum, is_in ? 'R' : 'T',
next_urb(qh)); next_urb(qh));
...@@ -2038,9 +2038,9 @@ static int musb_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) ...@@ -2038,9 +2038,9 @@ static int musb_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
goto done; goto done;
/* Any URB not actively programmed into endpoint hardware can be /* Any URB not actively programmed into endpoint hardware can be
* immediately given back. Such an URB must be at the head of its * immediately given back; that's any URB not at the head of an
* endpoint queue, unless someday we get real DMA queues. And even * endpoint queue, unless someday we get real DMA queues. And even
* then, it might not be known to the hardware... * if it's at the head, it might not be known to the hardware...
* *
* Otherwise abort current transfer, pending dma, etc.; urb->status * Otherwise abort current transfer, pending dma, etc.; urb->status
* has already been updated. This is a synchronous abort; it'd be * has already been updated. This is a synchronous abort; it'd be
...@@ -2079,6 +2079,15 @@ static int musb_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) ...@@ -2079,6 +2079,15 @@ static int musb_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
qh->is_ready = 0; qh->is_ready = 0;
__musb_giveback(musb, urb, 0); __musb_giveback(musb, urb, 0);
qh->is_ready = ready; qh->is_ready = ready;
/* If nothing else (usually musb_giveback) is using it
* and its URB list has emptied, recycle this qh.
*/
if (ready && list_empty(&qh->hep->urb_list)) {
qh->hep->hcpriv = NULL;
list_del(&qh->ring);
kfree(qh);
}
} else } else
ret = musb_cleanup_urb(urb, qh, urb->pipe & USB_DIR_IN); ret = musb_cleanup_urb(urb, qh, urb->pipe & USB_DIR_IN);
done: done:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment