From patchwork Sun Mar 22 13:00:31 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lukasz Majewski X-Patchwork-Id: 244099 List-Id: U-Boot discussion From: lukma at denx.de (Lukasz Majewski) Date: Sun, 22 Mar 2020 14:00:31 +0100 Subject: [RFT PATCH v1 5/5] usb: Handle QT_TOKEN_STATUS_XACTERR error when sending data In-Reply-To: <20200322130031.10455-1-lukma@denx.de> References: <20200322130031.10455-1-lukma@denx.de> Message-ID: <20200322130031.10455-6-lukma@denx.de> This code adds check if QT_TOKEN_STATUS_XACTERR error occurred. When it is detected the token is reconfigured and transmission is retried. This code is the port to newest U-Boot of the fix from - "rayvt" (from [1]). Links: [1] - https://forum.doozan.com/read.php?3,35295,35295#msg-35295 [2] - https://www.dropbox.com/s/nrkrd1no63viuu8/uboot-bodhi-2016.05-timeoutTD.patch?dl=0 Signed-off-by: Lukasz Majewski [Unfortunately, the original patch [2] did not contain S-o-B from the original author - "rayvt"] --- drivers/usb/host/ehci-hcd.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 0a77111f80..45eda7ad24 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -315,6 +315,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, int timeout; int ret = 0; struct ehci_ctrl *ctrl = ehci_get_ctrl(dev); + int trynum; debug("dev=%p, pipe=%lx, buffer=%p, length=%d, req=%p\n", dev, pipe, buffer, length, req); @@ -560,6 +561,10 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, ehci_writel(&ctrl->hcor->or_usbsts, (usbsts & 0x3f)); /* Enable async. schedule. */ + trynum = 1; /* No more than 2 tries, in case of XACTERR. */ +retry_xacterr:; + vtd = &qtd[qtd_counter - 1]; + cmd = ehci_readl(&ctrl->hcor->or_usbcmd); cmd |= CMD_ASE; ehci_writel(&ctrl->hcor->or_usbcmd, cmd); @@ -573,8 +578,8 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, /* Wait for TDs to be processed. */ ts = get_timer(0); - vtd = &qtd[qtd_counter - 1]; timeout = USB_TIMEOUT_MS(pipe); + timeout += dev->extra_timeout; do { /* Invalidate dcache */ invalidate_dcache_range((unsigned long)&ctrl->qh_list, @@ -589,6 +594,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, break; WATCHDOG_RESET(); } while (get_timer(ts) < timeout); + debug("took %4lu ms of %4d\n", get_timer(ts), timeout); /* * Invalidate the memory area occupied by buffer @@ -622,6 +628,25 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, token = hc32_to_cpu(qh->qh_overlay.qt_token); if (!(QT_TOKEN_GET_STATUS(token) & QT_TOKEN_STATUS_ACTIVE)) { debug("TOKEN=%#x\n", token); + if (token & QT_TOKEN_STATUS_XACTERR) { + if (--trynum >= 0) { + /* + * It is necessary to do this, otherwise the + * disk is clagged. + */ + debug("reset the TD and redo, because of XACTERR\n"); + token &= ~QT_TOKEN_STATUS_HALTED; + token |= QT_TOKEN_STATUS_ACTIVE | + QT_TOKEN_CERR(2); + vtd->qt_token = cpu_to_hc32(token); + qh->qh_overlay.qt_token = cpu_to_hc32(token); + goto retry_xacterr; + } + dev->status = USB_ST_XACTERR; + dev->act_len = length - QT_TOKEN_GET_TOTALBYTES(token); + goto fail; + } + switch (QT_TOKEN_GET_STATUS(token) & ~(QT_TOKEN_STATUS_SPLITXSTATE | QT_TOKEN_STATUS_PERR)) { case 0: