Hi Peter, On Wed, Jul 01, 2020 at 10:26:56AM +0800, Peter Chen wrote:
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?
I was greping my usb-wip stack where I have an extra Patch for the get_frame callback implementation of the chipidea/udc.c. I think I will have to post it.
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.
Good to know. Is there any measure to find out if it is there? I would add that limitation to the above mentioned patch. Thanks, Michael
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 |
-- 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 |
Attachment:
signature.asc
Description: PGP signature