RE: [PATCH 2/2] usb: cdns3: gadget: toggle cycle bit before reset endpoint

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

 



>
>If there are TRBs pending during clear stall and reset endpoint, the
>DMA will advance after reset operation, but it doesn't be expected,
>since the data has still not be ready (For OUT, the data has still
>not received). After the data is ready, there isn't any interrupt
>since the EP_TRADDR has already points to next TRB entry.
>
>To fix it, it toggles cyclt bit before reset operation, and restore
>it after reset, it could keep DMA stopping.
>
>Fixes: 7733f6c32e36 ("usb: cdns3: Add Cadence USB3 DRD Driver")
>Signed-off-by: Peter Chen <peter.chen@xxxxxxx>
>---
> drivers/usb/cdns3/gadget.c | 17 ++++++++++++++---
> 1 file changed, 14 insertions(+), 3 deletions(-)
>
>diff --git a/drivers/usb/cdns3/gadget.c b/drivers/usb/cdns3/gadget.c
>index 1d8a2af35bb0..7b6bb96b91d1 100644
>--- a/drivers/usb/cdns3/gadget.c
>+++ b/drivers/usb/cdns3/gadget.c
>@@ -2595,11 +2595,21 @@ int __cdns3_gadget_ep_clear_halt(struct cdns3_endpoint *priv_ep)
> {
> 	struct cdns3_device *priv_dev = priv_ep->cdns3_dev;
> 	struct usb_request *request;
>+	struct cdns3_request *priv_req;
>+	struct cdns3_trb *trb = NULL;
> 	int ret;
> 	int val;
>
> 	trace_cdns3_halt(priv_ep, 0, 0);
>
>+	request = cdns3_next_request(&priv_ep->pending_req_list);
>+	if (request) {
>+		priv_req = to_cdns3_request(request);
>+		trb = priv_req->trb;
>+		if (trb)
>+			trb->control = trb->control ^ 1;
>+	}
>+

What about doing simple read/write on ep_traddr register:
	u32 ep_traddr; 
	ep_traddr = readl(&priv_dev->regs->ep_traddr);

> 	writel(EP_CMD_CSTALL | EP_CMD_EPRST, &priv_dev->regs->ep_cmd);
	
	writel(&priv_dev->regs->ep_traddr, ep_traddr);
	
It should work in the same way but is simpler.  

And maybe we could add some comment because this code look little strange.  Something like:
When endpoint is armed during endpoint reset the controller can advance TRADDR to next TD,
so driver need to restore the previous value. 

>
> 	/* wait for EPRST cleared */
>@@ -2610,10 +2620,11 @@ int __cdns3_gadget_ep_clear_halt(struct cdns3_endpoint *priv_ep)
>
> 	priv_ep->flags &= ~(EP_STALLED | EP_STALL_PENDING);
>
>-	request = cdns3_next_request(&priv_ep->pending_req_list);
>-
>-	if (request)
>+	if (request) {
>+		if (trb)
>+			trb->control = trb->control ^ 1;
> 		cdns3_rearm_transfer(priv_ep, 1);
>+	}
>
> 	cdns3_start_all_request(priv_dev, priv_ep);
> 	return ret;
>--
>2.17.1





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

  Powered by Linux