diff options
author | Sarah Sharp <sarah.a.sharp@linux.intel.com> | 2009-10-09 15:28:41 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-10-14 17:54:43 -0400 |
commit | 36f21329d217016f0f212f0752ae595b4a76754d (patch) | |
tree | 20c3b63928586fdc7ea66a5945926cb4828b2a75 /drivers/usb/host/ehci-sched.c | |
parent | 12148da6722be3b44c2220206b6ccb80d2d9d8f8 (diff) |
USB: ehci: Fix IST boundary checking interval math.
When the EHCI driver falls behind in its scheduling, the active stream's
first empty microframe may be in the past with respect to the current
microframe. The code attempts to move the starting microframe ("start") N
number of microframes forward, where N is the interval of endpoint.
However, stream->interval is a copy of the endpoint's bInterval, which is
designated in frames for FS devices, and microframes for HS devices.
Convert stream->interval to microframes before using it to move the
starting microframe forward.
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host/ehci-sched.c')
-rw-r--r-- | drivers/usb/host/ehci-sched.c | 12 |
1 files changed, 6 insertions, 6 deletions
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 3efa59b18044..b25cdea93a1f 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c | |||
@@ -1400,6 +1400,10 @@ iso_stream_schedule ( | |||
1400 | goto fail; | 1400 | goto fail; |
1401 | } | 1401 | } |
1402 | 1402 | ||
1403 | period = urb->interval; | ||
1404 | if (!stream->highspeed) | ||
1405 | period <<= 3; | ||
1406 | |||
1403 | now = ehci_readl(ehci, &ehci->regs->frame_index) % mod; | 1407 | now = ehci_readl(ehci, &ehci->regs->frame_index) % mod; |
1404 | 1408 | ||
1405 | /* when's the last uframe this urb could start? */ | 1409 | /* when's the last uframe this urb could start? */ |
@@ -1417,8 +1421,8 @@ iso_stream_schedule ( | |||
1417 | 1421 | ||
1418 | /* Fell behind (by up to twice the slop amount)? */ | 1422 | /* Fell behind (by up to twice the slop amount)? */ |
1419 | if (start >= max - 2 * 8 * SCHEDULE_SLOP) | 1423 | if (start >= max - 2 * 8 * SCHEDULE_SLOP) |
1420 | start += stream->interval * DIV_ROUND_UP( | 1424 | start += period * DIV_ROUND_UP( |
1421 | max - start, stream->interval) - mod; | 1425 | max - start, period) - mod; |
1422 | 1426 | ||
1423 | /* Tried to schedule too far into the future? */ | 1427 | /* Tried to schedule too far into the future? */ |
1424 | if (unlikely((start + sched->span) >= max)) { | 1428 | if (unlikely((start + sched->span) >= max)) { |
@@ -1441,10 +1445,6 @@ iso_stream_schedule ( | |||
1441 | 1445 | ||
1442 | /* NOTE: assumes URB_ISO_ASAP, to limit complexity/bugs */ | 1446 | /* NOTE: assumes URB_ISO_ASAP, to limit complexity/bugs */ |
1443 | 1447 | ||
1444 | period = urb->interval; | ||
1445 | if (!stream->highspeed) | ||
1446 | period <<= 3; | ||
1447 | |||
1448 | /* find a uframe slot with enough bandwidth */ | 1448 | /* find a uframe slot with enough bandwidth */ |
1449 | for (; start < (stream->next_uframe + period); start++) { | 1449 | for (; start < (stream->next_uframe + period); start++) { |
1450 | int enough_space; | 1450 | int enough_space; |