mirror of
https://github.com/apache/nuttx.git
synced 2026-10-01 03:16:24 +00:00
drivers/usbhost: Release the xHCI slot when enumeration fails.
A device slot is a finite controller resource: HCSPARAMS1 reports how many exist and Enable Slot fails with No Slots Available once they are gone. Two paths took one and returned without giving it back. xhci_device_init() enables a slot before initialising the transfer ring, the slot context and the device address, and each of those returned directly on failure. It also treated a slot number larger than the controller supports as success, since Enable Slot itself had succeeded. xhci_enumerate() is the larger leak: the device is addressed by the time usbhost_enumerate() runs, so a device whose descriptor cannot be read, or that no class driver claims, leaves the slot held. That path clears hport->connected so the port is retried, taking another slot each time. Release the slot on both paths with xhci_device_deinit(), which issues Disable Slot, clears the DCBAA entry and resets the context. The endpoint ring is left allocated; xhci_ring_init() reuses an existing one. Tested on an EIC7700X board with a device no class driver claims, so the port retries indefinitely: previously the eighth attempt failed with completion code 9 and the controller enumerated nothing further on either port; now 1104 consecutive attempts produced no slot failure. Assisted-by: Claude:claude-opus-5 Signed-off-by: Justin Hammond <justin@dynam.ac>
This commit is contained in:
parent
fc58227802
commit
18c834b7d3
1 changed files with 38 additions and 4 deletions
|
|
@ -1810,7 +1810,15 @@ static int xhci_device_init(FAR struct usbhost_xhci_s *priv,
|
|||
ret = xhci_cmd_sloten(priv, &slot);
|
||||
if (ret < 0 || slot > priv->no_slots)
|
||||
{
|
||||
/* Something goes wrong ! */
|
||||
/* A slot the controller cannot address is no more usable than no
|
||||
* slot at all, and the command itself succeeds in that case, so the
|
||||
* caller needs an error either way.
|
||||
*/
|
||||
|
||||
if (ret >= 0)
|
||||
{
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
usbhost_vtrace1(XHCI_TRACE1_SLOTEN_FAILED, ret);
|
||||
return ret;
|
||||
|
|
@ -1834,7 +1842,7 @@ static int xhci_device_init(FAR struct usbhost_xhci_s *priv,
|
|||
if (ret < 0)
|
||||
{
|
||||
uerr("ep0 ring init failed\n");
|
||||
return ret;
|
||||
goto errout_with_slot;
|
||||
}
|
||||
|
||||
rhport->ep0.slot = slot;
|
||||
|
|
@ -1845,7 +1853,7 @@ static int xhci_device_init(FAR struct usbhost_xhci_s *priv,
|
|||
ret = xhci_slot_init(priv, dev);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
goto errout_with_slot;
|
||||
}
|
||||
|
||||
/* Step 6: Assign and address to the device and enable its Default
|
||||
|
|
@ -1860,12 +1868,21 @@ static int xhci_device_init(FAR struct usbhost_xhci_s *priv,
|
|||
if (ret < 0)
|
||||
{
|
||||
uerr("failed to set address %d\n", ret);
|
||||
return ret;
|
||||
goto errout_with_slot;
|
||||
}
|
||||
|
||||
/* Steps 7-12 don't belong here! */
|
||||
|
||||
return OK;
|
||||
|
||||
errout_with_slot:
|
||||
|
||||
/* Nothing else gives the slot back, and the controller has a fixed
|
||||
* number of them.
|
||||
*/
|
||||
|
||||
xhci_device_deinit(priv, rhport);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
|
@ -3770,6 +3787,23 @@ static int xhci_enumerate(FAR struct usbhost_connection_s *conn,
|
|||
{
|
||||
/* Failed to enumerate */
|
||||
|
||||
/* The device is addressed by now, so it holds a slot, and the retry
|
||||
* below asks for another.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_USBHOST_HUB
|
||||
if (ROOTHUB(hport))
|
||||
#endif
|
||||
{
|
||||
FAR struct usbhost_xhci_s *priv = XHCI_PRIV_FROM_CONN(conn);
|
||||
FAR struct xhci_rhport_s *rhport = &priv->rhport[hport->port];
|
||||
|
||||
if (rhport->dev != NULL)
|
||||
{
|
||||
xhci_device_deinit(priv, rhport);
|
||||
}
|
||||
}
|
||||
|
||||
/* If this is a root hub port, then marking the hub port not connected
|
||||
* will cause xhci_wait() to return and we will try the connection
|
||||
* again.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue