Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4005ad43 authored by Alan Stern's avatar Alan Stern Committed by Greg Kroah-Hartman
Browse files

EHCI: implement new semantics for URB_ISO_ASAP



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: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent a03bede5
Loading
Loading
Loading
Loading
+26 −7
Original line number Original line Diff line number Diff line
@@ -1386,8 +1386,8 @@ iso_stream_schedule (


	/* Typical case: reuse current schedule, stream is still active.
	/* Typical case: reuse current schedule, stream is still active.
	 * Hopefully there are no gaps from the host falling behind
	 * Hopefully there are no gaps from the host falling behind
	 * (irq delays etc), but if there are we'll take the next
	 * (irq delays etc).  If there are, the behavior depends on
	 * slot in the schedule, implicitly assuming URB_ISO_ASAP.
	 * whether URB_ISO_ASAP is set.
	 */
	 */
	if (likely (!list_empty (&stream->td_list))) {
	if (likely (!list_empty (&stream->td_list))) {


@@ -1414,9 +1414,25 @@ iso_stream_schedule (
			goto fail;
			goto fail;
		}
		}


		/* Behind the scheduling threshold?  Assume URB_ISO_ASAP. */
		/* Behind the scheduling threshold? */
		if (unlikely(start < next))
		if (unlikely(start < next)) {
			start += (next - start + period - 1) & (- period);

			/* 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;
		start += base;
	}
	}
@@ -1699,7 +1715,7 @@ static bool itd_complete(struct ehci_hcd *ehci, struct ehci_itd *itd)
			urb->actual_length += desc->actual_length;
			urb->actual_length += desc->actual_length;
		} else {
		} else {
			/* URB was too late */
			/* URB was too late */
			desc->status = -EXDEV;
			urb->error_count++;
		}
		}
	}
	}


@@ -2072,7 +2088,7 @@ static bool sitd_complete(struct ehci_hcd *ehci, struct ehci_sitd *sitd)
	t = hc32_to_cpup(ehci, &sitd->hw_results);
	t = hc32_to_cpup(ehci, &sitd->hw_results);


	/* report transfer status */
	/* report transfer status */
	if (t & SITD_ERRS) {
	if (unlikely(t & SITD_ERRS)) {
		urb->error_count++;
		urb->error_count++;
		if (t & SITD_STS_DBE)
		if (t & SITD_STS_DBE)
			desc->status = usb_pipein (urb->pipe)
			desc->status = usb_pipein (urb->pipe)
@@ -2082,6 +2098,9 @@ static bool sitd_complete(struct ehci_hcd *ehci, struct ehci_sitd *sitd)
			desc->status = -EOVERFLOW;
			desc->status = -EOVERFLOW;
		else /* XACT, MMF, etc */
		else /* XACT, MMF, etc */
			desc->status = -EPROTO;
			desc->status = -EPROTO;
	} else if (unlikely(t & SITD_STS_ACTIVE)) {
		/* URB was too late */
		urb->error_count++;
	} else {
	} else {
		desc->status = 0;
		desc->status = 0;
		desc->actual_length = desc->length - SITD_LENGTH(t);
		desc->actual_length = desc->length - SITD_LENGTH(t);