summaryrefslogtreecommitdiff
path: root/drivers/usb/host/ehci-sched.c
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2010-07-14 15:03:46 (GMT)
committerGreg Kroah-Hartman <gregkh@suse.de>2010-08-10 21:35:40 (GMT)
commitffda080353979273e8aa69fc1e6134f20643ae56 (patch)
tree3d4981380afc2123e906a85948c20a299c4a52bf /drivers/usb/host/ehci-sched.c
parentbccbefaae050186bed3bcc74b1fd1a9b8c6710b2 (diff)
downloadlinux-ffda080353979273e8aa69fc1e6134f20643ae56.tar.xz
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>
Diffstat (limited to 'drivers/usb/host/ehci-sched.c')
-rw-r--r--drivers/usb/host/ehci-sched.c21
1 files changed, 12 insertions, 9 deletions
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index 27dd841..dd37350 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;