diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/host/ehci-sched.c | 92 |
1 files changed, 47 insertions, 45 deletions
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 85dd24e..208518b 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -1384,12 +1384,57 @@ iso_stream_schedule ( now = ehci_read_frame_index(ehci) & (mod - 1); - /* Typical case: reuse current schedule, stream is still active. + /* + * Need to schedule; when's the next (u)frame we could start? + * This is bigger than ehci->i_thresh allows; scheduling itself + * isn't free, the delay should handle reasonably slow cpus. It + * can also help high bandwidth if the dma and irq loads don't + * jump until after the queue is primed. + */ + if (unlikely(list_empty(&stream->td_list))) { + int done = 0; + + base = now & ~0x07; + start = base + SCHEDULING_DELAY; + + /* find a uframe slot with enough bandwidth. + * Early uframes are more precious because full-speed + * iso IN transfers can't use late uframes, + * and therefore they should be allocated last. + */ + next = start; + start += period; + do { + start--; + /* check schedule: enough space? */ + if (stream->highspeed) { + if (itd_slot_ok(ehci, mod, start, + stream->usecs, period)) + done = 1; + } else { + if ((start % 8) >= 6) + continue; + if (sitd_slot_ok(ehci, mod, stream, + start, sched, period)) + done = 1; + } + } while (start > next && !done); + + /* no room in the schedule */ + if (!done) { + ehci_dbg(ehci, "iso sched full %p", urb); + status = -ENOSPC; + goto fail; + } + } + + /* + * Typical case: reuse current schedule, stream is still active. * Hopefully there are no gaps from the host falling behind * (irq delays etc). If there are, the behavior depends on * whether URB_ISO_ASAP is set. */ - if (likely (!list_empty (&stream->td_list))) { + else { /* Take the isochronous scheduling threshold into account */ if (ehci->i_thresh) @@ -1436,49 +1481,6 @@ iso_stream_schedule ( start += base; } - /* need to schedule; when's the next (u)frame we could start? - * this is bigger than ehci->i_thresh allows; scheduling itself - * isn't free, the delay should handle reasonably slow cpus. it - * can also help high bandwidth if the dma and irq loads don't - * jump until after the queue is primed. - */ - else { - int done = 0; - - base = now & ~0x07; - start = base + SCHEDULING_DELAY; - - /* find a uframe slot with enough bandwidth. - * Early uframes are more precious because full-speed - * iso IN transfers can't use late uframes, - * and therefore they should be allocated last. - */ - next = start; - start += period; - do { - start--; - /* check schedule: enough space? */ - if (stream->highspeed) { - if (itd_slot_ok(ehci, mod, start, - stream->usecs, period)) - done = 1; - } else { - if ((start % 8) >= 6) - continue; - if (sitd_slot_ok(ehci, mod, stream, - start, sched, period)) - done = 1; - } - } while (start > next && !done); - - /* no room in the schedule */ - if (!done) { - ehci_dbg(ehci, "iso sched full %p", urb); - status = -ENOSPC; - goto fail; - } - } - /* Tried to schedule too far into the future? */ if (unlikely(start - base + span - period >= mod)) { ehci_dbg(ehci, "request %p would overflow (%u+%u >= %u)\n", |