Skip to content

Commit

Permalink
USB: EHCI: add missing frame -> microframe conversion
Browse files Browse the repository at this point in the history
This patch (as1407) fixes a bug in ehci-hcd's isochronous scheduler.
All its calculations should be done in terms of microframes, but for
full-speed devices, sched->span is stored in frames.  It needs to be
converted.

This fix is liable to expose problems in other drivers.  The old code
would accept URBs that should not have been accepted, so drivers have
had no reason to avoid submitting URBs that exceeded the maximum
schedule length.  In an attempt to partially compensate for this, the
patch also adjusts the schedule length from a minimum of 256 frames up
to a minimum of 512 frames.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
CC: David Brownell <david-b@pacbell.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
  • Loading branch information
Alan Stern authored and Greg Kroah-Hartman committed Aug 10, 2010
1 parent bccbefa commit ffda080
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 10 deletions.
8 changes: 7 additions & 1 deletion drivers/usb/host/ehci-hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,13 @@ static const char hcd_name [] = "ehci_hcd";
#define EHCI_TUNE_RL_TT 0
#define EHCI_TUNE_MULT_HS 1 /* 1-3 transactions/uframe; 4.10.3 */
#define EHCI_TUNE_MULT_TT 1
#define EHCI_TUNE_FLS 2 /* (small) 256 frame schedule */
/*
* Some drivers think it's safe to schedule isochronous transfers more than
* 256 ms into the future (partly as a result of an old bug in the scheduling
* code). In an attempt to avoid trouble, we will use a minimum scheduling
* length of 512 frames instead of 256.
*/
#define EHCI_TUNE_FLS 1 /* (medium) 512-frame schedule */

#define EHCI_IAA_MSECS 10 /* arbitrary */
#define EHCI_IO_JIFFIES (HZ/10) /* io watchdog > irq_thresh */
Expand Down
21 changes: 12 additions & 9 deletions drivers/usb/host/ehci-sched.c
Original file line number Diff line number Diff line change
Expand Up @@ -1395,28 +1395,31 @@ iso_stream_schedule (
struct ehci_iso_stream *stream
)
{
u32 now, next, start, period;
u32 now, next, start, period, span;
int status;
unsigned mod = ehci->periodic_size << 3;
struct ehci_iso_sched *sched = urb->hcpriv;

if (sched->span > (mod - SCHEDULE_SLOP)) {
period = urb->interval;
span = sched->span;
if (!stream->highspeed) {
period <<= 3;
span <<= 3;
}

if (span > mod - SCHEDULE_SLOP) {
ehci_dbg (ehci, "iso request %p too long\n", urb);
status = -EFBIG;
goto fail;
}

if ((stream->depth + sched->span) > mod) {
if (stream->depth + span > mod) {
ehci_dbg (ehci, "request %p would overflow (%d+%d>%d)\n",
urb, stream->depth, sched->span, mod);
urb, stream->depth, span, mod);
status = -EFBIG;
goto fail;
}

period = urb->interval;
if (!stream->highspeed)
period <<= 3;

now = ehci_readl(ehci, &ehci->regs->frame_index) & (mod - 1);

/* Typical case: reuse current schedule, stream is still active.
Expand Down Expand Up @@ -1445,7 +1448,7 @@ iso_stream_schedule (
period);

/* Tried to schedule too far into the future? */
if (unlikely(((start - now) & (mod - 1)) + sched->span
if (unlikely(((start - now) & (mod - 1)) + span
>= mod - 2 * SCHEDULE_SLOP)) {
status = -EFBIG;
goto fail;
Expand Down

0 comments on commit ffda080

Please sign in to comment.