Self nak - I'll send a v2.
> If URB_ZERO_PACKET is set on a transfer that is an integral number
> of maximum length packets (1k for USB3 bulk) then an additional
> zero length fragment must be sent.
...
> if (urb->num_sgs == 0) {
> sg = NULL;
> addr = (u64)urb->transfer_dma;
> this_sg_len = urb->transfer_buffer_length;
> num_trbs = 0;
> } else {
> sg = urb->sg;
> addr = (u64)sg_dma_address(sg);
> this_sg_len = sg_dma_len(sg);
> /*
> * We only need an upper bound for the number of TRBs.
> * Add in two extra TRB for each subsequent segment.
> */
> num_trbs = (urb->num_mapped_sgs - 1) * 2;
> }
>
> /* One TRB for each 64k 'page' that contains data */
> num_trbs += DIV_ROUND_UP((addr & (TRB_MAX_BUFF_SIZE - 1)) +
> urb->transfer_buffer_length, TRB_MAX_BUFF_SIZE);
If a zero length transfer is requested from an aligned address the above
sets num_trbs to zero so the ring wrap check will be incorrect.
> max_packet = GET_MAX_PACKET(usb_endpoint_maxp(&urb->ep->desc));
>
> /*
> * For v 1.0 we need to calculate the number of TD needed to
> * complete the transfer.
> * The code here is equivalent to 4.11.2.4.
> */
> td_residue = urb->transfer_buffer_length;
> if (unlikely(urb->transfer_flags & URB_ZERO_PACKET)) {
Adding '|| unlikely(urb->transfer_buffer_length == 0)' here should fix it.
The td_residue value is irrelevant in this case.
> /* We need an extra zero length TD */
> num_trbs++;
> td_residue++;
> }
David
--
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