On 08/22/2014 08:16 PM, Dan Williams wrote:
> 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).
>
...
> }
>
> +static unsigned int xhci_ring_num_trbs_free(struct xhci_ring *ring)
> +{
> + unsigned int enq_idx, deq_idx, num_trbs, num_segs;
> +
> + enq_idx = xhci_ring_pointer_to_index(&ring->enq);
> + deq_idx = xhci_ring_pointer_to_index(&ring->deq);
> +
> + num_trbs = to_xhci_ring_index(ring, deq_idx - (enq_idx + 1));
> + num_segs = (enq_idx % TRBS_PER_SEGMENT + num_trbs) / TRBS_PER_SEGMENT;
> +
I'm don't really understand whats going on here. If we for example have a ring
with 3 segments, 256 trbs per segment.
enqueue is the first trb in seg3 and dequeue first trb in seg2.
enq_idx = 512
deq_idx = 256
deq_idq - (enq_idx + 1) = 256 - 513 = -xxx
Looks to me like to_xhci_ring_index() doesn't really like negative values
I feel that there's something clever going on here that I just can't figure out
-Mathias
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html