On Fri, 9 Oct 2009, Sarah Sharp wrote: > @@ -1354,6 +1354,7 @@ iso_stream_schedule ( > period <<= 3; > > now = ehci_readl(ehci, &ehci->regs->frame_index) % mod; > + next = now + ehci->i_thresh; > > /* when's the last uframe this urb could start? */ > max = now + mod; > @@ -1365,13 +1366,15 @@ iso_stream_schedule ( > */ > if (likely (!list_empty (&stream->td_list))) { > start = stream->next_uframe; > - if (start < now) > + if (start < next) > start += mod; > > /* Fell behind (by up to twice the slop amount)? */ > if (start >= max - 2 * 8 * SCHEDULE_SLOP) > start += period * DIV_ROUND_UP( > - max - start, period) - mod; > + max - start + ehci->i_thresh, > + period) > + - mod; > > /* Tried to schedule too far into the future? */ > if (unlikely((start + sched->span) >= max)) { Sorry, what I wrote before wasn't quite right. This computation is tricky. To check whether start is too small, you have to fit it into the interval from next to (next + mod - 1). But then to check whether it is too big, you have to fit it into the interval from now to (now + mod - 1). And then in the end, you need to assign stream->next_uframe a value between 0 and (mod - 1). Since mod is always a power of two, the easiest approach may be something like this: next = now + ehci->i_thread; ... start = stream->next_uframe; /* Fell behind (by up to twice the slop amount)? */ if ((start - next) & (mod - 1) >= mod - 2 * 8 * SCHEDULE_SLOP) start += period * DIV_ROUND_UP( (next - start) & (mod - 1), period); /* Tried to schedule too far into the future? */ if (unlikely(((start - now) & (mod - 1)) + sched->span >= max)) { ... } stream->next_uframe = start % mod; goto ready; Alan Stern -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html