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