diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-11 14:48:20 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-11 14:48:20 -0800 |
commit | 414a6750e59b0b687034764c464e9ddecac0f7a6 (patch) | |
tree | 18a5ceb11359cd72fcb2d31b5eabf3e35328697f /drivers/usb/host/uhci-q.c | |
parent | c6bd5bcc4983f1a2d2f87a3769bf309482ee8c04 (diff) | |
parent | fb37ef98015f864d22be223a0e0d93547cd1d4ef (diff) |
Merge tag 'usb-3.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB patches from Greg Kroah-Hartman:
"Here's the big set of USB patches for 3.8-rc1.
Lots of USB host driver cleanups in here, and a bit of a reorg of the
EHCI driver to make it easier for the different EHCI platform drivers
to all work together nicer, which was a reduction in overall code. We
also deleted some unused firmware files, and got rid of the very old
file_storage usb gadget driver that had been broken for a long time.
This means we ended up removing way more code than added, always a
nice thing to see:
310 files changed, 3028 insertions(+), 10754 deletions(-)
Other than that, the usual set of new device ids, driver fixes, gadget
driver and controller updates and the like.
All of these have been in the linux-next tree for a number of weeks.
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>"
* tag 'usb-3.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (228 commits)
USB: mark uas driver as BROKEN
xhci: Add Lynx Point LP to list of Intel switchable hosts
uwb: fix uwb_dev_unlock() missed at an error path in uwb_rc_cmd_async()
USB: ftdi_sio: Add support for Newport AGILIS motor drivers
MAINTAINERS: remove drivers/block/ub.c
USB: chipidea: fix use after free bug
ezusb: add dependency to USB
usb: ftdi_sio: fixup BeagleBone A5+ quirk
USB: cp210x: add Virtenio Preon32 device id
usb: storage: remove redundant memset() in usb_probe_stor1()
USB: option: blacklist network interface on Huawei E173
USB: OHCI: workaround for hardware bug: retired TDs not added to the Done Queue
USB: add new zte 3g-dongle's pid to option.c
USB: opticon: switch to generic read implementation
USB: opticon: refactor reab-urb processing
USB: opticon: use usb-serial bulk-in urb
USB: opticon: increase bulk-in size
USB: opticon: use port as urb context
USB: opticon: pass port to get_serial_info
USB: opticon: make private data port specific
...
Diffstat (limited to 'drivers/usb/host/uhci-q.c')
-rw-r--r-- | drivers/usb/host/uhci-q.c | 73 |
1 files changed, 36 insertions, 37 deletions
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index d2c6f5ac4626..15921fd55048 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -1256,7 +1256,8 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb, 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(struct uhci_hcd *uhci, struct urb *urb, 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(struct uhci_hcd *uhci, struct urb *urb, 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); |