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 majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html