} else if (qh->period != urb->interval) {
return -EINVAL; /* Can't change the period */
- } else { /* Pick up where the last URB leaves off */
+ } else {
+ /* Find the next unused frame */
if (list_empty(&qh->queue)) {
frame = qh->iso_frame;
} else {
lurb->number_of_packets *
lurb->interval;
}
- if (urb->transfer_flags & URB_ISO_ASAP)
- urb->start_frame = frame;
- else if (urb->start_frame != frame)
- return -EINVAL;
+ if (urb->transfer_flags & URB_ISO_ASAP) {
+ /* Skip some frames if necessary to insure
+ * the start frame is in the future.
+ */
+ 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;
}
/* Make sure we won't have to go too far into the future */