From ef529d5647ef2d4fe7f004d78b41e365dbe55178 Mon Sep 17 00:00:00 2001 From: Mayank Rana Date: Mon, 28 Sep 2015 20:01:21 -0700 Subject: [PATCH 1/2] Revert "usb: dwc3: fix TRB completion when multiple TRBs are started" commit 0b93a4c838fa ("usb: dwc3: fix TRB completion when multiple TRBs are started") enables XFERINPROGRESS event with all endpoint type except control endpoint. Currently we are not using XFERINPROGRESS for queuing next request and depends on XFERNOTREADY event only. Change-Id: I833c2311c5af48fd15f2813df9cc83c3471c4f94 Signed-off-by: Mayank Rana --- drivers/usb/dwc3/gadget.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index d90df256796c..3d96a8bef5f0 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -539,7 +539,7 @@ static int dwc3_gadget_set_ep_config(struct dwc3 *dwc, struct dwc3_ep *dep, dep->stream_capable = true; } - if (!usb_endpoint_xfer_control(desc)) + if (usb_endpoint_xfer_isoc(desc)) params.param1 |= DWC3_DEPCFG_XFER_IN_PROGRESS_EN; /* @@ -2564,6 +2564,12 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, break; case DWC3_DEPEVT_XFERINPROGRESS: dep->dbg_ep_events.xferinprogress++; + if (!usb_endpoint_xfer_isoc(dep->endpoint.desc)) { + dev_dbg(dwc->dev, "%s is not an Isochronous endpoint\n", + dep->name); + return; + } + dwc3_endpoint_transfer_complete(dwc, dep, event); break; case DWC3_DEPEVT_XFERNOTREADY: From f5a8583fbbcd28ffe94b7314b9c4196df4ed833d Mon Sep 17 00:00:00 2001 From: Mayank Rana Date: Sat, 27 Jun 2015 14:54:14 -0700 Subject: [PATCH 2/2] Revert "usb: dwc3: gadget: always enable IOC on bulk/interrupt transfers" This change reverts Commit f3af36511e60 ("usb: dwc3: gadget: always enable IOC on bulk/interrupt transfers") which sets IOC bit for both bulk/interrupt transfers resulting into interrupt for each TRB completion with event as XFERINPROGRESS. In some cases it has been observed that controller is not able to complete provided TRB on bulk-in endpoint causing stall conditions. Hence Fix this issue by not setting IOC bit for each TRB to receive XFERCOMPLETE interrupt with it. Change-Id: I5ff08188f37044332f7dadba8d677288e83bfec8 Signed-off-by: Mayank Rana Signed-off-by: Hemant Kumar --- drivers/usb/dwc3/gadget.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 3d96a8bef5f0..a798c4fa8812 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -891,11 +891,19 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, trb->ctrl = DWC3_TRBCTL_ISOCHRONOUS_FIRST; else trb->ctrl = DWC3_TRBCTL_ISOCHRONOUS; + + if (!req->request.no_interrupt && !chain) + trb->ctrl |= DWC3_TRB_CTRL_IOC; break; case USB_ENDPOINT_XFER_BULK: case USB_ENDPOINT_XFER_INT: trb->ctrl = DWC3_TRBCTL_NORMAL; + if (req->request.num_mapped_sgs > 0) { + if (!last && !chain && + !req->request.no_interrupt) + trb->ctrl |= DWC3_TRB_CTRL_IOC; + } break; default: /* @@ -905,9 +913,6 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, BUG(); } - if (!req->request.no_interrupt && !chain) - trb->ctrl |= DWC3_TRB_CTRL_IOC; - if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) { trb->ctrl |= DWC3_TRB_CTRL_ISP_IMI; trb->ctrl |= DWC3_TRB_CTRL_CSP; @@ -2477,6 +2482,9 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep, return 1; } + if ((event->status & DEPEVT_STATUS_IOC) && + (trb->ctrl & DWC3_TRB_CTRL_IOC)) + return 0; return 1; }