mirror of
https://github.com/apache/nuttx.git
synced 2026-10-02 19:58:01 +00:00
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 <justin@dynam.ac>
This commit is contained in:
parent
4b86c1dd23
commit
648aa30e37
1 changed files with 29 additions and 8 deletions
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue