This is an automated email from the ASF dual-hosted git repository. xiaoxiang781216 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit c7d6f51b9cac0d5122a0ed383c15ca3c27a913f8 Author: Justin Hammond <[email protected]> AuthorDate: Sat Aug 8 12:55:35 2026 +0800 drivers/usbhost: Stop retrying an xHCI port that will not enumerate. xhci_enumerate() reports failure by marking the hub port disconnected, which is what makes xhci_wait() return and the attempt repeat. The root port is still connected, so the two disagree again immediately and the attempt repeats for as long as the device stays plugged in. A device that fails every time is retried forever: 1055 attempts in 90 seconds on an EIC7700X board, enough console traffic to make the board unusable. Count consecutive failures per root port and stop at CONFIG_USBHOST_XHCI_ENUM_RETRIES, leaving the port as it is so xhci_wait() blocks until something physically changes. A new connection clears the count, as does a successful enumeration, so a device needing a second attempt still gets one. The default of three rides out a slow device or a marginal reset. The same board now makes three attempts, reports that it has given up and falls silent, while a keyboard on the other port enumerates throughout. Assisted-by: Claude:claude-opus-5 Signed-off-by: Justin Hammond <[email protected]> --- drivers/usbhost/Kconfig | 16 ++++++++++++++++ drivers/usbhost/usbhost_xhci.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/drivers/usbhost/Kconfig b/drivers/usbhost/Kconfig index ccc6e63022d..fbde6e51f59 100644 --- a/drivers/usbhost/Kconfig +++ b/drivers/usbhost/Kconfig @@ -832,6 +832,22 @@ config USBHOST_XHCI_MAX_DEVS ---help--- How many USB devices will be supported by xHCI driver. +config USBHOST_XHCI_ENUM_RETRIES + int "xHCI enumeration attempts per port" + default 3 + range 1 255 + ---help--- + How many times to attempt enumeration of a newly connected device + before leaving the port alone until the device is unplugged. + + A device whose descriptors cannot be read, or that no class driver + claims, fails enumeration every time. Each failure marks the port + disconnected so the attempt repeats, so without a limit such a + device is retried for as long as it stays plugged in, logging and + taking a device slot on every pass. + + The count is per root hub port and is cleared by a new connection. + endif # USBHOST_XHCI menuconfig USBHOST_XHCI_PCI diff --git a/drivers/usbhost/usbhost_xhci.c b/drivers/usbhost/usbhost_xhci.c index 31a70d98440..56d1642c24a 100644 --- a/drivers/usbhost/usbhost_xhci.c +++ b/drivers/usbhost/usbhost_xhci.c @@ -199,6 +199,7 @@ struct xhci_rhport_s /* Root hub port status */ bool connected; /* Connected to device */ + uint8_t enumfail; /* Consecutive failed enumerations */ int8_t slot; /* Slot ID associated with this port */ struct xhci_epinfo_s ep0; /* EP0 endpoint info */ struct usbhost_roothubport_s hport; /* This is the hub port description understood @@ -2882,6 +2883,12 @@ static void xhci_portsc_work(FAR void *arg) rhport->connected = true; + /* A new device gets the full allowance of attempts, + * whatever the last one that sat here managed. + */ + + rhport->enumfail = 0; + usbhost_vtrace2(XHCI_VTRACE2_PORTSC_CONNECTED, rhpndx + 1, priv->pscwait); @@ -3802,6 +3809,18 @@ static int xhci_enumerate(FAR struct usbhost_connection_s *conn, { xhci_device_deinit(priv, rhport); } + + /* Clearing connected below is what makes xhci_wait() return, + * so it is also what repeats the attempt. Leave the port alone + * past the limit; a new connection clears the count. + */ + + if (++rhport->enumfail >= CONFIG_USBHOST_XHCI_ENUM_RETRIES) + { + syslog(LOG_ERR, "%s: port %d: giving up after %d attempts\n", + priv->name, hport->port + 1, rhport->enumfail); + return ret; + } } /* If this is a root hub port, then marking the hub port not connected @@ -3811,6 +3830,17 @@ static int xhci_enumerate(FAR struct usbhost_connection_s *conn, hport->connected = false; } + else + { +#ifdef CONFIG_USBHOST_HUB + if (ROOTHUB(hport)) +#endif + { + FAR struct usbhost_xhci_s *priv = XHCI_PRIV_FROM_CONN(conn); + + priv->rhport[hport->port].enumfail = 0; + } + } return ret; }
