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