[PATCH 2/3] musb_host: fix urb_dequeue() method (take 3)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The urb_dequeue() method "forgets" to unlink 'struct musb_qh' from the control
or bulk schedule list when an 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, and so URBs queued to other endpoints
after this one will not be served.

Unlink 'struct musb_qh' from the list except when it's being already "dealt
with", typically by musb_giveback(), as indicated by 'is_ready' flag being 0.
Since 'struct musb_qh' with an empty USB list is now supposed to be freed,
do that after unlinking it. And as there should be no such endpoints in the
schedule lists anymore, remove now useless check from musb_advance_schedule()
(this check prevented kernel oops in musb_giveback() before)...

Signed-off-by: Sergei Shtylyov <sshtylyov@xxxxxxxxxxxxx>

---
This patch, with the description and comments somwewhat changed, is intended to
replace usb/usb-musb_host-fix-urb_dequeue-method.patch in Greg's series...

 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
@@ -432,7 +432,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));
@@ -2078,7 +2078,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, we need to recycle this qh.
+		 * Though if something else, like musb_giveback(), is already
+		 * using it, we'd better leave it alone for now -- it will be
+		 * recycled a bit later...
+		 */
+		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:

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

[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux