aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2013-01-30 16:35:02 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-01-31 04:14:48 -0500
commitb09a61cc0bc2a7151f4ab652489e85253d5d0175 (patch)
tree3bbb588669e38c1798c2e22cf5087dfc81a193b8
parent03eb466f276ceef9dcf023dc5474db02af68aad9 (diff)
USB: EHCI: fix for leaking isochronous data
This patch (as1653) fixes a bug in ehci-hcd. Unlike iTD entries, an siTD entry in the periodic schedule may not complete until the frame after the one it belongs to. Consequently, when scanning the periodic schedule it is necessary to start with the frame _preceding_ the one where the previous scan ended. Not doing this properly can result in memory leaks and failures to complete isochronous URBs. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Reported-by: Andy Leiserson <andy@leiserson.org> Cc: stable <stable@vger.kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/usb/host/ehci-sched.c7
1 files changed, 5 insertions, 2 deletions
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index 69ebee73c0c1..2b6917dc3996 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -2212,11 +2212,11 @@ static void scan_isoc(struct ehci_hcd *ehci)
2212 } 2212 }
2213 ehci->now_frame = now_frame; 2213 ehci->now_frame = now_frame;
2214 2214
2215 frame = ehci->last_iso_frame;
2215 for (;;) { 2216 for (;;) {
2216 union ehci_shadow q, *q_p; 2217 union ehci_shadow q, *q_p;
2217 __hc32 type, *hw_p; 2218 __hc32 type, *hw_p;
2218 2219
2219 frame = ehci->last_iso_frame;
2220restart: 2220restart:
2221 /* scan each element in frame's queue for completions */ 2221 /* scan each element in frame's queue for completions */
2222 q_p = &ehci->pshadow [frame]; 2222 q_p = &ehci->pshadow [frame];
@@ -2321,6 +2321,9 @@ restart:
2321 /* Stop when we have reached the current frame */ 2321 /* Stop when we have reached the current frame */
2322 if (frame == now_frame) 2322 if (frame == now_frame)
2323 break; 2323 break;
2324 ehci->last_iso_frame = (frame + 1) & fmask; 2324
2325 /* The last frame may still have active siTDs */
2326 ehci->last_iso_frame = frame;
2327 frame = (frame + 1) & fmask;
2325 } 2328 }
2326} 2329}