[PATCH] xhci: Add soft retry mechanism for control transaction
Роман Кузнецов
zubastikiko at gmail.com
Thu Jun 1 22:39:19 CEST 2023
>From b887f8bb547b56f6a0c0c7102a9d232df6f174c6 Mon Sep 17 00:00:00 2001
From: cidlik <zubastikiko at gmail.com>
Date: Thu, 1 Jun 2023 23:20:03 +0300
Subject: [PATCH] xhci: Add soft retry mechanism for control transaction
A Soft Retry may effectively be used to recover from a USB Transaction
Error that was due to a temporary error condition.
Software shall limit the number of unsuccessful Soft Retry attempts to
prevent an infinite loop.
For more details on Soft retry see xhci specs 4.6.8.1
---
drivers/usb/host/xhci-ring.c | 7 +++++++
drivers/usb/host/xhci.c | 12 +++++++++++-
include/usb/xhci.h | 2 ++
3 files changed, 20 insertions(+), 1 deletion(-)
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index c8260cbdf9..10f5fe4d06 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -580,6 +580,9 @@ static void record_transfer_result(struct usb_device *udev,
case COMP_SHORT_TX:
udev->status = 0;
break;
+ case COMP_TX_ERR:
+ udev->status = USB_ST_CRC_ERR;
+ break;
case COMP_STALL:
udev->status = USB_ST_STALLED;
break;
@@ -979,6 +982,10 @@ int xhci_ctrl_tx(struct usb_device *udev,
unsigned long pipe,
reset_ep(udev, ep_index);
return -EPIPE;
}
+ if (udev->status == USB_ST_CRC_ERR ) {
+ reset_ep(udev, ep_index);
+ return -EAGAIN;
+ }
/* Invalidate buffer to make it available to usb-core */
if (length > 0) {
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 9e33c5d855..efb9fc2950 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -1156,6 +1156,7 @@ static int _xhci_submit_control_msg(struct
usb_device *udev, unsigned long pipe,
{
struct xhci_ctrl *ctrl = xhci_get_ctrl(udev);
int ret = 0;
+ int soft_reset_attempt = SOFT_RESET_ATTEMPTS;
if (usb_pipetype(pipe) != PIPE_CONTROL) {
printf("non-control pipe (type=%lu)", usb_pipetype(pipe));
@@ -1178,7 +1179,16 @@ static int _xhci_submit_control_msg(struct
usb_device *udev, unsigned long pipe,
}
}
- return xhci_ctrl_tx(udev, pipe, setup, length, buffer);
+ while(soft_reset_attempt > 0)
+ {
+ ret = xhci_ctrl_tx(udev, pipe, setup, length, buffer);
+ if (ret == -EAGAIN)
+ soft_reset_attempt--;
+ else
+ return ret;
+ }
+ printf("control transfer is unsuccessful after %d attempts\n",
SOFT_RESET_ATTEMPTS);
+ return ret;
}
static int xhci_lowlevel_init(struct xhci_ctrl *ctrl)
diff --git a/include/usb/xhci.h b/include/usb/xhci.h
index 4a4ac10229..9cc3bfaf3c 100644
--- a/include/usb/xhci.h
+++ b/include/usb/xhci.h
@@ -33,6 +33,8 @@
/* Section 5.3.3 - MaxPorts */
#define MAX_HC_PORTS 255
+#define SOFT_RESET_ATTEMPTS 3
+
/* Up to 16 ms to halt an HC */
#define XHCI_MAX_HALT_USEC (16*1000)
--
2.38.0.windows.1
More information about the U-Boot
mailing list