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;
 }

Reply via email to