Message ID | 20200701093137.19485-3-m.grzeschik@pengutronix.de (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | usb: dwc3: gadget: improve isoc handling | expand |
Michael Grzeschik wrote: > From: Michael Olbrich <m.olbrich@pengutronix.de> > > 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. > > Reviewed-by: Thinh Nguyen <thinhn@synopsys.com> > Signed-off-by: Michael Olbrich <m.olbrich@pengutronix.de> > Signed-off-by: Michael Tretter <m.tretter@pengutronix.de> > Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de> > > --- > 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 > v3 -> v4: - used define for 0x3fff framenumber mask > - added limitation for this to usb > fullspeed > > drivers/usb/dwc3/gadget.c | 22 ++++++++++++++++++++++ > 1 file changed, 22 insertions(+) > > diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c > index 5fb78535efa9bdc..a2145f905d67067 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,27 @@ static int __dwc3_gadget_start_isoc(struct dwc3_ep *dep) > return dwc3_gadget_start_isoc_quirk(dep); > } > > + if (desc->bInterval <= 14 && > + dwc->gadget.speed >= USB_SPEED_SUPER) { Highspeed is still applicable. Just ignore fullspeed. > + u32 frame = __dwc3_gadget_get_frame(dwc); > + bool rollover = frame < > + (dep->frame_number & DWC3_FRNUMBER_MASK); > + > + /* > + * 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 & ~DWC3_FRNUMBER_MASK) | > + 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); > BR, Thinh
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 5fb78535efa9bdc..a2145f905d67067 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,27 @@ static int __dwc3_gadget_start_isoc(struct dwc3_ep *dep) return dwc3_gadget_start_isoc_quirk(dep); } + if (desc->bInterval <= 14 && + dwc->gadget.speed >= USB_SPEED_SUPER) { + u32 frame = __dwc3_gadget_get_frame(dwc); + bool rollover = frame < + (dep->frame_number & DWC3_FRNUMBER_MASK); + + /* + * 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 & ~DWC3_FRNUMBER_MASK) | + 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);