aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host
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 17:35:40 -0400
commitffda080353979273e8aa69fc1e6134f20643ae56 (patch)
tree3d4981380afc2123e906a85948c20a299c4a52bf /drivers/usb/host
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>
Diffstat (limited to 'drivers/usb/host')
-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 2e704fa3cedf..34a928d3b7d2 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";
79#define EHCI_TUNE_RL_TT 0 79#define EHCI_TUNE_RL_TT 0
80#define EHCI_TUNE_MULT_HS 1 /* 1-3 transactions/uframe; 4.10.3 */ 80#define EHCI_TUNE_MULT_HS 1 /* 1-3 transactions/uframe; 4.10.3 */
81#define EHCI_TUNE_MULT_TT 1 81#define EHCI_TUNE_MULT_TT 1
82#define EHCI_TUNE_FLS 2 /* (small) 256 frame schedule */ 82/*
83 * Some drivers think it's safe to schedule isochronous transfers more than
84 * 256 ms into the future (partly as a result of an old bug in the scheduling
85 * code). In an attempt to avoid trouble, we will use a minimum scheduling
86 * length of 512 frames instead of 256.
87 */
88#define EHCI_TUNE_FLS 1 /* (medium) 512-frame schedule */
83 89
84#define EHCI_IAA_MSECS 10 /* arbitrary */ 90#define EHCI_IAA_MSECS 10 /* arbitrary */
85#define EHCI_IO_JIFFIES (HZ/10) /* io watchdog > irq_thresh */ 91#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 27dd841b9aa2..dd37350170bb 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -1395,28 +1395,31 @@ iso_stream_schedule (
1395 struct ehci_iso_stream *stream 1395 struct ehci_iso_stream *stream
1396) 1396)
1397{ 1397{
1398 u32 now, next, start, period; 1398 u32 now, next, start, period, span;
1399 int status; 1399 int status;
1400 unsigned mod = ehci->periodic_size << 3; 1400 unsigned mod = ehci->periodic_size << 3;
1401 struct ehci_iso_sched *sched = urb->hcpriv; 1401 struct ehci_iso_sched *sched = urb->hcpriv;
1402 1402
1403 if (sched->span > (mod - SCHEDULE_SLOP)) { 1403 period = urb->interval;
1404 span = sched->span;
1405 if (!stream->highspeed) {
1406 period <<= 3;
1407 span <<= 3;
1408 }
1409
1410 if (span > mod - SCHEDULE_SLOP) {
1404 ehci_dbg (ehci, "iso request %p too long\n", urb); 1411 ehci_dbg (ehci, "iso request %p too long\n", urb);
1405 status = -EFBIG; 1412 status = -EFBIG;
1406 goto fail; 1413 goto fail;
1407 } 1414 }
1408 1415
1409 if ((stream->depth + sched->span) > mod) { 1416 if (stream->depth + span > mod) {
1410 ehci_dbg (ehci, "request %p would overflow (%d+%d>%d)\n", 1417 ehci_dbg (ehci, "request %p would overflow (%d+%d>%d)\n",
1411 urb, stream->depth, sched->span, mod); 1418 urb, stream->depth, span, mod);
1412 status = -EFBIG; 1419 status = -EFBIG;
1413 goto fail; 1420 goto fail;
1414 } 1421 }
1415 1422
1416 period = urb->interval;
1417 if (!stream->highspeed)
1418 period <<= 3;
1419
1420 now = ehci_readl(ehci, &ehci->regs->frame_index) & (mod - 1); 1423 now = ehci_readl(ehci, &ehci->regs->frame_index) & (mod - 1);
1421 1424
1422 /* Typical case: reuse current schedule, stream is still active. 1425 /* Typical case: reuse current schedule, stream is still active.
@@ -1445,7 +1448,7 @@ iso_stream_schedule (
1445 period); 1448 period);
1446 1449
1447 /* Tried to schedule too far into the future? */ 1450 /* Tried to schedule too far into the future? */
1448 if (unlikely(((start - now) & (mod - 1)) + sched->span 1451 if (unlikely(((start - now) & (mod - 1)) + span
1449 >= mod - 2 * SCHEDULE_SLOP)) { 1452 >= mod - 2 * SCHEDULE_SLOP)) {
1450 status = -EFBIG; 1453 status = -EFBIG;
1451 goto fail; 1454 goto fail;