]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/usb/host/uhci-q.c
Merge branch 'avr32-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/hskinnemo...
[karo-tx-linux.git] / drivers / usb / host / uhci-q.c
index e5d60d5b105a8975979c731a401eee26b0effd62..60379b17bbc144a910a47b5021549f03cacc77f6 100644 (file)
@@ -1271,7 +1271,8 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
        } 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 {
@@ -1283,10 +1284,18 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
                                        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 */