diff options
author | Karsten Wiese <fzuuzf@googlemail.com> | 2009-02-25 19:47:48 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-03-17 17:01:29 -0400 |
commit | 508db8c954d55ed30f870d2c24d741ba6269d13c (patch) | |
tree | aed956a468d6d2dcd6103554f535aed978eec4fe /drivers | |
parent | 9ea19b82f3126da4e47d6b94563a3c2cd586f6e2 (diff) |
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: Karsten Wiese <fzu@wemgehoertderstaat.de>
Cc: David Brownell <david-b@pacbell.net>
Cc: stable <stable@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/host/ehci-sched.c | 10 |
1 files changed, 4 insertions, 6 deletions
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 07bcb931021b..1d0b49e3f192 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c | |||
@@ -1536,7 +1536,7 @@ itd_link_urb ( | |||
1536 | struct ehci_itd, itd_list); | 1536 | struct ehci_itd, itd_list); |
1537 | list_move_tail (&itd->itd_list, &stream->td_list); | 1537 | list_move_tail (&itd->itd_list, &stream->td_list); |
1538 | itd->stream = iso_stream_get (stream); | 1538 | itd->stream = iso_stream_get (stream); |
1539 | itd->urb = usb_get_urb (urb); | 1539 | itd->urb = urb; |
1540 | itd_init (ehci, stream, itd); | 1540 | itd_init (ehci, stream, itd); |
1541 | } | 1541 | } |
1542 | 1542 | ||
@@ -1645,7 +1645,7 @@ itd_complete ( | |||
1645 | (void) disable_periodic(ehci); | 1645 | (void) disable_periodic(ehci); |
1646 | ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; | 1646 | ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; |
1647 | 1647 | ||
1648 | if (unlikely (list_empty (&stream->td_list))) { | 1648 | if (unlikely(list_is_singular(&stream->td_list))) { |
1649 | ehci_to_hcd(ehci)->self.bandwidth_allocated | 1649 | ehci_to_hcd(ehci)->self.bandwidth_allocated |
1650 | -= stream->bandwidth; | 1650 | -= stream->bandwidth; |
1651 | ehci_vdbg (ehci, | 1651 | ehci_vdbg (ehci, |
@@ -1656,7 +1656,6 @@ itd_complete ( | |||
1656 | iso_stream_put (ehci, stream); | 1656 | iso_stream_put (ehci, stream); |
1657 | 1657 | ||
1658 | done: | 1658 | done: |
1659 | usb_put_urb(urb); | ||
1660 | itd->urb = NULL; | 1659 | itd->urb = NULL; |
1661 | if (ehci->clock_frame != itd->frame || itd->index[7] != -1) { | 1660 | if (ehci->clock_frame != itd->frame || itd->index[7] != -1) { |
1662 | /* OK to recycle this ITD now. */ | 1661 | /* OK to recycle this ITD now. */ |
@@ -1949,7 +1948,7 @@ sitd_link_urb ( | |||
1949 | struct ehci_sitd, sitd_list); | 1948 | struct ehci_sitd, sitd_list); |
1950 | list_move_tail (&sitd->sitd_list, &stream->td_list); | 1949 | list_move_tail (&sitd->sitd_list, &stream->td_list); |
1951 | sitd->stream = iso_stream_get (stream); | 1950 | sitd->stream = iso_stream_get (stream); |
1952 | sitd->urb = usb_get_urb (urb); | 1951 | sitd->urb = urb; |
1953 | 1952 | ||
1954 | sitd_patch(ehci, stream, sitd, sched, packet); | 1953 | sitd_patch(ehci, stream, sitd, sched, packet); |
1955 | sitd_link (ehci, (next_uframe >> 3) % ehci->periodic_size, | 1954 | sitd_link (ehci, (next_uframe >> 3) % ehci->periodic_size, |
@@ -2034,7 +2033,7 @@ sitd_complete ( | |||
2034 | (void) disable_periodic(ehci); | 2033 | (void) disable_periodic(ehci); |
2035 | ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; | 2034 | ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; |
2036 | 2035 | ||
2037 | if (list_empty (&stream->td_list)) { | 2036 | if (list_is_singular(&stream->td_list)) { |
2038 | ehci_to_hcd(ehci)->self.bandwidth_allocated | 2037 | ehci_to_hcd(ehci)->self.bandwidth_allocated |
2039 | -= stream->bandwidth; | 2038 | -= stream->bandwidth; |
2040 | ehci_vdbg (ehci, | 2039 | ehci_vdbg (ehci, |
@@ -2045,7 +2044,6 @@ sitd_complete ( | |||
2045 | iso_stream_put (ehci, stream); | 2044 | iso_stream_put (ehci, stream); |
2046 | /* OK to recycle this SITD now that its completion callback ran. */ | 2045 | /* OK to recycle this SITD now that its completion callback ran. */ |
2047 | done: | 2046 | done: |
2048 | usb_put_urb(urb); | ||
2049 | sitd->urb = NULL; | 2047 | sitd->urb = NULL; |
2050 | sitd->stream = NULL; | 2048 | sitd->stream = NULL; |
2051 | list_move(&sitd->sitd_list, &stream->free_list); | 2049 | list_move(&sitd->sitd_list, &stream->free_list); |