[PATCH 2/4] EHCI: implement new semantics for URB_ISO_ASAP

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

 



This patch (as1612) updates the isochronous scheduling and processing
in ehci-hcd to match the new semantics for URB_ISO_ASAP.  It also adds
a missing "unlikely" in sitd_complete() to match the corresponding
statement in itd_complete(), and it increments urb->error_count in a
couple of places that had been overlooked.

Signed-off-by: Alan Stern <stern@xxxxxxxxxxxxxxxxxxx>

---

 drivers/usb/host/ehci-sched.c |   33 ++++++++++++++++++++++++++-------
 1 file changed, 26 insertions(+), 7 deletions(-)

Index: usb-3.6/drivers/usb/host/ehci-sched.c
===================================================================
--- usb-3.6.orig/drivers/usb/host/ehci-sched.c
+++ usb-3.6/drivers/usb/host/ehci-sched.c
@@ -1386,8 +1386,8 @@ iso_stream_schedule (
 
 	/* Typical case: reuse current schedule, stream is still active.
 	 * Hopefully there are no gaps from the host falling behind
-	 * (irq delays etc), but if there are we'll take the next
-	 * slot in the schedule, implicitly assuming URB_ISO_ASAP.
+	 * (irq delays etc).  If there are, the behavior depends on
+	 * whether URB_ISO_ASAP is set.
 	 */
 	if (likely (!list_empty (&stream->td_list))) {
 
@@ -1414,9 +1414,25 @@ iso_stream_schedule (
 			goto fail;
 		}
 
-		/* Behind the scheduling threshold?  Assume URB_ISO_ASAP. */
-		if (unlikely(start < next))
-			start += (next - start + period - 1) & (- period);
+		/* Behind the scheduling threshold? */
+		if (unlikely(start < next)) {
+
+			/* USB_ISO_ASAP: Round up to the first available slot */
+			if (urb->transfer_flags & URB_ISO_ASAP)
+				start += (next - start + period - 1) & -period;
+
+			/*
+			 * Not ASAP: Use the next slot in the stream.  If
+			 * the entire URB falls before the threshold, fail.
+			 */
+			else if (start + span - period < next) {
+				ehci_dbg(ehci, "iso urb late %p (%u+%u < %u)\n",
+						urb, start + base,
+						span - period, next + base);
+				status = -EXDEV;
+				goto fail;
+			}
+		}
 
 		start += base;
 	}
@@ -1699,7 +1715,7 @@ static bool itd_complete(struct ehci_hcd
 			urb->actual_length += desc->actual_length;
 		} else {
 			/* URB was too late */
-			desc->status = -EXDEV;
+			urb->error_count++;
 		}
 	}
 
@@ -2072,7 +2088,7 @@ static bool sitd_complete(struct ehci_hc
 	t = hc32_to_cpup(ehci, &sitd->hw_results);
 
 	/* report transfer status */
-	if (t & SITD_ERRS) {
+	if (unlikely(t & SITD_ERRS)) {
 		urb->error_count++;
 		if (t & SITD_STS_DBE)
 			desc->status = usb_pipein (urb->pipe)
@@ -2082,6 +2098,9 @@ static bool sitd_complete(struct ehci_hc
 			desc->status = -EOVERFLOW;
 		else /* XACT, MMF, etc */
 			desc->status = -EPROTO;
+	} else if (unlikely(t & SITD_STS_ACTIVE)) {
+		/* URB was too late */
+		urb->error_count++;
 	} else {
 		desc->status = 0;
 		desc->actual_length = desc->length - SITD_LENGTH(t);

--
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