linux-usb.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Re: [PATCH 1/1] usb: cdns3: gadget: fix new urb never complete if ep cancel requests before.
@ 2021-11-20  7:18 Peter Chen
  2021-11-30 15:26 ` Zhi Li
  0 siblings, 1 reply; 3+ messages in thread
From: Peter Chen @ 2021-11-20  7:18 UTC (permalink / raw)
  To: Frank Li; +Cc: pawell, linux-usb, linux-kernel, lznuaa

Delete '.' please

Reply-To: 
In-Reply-To: <20211117204447.16869-1-Frank.Li@nxp.com>

On 21-11-17 14:44:47, Frank Li wrote:
> This issue was found at android12 MTP.
> 1. MTP submit many out urb request.
> 2. Cancel left requests (>20) when enough data get from host
> 3. Send ACK by IN endpoint.
> 4. MTP submit new out urb request.
> 5. 4's urb never complete.

New out request new complete?

> 
> TRACE LOG:
> 
> MtpServer-2157    [000] d..3  1287.150391: cdns3_ep_dequeue: ep1out: req: 00000000299e6836, req buff 000000009df42287, length: 0/16384 zsi, status: -115, trb: [start:87, end:87: virt addr 0x80004000ffd50420], flags:1 SID: 0
> MtpServer-2157    [000] d..3  1287.150410: cdns3_gadget_giveback: ep1out: req: 00000000299e6836, req buff 000000009df42287, length: 0/16384 zsi, status: -104, trb: [start:87, end:87: virt addr 0x80004000ffd50420], flags:0 SID: 0
> MtpServer-2157    [000] d..3  1287.150433: cdns3_ep_dequeue: ep1out: req: 0000000080b7bde6, req buff 000000009ed5c556, length: 0/16384 zsi, status: -115, trb: [start:88, end:88: virt addr 0x80004000ffd5042c], flags:1 SID: 0
> MtpServer-2157    [000] d..3  1287.150446: cdns3_gadget_giveback: ep1out: req: 0000000080b7bde6, req buff 000000009ed5c556, length: 0/16384 zsi, status: -104, trb: [start:88, end:88: virt addr 0x80004000ffd5042c], flags:0 SID: 0
> 	....
> MtpServer-2157    [000] d..1  1293.630410: cdns3_alloc_request: ep1out: req: 00000000afbccb7d, req buff 0000000000000000, length: 0/0 zsi, status: 0, trb: [start:0, end:0: virt addr (null)], flags:0 SID: 0
> MtpServer-2157    [000] d..2  1293.630421: cdns3_ep_queue: ep1out: req: 00000000afbccb7d, req buff 00000000871caf90, length: 0/512 zsi, status: -115, trb: [start:0, end:0: virt addr (null)], flags:0 SID: 0
> MtpServer-2157    [000] d..2  1293.630445: cdns3_wa1: WA1: ep1out set guard
> MtpServer-2157    [000] d..2  1293.630450: cdns3_wa1: WA1: ep1out restore cycle bit
> MtpServer-2157    [000] d..2  1293.630453: cdns3_prepare_trb: ep1out: trb 000000007317b3ee, dma buf: 0xffd5bc00, size: 512, burst: 128 ctrl: 0x00000424 (C=0, T=0, ISP, IOC, Normal) SID:0 LAST_SID:0
> MtpServer-2157    [000] d..2  1293.630460: cdns3_doorbell_epx: ep1out, ep_trbaddr ffd50414
> 	....
> irq/241-5b13000-2154    [000] d..1  1293.680849: cdns3_epx_irq: IRQ for ep1out: 01000408 ISP , ep_traddr: ffd508ac ep_last_sid: 00000000 use_streams: 0
> irq/241-5b13000-2154    [000] d..1  1293.680858: cdns3_complete_trb: ep1out: trb 0000000021a11b54, dma buf: 0xffd50420, size: 16384, burst: 128 ctrl: 0x00001810 (C=0, T=0, CHAIN, LINK) SID:0 LAST_SID:0
> irq/241-5b13000-2154    [000] d..1  1293.680865: cdns3_request_handled: Req: 00000000afbccb7d not handled, DMA pos: 185, ep deq: 88, ep enq: 185, start trb: 184, end trb: 184
> 
> Actually DMA pos already bigger than prevous submit request afbccb7d's TRB (184-184). The reason of (not handled) is that deq position is wrong.

%s/prevous/previous. Ok, so the reason is dep position is wrong, and
%cdns3_trb_handled returns false, so the completion is not called?

> 
> The TRB link is below when irq happen.
> 
> 	DEQ LINK LINK LINK LINK LINK .... TRB(afbccb7d):START  DMA(EP_TRADDR).
> 
> Original code check LINK TRB, but DEQ just move one step.
> 
> 	LINK DEQ LINK LINK LINK LINK .... TRB(afbccb7d):START  DMA(EP_TRADDR).
> 
> This patch skip all LINK TRB and sync DEQ to trb's start.
> 
> 	LINK LINK LINK LINK LINK .... DEQ = TRB(afbccb7d):START  DMA(EP_TRADDR).
> 
> Signed-off-by: Frank Li <Frank.Li@nxp.com>
> Signed-off-by: Jun Li <jun.li@nxp.com>
> ---
>  drivers/usb/cdns3/cdns3-gadget.c | 23 ++++++++++++-----------
>  1 file changed, 12 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/usb/cdns3/cdns3-gadget.c b/drivers/usb/cdns3/cdns3-gadget.c
> index 1f3b4a1422126..01d0e09a87ad7 100644
> --- a/drivers/usb/cdns3/cdns3-gadget.c
> +++ b/drivers/usb/cdns3/cdns3-gadget.c
> @@ -337,17 +337,21 @@ static void cdns3_ep_inc_deq(struct cdns3_endpoint *priv_ep)
>  	cdns3_ep_inc_trb(&priv_ep->dequeue, &priv_ep->ccs, priv_ep->num_trbs);
>  }
>  
> -static void cdns3_move_deq_to_next_trb(struct cdns3_request *priv_req)
> +static void cdns3_sync_deq_to_trb(struct cdns3_request *priv_req)
>  {
>  	struct cdns3_endpoint *priv_ep = priv_req->priv_ep;
> -	int current_trb = priv_req->start_trb;
> +	struct cdns3_trb *trb =  priv_ep->trb_pool + priv_ep->dequeue;
>  
> -	while (current_trb != priv_req->end_trb) {
> -		cdns3_ep_inc_deq(priv_ep);
> -		current_trb = priv_ep->dequeue;
> -	}
> +	if (TRB_FIELD_TO_TYPE(le32_to_cpu(trb->control)) == TRB_LINK) {
> +		while (priv_ep->dequeue != priv_req->start_trb) {
> +			dev_dbg(priv_ep->cdns3_dev->dev, "Remove TRB_LINK");
> +			trb = priv_ep->trb_pool + priv_ep->dequeue;
> +			WARN_ON_ONCE(TRB_FIELD_TO_TYPE(le32_to_cpu(trb->control)) != TRB_LINK);
> +			trace_cdns3_complete_trb(priv_ep, trb);
>  
> -	cdns3_ep_inc_deq(priv_ep);
> +			cdns3_ep_inc_deq(priv_ep);
> +		}
> +	}
>  }
>  
>  /**
> @@ -1518,10 +1522,7 @@ static void cdns3_transfer_completed(struct cdns3_device *priv_dev,
>  		trb = priv_ep->trb_pool + priv_ep->dequeue;
>  
>  		/* Request was dequeued and TRB was changed to TRB_LINK. */
> -		if (TRB_FIELD_TO_TYPE(le32_to_cpu(trb->control)) == TRB_LINK) {
> -			trace_cdns3_complete_trb(priv_ep, trb);
> -			cdns3_move_deq_to_next_trb(priv_req);
> -		}
> +		cdns3_sync_deq_to_trb(priv_req);

So, the issue is it doesn't skip all link trb's handler? How about below
change?


diff --git a/drivers/usb/cdns3/cdns3-gadget.c b/drivers/usb/cdns3/cdns3-gadget.c
index 1f3b4a142212..8463e5429cb0 100644
--- a/drivers/usb/cdns3/cdns3-gadget.c
+++ b/drivers/usb/cdns3/cdns3-gadget.c
@@ -337,19 +337,6 @@ static void cdns3_ep_inc_deq(struct cdns3_endpoint *priv_ep)
 	cdns3_ep_inc_trb(&priv_ep->dequeue, &priv_ep->ccs, priv_ep->num_trbs);
 }
 
-static void cdns3_move_deq_to_next_trb(struct cdns3_request *priv_req)
-{
-	struct cdns3_endpoint *priv_ep = priv_req->priv_ep;
-	int current_trb = priv_req->start_trb;
-
-	while (current_trb != priv_req->end_trb) {
-		cdns3_ep_inc_deq(priv_ep);
-		current_trb = priv_ep->dequeue;
-	}
-
-	cdns3_ep_inc_deq(priv_ep);
-}
-
 /**
  * cdns3_allow_enable_l1 - enable/disable permits to transition to L1.
  * @priv_dev: Extended gadget object
@@ -1517,10 +1504,11 @@ static void cdns3_transfer_completed(struct cdns3_device *priv_dev,
 
 		trb = priv_ep->trb_pool + priv_ep->dequeue;
 
-		/* Request was dequeued and TRB was changed to TRB_LINK. */
-		if (TRB_FIELD_TO_TYPE(le32_to_cpu(trb->control)) == TRB_LINK) {
+		/* The TRB was changed as link TRB, and the request was handled at .ep_deuque */
+		while (TRB_FIELD_TO_TYPE(le32_to_cpu(trb->control)) == TRB_LINK) {
 			trace_cdns3_complete_trb(priv_ep, trb);
-			cdns3_move_deq_to_next_trb(priv_req);
+			cdns3_ep_inc_deq(priv_ep);
+			trb = priv_ep->trb_pool + priv_ep->dequeue;
 		}
 
 		if (!request->stream_id) {

-- 

Thanks,
Peter Chen


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

* Re: [PATCH 1/1] usb: cdns3: gadget: fix new urb never complete if ep cancel requests before.
  2021-11-20  7:18 [PATCH 1/1] usb: cdns3: gadget: fix new urb never complete if ep cancel requests before Peter Chen
@ 2021-11-30 15:26 ` Zhi Li
  0 siblings, 0 replies; 3+ messages in thread
From: Zhi Li @ 2021-11-30 15:26 UTC (permalink / raw)
  To: Peter Chen; +Cc: Frank Li, pawell, linux-usb, kernel list

On Sat, Nov 20, 2021 at 1:19 AM Peter Chen <peter.chen@kernel.org> wrote:
>
> Delete '.' please
>
> Reply-To:
> In-Reply-To: <20211117204447.16869-1-Frank.Li@nxp.com>
>
> On 21-11-17 14:44:47, Frank Li wrote:
> > This issue was found at android12 MTP.
> > 1. MTP submit many out urb request.
> > 2. Cancel left requests (>20) when enough data get from host
> > 3. Send ACK by IN endpoint.
> > 4. MTP submit new out urb request.
> > 5. 4's urb never complete.
>
> New out request new complete?


New out request never complete.
>
>
> >
> > TRACE LOG:
> >
> > MtpServer-2157    [000] d..3  1287.150391: cdns3_ep_dequeue: ep1out: req: 00000000299e6836, req buff 000000009df42287, length: 0/16384 zsi, status: -115, trb: [start:87, end:87: virt addr 0x80004000ffd50420], flags:1 SID: 0
> > MtpServer-2157    [000] d..3  1287.150410: cdns3_gadget_giveback: ep1out: req: 00000000299e6836, req buff 000000009df42287, length: 0/16384 zsi, status: -104, trb: [start:87, end:87: virt addr 0x80004000ffd50420], flags:0 SID: 0
> > MtpServer-2157    [000] d..3  1287.150433: cdns3_ep_dequeue: ep1out: req: 0000000080b7bde6, req buff 000000009ed5c556, length: 0/16384 zsi, status: -115, trb: [start:88, end:88: virt addr 0x80004000ffd5042c], flags:1 SID: 0
> > MtpServer-2157    [000] d..3  1287.150446: cdns3_gadget_giveback: ep1out: req: 0000000080b7bde6, req buff 000000009ed5c556, length: 0/16384 zsi, status: -104, trb: [start:88, end:88: virt addr 0x80004000ffd5042c], flags:0 SID: 0
> >       ....
> > MtpServer-2157    [000] d..1  1293.630410: cdns3_alloc_request: ep1out: req: 00000000afbccb7d, req buff 0000000000000000, length: 0/0 zsi, status: 0, trb: [start:0, end:0: virt addr (null)], flags:0 SID: 0
> > MtpServer-2157    [000] d..2  1293.630421: cdns3_ep_queue: ep1out: req: 00000000afbccb7d, req buff 00000000871caf90, length: 0/512 zsi, status: -115, trb: [start:0, end:0: virt addr (null)], flags:0 SID: 0
> > MtpServer-2157    [000] d..2  1293.630445: cdns3_wa1: WA1: ep1out set guard
> > MtpServer-2157    [000] d..2  1293.630450: cdns3_wa1: WA1: ep1out restore cycle bit
> > MtpServer-2157    [000] d..2  1293.630453: cdns3_prepare_trb: ep1out: trb 000000007317b3ee, dma buf: 0xffd5bc00, size: 512, burst: 128 ctrl: 0x00000424 (C=0, T=0, ISP, IOC, Normal) SID:0 LAST_SID:0
> > MtpServer-2157    [000] d..2  1293.630460: cdns3_doorbell_epx: ep1out, ep_trbaddr ffd50414
> >       ....
> > irq/241-5b13000-2154    [000] d..1  1293.680849: cdns3_epx_irq: IRQ for ep1out: 01000408 ISP , ep_traddr: ffd508ac ep_last_sid: 00000000 use_streams: 0
> > irq/241-5b13000-2154    [000] d..1  1293.680858: cdns3_complete_trb: ep1out: trb 0000000021a11b54, dma buf: 0xffd50420, size: 16384, burst: 128 ctrl: 0x00001810 (C=0, T=0, CHAIN, LINK) SID:0 LAST_SID:0
> > irq/241-5b13000-2154    [000] d..1  1293.680865: cdns3_request_handled: Req: 00000000afbccb7d not handled, DMA pos: 185, ep deq: 88, ep enq: 185, start trb: 184, end trb: 184
> >
> > Actually DMA pos already bigger than prevous submit request afbccb7d's TRB (184-184). The reason of (not handled) is that deq position is wrong.
>
> %s/prevous/previous. Ok, so the reason is dep position is wrong, and
> %cdns3_trb_handled returns false, so the completion is not called?


Yes, cdns_trb_handled return false. so the completion is not called.

>
> >
> > The TRB link is below when irq happen.
> >
> >       DEQ LINK LINK LINK LINK LINK .... TRB(afbccb7d):START  DMA(EP_TRADDR).
> >
> > Original code check LINK TRB, but DEQ just move one step.
> >
> >       LINK DEQ LINK LINK LINK LINK .... TRB(afbccb7d):START  DMA(EP_TRADDR).
> >
> > This patch skip all LINK TRB and sync DEQ to trb's start.
> >
> >       LINK LINK LINK LINK LINK .... DEQ = TRB(afbccb7d):START  DMA(EP_TRADDR).
> >
> > Signed-off-by: Frank Li <Frank.Li@nxp.com>
> > Signed-off-by: Jun Li <jun.li@nxp.com>
> > ---
> >  drivers/usb/cdns3/cdns3-gadget.c | 23 ++++++++++++-----------
> >  1 file changed, 12 insertions(+), 11 deletions(-)
> >
> > diff --git a/drivers/usb/cdns3/cdns3-gadget.c b/drivers/usb/cdns3/cdns3-gadget.c
> > index 1f3b4a1422126..01d0e09a87ad7 100644
> > --- a/drivers/usb/cdns3/cdns3-gadget.c
> > +++ b/drivers/usb/cdns3/cdns3-gadget.c
> > @@ -337,17 +337,21 @@ static void cdns3_ep_inc_deq(struct cdns3_endpoint *priv_ep)
> >       cdns3_ep_inc_trb(&priv_ep->dequeue, &priv_ep->ccs, priv_ep->num_trbs);
> >  }
> >
> > -static void cdns3_move_deq_to_next_trb(struct cdns3_request *priv_req)
> > +static void cdns3_sync_deq_to_trb(struct cdns3_request *priv_req)
> >  {
> >       struct cdns3_endpoint *priv_ep = priv_req->priv_ep;
> > -     int current_trb = priv_req->start_trb;
> > +     struct cdns3_trb *trb =  priv_ep->trb_pool + priv_ep->dequeue;
> >
> > -     while (current_trb != priv_req->end_trb) {
> > -             cdns3_ep_inc_deq(priv_ep);
> > -             current_trb = priv_ep->dequeue;
> > -     }
> > +     if (TRB_FIELD_TO_TYPE(le32_to_cpu(trb->control)) == TRB_LINK) {
> > +             while (priv_ep->dequeue != priv_req->start_trb) {
> > +                     dev_dbg(priv_ep->cdns3_dev->dev, "Remove TRB_LINK");
> > +                     trb = priv_ep->trb_pool + priv_ep->dequeue;
> > +                     WARN_ON_ONCE(TRB_FIELD_TO_TYPE(le32_to_cpu(trb->control)) != TRB_LINK);
> > +                     trace_cdns3_complete_trb(priv_ep, trb);
> >
> > -     cdns3_ep_inc_deq(priv_ep);
> > +                     cdns3_ep_inc_deq(priv_ep);
> > +             }
> > +     }
> >  }
> >
> >  /**
> > @@ -1518,10 +1522,7 @@ static void cdns3_transfer_completed(struct cdns3_device *priv_dev,
> >               trb = priv_ep->trb_pool + priv_ep->dequeue;
> >
> >               /* Request was dequeued and TRB was changed to TRB_LINK. */
> > -             if (TRB_FIELD_TO_TYPE(le32_to_cpu(trb->control)) == TRB_LINK) {
> > -                     trace_cdns3_complete_trb(priv_ep, trb);
> > -                     cdns3_move_deq_to_next_trb(priv_req);
> > -             }
> > +             cdns3_sync_deq_to_trb(priv_req);
>
> > So, the issue is it doesn't skip all link trb's handler? How about below Change?

Yes, below change can work. let me send v2 patch
>
>
> diff --git a/drivers/usb/cdns3/cdns3-gadget.c b/drivers/usb/cdns3/cdns3-gadget.c
> index 1f3b4a142212..8463e5429cb0 100644
> --- a/drivers/usb/cdns3/cdns3-gadget.c
> +++ b/drivers/usb/cdns3/cdns3-gadget.c
> @@ -337,19 +337,6 @@ static void cdns3_ep_inc_deq(struct cdns3_endpoint *priv_ep)
>         cdns3_ep_inc_trb(&priv_ep->dequeue, &priv_ep->ccs, priv_ep->num_trbs);
>  }
>
> -static void cdns3_move_deq_to_next_trb(struct cdns3_request *priv_req)
> -{
> -       struct cdns3_endpoint *priv_ep = priv_req->priv_ep;
> -       int current_trb = priv_req->start_trb;
> -
> -       while (current_trb != priv_req->end_trb) {
> -               cdns3_ep_inc_deq(priv_ep);
> -               current_trb = priv_ep->dequeue;
> -       }
> -
> -       cdns3_ep_inc_deq(priv_ep);
> -}
> -
>  /**
>   * cdns3_allow_enable_l1 - enable/disable permits to transition to L1.
>   * @priv_dev: Extended gadget object
> @@ -1517,10 +1504,11 @@ static void cdns3_transfer_completed(struct cdns3_device *priv_dev,
>
>                 trb = priv_ep->trb_pool + priv_ep->dequeue;
>
> -               /* Request was dequeued and TRB was changed to TRB_LINK. */
> -               if (TRB_FIELD_TO_TYPE(le32_to_cpu(trb->control)) == TRB_LINK) {
> +               /* The TRB was changed as link TRB, and the request was handled at .ep_deuque */
> +               while (TRB_FIELD_TO_TYPE(le32_to_cpu(trb->control)) == TRB_LINK) {
>                         trace_cdns3_complete_trb(priv_ep, trb);
> -                       cdns3_move_deq_to_next_trb(priv_req);
> +                       cdns3_ep_inc_deq(priv_ep);
> +                       trb = priv_ep->trb_pool + priv_ep->dequeue;
>                 }
>
>                 if (!request->stream_id) {
>
> --
>
> Thanks,
> Peter Chen
>

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

* [PATCH 1/1] usb: cdns3: gadget: fix new urb never complete if ep cancel requests before.
@ 2021-11-17 20:44 Frank Li
  0 siblings, 0 replies; 3+ messages in thread
From: Frank Li @ 2021-11-17 20:44 UTC (permalink / raw)
  To: peter.chen, pawell; +Cc: linux-usb, linux-kernel, lznuaa

This issue was found at android12 MTP.
1. MTP submit many out urb request.
2. Cancel left requests (>20) when enough data get from host
3. Send ACK by IN endpoint.
4. MTP submit new out urb request.
5. 4's urb never complete.

TRACE LOG:

MtpServer-2157    [000] d..3  1287.150391: cdns3_ep_dequeue: ep1out: req: 00000000299e6836, req buff 000000009df42287, length: 0/16384 zsi, status: -115, trb: [start:87, end:87: virt addr 0x80004000ffd50420], flags:1 SID: 0
MtpServer-2157    [000] d..3  1287.150410: cdns3_gadget_giveback: ep1out: req: 00000000299e6836, req buff 000000009df42287, length: 0/16384 zsi, status: -104, trb: [start:87, end:87: virt addr 0x80004000ffd50420], flags:0 SID: 0
MtpServer-2157    [000] d..3  1287.150433: cdns3_ep_dequeue: ep1out: req: 0000000080b7bde6, req buff 000000009ed5c556, length: 0/16384 zsi, status: -115, trb: [start:88, end:88: virt addr 0x80004000ffd5042c], flags:1 SID: 0
MtpServer-2157    [000] d..3  1287.150446: cdns3_gadget_giveback: ep1out: req: 0000000080b7bde6, req buff 000000009ed5c556, length: 0/16384 zsi, status: -104, trb: [start:88, end:88: virt addr 0x80004000ffd5042c], flags:0 SID: 0
	....
MtpServer-2157    [000] d..1  1293.630410: cdns3_alloc_request: ep1out: req: 00000000afbccb7d, req buff 0000000000000000, length: 0/0 zsi, status: 0, trb: [start:0, end:0: virt addr (null)], flags:0 SID: 0
MtpServer-2157    [000] d..2  1293.630421: cdns3_ep_queue: ep1out: req: 00000000afbccb7d, req buff 00000000871caf90, length: 0/512 zsi, status: -115, trb: [start:0, end:0: virt addr (null)], flags:0 SID: 0
MtpServer-2157    [000] d..2  1293.630445: cdns3_wa1: WA1: ep1out set guard
MtpServer-2157    [000] d..2  1293.630450: cdns3_wa1: WA1: ep1out restore cycle bit
MtpServer-2157    [000] d..2  1293.630453: cdns3_prepare_trb: ep1out: trb 000000007317b3ee, dma buf: 0xffd5bc00, size: 512, burst: 128 ctrl: 0x00000424 (C=0, T=0, ISP, IOC, Normal) SID:0 LAST_SID:0
MtpServer-2157    [000] d..2  1293.630460: cdns3_doorbell_epx: ep1out, ep_trbaddr ffd50414
	....
irq/241-5b13000-2154    [000] d..1  1293.680849: cdns3_epx_irq: IRQ for ep1out: 01000408 ISP , ep_traddr: ffd508ac ep_last_sid: 00000000 use_streams: 0
irq/241-5b13000-2154    [000] d..1  1293.680858: cdns3_complete_trb: ep1out: trb 0000000021a11b54, dma buf: 0xffd50420, size: 16384, burst: 128 ctrl: 0x00001810 (C=0, T=0, CHAIN, LINK) SID:0 LAST_SID:0
irq/241-5b13000-2154    [000] d..1  1293.680865: cdns3_request_handled: Req: 00000000afbccb7d not handled, DMA pos: 185, ep deq: 88, ep enq: 185, start trb: 184, end trb: 184

Actually DMA pos already bigger than prevous submit request afbccb7d's TRB (184-184). The reason of (not handled) is that deq position is wrong.

The TRB link is below when irq happen.

	DEQ LINK LINK LINK LINK LINK .... TRB(afbccb7d):START  DMA(EP_TRADDR).

Original code check LINK TRB, but DEQ just move one step.

	LINK DEQ LINK LINK LINK LINK .... TRB(afbccb7d):START  DMA(EP_TRADDR).

This patch skip all LINK TRB and sync DEQ to trb's start.

	LINK LINK LINK LINK LINK .... DEQ = TRB(afbccb7d):START  DMA(EP_TRADDR).

Signed-off-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Jun Li <jun.li@nxp.com>
---
 drivers/usb/cdns3/cdns3-gadget.c | 23 ++++++++++++-----------
 1 file changed, 12 insertions(+), 11 deletions(-)

diff --git a/drivers/usb/cdns3/cdns3-gadget.c b/drivers/usb/cdns3/cdns3-gadget.c
index 1f3b4a1422126..01d0e09a87ad7 100644
--- a/drivers/usb/cdns3/cdns3-gadget.c
+++ b/drivers/usb/cdns3/cdns3-gadget.c
@@ -337,17 +337,21 @@ static void cdns3_ep_inc_deq(struct cdns3_endpoint *priv_ep)
 	cdns3_ep_inc_trb(&priv_ep->dequeue, &priv_ep->ccs, priv_ep->num_trbs);
 }
 
-static void cdns3_move_deq_to_next_trb(struct cdns3_request *priv_req)
+static void cdns3_sync_deq_to_trb(struct cdns3_request *priv_req)
 {
 	struct cdns3_endpoint *priv_ep = priv_req->priv_ep;
-	int current_trb = priv_req->start_trb;
+	struct cdns3_trb *trb =  priv_ep->trb_pool + priv_ep->dequeue;
 
-	while (current_trb != priv_req->end_trb) {
-		cdns3_ep_inc_deq(priv_ep);
-		current_trb = priv_ep->dequeue;
-	}
+	if (TRB_FIELD_TO_TYPE(le32_to_cpu(trb->control)) == TRB_LINK) {
+		while (priv_ep->dequeue != priv_req->start_trb) {
+			dev_dbg(priv_ep->cdns3_dev->dev, "Remove TRB_LINK");
+			trb = priv_ep->trb_pool + priv_ep->dequeue;
+			WARN_ON_ONCE(TRB_FIELD_TO_TYPE(le32_to_cpu(trb->control)) != TRB_LINK);
+			trace_cdns3_complete_trb(priv_ep, trb);
 
-	cdns3_ep_inc_deq(priv_ep);
+			cdns3_ep_inc_deq(priv_ep);
+		}
+	}
 }
 
 /**
@@ -1518,10 +1522,7 @@ static void cdns3_transfer_completed(struct cdns3_device *priv_dev,
 		trb = priv_ep->trb_pool + priv_ep->dequeue;
 
 		/* Request was dequeued and TRB was changed to TRB_LINK. */
-		if (TRB_FIELD_TO_TYPE(le32_to_cpu(trb->control)) == TRB_LINK) {
-			trace_cdns3_complete_trb(priv_ep, trb);
-			cdns3_move_deq_to_next_trb(priv_req);
-		}
+		cdns3_sync_deq_to_trb(priv_req);
 
 		if (!request->stream_id) {
 			/* Re-select endpoint. It could be changed by other CPU
-- 
2.24.0.rc1


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

end of thread, other threads:[~2021-11-30 15:26 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-11-20  7:18 [PATCH 1/1] usb: cdns3: gadget: fix new urb never complete if ep cancel requests before Peter Chen
2021-11-30 15:26 ` Zhi Li
  -- strict thread matches above, loose matches on Subject: below --
2021-11-17 20:44 Frank Li

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).