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 648aa30e37bdcaab6cc2eaa7a2c89384a5149eb3 Author: Justin Hammond <[email protected]> AuthorDate: Sun Aug 16 17:09:58 2026 +0800 drivers/usbhost: Attach the xHCI interrupt after the controller starts. The handler defers to a worker that walks the event ring, and the ring is not allocated until the controller is started, several steps later. A controller left running by a boot loader has an interrupt pending as soon as the line is enabled, so attaching earlier is a race with nothing able to answer it. Attach after the start, and clear USBSTS and the interrupter pending flag once the handler is in place: a message signalled interrupt is sent on the flag's clear to set transition, so a flag raised before the handler existed would never produce another. Assisted-by: Claude:claude-opus-5 Signed-off-by: Justin Hammond <[email protected]> --- drivers/usbhost/usbhost_xhci.c | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/drivers/usbhost/usbhost_xhci.c b/drivers/usbhost/usbhost_xhci.c index ff628cf31fd..efea0fb89dd 100644 --- a/drivers/usbhost/usbhost_xhci.c +++ b/drivers/usbhost/usbhost_xhci.c @@ -4545,14 +4545,6 @@ static int xhci_hw_initialize(FAR struct usbhost_xhci_s *priv) goto errout; } - /* Configure interrupts */ - - ret = xhci_irq_initialize(priv); - if (ret < 0) - { - goto errout; - } - /* Halt controller */ ret = xhci_ctrl_halt(priv); @@ -4697,6 +4689,7 @@ xhci_initialize(FAR const char *name, uintptr_t base, { FAR struct usbhost_conn_xhci_s *conn = NULL; FAR struct usbhost_xhci_s *priv = NULL; + uint32_t regval; int ret; DEBUGASSERT(name != NULL && base != 0 && ops != NULL && @@ -4756,6 +4749,34 @@ xhci_initialize(FAR const char *name, uintptr_t base, goto errout; } + /* Take the interrupt only now. + * + * The handler defers to a worker that walks the event ring, and the ring + * does not exist until the controller has been started. A controller + * left running by a boot loader can have an interrupt pending the moment + * the line is enabled, so attaching any earlier is a race with nothing + * to answer it. + */ + + ret = xhci_irq_initialize(priv); + if (ret < 0) + { + uerr("failed to attach interrupt: %d\n", ret); + goto errout; + } + + /* Acknowledge anything the controller raised before the handler was + * attached. A message is sent once, on the transition, so a bit set in + * that window would never produce another. Clear them, so the next + * event is a fresh assertion. + */ + + regval = xhci_oper_getreg(priv, XHCI_USBSTS); + xhci_oper_putreg(priv, XHCI_USBSTS, regval); + + regval = xhci_runt_getreg(priv, XHCI_IMAN(0)); + xhci_runt_putreg(priv, XHCI_IMAN(0), regval | XHCI_IMAN_IP); + #ifdef CONFIG_DEBUG_USB_INFO xhci_dump_mem(priv, "after init"); #endif
