All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 1/3] usb: dwc3: gadget: increment request->actual once
@ 2016-08-10 11:12 Felipe Balbi
  2016-08-10 11:12 ` [PATCH v2 2/3] usb: dwc3: gadget: fix for short pkts during chained xfers Felipe Balbi
  2016-08-10 11:12 ` [PATCH v2 3/3] usb: dwc3: gadget: always cleanup all TRBs Felipe Balbi
  0 siblings, 2 replies; 3+ messages in thread
From: Felipe Balbi @ 2016-08-10 11:12 UTC (permalink / raw)
  To: Linux USB; +Cc: Brian E Rogers, Felipe Balbi, stable

When using SG lists, we would end up setting
request->actual to:

	num_mapped_sgs * (request->length - count)

Let's fix that up by incrementing request->actual
only once.

Cc: <stable@vger.kernel.org>
Reported-by: Brian E Rogers <brian.e.rogers@intel.com>
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
---

Changes since V1:
	- NONE

 drivers/usb/dwc3/gadget.c | 19 +++++++++++--------
 1 file changed, 11 insertions(+), 8 deletions(-)

diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 8f8c2157910e..863c306ebb69 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -2013,14 +2013,6 @@ static int __dwc3_cleanup_done_trbs(struct dwc3 *dwc, struct dwc3_ep *dep,
 			s_pkt = 1;
 	}
 
-	/*
-	 * We assume here we will always receive the entire data block
-	 * which we should receive. Meaning, if we program RX to
-	 * receive 4K but we receive only 2K, we assume that's all we
-	 * should receive and we simply bounce the request back to the
-	 * gadget driver for further processing.
-	 */
-	req->request.actual += req->request.length - count;
 	if (s_pkt)
 		return 1;
 	if ((event->status & DEPEVT_STATUS_LST) &&
@@ -2040,6 +2032,7 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep,
 	struct dwc3_trb		*trb;
 	unsigned int		slot;
 	unsigned int		i;
+	int			count = 0;
 	int			ret;
 
 	do {
@@ -2054,6 +2047,8 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep,
 				slot++;
 			slot %= DWC3_TRB_NUM;
 			trb = &dep->trb_pool[slot];
+			count += trb->size & DWC3_TRB_SIZE_MASK;
+
 
 			ret = __dwc3_cleanup_done_trbs(dwc, dep, req, trb,
 					event, status);
@@ -2061,6 +2056,14 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep,
 				break;
 		} while (++i < req->request.num_mapped_sgs);
 
+		/*
+		 * We assume here we will always receive the entire data block
+		 * which we should receive. Meaning, if we program RX to
+		 * receive 4K but we receive only 2K, we assume that's all we
+		 * should receive and we simply bounce the request back to the
+		 * gadget driver for further processing.
+		 */
+		req->request.actual += req->request.length - count;
 		dwc3_gadget_giveback(dep, req, status);
 
 		if (ret)
-- 
2.9.1


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH v2 2/3] usb: dwc3: gadget: fix for short pkts during chained xfers
  2016-08-10 11:12 [PATCH v2 1/3] usb: dwc3: gadget: increment request->actual once Felipe Balbi
@ 2016-08-10 11:12 ` Felipe Balbi
  2016-08-10 11:12 ` [PATCH v2 3/3] usb: dwc3: gadget: always cleanup all TRBs Felipe Balbi
  1 sibling, 0 replies; 3+ messages in thread
From: Felipe Balbi @ 2016-08-10 11:12 UTC (permalink / raw)
  To: Linux USB; +Cc: Brian E Rogers, Felipe Balbi, stable

DWC3 has one interesting peculiarity with chained
transfers. If we setup N chained transfers and we
get a short packet before processing all N TRBs,
DWC3 will (conditionally) issue a XferComplete or
XferInProgress event and retire all TRBs from the
one which got a short packet to the last without
clearing their HWO bits.

This means SW must clear HWO bit manually, which
this patch is doing.

Cc: <stable@vger.kernel.org>
Cc: Brian E Rogers <brian.e.rogers@intel.com>
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
---

Changes since V1:
	- NONE

 drivers/usb/dwc3/gadget.c | 23 ++++++++++++++++++++---
 1 file changed, 20 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 863c306ebb69..241f5c7b34bf 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1955,7 +1955,8 @@ static void dwc3_gadget_free_endpoints(struct dwc3 *dwc)
 
 static int __dwc3_cleanup_done_trbs(struct dwc3 *dwc, struct dwc3_ep *dep,
 		struct dwc3_request *req, struct dwc3_trb *trb,
-		const struct dwc3_event_depevt *event, int status)
+		const struct dwc3_event_depevt *event, int status,
+		int chain)
 {
 	unsigned int		count;
 	unsigned int		s_pkt = 0;
@@ -1964,6 +1965,19 @@ static int __dwc3_cleanup_done_trbs(struct dwc3 *dwc, struct dwc3_ep *dep,
 	dep->queued_requests--;
 	trace_dwc3_complete_trb(dep, trb);
 
+	/*
+	 * If we're in the middle of series of chained TRBs and we
+	 * receive a short transfer along the way, DWC3 will skip
+	 * through all TRBs including the last TRB in the chain (the
+	 * where CHN bit is zero. DWC3 will also avoid clearing HWO
+	 * bit and SW has to do it manually.
+	 *
+	 * We're going to do that here to avoid problems of HW trying
+	 * to use bogus TRBs for transfers.
+	 */
+	if (chain && (trb->ctrl & DWC3_TRB_CTRL_HWO))
+		trb->ctrl &= ~DWC3_TRB_CTRL_HWO;
+
 	if ((trb->ctrl & DWC3_TRB_CTRL_HWO) && status != -ESHUTDOWN)
 		/*
 		 * We continue despite the error. There is not much we
@@ -1975,6 +1989,7 @@ static int __dwc3_cleanup_done_trbs(struct dwc3 *dwc, struct dwc3_ep *dep,
 		 */
 		dev_err(dwc->dev, "%s's TRB (%p) still owned by HW\n",
 				dep->name, trb);
+
 	count = trb->size & DWC3_TRB_SIZE_MASK;
 
 	if (dep->direction) {
@@ -2036,10 +2051,13 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep,
 	int			ret;
 
 	do {
+		int chain;
+
 		req = next_request(&dep->started_list);
 		if (WARN_ON_ONCE(!req))
 			return 1;
 
+		chain = req->request.num_mapped_sgs > 0;
 		i = 0;
 		do {
 			slot = req->first_trb_index + i;
@@ -2049,9 +2067,8 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep,
 			trb = &dep->trb_pool[slot];
 			count += trb->size & DWC3_TRB_SIZE_MASK;
 
-
 			ret = __dwc3_cleanup_done_trbs(dwc, dep, req, trb,
-					event, status);
+					event, status, chain);
 			if (ret)
 				break;
 		} while (++i < req->request.num_mapped_sgs);
-- 
2.9.1


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH v2 3/3] usb: dwc3: gadget: always cleanup all TRBs
  2016-08-10 11:12 [PATCH v2 1/3] usb: dwc3: gadget: increment request->actual once Felipe Balbi
  2016-08-10 11:12 ` [PATCH v2 2/3] usb: dwc3: gadget: fix for short pkts during chained xfers Felipe Balbi
@ 2016-08-10 11:12 ` Felipe Balbi
  1 sibling, 0 replies; 3+ messages in thread
From: Felipe Balbi @ 2016-08-10 11:12 UTC (permalink / raw)
  To: Linux USB; +Cc: Brian E Rogers, Felipe Balbi, stable

If we stop earlier due to short packet, we will
not be able to giveback all TRBs.

Cc: <stable@vger.kernel.org>
Cc: Brian E Rogers <brian.e.rogers@intel.com>
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
---

Changes since V1:
	- Avoid a regression with non scatterlist transfers

 drivers/usb/dwc3/gadget.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 241f5c7b34bf..eb820e4ab49d 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -2028,7 +2028,7 @@ static int __dwc3_cleanup_done_trbs(struct dwc3 *dwc, struct dwc3_ep *dep,
 			s_pkt = 1;
 	}
 
-	if (s_pkt)
+	if (s_pkt && !chain)
 		return 1;
 	if ((event->status & DEPEVT_STATUS_LST) &&
 			(trb->ctrl & (DWC3_TRB_CTRL_LST |
-- 
2.9.1


^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2016-08-10 18:05 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-08-10 11:12 [PATCH v2 1/3] usb: dwc3: gadget: increment request->actual once Felipe Balbi
2016-08-10 11:12 ` [PATCH v2 2/3] usb: dwc3: gadget: fix for short pkts during chained xfers Felipe Balbi
2016-08-10 11:12 ` [PATCH v2 3/3] usb: dwc3: gadget: always cleanup all TRBs Felipe Balbi

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.