USB: EHCI: add missing frame -> microframe conversion
authorAlan Stern <stern@rowland.harvard.edu>
Wed, 14 Jul 2010 15:03:46 +0000 (11:03 -0400)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 10 Aug 2010 21:35:40 +0000 (14:35 -0700)
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>
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-sched.c

index 2e704fa3cedfb70a6e88e8f48d2994c86a889bff..34a928d3b7d2f69ddf671330cc9bbb60dbf5405c 100644 (file)
@@ -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 */
index 27dd841b9aa290077f1ae61c152db2749217b6c2..dd37350170bb4de50f1a01f598f55583af9d6f5b 100644 (file)
@@ -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.
@@ -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;