[RFC] Fix for scheduling bug in ehci-hcd

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



I'm sending this in for discussion.  It fixes a real bug in ehci-hcd
(the sched->span value is not getting converted from frames to
microframes).  The effect of the bug is that some Isochronous URB
submissions are accepted when they should not be, messing up the
periodic schedule.

I'm not submitting this patch right now because it is certain to cause
new failures.  It's hard to say whether it will cause any regressions;
the things that would fail might not be working correctly now anyway.  
There's a good chance some regressions will occur.

The problem is that with some types of hardware, ehci-hcd uses a 
scheduling horizon of only 256 ms.  It won't accept Isochronous URBs 
that go farther than that into the future.  However the usbaudio driver 
is known to submit URBs for timing synchronization that will overrun 
this limit.  (The current version of ehci-hcd accepts these URBs even 
though it shouldn't; that's the bug.)

The default scheduling horizon is 1024 ms but ehci-hcd uses the 
smaller value if the hardware supports it, in order to reduce the 
amount of processing needed when updating the schedule.

I can see two possible approaches.  One is for ehci-hcd always to use
1024 ms and not worry about the extra processing costs.  The other is
to change the drivers that want to schedule URBs too far into the
future.  The difficulty here is that I'm not aware of all the drivers
that might need changes; there may be others in addition to usbaudio.

Suggestions?

Alan Stern


Index: usb-2.6/drivers/usb/host/ehci-sched.c
===================================================================
--- usb-2.6.orig/drivers/usb/host/ehci-sched.c
+++ usb-2.6/drivers/usb/host/ehci-sched.c
@@ -1396,29 +1396,32 @@ 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;
 	struct pci_dev		*pdev;
 
-	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;
 
 	/* Typical case: reuse current schedule, stream is still active.
@@ -1448,7 +1451,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;

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux