[PATCH 3/4] UHCI: implement new semantics for URB_ISO_ASAP

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

 



This patch (as1613) updates the isochronous scheduling in uhci-hcd to
match the new semantics for URB_ISO_ASAP.  The amount of code
alteration is smaller than it looks because of a change in the
indentation level.

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

---

 drivers/usb/host/uhci-q.c |   73 ++++++++++++++++++++++------------------------
 1 file changed, 36 insertions(+), 37 deletions(-)

Index: usb-3.6/drivers/usb/host/uhci-q.c
===================================================================
--- usb-3.6.orig/drivers/usb/host/uhci-q.c
+++ usb-3.6/drivers/usb/host/uhci-q.c
@@ -1256,7 +1256,8 @@ static int uhci_submit_isochronous(struc
 		struct uhci_qh *qh)
 {
 	struct uhci_td *td = NULL;	/* Since urb->number_of_packets > 0 */
-	int i, frame;
+	int i;
+	unsigned frame, next;
 	unsigned long destination, status;
 	struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv;
 
@@ -1265,37 +1266,29 @@ static int uhci_submit_isochronous(struc
 			urb->number_of_packets >= UHCI_NUMFRAMES)
 		return -EFBIG;
 
+	uhci_get_current_frame_number(uhci);
+
 	/* Check the period and figure out the starting frame number */
 	if (!qh->bandwidth_reserved) {
 		qh->period = urb->interval;
-		if (urb->transfer_flags & URB_ISO_ASAP) {
-			qh->phase = -1;		/* Find the best phase */
-			i = uhci_check_bandwidth(uhci, qh);
-			if (i)
-				return i;
-
-			/* Allow a little time to allocate the TDs */
-			uhci_get_current_frame_number(uhci);
-			frame = uhci->frame_number + 10;
-
-			/* Move forward to the first frame having the
-			 * correct phase */
-			urb->start_frame = frame + ((qh->phase - frame) &
-					(qh->period - 1));
-		} else {
-			i = urb->start_frame - uhci->last_iso_frame;
-			if (i <= 0 || i >= UHCI_NUMFRAMES)
-				return -EINVAL;
-			qh->phase = urb->start_frame & (qh->period - 1);
-			i = uhci_check_bandwidth(uhci, qh);
-			if (i)
-				return i;
-		}
+		qh->phase = -1;		/* Find the best phase */
+		i = uhci_check_bandwidth(uhci, qh);
+		if (i)
+			return i;
+
+		/* Allow a little time to allocate the TDs */
+		next = uhci->frame_number + 10;
+		frame = qh->phase;
+
+		/* Round up to the first available slot */
+		frame += (next - frame + qh->period - 1) & -qh->period;
 
 	} else if (qh->period != urb->interval) {
 		return -EINVAL;		/* Can't change the period */
 
 	} else {
+		next = uhci->frame_number + 2;
+
 		/* Find the next unused frame */
 		if (list_empty(&qh->queue)) {
 			frame = qh->iso_frame;
@@ -1308,25 +1301,31 @@ static int uhci_submit_isochronous(struc
 					lurb->number_of_packets *
 					lurb->interval;
 		}
-		if (urb->transfer_flags & URB_ISO_ASAP) {
-			/* Skip some frames if necessary to insure
-			 * the start frame is in the future.
+
+		/* Fell behind? */
+		if (uhci_frame_before_eq(frame, next)) {
+
+			/* USB_ISO_ASAP: Round up to the first available slot */
+			if (urb->transfer_flags & URB_ISO_ASAP)
+				frame += (next - frame + qh->period - 1) &
+						-qh->period;
+
+			/*
+			 * Not ASAP: Use the next slot in the stream.  If
+			 * the entire URB falls before the threshold, fail.
 			 */
-			uhci_get_current_frame_number(uhci);
-			if (uhci_frame_before_eq(frame, uhci->frame_number)) {
-				frame = uhci->frame_number + 1;
-				frame += ((qh->phase - frame) &
-					(qh->period - 1));
-			}
-		}	/* Otherwise pick up where the last URB leaves off */
-		urb->start_frame = frame;
+			else if (!uhci_frame_before_eq(next,
+					frame + (urb->number_of_packets - 1) *
+						qh->period))
+				return -EXDEV;
+		}
 	}
 
 	/* Make sure we won't have to go too far into the future */
 	if (uhci_frame_before_eq(uhci->last_iso_frame + UHCI_NUMFRAMES,
-			urb->start_frame + urb->number_of_packets *
-				urb->interval))
+			frame + urb->number_of_packets * urb->interval))
 		return -EFBIG;
+	urb->start_frame = frame;
 
 	status = TD_CTRL_ACTIVE | TD_CTRL_IOS;
 	destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe);

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