There are two reasons to generate missed isoc.

1. when the host does not poll for all the data.
2. because of application-side delays that prevent all the data from
being transferred in programmed microframe.

Current code was able to handle first case only.  Now we take following
approach to handle missed isoc.

If missed isoc occurred and there is no request queued then issue END
TRANSFER, so that core generates next xfernotready and we will issue a
fresh START TRANSFER.
If there are still queued request then wait, do not issue either END or
UPDATE TRANSFER, just attach next request in request_list during giveback.
If any future queued request is successfully transferred then we will issue
UPDATE TRANSFER for all request in the request_list.

Signed-off-by: Pratyush Anand <pratyush.an...@st.com>
---
 drivers/usb/dwc3/core.h   |    1 -
 drivers/usb/dwc3/gadget.c |   36 ++++++++++++++++++++++++------------
 2 files changed, 24 insertions(+), 13 deletions(-)

diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 4470c6f..916a4bf 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -439,7 +439,6 @@ struct dwc3_ep {
        u8                      number;
        u8                      type;
        u8                      resource_index;
-       u16                     current_uf;
        u32                     interval;
 
        char                    name[20];
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 9699723..d6d31cf 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1134,16 +1134,6 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, 
struct dwc3_request *req)
                }
        }
 
-       /*
-        * 3. Missed ISOC Handling. We need to start isoc transfer on the saved
-        * uframe number.
-        */
-       if (usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
-               (dep->flags & DWC3_EP_MISSED_ISOC)) {
-                       __dwc3_gadget_start_isoc(dwc, dep, dep->current_uf);
-                       dep->flags &= ~DWC3_EP_MISSED_ISOC;
-       }
-
        return 0;
 }
 
@@ -1709,14 +1699,29 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, 
struct dwc3_ep *dep,
                                if (trb_status == DWC3_TRBSTS_MISSED_ISOC) {
                                        dev_dbg(dwc->dev, "incomplete IN 
transfer %s\n",
                                                        dep->name);
-                                       dep->current_uf = event->parameters &
-                                               ~(dep->interval - 1);
+                                       /*
+                                        * If missed isoc occurred and there is
+                                        * no request queued then issue END
+                                        * TRANSFER, so that core generates
+                                        * next xfernotready and we will issue
+                                        * a fresh START TRANSFER.
+                                        * If there are still queued request
+                                        * then wait, do not issue either END
+                                        * or UPDATE TRANSFER, just attach next
+                                        * request in request_list during
+                                        * giveback.If any future queued request
+                                        * is successfully transferred then we
+                                        * will issue UPDATE TRANSFER for all
+                                        * request in the request_list.
+                                        */
                                        dep->flags |= DWC3_EP_MISSED_ISOC;
                                } else {
                                        dev_err(dwc->dev, "incomplete IN 
transfer %s\n",
                                                        dep->name);
                                        status = -ECONNRESET;
                                }
+                       } else {
+                               dep->flags &= ~DWC3_EP_MISSED_ISOC;
                        }
                } else {
                        if (count && (event->status & DEPEVT_STATUS_SHORT))
@@ -1743,6 +1748,13 @@ 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;
+               return 1;
+       }
+
        if ((event->status & DEPEVT_STATUS_IOC) &&
                        (trb->ctrl & DWC3_TRB_CTRL_IOC))
                return 0;
-- 
1.7.5.4

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to