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]

 



Hi,

John Youn <John.Youn@xxxxxxxxxxxx> writes:
> 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.

thanks :-)

>>> 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.

oh, you're right. I completely missed the case were gadget driver fills
up the ring in one go.

> 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.

right

>> 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.

okay.

>>> 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);

I like dwc3_prev_trb(), actually.

-- 
balbi

Attachment: signature.asc
Description: PGP signature


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

  Powered by Linux