[PATCH] xhci: create one unified function to calculate TRB TD remainder.

Mathias Nyman mathias.nyman at linux.intel.com
Tue Oct 6 06:48:32 PDT 2015


On 11.09.2015 07:08, chunfeng yun wrote:
> Hi,
> On Tue, 2015-09-08 at 14:09 +0300, Mathias Nyman wrote:
>> xhci versions 1.0 and later report the untransferred data remaining in a
>> TD a bit differently than older hosts.
>>
>> We used to have separate functions for these, and needed to check host
>>   version before calling the right function.
>>
>> Now Mediatek host has an additional quirk on how it uses the TD Size
>> field for remaining data. To prevent yet another function for calculating
>> remainder we instead want to make one quirk friendly unified function.
>>
>> Signed-off-by: Mathias Nyman <mathias.nyman at linux.intel.com>
>> ---
>>   drivers/usb/host/xhci-ring.c | 106 ++++++++++++++++++-------------------------
>>   drivers/usb/host/xhci.h      |   2 +
>>   2 files changed, 46 insertions(+), 62 deletions(-)
>>
>> diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
>> index a47a1e8..57f40a1 100644
>> --- a/drivers/usb/host/xhci-ring.c
>> +++ b/drivers/usb/host/xhci-ring.c
>> @@ -3020,21 +3020,6 @@ int xhci_queue_intr_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
>>   }
>>
>>   /*
>> - * The TD size is the number of bytes remaining in the TD (including this TRB),
>> - * right shifted by 10.
>> - * It must fit in bits 21:17, so it can't be bigger than 31.
>> - */
>> -static u32 xhci_td_remainder(unsigned int remainder)
>> -{
>> -	u32 max = (1 << (21 - 17 + 1)) - 1;
>> -
>> -	if ((remainder >> 10) >= max)
>> -		return max << 17;
>> -	else
>> -		return (remainder >> 10) << 17;
>> -}
>> -
>> -/*
>>    * For xHCI 1.0 host controllers, TD size is the number of max packet sized
>>    * packets remaining in the TD (*not* including this TRB).
>>    *
>> @@ -3046,30 +3031,36 @@ static u32 xhci_td_remainder(unsigned int remainder)
>>    *
>>    * TD size = total_packet_count - packets_transferred
>>    *
>> - * It must fit in bits 21:17, so it can't be bigger than 31.
>> + * For xHCI 0.96 and older, TD size field should be the remaining bytes
>> + * including this TRB, right shifted by 10
>> + *
>> + * For all hosts it must fit in bits 21:17, so it can't be bigger than 31.
>> + * This is taken care of in the TRB_TD_SIZE() macro
>> + *
>>    * The last TRB in a TD must have the TD size set to zero.
>>    */
>> -static u32 xhci_v1_0_td_remainder(int running_total, int trb_buff_len,
>> -		unsigned int total_packet_count, struct urb *urb,
>> -		unsigned int num_trbs_left)
>> +static u32 xhci_td_remainder(struct xhci_hcd *xhci, int transferred,
>> +			      int trb_buff_len, unsigned int td_total_len,
>> +			      struct urb *urb, unsigned int num_trbs_left)
>>   {
>> -	int packets_transferred;
>> +	u32 maxp, total_packet_count;
>> +
>> +	if (xhci->hci_version < 0x100)
>> +		return ((td_total_len - transferred) >> 10);
>> +
>> +	maxp = GET_MAX_PACKET(usb_endpoint_maxp(&urb->ep->desc));
>> +	total_packet_count = DIV_ROUND_UP(td_total_len, maxp);
>>
>>   	/* One TRB with a zero-length data packet. */
>> -	if (num_trbs_left == 0 || (running_total == 0 && trb_buff_len == 0))
>> +	if (num_trbs_left == 0 || (transferred == 0 && trb_buff_len == 0) ||
>> +	    trb_buff_len == td_total_len)
>>   		return 0;
>>
> I think when trb_buff_len == td_total_len, the TD only needs one trb, so
> num_trbs_left will equal to 0; that means no need add this condition.
>

Sorry about the really long delay, I had to focus on other things for a while.

You're right, but I didn't want to change the functionality of the old code.

For some reason the old code called xhci_td_remainder() for both older (0.9)
and newer (>= 1.0) xhci hosts in the control transfer case.
I wanted the outcome to stay the same as with the old code, With the old code the
TD size of a control tranfers was usually 0, without the additional
check we would end up with a remainder of "1". (as num_trbs_left is one)

This should enable easier TD size quirking for control transfers

I'll add the tested-by tag you sent in a later mail

-Mathias



More information about the Linux-mediatek mailing list