usb: dwc3: gadget: never pre-start Isochronous endpoints
authorFelipe Balbi <felipe.balbi@linux.intel.com>
Thu, 29 Sep 2016 12:44:29 +0000 (15:44 +0300)
committerFelipe Balbi <felipe.balbi@linux.intel.com>
Mon, 17 Oct 2016 08:14:00 +0000 (11:14 +0300)
We cannot pre-start isochronous endpoints because we
rely on the micro-frame number passed via
XferNotReady command for proper Isochronous
scheduling.

Fixes: 08a36b543803 ("usb: dwc3: gadget: simplify __dwc3_gadget_ep_queue()")
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
drivers/usb/dwc3/gadget.c

index 3c3ced1..f15147f 100644 (file)
@@ -1073,9 +1073,17 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
 
        list_add_tail(&req->list, &dep->pending_list);
 
-       if (usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
-                       dep->flags & DWC3_EP_PENDING_REQUEST) {
-               if (list_empty(&dep->started_list)) {
+       /*
+        * NOTICE: Isochronous endpoints should NEVER be prestarted. We must
+        * wait for a XferNotReady event so we will know what's the current
+        * (micro-)frame number.
+        *
+        * Without this trick, we are very, very likely gonna get Bus Expiry
+        * errors which will force us issue EndTransfer command.
+        */
+       if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
+               if ((dep->flags & DWC3_EP_PENDING_REQUEST) &&
+                               list_empty(&dep->started_list)) {
                        dwc3_stop_active_transfer(dwc, dep->number, true);
                        dep->flags = DWC3_EP_ENABLED;
                }