On Mon, May 27, 2019 at 5:04 PM Sergei Shtylyov <sergei.shtylyov@xxxxxxxxxxxxxxxxxx> wrote: > > On 27.05.2019 10:42, Peter Chen wrote: > > > An endpoint conflict occurs when the USB is working in device mode > > during an isochronous communication. When the endpointA IN direction > > is an isochronous IN endpoint, and the host sends an IN token to > > endpointA on another device, then the OUT transaction may be missed > > regardless the OUT endpoint number. Generally, this occurs when the > > device is connected to the host through a hub and other devices are > > connected to the same hub. > > > > The affected OUT endpoint can be either control, bulk, isochronous, or > > an interrupt endpoint. After the OUT endpoint is primed, if an IN token > > to the same endpoint number on another device is received, then the OUT > > endpoint may be unprimed (cannot be detected by software), which causes > > this endpoint to no longer respond to the host OUT token, and thus, no > > corresponding interrupt occurs. > > > > There is no good workaround for this issue, the only thing the software > > could do is numbering isochronous IN from the highest endpoint since we > > have observed most of device number endpoint from the lowest. > > > > Cc: <stable@xxxxxxxxxxxxxxx> #v3.14+ > > Cc: Jun Li <jun.li@xxxxxxx> > > Signed-off-by: Peter Chen <peter.chen@xxxxxxx> > > --- > > drivers/usb/chipidea/udc.c | 24 ++++++++++++++++++++++++ > > 1 file changed, 24 insertions(+) > > > > diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c > > index 829e947cabf5..411d387a45c9 100644 > > --- a/drivers/usb/chipidea/udc.c > > +++ b/drivers/usb/chipidea/udc.c > > @@ -1622,6 +1622,29 @@ static int ci_udc_pullup(struct usb_gadget *_gadget, int is_on) > > static int ci_udc_start(struct usb_gadget *gadget, > > struct usb_gadget_driver *driver); > > static int ci_udc_stop(struct usb_gadget *gadget); > > + > > + > > +/* Match ISOC IN from the highest endpoint */ > > +static struct > > Um, please break the line before the function's type is fully described. > > > +usb_ep *ci_udc_match_ep(struct usb_gadget *gadget, > > + struct usb_endpoint_descriptor *desc, > > + struct usb_ss_ep_comp_descriptor *comp_desc) > > +{ > > + struct ci_hdrc *ci = container_of(gadget, struct ci_hdrc, gadget); > > + struct usb_ep *ep; > > + u8 type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; > > + > > + if ((type == USB_ENDPOINT_XFER_ISOC) && > > + (desc->bEndpointAddress & USB_DIR_IN)) { > > Please add 1 more tab here, so that this line doesn't blend with the > following statement. > > > + list_for_each_entry_reverse(ep, &ci->gadget.ep_list, ep_list) { > > + if (ep->caps.dir_in && !ep->claimed) > > + return ep; > > + } > > + } > > + > > + return NULL; > > +} > > + > > /** > > * Device operations part of the API to the USB controller hardware, > > * which don't involve endpoints (or i/o) Will change both comments, thanks. Peter