RE: [PATCH v2] usb: cdnsp: fix issue with ZLP - added TD_SIZE = 1

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



>
>
>On 22-10-27 08:46:17, Pawel Laszczak wrote:
>>
>> >
>> >On 22-10-24 10:04:35, Pawel Laszczak wrote:
>> >> Patch modifies the TD_SIZE in TRB before ZLP TRB.
>> >> The TD_SIZE in TRB before ZLP TRB must be set to 1 to force
>> >> processing ZLP TRB by controller.
>> >>
>> >> cc: <stable@xxxxxxxxxxxxxxx>
>> >> Fixes: 3d82904559f4 ("usb: cdnsp: cdns3 Add main part of Cadence
>> >> USBSSP DRD Driver")
>> >> Signed-off-by: Pawel Laszczak <pawell@xxxxxxxxxxx>
>> >>
>> >> ---
>> >> Changelog:
>> >> v2:
>> >> - returned value for last TRB must be 0
>> >>
>> >>  drivers/usb/cdns3/cdnsp-ring.c | 7 ++++++-
>> >>  1 file changed, 6 insertions(+), 1 deletion(-)
>> >>
>> >> diff --git a/drivers/usb/cdns3/cdnsp-ring.c
>> >> b/drivers/usb/cdns3/cdnsp-ring.c index 04dfcaa08dc4..aa79bce89d8a
>> >> 100644
>> >> --- a/drivers/usb/cdns3/cdnsp-ring.c
>> >> +++ b/drivers/usb/cdns3/cdnsp-ring.c
>> >> @@ -1769,8 +1769,13 @@ static u32 cdnsp_td_remainder(struct
>> >> cdnsp_device *pdev,
>> >>
>> >>  	/* One TRB with a zero-length data packet. */
>> >>  	if (!more_trbs_coming || (transferred == 0 && trb_buff_len == 0) ||
>> >> -	    trb_buff_len == td_total_len)
>> >> +	    trb_buff_len == td_total_len) {
>> >> +		/* Before ZLP driver needs set TD_SIZE=1. */
>> >> +		if (more_trbs_coming)
>> >> +			return 1;
>> >> +
>> >>  		return 0;
>> >> +	}
>> >
>> >Does that fix the issue you want at bulk transfer, which has
>> >zero-length packet at the last packet? It seems not align with your previous
>fix.
>> >Would you mind explaining more?
>>
>> Value returned by function cdnsp_td_remainder is used as TD_SIZE in
>> TRB.
>>
>> The last TRB in TD should have TD_SIZE=0, so trb for ZLP should have
>> set also TD_SIZE=0. If driver set TD_SIZE=0 on before the last one TRB
>> then the controller stops the transfer and ignore trb for ZLP packet.
>>
>> To fix this, the driver in such case must set TD_SIZE = 1 before the
>> last TRB.
>
>  	if (!more_trbs_coming || (transferred == 0 && trb_buff_len == 0) ||
> -	    trb_buff_len == td_total_len)
> +	    trb_buff_len == td_total_len) {
> +		/* Before ZLP driver needs set TD_SIZE=1. */
> +		if (more_trbs_coming)
> +			return 1;
> +
>  		return 0;
> +	}
>
>How your above fix could return TD_SIZE as 1 for last non-ZLP TRB?
>Which conditions are satisfied?

For last non-ZLP TRB TD_SIZE should be 0 or 1.

We have three casess: 
1.  
	TRB1 - length > 1
	TRb2 - ZLP

In this case TRB1 should have set TD_SIZE = 1. In this case the condition
	if (more_trbs_coming)
		return 1;

returns TD_SIZE=1. In this case more_trb_comming for TRB1 is 1 and for TRB2 is 0


2. 
	TRB1 - length >1 and we don't except ZLP

In this case TD_SIZE should be set to 0 for TRB1 and function returns 0, more_trbs_comming for TRB1 will be set to 0.

3 More TRBs without ZLP:
	e.g.
	TRB1  -  length > 0,  more_trbs_comming = 1 - TD_SIZE  > 0
	TRB2 -  length > 0, more_trbs_comming = 1  - TD_SIZE > 0
	TRB3 - length >= 0, more_trbs_comming = 0 -  TD_SIZE  = 0

Pawel

>
>Peter
>
>> e.g.
>>
>> TD -> TRB1  transfer_length = 64KB, TD_SIZE =0
>>           TRB2 transfer_length =0, TD_SIZE = 0  - controller will
>> 		    ignore this transfer and stop transfer on previous one
>>
>> TD -> TRB1  transfer_length = 64KB, TD_SIZE =1
>>           TRB2 transfer_length =0, TD_SIZE = 0  - controller will
>> 		    execute this trb and send ZLP
>>
>> As you noticed previously, previous fix for last TRB returned TD_SIZE
>> = 1 in some cases.
>> Previous fix was working correct but was not compliance with
>> controller specification.
>>
>> >
>> >>
>> >>  	maxp = usb_endpoint_maxp(preq->pep->endpoint.desc);
>> >>  	total_packet_count = DIV_ROUND_UP(td_total_len, maxp);
>> >> --
>> >> 2.25.1
>> >>
>> >
>> >--
>> >
>>
>> Thanks,
>> Pawel Laszczak
>
>--
>
>Thanks,
>Peter Chen

Regards,
Pawel Laszczak 




[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux