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

Reply via email to