Re: [PATCH 2/2] usb: dwc3: gadget: Various fixes to trbs_left calculation

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

 



On 5/19/2016 12:51 AM, Felipe Balbi wrote:
> 
> Hi,
> 
> John Youn <johnyoun@xxxxxxxxxxxx> writes:
>> This patch fixes up some issues related to the trb_left calculation.
>>
>> This calculation sometimes included the link trb slot in the trbs_left
>> and sometimes didn't.
> 
> good catch. But this patch seems like it can be broken into smaller
> pieces. See below

Ok, I can split it up.

> 
>> In the case where the dequeue < enqueue, this number does not include
>> the link trb and should be used as-is. Otherwise it will include the
>> link_trb and should be decremented to reflect the actual amount of free
>> trb slots. The fixed calculation will be the proper amount of free TRB
>> slots left, taking into account whether a link TRB takes up one of the
>> slots.
> 
> this is one fix :-)
> 
>> When checking for full or empty where enqueue == dequeue, the pointer
>> may be 0. In that case previous TRB is the one before the link TRB. Use
>> that to check the HWO bit to see if we are full or empty.
> 
> if enqueue == dequeue, we could be anywhere in the ring. So previous TRB
> might not be the one before the link. Care to further explain this case?

The enqueue and dequeue can both be 0 and full and index 0 is treated
just like any other index in the ring. That has to be the case as
whenever we increment we don't ever point to a link TRB. We pretend it
doesn't exist and that it is just a 255-TRB circular queue. How we end
up full at index 0 is that they are both initially 0, then we enqueue
255 TRBs without the hardware getting a chance to process anything
yet. The enqueue will wrap and point to 0 again, and then it will be
full.

We check for empty/full in the same way, except that at index 0, when
we look at the previous TRB, we must wrap around backwards, skip the
link trb, and look at the TRB prior to the link TRB.

> 
> It's also a separate fix, btw.
> 
>> In case DWC3_TRB_NUM is ever set lower than 256, mod trbs_left result by
>> DWC3_TRB_NUM.
> 
> I don't get this. Where did we have % 256? I can only see % DWC3_TRB_NUM.

Right. That was taken care of in the trb_enqueue/deqeuue increment
functions. But it also needs to be accounted for in the trbs_left
calculation which was just returning (trb->dequeue - trb->enqueue).

For example if you queue one trb the calculation would
0x00 - 0x01 = 0xFF (255), minus 1 for link trb = 254 TRB slots
free. But if DWC3_TRB_NUM = 8, then I have 254 % 8 = 6 slots free.


> 
>> In dwc3_prepare_trbs, if trbs_left is 0, do nothing and return early.
> 
> another fix.
> 
>> When an EP is enabled, initialized the TRB pool to clean up any stale
>> data. When the previous TRB was not properly cleaned up on disconnect,
>> the empty/full checking logic sometimes failed causing the EP to stop
>> processing requests.
> 
> another fix.
> 
>> Signed-off-by: John Youn <johnyoun@xxxxxxxxxxxx>
>> ---
>>  drivers/usb/dwc3/gadget.c | 37 ++++++++++++++++++++++++++++++-------
>>  1 file changed, 30 insertions(+), 7 deletions(-)
>>
>> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
>> index 3eaef22..a76634b 100644
>> --- a/drivers/usb/dwc3/gadget.c
>> +++ b/drivers/usb/dwc3/gadget.c
>> @@ -561,6 +561,12 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep,
>>  		if (usb_endpoint_xfer_control(desc))
>>  			goto out;
>>  
>> +		/* Initialize the TRB pool */
>> +		dep->trb_dequeue = 0;
>> +		dep->trb_enqueue = 0;
>> +		memset(dep->trb_pool, 0,
>> +		       sizeof(struct dwc3_trb) * DWC3_TRB_NUM);
> 
> this is a separate fix. A very good one, actually ;-)
> 
>>  		/* Link TRB. The HWO bit is never reset */
>>  		trb_st_hw = &dep->trb_pool[0];
>>  
>> @@ -849,6 +855,8 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
>>  static u32 dwc3_calc_trbs_left(struct dwc3_ep *dep)
>>  {
>>  	struct dwc3_trb		*tmp;
>> +	u8			tmp_index;
>> +	u8			trbs_left;
>>  
>>  	/*
>>  	 * If enqueue & dequeue are equal than it is either full or empty.
>> @@ -858,17 +866,29 @@ static u32 dwc3_calc_trbs_left(struct dwc3_ep *dep)
>>  	 * more transfers in our ring.
>>  	 */
>>  	if (dep->trb_enqueue == dep->trb_dequeue) {
>> -		/* If we're full, enqueue/dequeue are > 0 */
>> -		if (dep->trb_enqueue) {
>> -			tmp = &dep->trb_pool[dep->trb_enqueue - 1];
>> -			if (tmp->ctrl & DWC3_TRB_CTRL_HWO)
>> -				return 0;
>> -		}
>> +		if (!dep->trb_enqueue)
>> +			/*
>> +			 * The TRB just before the zeroth one is the
>> +			 * one just before the LINK TRB.
>> +			 */
>> +			tmp_index = DWC3_TRB_NUM - 2;
> 
> this seems wrong. If both enqueue and dequeue are 0, it means our entire
> ring is empty, and we can use (by default) 255 TRBs, with one space left
> for the link. This DWC3_TRB_NUM - 2 will give me 254, instead of 255.
> 

See above explanation. Though this could be simplified so that the
handling of index 0 is enclosed in a function like:

   trb = dwc3_prev_trb(dep, dep->enqueue);


Regards,
John
--
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



[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux