aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSarah Sharp <sarah.a.sharp@linux.intel.com>2009-10-09 12:28:41 -0700
committerGreg Kroah-Hartman <gregkh@suse.de>2009-10-14 14:54:43 -0700
commit36f21329d217016f0f212f0752ae595b4a76754d (patch)
tree20c3b63928586fdc7ea66a5945926cb4828b2a75
parent12148da6722be3b44c2220206b6ccb80d2d9d8f8 (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>
-rw-r--r--drivers/usb/host/ehci-sched.c12
1 files changed, 6 insertions, 6 deletions
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index 3efa59b1804..b25cdea93a1 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -1400,6 +1400,10 @@ iso_stream_schedule (
goto fail;
}
+ period = urb->interval;
+ if (!stream->highspeed)
+ period <<= 3;
+
now = ehci_readl(ehci, &ehci->regs->frame_index) % mod;
/* when's the last uframe this urb could start? */
@@ -1417,8 +1421,8 @@ iso_stream_schedule (
/* Fell behind (by up to twice the slop amount)? */
if (start >= max - 2 * 8 * SCHEDULE_SLOP)
- start += stream->interval * DIV_ROUND_UP(
- max - start, stream->interval) - mod;
+ start += period * DIV_ROUND_UP(
+ max - start, period) - mod;
/* Tried to schedule too far into the future? */
if (unlikely((start + sched->span) >= max)) {
@@ -1441,10 +1445,6 @@ iso_stream_schedule (
/* NOTE: assumes URB_ISO_ASAP, to limit complexity/bugs */
- period = urb->interval;
- if (!stream->highspeed)
- period <<= 3;
-
/* find a uframe slot with enough bandwidth */
for (; start < (stream->next_uframe + period); start++) {
int enough_space;