Commit 508db8c9 authored by Karsten Wiese's avatar Karsten Wiese Committed by Greg Kroah-Hartman

USB: EHCI: Fix isochronous URB leak

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: default avatarKarsten Wiese <fzu@wemgehoertderstaat.de>
Cc: David Brownell <david-b@pacbell.net>
Cc: stable <stable@kernel.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 9ea19b82
...@@ -1536,7 +1536,7 @@ itd_link_urb ( ...@@ -1536,7 +1536,7 @@ itd_link_urb (
struct ehci_itd, itd_list); struct ehci_itd, itd_list);
list_move_tail (&itd->itd_list, &stream->td_list); list_move_tail (&itd->itd_list, &stream->td_list);
itd->stream = iso_stream_get (stream); itd->stream = iso_stream_get (stream);
itd->urb = usb_get_urb (urb); itd->urb = urb;
itd_init (ehci, stream, itd); itd_init (ehci, stream, itd);
} }
...@@ -1645,7 +1645,7 @@ itd_complete ( ...@@ -1645,7 +1645,7 @@ itd_complete (
(void) disable_periodic(ehci); (void) disable_periodic(ehci);
ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; 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 ehci_to_hcd(ehci)->self.bandwidth_allocated
-= stream->bandwidth; -= stream->bandwidth;
ehci_vdbg (ehci, ehci_vdbg (ehci,
...@@ -1656,7 +1656,6 @@ itd_complete ( ...@@ -1656,7 +1656,6 @@ itd_complete (
iso_stream_put (ehci, stream); iso_stream_put (ehci, stream);
done: done:
usb_put_urb(urb);
itd->urb = NULL; itd->urb = NULL;
if (ehci->clock_frame != itd->frame || itd->index[7] != -1) { if (ehci->clock_frame != itd->frame || itd->index[7] != -1) {
/* OK to recycle this ITD now. */ /* OK to recycle this ITD now. */
...@@ -1949,7 +1948,7 @@ sitd_link_urb ( ...@@ -1949,7 +1948,7 @@ sitd_link_urb (
struct ehci_sitd, sitd_list); struct ehci_sitd, sitd_list);
list_move_tail (&sitd->sitd_list, &stream->td_list); list_move_tail (&sitd->sitd_list, &stream->td_list);
sitd->stream = iso_stream_get (stream); sitd->stream = iso_stream_get (stream);
sitd->urb = usb_get_urb (urb); sitd->urb = urb;
sitd_patch(ehci, stream, sitd, sched, packet); sitd_patch(ehci, stream, sitd, sched, packet);
sitd_link (ehci, (next_uframe >> 3) % ehci->periodic_size, sitd_link (ehci, (next_uframe >> 3) % ehci->periodic_size,
...@@ -2034,7 +2033,7 @@ sitd_complete ( ...@@ -2034,7 +2033,7 @@ sitd_complete (
(void) disable_periodic(ehci); (void) disable_periodic(ehci);
ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; 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 ehci_to_hcd(ehci)->self.bandwidth_allocated
-= stream->bandwidth; -= stream->bandwidth;
ehci_vdbg (ehci, ehci_vdbg (ehci,
...@@ -2045,7 +2044,6 @@ sitd_complete ( ...@@ -2045,7 +2044,6 @@ sitd_complete (
iso_stream_put (ehci, stream); iso_stream_put (ehci, stream);
/* OK to recycle this SITD now that its completion callback ran. */ /* OK to recycle this SITD now that its completion callback ran. */
done: done:
usb_put_urb(urb);
sitd->urb = NULL; sitd->urb = NULL;
sitd->stream = NULL; sitd->stream = NULL;
list_move(&sitd->sitd_list, &stream->free_list); list_move(&sitd->sitd_list, &stream->free_list);
......
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