[PATCH 11/22] usb: dwc3: gadget: clear LST from previous TRB on Update Transfer

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

 



If we're going to issue a Update Transfer command,
let's clear LST bit from previous TRB. This will let
us continue processing TRBs and convert previous IRQ
into XferInProgress, instead of XferComplete.

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

diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 4a3ed4cbe39b..809445ec6a87 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -770,7 +770,8 @@ static void dwc3_gadget_ep_free_request(struct usb_ep *ep,
  */
 static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
 		struct dwc3_request *req, dma_addr_t dma,
-		unsigned length, unsigned last, unsigned chain, unsigned node)
+		unsigned length, unsigned last, unsigned chain,
+		unsigned node, int starting)
 {
 	struct dwc3_trb		*trb;
 
@@ -779,6 +780,15 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
 			length, last ? " last" : "",
 			chain ? " chain" : "");
 
+	/*
+	 * When trying to issue Update Transfer, we can remove LST bit from
+	 * previous TRB and avoid a XferComplete
+	 */
+	if (!starting) {
+		trb = &dep->trb_pool[dep->trb_enqueue - 1];
+		if (trb->ctrl & DWC3_TRB_CTRL_HWO)
+			trb->ctrl &= ~DWC3_TRB_CTRL_LST;
+	}
 
 	trb = &dep->trb_pool[dep->trb_enqueue];
 
@@ -871,7 +881,8 @@ static u32 dwc3_calc_trbs_left(struct dwc3_ep *dep)
 }
 
 static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep,
-		struct dwc3_request *req, unsigned int trbs_left)
+		struct dwc3_request *req, unsigned int trbs_left,
+		int starting)
 {
 	struct usb_request *request = &req->request;
 	struct scatterlist *sg = request->sg;
@@ -901,7 +912,7 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep,
 			chain = false;
 
 		dwc3_prepare_one_trb(dep, req, dma, length,
-				last, chain, i);
+				last, chain, i, starting);
 
 		if (last)
 			break;
@@ -909,7 +920,8 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep,
 }
 
 static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep,
-		struct dwc3_request *req, unsigned int trbs_left)
+		struct dwc3_request *req, unsigned int trbs_left,
+		int starting)
 {
 	unsigned int	last = false;
 	unsigned int	length;
@@ -926,7 +938,7 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep,
 		last = true;
 
 	dwc3_prepare_one_trb(dep, req, dma, length,
-			last, false, 0);
+			last, false, 0, starting);
 }
 
 /*
@@ -937,7 +949,7 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep,
  * 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)
+static void dwc3_prepare_trbs(struct dwc3_ep *dep, int starting)
 {
 	struct dwc3_request	*req, *n;
 	u32			trbs_left;
@@ -948,9 +960,11 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep)
 
 	list_for_each_entry_safe(req, n, &dep->pending_list, list) {
 		if (req->request.num_mapped_sgs > 0)
-			dwc3_prepare_one_trb_sg(dep, req, trbs_left--);
+			dwc3_prepare_one_trb_sg(dep, req, trbs_left--,
+					starting);
 		else
-			dwc3_prepare_one_trb_linear(dep, req, trbs_left--);
+			dwc3_prepare_one_trb_linear(dep, req, trbs_left--,
+					starting);
 
 		if (!trbs_left)
 			return;
@@ -968,7 +982,7 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param)
 
 	starting = !(dep->flags & DWC3_EP_BUSY);
 
-	dwc3_prepare_trbs(dep);
+	dwc3_prepare_trbs(dep, starting);
 	req = next_request(&dep->started_list);
 	if (!req) {
 		dep->flags |= DWC3_EP_PENDING_REQUEST;
-- 
2.8.2

---------------------------------------------------------------------
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