static void periodic_tt_usecs ( struct ehci_hcd *ehci, struct usb_device *dev, unsigned frame, unsigned short tt_usecs[8] ) { __hc32 *hw_p = &ehci->periodic [frame]; union ehci_shadow *q = &ehci->pshadow [frame]; unsigned char uf; memset(tt_usecs, 0, 16); while (q->ptr) { switch (hc32_to_cpu(ehci, Q_NEXT_TYPE(ehci, *hw_p))) { case Q_TYPE_ITD: hw_p = &q->itd->hw_next; q = &q->itd->itd_next; continue; case Q_TYPE_QH: if (same_tt(dev, q->qh->dev)) { uf = tt_start_uframe(ehci, q->qh->hw->hw_info2); tt_usecs[uf] += q->qh->tt_usecs; } hw_p = &q->qh->hw->hw_next; q = &q->qh->qh_next; continue; case Q_TYPE_SITD: if (same_tt(dev, q->sitd->urb->dev)) { uf = tt_start_uframe(ehci, q->sitd->hw_uframe); tt_usecs[uf] += q->sitd->stream->tt_usecs; } hw_p = &q->sitd->hw_next; q = &q->sitd->sitd_next; continue; default: ehci_dbg(ehci, "ignoring periodic frame %d FSTN\n", frame); hw_p = &q->fstn->hw_next; q = &q->fstn->fstn_next; } } carryover_tt_bandwidth(tt_usecs); if (max_tt_usecs[7] < tt_usecs[7]) ehci_err(ehci, "frame %d tt sched overrun: %d usecs\n", frame, tt_usecs[7] - max_tt_usecs[7]); }
/* return true iff the device's transaction translator is available * for a periodic transfer starting at the specified frame, using * all the uframes in the mask. */ static int tt_no_collision ( struct ehci_hcd *ehci, unsigned period, struct usb_device *dev, unsigned frame, u32 uf_mask ) { if (period == 0) /* error */ return 0; /* note bandwidth wastage: split never follows csplit * (different dev or endpoint) until the next uframe. * calling convention doesn't make that distinction. */ for (; frame < ehci->periodic_size; frame += period) { union ehci_shadow here; __le32 type; here = ehci->pshadow [frame]; type = Q_NEXT_TYPE (ehci->periodic [frame]); while (here.ptr) { switch (type) { case Q_TYPE_ITD: type = Q_NEXT_TYPE (here.itd->hw_next); here = here.itd->itd_next; continue; case Q_TYPE_QH: if (same_tt (dev, here.qh->dev)) { u32 mask; mask = le32_to_cpu (here.qh->hw_info2); /* "knows" no gap is needed */ mask |= mask >> 8; if (mask & uf_mask) break; } type = Q_NEXT_TYPE (here.qh->hw_next); here = here.qh->qh_next; continue; case Q_TYPE_SITD: if (same_tt (dev, here.itd->urb->dev)) { u16 mask; mask = le32_to_cpu (here.sitd ->hw_uframe); /* FIXME assumes no gap for IN! */ mask |= mask >> 8; if (mask & uf_mask) break; } type = Q_NEXT_TYPE (here.qh->hw_next); here = here.sitd->sitd_next; continue; // case Q_TYPE_FSTN: default: ehci_dbg (ehci, "periodic frame %d bogus type %d\n", frame, type); } /* collision or error */ return 0; }
static int tt_no_collision ( struct ehci_hcd *ehci, unsigned period, struct usb_device *dev, unsigned frame, u32 uf_mask ) { if (period == 0) return 0; for (; frame < ehci->periodic_size; frame += period) { union ehci_shadow here; __hc32 type; struct ehci_qh_hw *hw; here = ehci->pshadow [frame]; type = Q_NEXT_TYPE(ehci, ehci->periodic [frame]); while (here.ptr) { switch (hc32_to_cpu(ehci, type)) { case Q_TYPE_ITD: type = Q_NEXT_TYPE(ehci, here.itd->hw_next); here = here.itd->itd_next; continue; case Q_TYPE_QH: hw = here.qh->hw; if (same_tt (dev, here.qh->dev)) { u32 mask; mask = hc32_to_cpu(ehci, hw->hw_info2); mask |= mask >> 8; if (mask & uf_mask) break; } type = Q_NEXT_TYPE(ehci, hw->hw_next); here = here.qh->qh_next; continue; case Q_TYPE_SITD: if (same_tt (dev, here.sitd->urb->dev)) { u16 mask; mask = hc32_to_cpu(ehci, here.sitd ->hw_uframe); mask |= mask >> 8; if (mask & uf_mask) break; } type = Q_NEXT_TYPE(ehci, here.sitd->hw_next); here = here.sitd->sitd_next; continue; default: ehci_dbg (ehci, "periodic frame %d bogus type %d\n", frame, type); } return 0; }