X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fusb%2Fhost%2Fuhci-q.c;h=db645936eedd3b5f8f5aff71a9eee85a12223757;hb=b312bf359e20cc39c00d480fd40a24c245d80bf7;hp=bab5672665597b29f28ea6c6b3f7b3c948fba1d9;hpb=eb23105462304fd35571fd0cab1de7aec79a9ec5;p=linux-2.6 diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index bab5672665..db645936ee 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -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,10 +1565,6 @@ static void uhci_scan_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) if (status == -EINPROGRESS) break; - spin_lock(&urb->lock); - urb->status = status; - spin_unlock(&urb->lock); - /* Dequeued but completed URBs can't be given back unless * the QH is stopped or has finished unlinking. */ if (urb->unlinked) { @@ -1569,7 +1574,7 @@ static void uhci_scan_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) return; } - uhci_giveback_urb(uhci, qh, urb); + uhci_giveback_urb(uhci, qh, urb, status); if (status < 0) break; } @@ -1594,7 +1599,7 @@ restart: qh->is_stopped = 0; return; } - uhci_giveback_urb(uhci, qh, urb); + uhci_giveback_urb(uhci, qh, urb, 0); goto restart; } }