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 c288d9f9e470fa08ce833beb94e066f4fe77223b
Author: Justin Hammond <[email protected]>
AuthorDate: Sun Aug 16 17:15:08 2026 +0800

    drivers/usbhost: Compute the event ring segment count at full width.
    
    The number of event ring segments a controller allows is a power of two
    reported as its exponent, and the exponent can reach 15.  Computing
    1 << exponent into the uint8_t that holds it wraps to zero on any
    controller offering more than 128 segments, and a controller told its
    event ring table holds no entries has nowhere to report anything: every
    command times out.
    
    Work it out at full width and narrow afterwards.
    
    Assisted-by: Claude:claude-opus-5
    Signed-off-by: Justin Hammond <[email protected]>
---
 drivers/usbhost/usbhost_xhci.c | 18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/drivers/usbhost/usbhost_xhci.c b/drivers/usbhost/usbhost_xhci.c
index b1f05a3385b..144a4b66faa 100644
--- a/drivers/usbhost/usbhost_xhci.c
+++ b/drivers/usbhost/usbhost_xhci.c
@@ -4611,6 +4611,7 @@ static void xhci_disconnect(FAR struct usbhost_driver_s 
*drvr,
 static int xhci_hw_getparams(FAR struct usbhost_xhci_s *priv)
 {
   uint32_t regval;
+  uint32_t erst;
 
   /* Get data form Host Controller Capability 1 Parameters */
 
@@ -4651,16 +4652,21 @@ static int xhci_hw_getparams(FAR struct usbhost_xhci_s 
*priv)
 
   uinfo("no scratch = %d\n", priv->no_scratch);
 
-  priv->no_erst = 1 << XHCI_HCSPARAMS2_ERST(regval);
+  /* How many event ring segments the controller will allow, which is a
+   * power of two and can reach 32768, so it is worked out at full width
+   * and only then narrowed to what this driver actually uses.  Computed
+   * into the field directly it would wrap to zero on any controller
+   * offering more than 128 segments, and a table declared to hold no
+   * entries gives a controller with nowhere to report anything.
+   */
+
+  erst = 1ul << XHCI_HCSPARAMS2_ERST(regval);
 
-  uinfo("no_erst = %d\n", priv->no_erst);
+  uinfo("erst max = %" PRIu32 "\n", erst);
 
   /* Limit event ring segment table to 1 */
 
-  if (priv->no_erst > XHCI_MAX_ERST)
-    {
-      priv->no_erst = XHCI_MAX_ERST;
-    }
+  priv->no_erst = (erst > XHCI_MAX_ERST) ? XHCI_MAX_ERST : erst;
 
   uinfo("no erst = %d\n", priv->no_erst);
 

Reply via email to