[PATCH 07/62] usb: dwc3: gadget: prepare TRBs on update transfers too

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



If we're updating transfers, we can also prepare as
many TRBs as we can fit in the ring. Let's start
doing that.

This patch 'solves' a limitation of how many TRBs we
can prepare when we're getting close the end of the
ring. Instead driver to prepare only up to end of
the ring, we check if we have space to wrap around
the ring properly.

Note that this only happens when our enqueue and
dequeue pointers are equal (which is the case for
bulk endpoints after an XferComplete event).

Signed-off-by: Felipe Balbi <felipe.balbi@xxxxxxxxxxxxxxx>
---
 drivers/usb/dwc3/gadget.c | 50 +++++++++++++++++++++++++++--------------------
 1 file changed, 29 insertions(+), 21 deletions(-)

diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 309cdb4d950b..fa38ab3086e7 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -858,16 +858,40 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
 	trace_dwc3_prepare_trb(dep, trb);
 }
 
+static u32 dwc3_calc_trbs_left(struct dwc3_ep *dep)
+{
+	struct dwc3_trb		*tmp;
+
+	/*
+	 * If enqueue & dequeue are equal than it is either full or empty.
+	 *
+	 * One way to know for sure is if the TRB right before us has HWO bit
+	 * set or not. If it has, then we're definitely full and can't fit any
+	 * more transfers in our ring.
+	 */
+	if (dep->trb_enqueue == dep->trb_dequeue) {
+		/* If we're full, enqueue/dequeue are > 0 */
+		if (dep->trb_enqueue) {
+			tmp = &dep->trb_pool[dep->trb_enqueue - 1];
+			if (tmp->ctrl & DWC3_TRB_CTRL_HWO)
+				return 0;
+		}
+
+		return DWC3_TRB_NUM - 1;
+	}
+
+	return dep->trb_dequeue - dep->trb_enqueue;
+}
+
 /*
  * dwc3_prepare_trbs - setup TRBs from requests
  * @dep: endpoint for which requests are being prepared
- * @starting: true if the endpoint is idle and no requests are queued.
  *
  * The function goes through the requests list and sets up TRBs for the
  * transfers. The function returns once there are no more TRBs available or
  * it runs out of requests.
  */
-static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting)
+static void dwc3_prepare_trbs(struct dwc3_ep *dep)
 {
 	struct dwc3_request	*req, *n;
 	u32			trbs_left;
@@ -875,23 +899,7 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting)
 
 	BUILD_BUG_ON_NOT_POWER_OF_2(DWC3_TRB_NUM);
 
-	trbs_left = dep->trb_dequeue - dep->trb_enqueue;
-
-	/*
-	 * If enqueue & dequeue are equal than it is either full or empty. If we
-	 * are starting to process requests then we are empty. Otherwise we are
-	 * full and don't do anything
-	 */
-	if (!trbs_left) {
-		if (!starting)
-			return;
-
-		trbs_left = DWC3_TRB_NUM;
-	}
-
-	/* The last TRB is a link TRB, not used for xfer */
-	if (trbs_left <= 1)
-		return;
+	trbs_left = dwc3_calc_trbs_left(dep);
 
 	list_for_each_entry_safe(req, n, &dep->pending_list, list) {
 		unsigned	length;
@@ -974,12 +982,12 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param,
 	 */
 	if (start_new) {
 		if (list_empty(&dep->started_list))
-			dwc3_prepare_trbs(dep, start_new);
+			dwc3_prepare_trbs(dep);
 
 		/* req points to the first request which will be sent */
 		req = next_request(&dep->started_list);
 	} else {
-		dwc3_prepare_trbs(dep, start_new);
+		dwc3_prepare_trbs(dep);
 
 		/*
 		 * req points to the first request where HWO changed from 0 to 1
-- 
2.8.3

---------------------------------------------------------------------
Intel Finland Oy
Registered Address: PL 281, 00181 Helsinki 
Business Identity Code: 0357606 - 4 
Domiciled in Helsinki 

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.

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



[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux