summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2010-07-14 11:03:46 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-08-10 14:35:40 -0700
commitffda080353979273e8aa69fc1e6134f20643ae56 (patch)
tree3d4981380afc2123e906a85948c20a299c4a52bf
parentbccbefaae050186bed3bcc74b1fd1a9b8c6710b2 (diff)
USB: EHCI: add missing frame -> microframe conversion
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>
-rw-r--r--drivers/usb/host/ehci-hcd.c8
-rw-r--r--drivers/usb/host/ehci-sched.c21
2 files changed, 19 insertions, 10 deletions
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 2e704fa3ced..34a928d3b7d 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -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 */
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index 27dd841b9aa..dd37350170b 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -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;