Patchwork [21/32] USB: EHCI: Fix isochronous URB leak

login
register
mail settings
Submitter Greg Kroah-Hartman
Date March 20, 2009, 10:26 p.m.
Message ID <20090320222712.293646809@mini.kroah.org>
Download mbox | patch
Permalink /patch/13428/
State New, archived
Headers show

Comments

Greg Kroah-Hartman - March 20, 2009, 10:26 p.m.
2.6.27-stable review patch.  If anyone has any objections, please let us know.

------------------

From: Karsten Wiese <fzuuzf@googlemail.com>

commit 508db8c954d55ed30f870d2c24d741ba6269d13c upstream.

ehci-hcd uses usb_get_urb() and usb_put_urb() in an unbalanced way causing
isochronous URB's kref.counts incrementing once per usb_submit_urb() call.
The culprit is *usb being set to NULL when usb_put_urb() is called after URB
is given back.
Due to other fixes there is no need for ehci-hcd to deal with usb_get_urb()
nor usb_put_urb() anymore, so patch removes their usages in ehci-hcd.
Patch also makes ehci_to_hcd(ehci)->self.bandwidth_allocated adjust, if a
stream finishes.

Signed-off-by: Karsten Wiese <fzu@wemgehoertderstaat.de>
Cc: David Brownell <david-b@pacbell.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

---
 drivers/usb/host/ehci-sched.c |   10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)



--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Patch

--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -1536,7 +1536,7 @@  itd_link_urb (
 					struct ehci_itd, itd_list);
 			list_move_tail (&itd->itd_list, &stream->td_list);
 			itd->stream = iso_stream_get (stream);
-			itd->urb = usb_get_urb (urb);
+			itd->urb = urb;
 			itd_init (ehci, stream, itd);
 		}
 
@@ -1645,7 +1645,7 @@  itd_complete (
 	(void) disable_periodic(ehci);
 	ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--;
 
-	if (unlikely (list_empty (&stream->td_list))) {
+	if (unlikely(list_is_singular(&stream->td_list))) {
 		ehci_to_hcd(ehci)->self.bandwidth_allocated
 				-= stream->bandwidth;
 		ehci_vdbg (ehci,
@@ -1656,7 +1656,6 @@  itd_complete (
 	iso_stream_put (ehci, stream);
 
 done:
-	usb_put_urb(urb);
 	itd->urb = NULL;
 	if (ehci->clock_frame != itd->frame || itd->index[7] != -1) {
 		/* OK to recycle this ITD now. */
@@ -1949,7 +1948,7 @@  sitd_link_urb (
 				struct ehci_sitd, sitd_list);
 		list_move_tail (&sitd->sitd_list, &stream->td_list);
 		sitd->stream = iso_stream_get (stream);
-		sitd->urb = usb_get_urb (urb);
+		sitd->urb = urb;
 
 		sitd_patch(ehci, stream, sitd, sched, packet);
 		sitd_link (ehci, (next_uframe >> 3) % ehci->periodic_size,
@@ -2034,7 +2033,7 @@  sitd_complete (
 	(void) disable_periodic(ehci);
 	ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--;
 
-	if (list_empty (&stream->td_list)) {
+	if (list_is_singular(&stream->td_list)) {
 		ehci_to_hcd(ehci)->self.bandwidth_allocated
 				-= stream->bandwidth;
 		ehci_vdbg (ehci,
@@ -2045,7 +2044,6 @@  sitd_complete (
 	iso_stream_put (ehci, stream);
 	/* OK to recycle this SITD now that its completion callback ran. */
 done:
-	usb_put_urb(urb);
 	sitd->urb = NULL;
 	sitd->stream = NULL;
 	list_move(&sitd->sitd_list, &stream->free_list);