]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/usb/host/uhci-q.c
USB: drivers/usb/host/isp1760-hcd.c: processor flags have type `unsigned long'
[linux-2.6-omap-h63xx.git] / drivers / usb / host / uhci-q.c
index fbc3af392c26540429bb92530aeb99b9ee086188..db645936eedd3b5f8f5aff71a9eee85a12223757 100644 (file)
@@ -1171,7 +1171,7 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb)
                                /* Some debugging code */
                                dev_dbg(&urb->dev->dev,
                                                "%s: failed with status %x\n",
-                                               __FUNCTION__, status);
+                                               __func__, status);
 
                                if (debug > 1 && errbuf) {
                                        /* Print the chain for debugging */
@@ -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 */
@@ -1480,7 +1489,7 @@ done:
  * Finish unlinking an URB and give it back
  */
 static void uhci_giveback_urb(struct uhci_hcd *uhci, struct uhci_qh *qh,
-               struct urb *urb)
+               struct urb *urb, int status)
 __releases(uhci->lock)
 __acquires(uhci->lock)
 {
@@ -1520,7 +1529,7 @@ __acquires(uhci->lock)
        usb_hcd_unlink_urb_from_ep(uhci_to_hcd(uhci), urb);
 
        spin_unlock(&uhci->lock);
-       usb_hcd_giveback_urb(uhci_to_hcd(uhci), urb);
+       usb_hcd_giveback_urb(uhci_to_hcd(uhci), urb, status);
        spin_lock(&uhci->lock);
 
        /* If the queue is now empty, we can unlink the QH and give up its
@@ -1556,23 +1565,16 @@ static void uhci_scan_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
                if (status == -EINPROGRESS)
                        break;
 
-               spin_lock(&urb->lock);
-               if (urb->status == -EINPROGRESS)        /* Not dequeued */
-                       urb->status = status;
-               else
-                       status = ECONNRESET;            /* Not -ECONNRESET */
-               spin_unlock(&urb->lock);
-
                /* Dequeued but completed URBs can't be given back unless
                 * the QH is stopped or has finished unlinking. */
-               if (status == ECONNRESET) {
+               if (urb->unlinked) {
                        if (QH_FINISHED_UNLINKING(qh))
                                qh->is_stopped = 1;
                        else if (!qh->is_stopped)
                                return;
                }
 
-               uhci_giveback_urb(uhci, qh, urb);
+               uhci_giveback_urb(uhci, qh, urb, status);
                if (status < 0)
                        break;
        }
@@ -1588,7 +1590,7 @@ static void uhci_scan_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
 restart:
        list_for_each_entry(urbp, &qh->queue, node) {
                urb = urbp->urb;
-               if (urb->status != -EINPROGRESS) {
+               if (urb->unlinked) {
 
                        /* Fix up the TD links and save the toggles for
                         * non-Isochronous queues.  For Isochronous queues,
@@ -1597,7 +1599,7 @@ restart:
                                qh->is_stopped = 0;
                                return;
                        }
-                       uhci_giveback_urb(uhci, qh, urb);
+                       uhci_giveback_urb(uhci, qh, urb, 0);
                        goto restart;
                }
        }