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

    drivers/usbhost: Acknowledge xHCI events before walking the ring.
    
    The event ring was acknowledged after being walked.  An event arriving
    during the walk sets the pending bit again, and clearing the bit
    afterwards discards it.  Transfers have no timeout, so the transfer that
    event belonged to waits forever.
    
    Acknowledge first.  A spurious second pass over an empty ring costs
    nothing.
    
    Assisted-by: Claude:claude-opus-5
    Signed-off-by: Justin Hammond <[email protected]>
---
 drivers/usbhost/usbhost_xhci.c | 26 ++++++++++++++------------
 1 file changed, 14 insertions(+), 12 deletions(-)

diff --git a/drivers/usbhost/usbhost_xhci.c b/drivers/usbhost/usbhost_xhci.c
index 50ee8f0f760..423090e840d 100644
--- a/drivers/usbhost/usbhost_xhci.c
+++ b/drivers/usbhost/usbhost_xhci.c
@@ -2907,6 +2907,20 @@ static void xhci_interrupt_work(FAR void *arg)
   FAR struct usbhost_xhci_s *priv = arg;
   uint32_t                   iman;
 
+  /* Acknowledge before walking the ring, not after.  An event arriving
+   * during the walk sets the pending bit again, and clearing after the
+   * walk discards it.  Transfers have no timeout, so the one it belonged
+   * to would wait forever.
+   */
+
+  xhci_oper_putreg(priv, XHCI_USBSTS, priv->pending);
+
+  iman = xhci_runt_getreg(priv, XHCI_IMAN(0));
+  if (iman & XHCI_IMAN_IP)
+    {
+      xhci_runt_putreg(priv, XHCI_IMAN(0), iman);
+    }
+
   xhci_events_poll(priv);
 
   /* Port Change Detect */
@@ -2939,18 +2953,6 @@ static void xhci_interrupt_work(FAR void *arg)
       uinfo("Host Controller Error\n");
     }
 
-  /* ACK interrupts */
-
-  xhci_oper_putreg(priv, XHCI_USBSTS, priv->pending);
-
-  /* Clear interrupter pending bit */
-
-  iman = xhci_runt_getreg(priv, XHCI_IMAN(0));
-  if (iman & XHCI_IMAN_IP)
-    {
-      xhci_runt_putreg(priv, XHCI_IMAN(0), iman);
-    }
-
   /* Clear pending bits */
 
   priv->pending = 0;

Reply via email to