Re: [PATCH 2/3] usb: dwc3: gadget: Don't skip updating remaining data

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

 



On 8/1/2018 6:26 PM, Thinh Nguyen wrote:
> Hi Felipe,
>
>
> On 8/1/2018 1:33 AM, Felipe Balbi wrote:
>> Felipe Balbi <balbi@xxxxxxxxxx> writes:
>>
>>> Hi,
>>>
>>> Felipe Balbi <balbi@xxxxxxxxxx> writes:
>>>
>>> <snip>
>>>
>>>>> This is an issue, but it's not the same one.
>>>>>
>>>>>      irq/16-dwc3-5032  [003] d...    65.404194: dwc3_complete_trb:
>>>>> ep1out: trb 00000000890522d5 buf 00000000b8d6d000 size 0 ctrl 3b56446c
>>>>> (hlCS:Sc:isoc-first)
>>>>>
>>>> So this is chained to the next one, that's correct.
>>>>
>>>>
>>>>>      irq/16-dwc3-5032  [003] d...    65.404209: dwc3_complete_trb:
>>>>> ep1out: trb 00000000c15f388f buf 0000000037821000 size 1023 ctrl
>>>>> 3b564c78 (hlcS:SC:isoc)
>>>>>
>>>> But here, HWO should've been left as is, because of the short packet.
>>>> That's what the databook says on the two notes on section 8.2.3 after
>>>> table 8-8 of Databook 2.60a:
> My proposal doesn't change how we handle the TRB's HWO currently.
>
>>>> 1. When a TRB receives whose CSP bit is 0 and CHN bit is 1 receives a
>>>> short packet, the chained TRBs that follow it are not written back
>>>> (e.g. the BUFSIZ and HWO fields remain the same as the
>>>> software-prepared value)
>>>>
>>>> 2. In the case of an OUT endpoint, if the CHN bit is set (and CSP is
>>>> also set), and a short packet is received, the core retires the TRB in
>>>> progress and skip past the TRB where CHN=0, accumulating the ISP and
>>>> IOC bits from each TRB. If ISP or IOC is set in any TRB, the core
>>>> generates an XferInProgress event. Hardware does not set the HWO bit
>>>> to 0 in skipped TRBs. If the endpoint type is isochronous, the CHN=0
>>>> TRB will also be retired and its buffer size field updated with the
>>>> total number of bytes remaining in the BD.
>>>>
>>>> Note that at most we have confirmation that SIZE will be updated in
>>>> case of Isoc endpoints, but there's nothing there about HWO, so I
>>>> expected it to remain set according to the rest of the text.
>>>>
>>>> There's one possibility that "TRB will also be *retired*" means that
>>>> it's not skipped, which would mean that HWO is, indeed, set to 0. To
> Right. And the programming guide also says that for isoc OUT transfer,
> - Any non-first TRBs with CHN=1 that had not already been retired will
> not be written back. HWO will still be 1, and software can reclaim them
> for another transfer.
> - The last TRB of the Buffer Descriptor will be retired with:
>     * HWO = 0.
>     * BUFSIZ = The total remaining buffer size of the Buffer Descriptor.
>  
> So we know that the last isoc TRB will have CHN=0 and HWO=0.
>
>
>>>> patch that, however, we don't need all the extra checking you have
>>>> implemented. I'll try to propose a slightly simpler fix if you're
>>>> willing to test it out.
>>> Something like below:
>> and here's another possibility. This makes it clearer that we want to
>> skip all TRBs with CHN bit set:
>>
>> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
>> index 9ba614032d5d..56e2a2ebae66 100644
>> --- a/drivers/usb/dwc3/gadget.c
>> +++ b/drivers/usb/dwc3/gadget.c
>> @@ -2227,6 +2227,7 @@ static int dwc3_gadget_ep_reclaim_completed_trb(struct dwc3_ep *dep,
>>                 struct dwc3_request *req, struct dwc3_trb *trb,
>>                 const struct dwc3_event_depevt *event, int status, int chain)
>>  {
>> +       const struct usb_endpoint_descriptor *desc = dep->endpoint.desc;
>>         unsigned int            count;
>>  
>>         dwc3_ep_inc_deq(dep);
>> @@ -2256,6 +2257,16 @@ static int dwc3_gadget_ep_reclaim_completed_trb(struct dwc3_ep *dep,
>>                 return 1;
>>         }
>>  
>> +       /*
>> +        * In case of ISOC endpoints and Short or Zero packets, the
>> +        * last TRB will be retired and its size field will be updated
>> +        * to contain the full remaining size; meaning req->remaining
>> +        * will be count from the last TRB in the chain.
>> +        */
>> +       if ((req->zero || req->unaligned) && usb_endpoint_xfer_isoc(desc)
>> +                       && chain)
>> +               return 0;
>> +
>>         count = trb->size & DWC3_TRB_SIZE_MASK;
>>         req->remaining += count;
>>
> These patches will not fix the issue.
>

What do you think of this fix?

diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index f452ab708ffc..338f7ab8a8b4 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -2277,8 +2277,10 @@ static int
dwc3_gadget_ep_reclaim_completed_trb(struct dwc3_ep *dep,
         * with one TRB pending in the ring. We need to manually clear
HWO bit
         * from that TRB.
         */
-       if ((req->zero || req->unaligned) && (trb->ctrl &
DWC3_TRB_CTRL_HWO)) {
-               trb->ctrl &= ~DWC3_TRB_CTRL_HWO;
+       if ((req->zero || req->unaligned) && !chain) {
+               if (trb->ctrl & DWC3_TRB_CTRL_HWO)
+                       trb->ctrl &= ~DWC3_TRB_CTRL_HWO;
+
                return 1;
        }


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