]> Pileus Git - ~andy/linux/blobdiff - drivers/usb/dwc3/gadget.c
usb: dwc3: gadget: fix skip LINK_TRB on ISOC
[~andy/linux] / drivers / usb / dwc3 / gadget.c
index 356a5a2af75074c69bc5dc3baf935c47978875fe..da8d57cb00e8108a9289fb9acc515dd1b1800e2d 100644 (file)
@@ -754,21 +754,18 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
        struct dwc3             *dwc = dep->dwc;
        struct dwc3_trb         *trb;
 
-       unsigned int            cur_slot;
-
        dev_vdbg(dwc->dev, "%s: req %p dma %08llx length %d%s%s\n",
                        dep->name, req, (unsigned long long) dma,
                        length, last ? " last" : "",
                        chain ? " chain" : "");
 
-       trb = &dep->trb_pool[dep->free_slot & DWC3_TRB_MASK];
-       cur_slot = dep->free_slot;
-       dep->free_slot++;
-
        /* Skip the LINK-TRB on ISOC */
-       if (((cur_slot & DWC3_TRB_MASK) == DWC3_TRB_NUM - 1) &&
+       if (((dep->free_slot & DWC3_TRB_MASK) == DWC3_TRB_NUM - 1) &&
                        usb_endpoint_xfer_isoc(dep->endpoint.desc))
-               return;
+               dep->free_slot++;
+
+       trb = &dep->trb_pool[dep->free_slot & DWC3_TRB_MASK];
+       dep->free_slot++;
 
        if (!req->trb) {
                dwc3_gadget_move_request_queued(req);
@@ -1089,7 +1086,10 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
                 * notion of current microframe.
                 */
                if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
-                       dwc3_stop_active_transfer(dwc, dep->number);
+                       if (list_empty(&dep->req_queued)) {
+                               dwc3_stop_active_transfer(dwc, dep->number);
+                               dep->flags = DWC3_EP_ENABLED;
+                       }
                        return 0;
                }
 
@@ -1097,6 +1097,7 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
                if (ret && ret != -EBUSY)
                        dev_dbg(dwc->dev, "%s: failed to kick transfers\n",
                                        dep->name);
+               return ret;
        }
 
        /*
@@ -1113,6 +1114,7 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
                if (ret && ret != -EBUSY)
                        dev_dbg(dwc->dev, "%s: failed to kick transfers\n",
                                        dep->name);
+               return ret;
        }
 
        return 0;
@@ -1725,10 +1727,20 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep,
                        break;
        } while (1);
 
-       if (list_empty(&dep->req_queued) &&
-                       (dep->flags & DWC3_EP_MISSED_ISOC)) {
-               dwc3_stop_active_transfer(dwc, dep->number);
-               dep->flags &= ~DWC3_EP_MISSED_ISOC;
+       if (usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
+                       list_empty(&dep->req_queued)) {
+               if (list_empty(&dep->request_list)) {
+                       /*
+                        * If there is no entry in request list then do
+                        * not issue END TRANSFER now. Just set PENDING
+                        * flag, so that END TRANSFER is issued when an
+                        * entry is added into request list.
+                        */
+                       dep->flags = DWC3_EP_PENDING_REQUEST;
+               } else {
+                       dwc3_stop_active_transfer(dwc, dep->number);
+                       dep->flags = DWC3_EP_ENABLED;
+               }
                return 1;
        }