aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorSergei Shtylyov <sshtylyov@ru.mvista.com>2009-02-21 18:30:45 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2009-02-27 17:40:51 -0500
commita2fd814e6a9e172f7077b68a2a9391bbde777a92 (patch)
tree1ac5659086a835b9935927621c72799f9d17f989 /drivers/usb
parentb7bdcb79de6de32e40dcc85a5e8c669bec2483d5 (diff)
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: Sergei Shtylyov <sshtylyov@ru.mvista.com> Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Cc: Felipe Balbi <felipe.balbi@nokia.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/musb/musb_host.c15
1 files changed, 12 insertions, 3 deletions
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index b47ca948bcf4..e32323938e98 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -432,7 +432,7 @@ musb_advance_schedule(struct musb *musb, struct urb *urb,
432 else 432 else
433 qh = musb_giveback(qh, urb, urb->status); 433 qh = musb_giveback(qh, urb, urb->status);
434 434
435 if (qh && qh->is_ready && !list_empty(&qh->hep->urb_list)) { 435 if (qh != NULL && qh->is_ready) {
436 DBG(4, "... next ep%d %cX urb %p\n", 436 DBG(4, "... next ep%d %cX urb %p\n",
437 hw_ep->epnum, is_in ? 'R' : 'T', 437 hw_ep->epnum, is_in ? 'R' : 'T',
438 next_urb(qh)); 438 next_urb(qh));
@@ -2038,9 +2038,9 @@ static int musb_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
2038 goto done; 2038 goto done;
2039 2039
2040 /* Any URB not actively programmed into endpoint hardware can be 2040 /* Any URB not actively programmed into endpoint hardware can be
2041 * immediately given back. Such an URB must be at the head of its 2041 * immediately given back; that's any URB not at the head of an
2042 * endpoint queue, unless someday we get real DMA queues. And even 2042 * endpoint queue, unless someday we get real DMA queues. And even
2043 * then, it might not be known to the hardware... 2043 * if it's at the head, it might not be known to the hardware...
2044 * 2044 *
2045 * Otherwise abort current transfer, pending dma, etc.; urb->status 2045 * Otherwise abort current transfer, pending dma, etc.; urb->status
2046 * has already been updated. This is a synchronous abort; it'd be 2046 * 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 qh->is_ready = 0; 2079 qh->is_ready = 0;
2080 __musb_giveback(musb, urb, 0); 2080 __musb_giveback(musb, urb, 0);
2081 qh->is_ready = ready; 2081 qh->is_ready = ready;
2082
2083 /* If nothing else (usually musb_giveback) is using it
2084 * and its URB list has emptied, recycle this qh.
2085 */
2086 if (ready && list_empty(&qh->hep->urb_list)) {
2087 qh->hep->hcpriv = NULL;
2088 list_del(&qh->ring);
2089 kfree(qh);
2090 }
2082 } else 2091 } else
2083 ret = musb_cleanup_urb(urb, qh, urb->pipe & USB_DIR_IN); 2092 ret = musb_cleanup_urb(urb, qh, urb->pipe & USB_DIR_IN);
2084done: 2093done: