Hi,

John Youn <john.y...@synopsys.com> writes:
> On 5/19/2016 12:51 AM, Felipe Balbi wrote:
>> 
>> Hi,
>> 
>> John Youn <johny...@synopsys.com> 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 <johny...@synopsys.com>
>>> ---
>>>  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

Reply via email to