xhci: v1.0 scatterlist enqueue support (td-fragment rework)
v1.0 hosts require that TD-fragments (portions of a TD that do not end
on a MPB boundary) not cross a TRB segment boundary. This constraint is
in addition to the constraint that a TRB may not specify a transfer that
crosses a 64K boundary. This enabling permits the driver to accept
scatterlists of nearly any geometry. "Nearly" because there is one
unlikely remaining degenerate case of a driver submitting a transfer
that consumes all the TRBs in a segment before hitting an MBP boundary.
That case is trapped and the transfer is rejected.
Given the multi-dimensional constraints of queuing TRBs from a
scattelist, this implementation does not attempt to pre-calculate the
number TRBs in a TD. Instead it attempts a dry-run of enqueuing the
TRBs to the ring. If it discovers a TD-fragment straddling a segment
boundary it backs up to the last MBP boundary, inserts a link-trb at
that boundary, and restarts enqueuing in the next segment. A side
effect of not pre-calculating the number of required TRBs is that the
ring is now expanded as the scatterlist is walked, rather than in
prepare_ring().
To simplify the math and forgo the need to track (union xhci_trb *) and
(struct xhci_segment *) pointers, modulo-power-of-2 ring indexes are
used. A small portion of the patch is adding infrastructure to convert
from a (struct xhci_ring_pointer *) to an integer index.
Glossary of acronyms:
TRB: Transfer Request Buffer, 16-byte xhci-hardware scatterlist entry
TD: Transfer Descriptor, the set of trbs that comprise a transfer
TRB segment: A contiguous allocation of TRBs. They are of size
PAGE_SIZE in the xhci driver. Each segment ends with a link TRB
pointing to the next segment, but the link trb may appear at any TRB
boundary in the segment.
Ring: A linked list of segments.
MBP: Max Burst Packet, is the minimum amount of data hardware expects to
transfer before the end of a segment (assuming the TD spans a segment
boundary).
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
3 files changed