Hi Michael, Michael Olbrich wrote: > Currently, most gadget drivers handle isoc transfers on a best effort > bases: If the request queue runs empty, then there will simply be gaps in > the isoc data stream. > > The UVC gadget depends on this behaviour. It simply provides new requests > when video frames are available and assumes that they are sent as soon as > possible. > > The dwc3 gadget currently works differently: It assumes that there is a > contiguous stream of requests without any gaps. If a request is too late, > then it is dropped by the hardware. > For the UVC gadget this means that a live stream stops after the first > frame because all following requests are late. Can you explain little more how UVC gadget fails? dwc3 controller expects a steady stream of data otherwise it will result in missed_isoc status, and it should be fine as long as new requests are queued. The controller doesn't just drop the request unless there's some other failure. > This patch changes the behaviour of the dwc3 gadget driver to match the > expectations. If a request arrives too late, then the transfer will be > restart to create the needed gap. > > A request is late if: > 1. There are currently no requests queued in the hardware > 2. The current frame number provided by DSTS does not match the frame > number returned by the last transfer. > > If this happens transfers are stopped. The following XferNotReady provides > the new correct frame number and restarts the transfer. > > Signed-off-by: Michael Olbrich <m.olbrich@xxxxxxxxxxxxxx> > --- > drivers/usb/dwc3/gadget.c | 8 ++++++++ > 1 file changed, 8 insertions(+) > > diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c > index ac4673d91939..eb7f09929f28 100644 > --- a/drivers/usb/dwc3/gadget.c > +++ b/drivers/usb/dwc3/gadget.c > @@ -1473,6 +1473,14 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) > return __dwc3_gadget_start_isoc(dep); > } > } > + if ((dep->flags & DWC3_EP_TRANSFER_STARTED) && > + list_empty(&dep->started_list) && > + ((dep->frame_number & 0x3fff) != > + __dwc3_gadget_get_frame(dwc))) { > + dwc3_stop_active_transfer(dep, true, true); > + dep->flags = DWC3_EP_ENABLED; > + return 0; > + } > } > > return __dwc3_gadget_kick_transfer(dep, false); BR, Thinh