Re: [PATCH v3 1/2] usb: dwc3: gadget: make starting isoc transfers more robust

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

 



On Tue, Jun 30, 2020 at 3:15 PM Michael Grzeschik <mgr@xxxxxxxxxxxxxx> wrote:
>
> On Mon, Jun 29, 2020 at 09:20:02PM +0000, Thinh Nguyen wrote:
> >Hi,
> >
> >Michael Grzeschik wrote:
> >> From: Michael Olbrich <m.olbrich@xxxxxxxxxxxxxx>
> >>
> >> Currently __dwc3_gadget_start_isoc must be called very shortly after
> >> XferNotReady. Otherwise the frame number is outdated and start transfer
> >> will fail, even with several retries.
> >>
> >> DSTS provides the lower 14 bit of the frame number. Use it in combination
> >> with the frame number provided by XferNotReady to guess the current frame
> >> number. This will succeed unless more than one 14 rollover has happened
> >> since XferNotReady.
> >>
> >> Start transfer might still fail if the frame number is increased
> >> immediately after DSTS is read. So retries are still needed.
> >> Don't drop the current request if this happens. This way it is not lost and
> >> can be used immediately to try again with the next frame number.
> >>
> >> With this change, __dwc3_gadget_start_isoc is still not successfully in all
> >> cases bit it increases the acceptable delay after XferNotReady
> >> significantly.
> >>
> >> Signed-off-by: Michael Olbrich <m.olbrich@xxxxxxxxxxxxxx>
> >> Signed-off-by: Michael Tretter <m.tretter@xxxxxxxxxxxxxx>
> >> Signed-off-by: Michael Grzeschik <m.grzeschik@xxxxxxxxxxxxxx>
> >>
> >> ---
> >> v1 -> v2: - removed last_frame_number from struct
> >>            - included rollover variable
> >> v2 -> v3: - moved the calculation before the retry loop
> >>            - skipping the calculation if bInterval > 14
> >>
> >>   drivers/usb/dwc3/gadget.c | 19 +++++++++++++++++++
> >>   1 file changed, 19 insertions(+)
> >>
> >> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
> >> index 8de6f10d335e1c0..7ad85a7d06f70bf 100644
> >> --- a/drivers/usb/dwc3/gadget.c
> >> +++ b/drivers/usb/dwc3/gadget.c
> >> @@ -1463,6 +1463,7 @@ static int dwc3_gadget_start_isoc_quirk(struct dwc3_ep *dep)
> >>
> >>   static int __dwc3_gadget_start_isoc(struct dwc3_ep *dep)
> >>   {
> >> +    const struct usb_endpoint_descriptor *desc = dep->endpoint.desc;
> >>      struct dwc3 *dwc = dep->dwc;
> >>      int ret;
> >>      int i;
> >> @@ -1480,6 +1481,24 @@ static int __dwc3_gadget_start_isoc(struct dwc3_ep *dep)
> >>                      return dwc3_gadget_start_isoc_quirk(dep);
> >>      }
> >>
> >> +    if (desc->bInterval <= 14) {
> >> +            u32 frame = __dwc3_gadget_get_frame(dwc);
> >> +            bool rollover = frame < (dep->frame_number & 0x3fff);
> >> +
> >> +            /*
> >> +             * frame_number is set from XferNotReady and may be already
> >> +             * out of date. DSTS only provides the lower 14 bit of the
> >> +             * current frame number. So add the upper two bits of
> >> +             * frame_number and handle a possible rollover.
> >> +             * This will provide the correct frame_number unless more than
> >> +             * rollover has happened since XferNotReady.
> >> +             */
> >> +
> >> +            dep->frame_number = (dep->frame_number & ~0x3fff) | frame;
> >> +            if (rollover)
> >> +                    dep->frame_number += BIT(14);
> >> +    }
> >> +
> >>      for (i = 0; i < DWC3_ISOC_MAX_RETRIES; i++) {
> >>              dep->frame_number = DWC3_ALIGN_FRAME(dep, i + 1);
> >>
> >
> >I think it's cleaner to create a mask for 0x3fff, but I can see how it
> >can arguably clearer for not using a macro also. It's fine to me either way.
>
> This mask is used on many usb controllers and
> everyone is defining their own.
>
> drivers/usb/gadget/udc/mv_udc.h
> 34:#define USB_FRINDEX_MASKS    0x3fff
>
> drivers/usb/gadget/udc/fsl_usb2_udc.h
> 116:#define     USB_FRINDEX_MASKS                       0x3fff
>
>
> Even other drivers using the mask without defining it:
>
> drivers/usb/misc/ftdi-elan.c
> 2224:   hc_fminterval &= 0x3fff;
> 2313:                              ((9 *hc_fminterval) / 10) & 0x3fff);
>
> drivers/usb/chipidea/udc.c
> 1634:   ret = hw_read(ci, OP_FRINDEX, 0x3fff);

Hi Michael,

I can't find the above code for chipidea, where did you get?
The frame index value register is a standard EHCI register,
but for UDC, it is not a common register. UDC design is varied
for vendors.

Peter

>
> drivers/usb/dwc3/gadget.c
> 1406:           test_frame_number = dep->frame_number & 0x3fff;
> 1453:   dep->frame_number &= 0x3fff;
>
> drivers/usb/host/ohci-hcd.c
> 557:            ohci->fminterval = val & 0x3fff;
>
> drivers/usb/host/xhci-ring.c
> 3980:   start_frame &= 0x3fff;
>
> drivers/usb/host/ohci-dbg.c
> 635:                    rdata & 0x3fff);
> 641:                    rdata & 0x3fff);
> 647:                    rdata & 0x3fff);
>
> drivers/usb/host/u132-hcd.c
> 1535:          ((9 * fi) / 10) & 0x3fff);
> 1605:           u132->hc_fminterval = temp & 0x3fff;
>
> drivers/usb/host/ohci.h
> 701:    ohci_writel (ohci, ((9 * fi) / 10) & 0x3fff,
>
> I could write a patch changing them all or at least
> make a common gadget define.
>
> What could be a common place for that?
>
> On device level only it could be include/linux/usb/gadget.h
> On whole usb level this could be include/uapi/linux/usb/ch9.h
>
> Ideas?
>
> >For both patches in this series:
> >Reviewed-by: Thinh Nguyen <thinhn@xxxxxxxxxxxx>
> >
> >Thanks,
> >Thinh
>
> Thanks!
> Michael
>
> --
> Pengutronix e.K.                           |                             |
> Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
> 31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |



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

  Powered by Linux