usbhost: Fix function address generation for multi-port root hubs.

Devices connected to the same USB bus should have unique function addresses.
This was not true for root hubs with multiple ports. After this change,
enumeration is more reliable on the sama5d3-xplained board when both root hub
ports are used.

This change amounts to using one usbhost_devaddr_s object per root hub
instead of one per root hub port. For the majority of boards only one
root hub port is available so no change in behavior should be expected.
This commit is contained in:
Lwazi Dube 2023-05-10 20:05:21 -04:00 committed by Alin Jerpelea
parent 4ed48c33e9
commit d66282a893
22 changed files with 118 additions and 58 deletions

View File

@ -252,6 +252,8 @@ struct efm32_usbhost_s
volatile struct usbhost_hubport_s *hport;
#endif
struct usbhost_devaddr_s devgen; /* Address generation data */
/* The state of each host channel */
struct efm32_chan_s chan[EFM32_MAX_TX_FIFOS];
@ -1246,7 +1248,7 @@ static void efm32_chan_wakeup(struct efm32_usbhost_s *priv,
USBHOST_VTRACE2_CHANWAKEUP_OUT,
chan->epno, chan->result);
nxsem_post(chan->waitsem);
nxsem_post(&chan->waitsem);
chan->waiter = false;
}
@ -5252,7 +5254,8 @@ static inline void efm32_sw_initialize(struct efm32_usbhost_s *priv)
/* Initialize function address generation logic */
usbhost_devaddr_initialize(&priv->rhport);
usbhost_devaddr_initialize(&priv->devgen);
priv->rhport.pdevgen = &priv->devgen;
/* Initialize the driver state data */

View File

@ -290,6 +290,8 @@ struct imxrt_ehci_s
volatile struct usbhost_hubport_s *hport;
#endif
struct usbhost_devaddr_s devgen; /* Address generation data */
/* Root hub ports */
struct imxrt_rhport_s rhport[IMXRT_EHCI_NRHPORT];
@ -5002,6 +5004,10 @@ struct usbhost_connection_s *imxrt_ehci_initialize(int controller)
usbhost_vtrace1(EHCI_VTRACE1_INITIALIZING, 0);
/* Initialize function address generation logic */
usbhost_devaddr_initialize(&g_ehci.devgen);
/* Initialize the root hub port structures */
for (i = 0; i < IMXRT_EHCI_NRHPORT; i++)
@ -5028,6 +5034,7 @@ struct usbhost_connection_s *imxrt_ehci_initialize(int controller)
rhport->drvr.connect = imxrt_connect;
# endif
rhport->drvr.disconnect = imxrt_disconnect;
rhport->hport.pdevgen = &g_ehci.devgen;
/* Initialize EP0 */
@ -5046,10 +5053,6 @@ struct usbhost_connection_s *imxrt_ehci_initialize(int controller)
hport->ep0 = &rhport->ep0;
hport->port = i;
hport->speed = USB_SPEED_FULL;
/* Initialize function address generation logic */
usbhost_devaddr_initialize(&rhport->hport);
}
# ifndef CONFIG_IMXRT_EHCI_PREALLOCATE

View File

@ -300,6 +300,8 @@ struct kinetis_ehci_s
volatile struct usbhost_hubport_s *hport;
#endif
struct usbhost_devaddr_s devgen; /* Address generation data */
/* Root hub ports */
struct kinetis_rhport_s rhport[KINETIS_EHCI_NRHPORT];
@ -5072,6 +5074,10 @@ struct usbhost_connection_s *kinetis_ehci_initialize(int controller)
usbhost_vtrace1(EHCI_VTRACE1_INITIALIZING, 0);
/* Initialize function address generation logic */
usbhost_devaddr_initialize(&g_ehci.devgen);
/* Initialize the root hub port structures */
for (i = 0; i < KINETIS_EHCI_NRHPORT; i++)
@ -5098,6 +5104,7 @@ struct usbhost_connection_s *kinetis_ehci_initialize(int controller)
rhport->drvr.connect = kinetis_connect;
# endif
rhport->drvr.disconnect = kinetis_disconnect;
rhport->hport.pdevgen = &g_ehci.devgen;
/* Initialize EP0 */
@ -5116,10 +5123,6 @@ struct usbhost_connection_s *kinetis_ehci_initialize(int controller)
hport->ep0 = &rhport->ep0;
hport->port = i;
hport->speed = USB_SPEED_FULL;
/* Initialize function address generation logic */
usbhost_devaddr_initialize(&rhport->hport);
}
# ifndef CONFIG_KINETIS_EHCI_PREALLOCATE

View File

@ -172,6 +172,8 @@ struct lpc17_40_usbhost_s
volatile struct usbhost_hubport_s *hport;
#endif
struct usbhost_devaddr_s devgen; /* Address generation data */
};
/* This structure describes one asynchronous transfer */
@ -3738,7 +3740,8 @@ struct usbhost_connection_s *lpc17_40_usbhost_initialize(int controller)
/* Initialize function address generation logic */
usbhost_devaddr_initialize(&priv->rhport);
usbhost_devaddr_initialize(&priv->devgen);
priv->rhport.pdevgen = &priv->devgen;
#ifndef CONFIG_USBHOST_INT_DISABLE
priv->ininterval = MAX_PERINTERVAL;

View File

@ -291,6 +291,8 @@ struct lpc31_ehci_s
volatile struct usbhost_hubport_s *hport;
#endif
struct usbhost_devaddr_s devgen; /* Address generation data */
/* Root hub ports */
struct lpc31_rhport_s rhport[LPC31_EHCI_NRHPORT];
@ -5025,6 +5027,10 @@ struct usbhost_connection_s *lpc31_ehci_initialize(int controller)
usbhost_vtrace1(EHCI_VTRACE1_INITIALIZING, 0);
/* Initialize function address generation logic */
usbhost_devaddr_initialize(&g_ehci.devgen);
/* Initialize the root hub port structures */
for (i = 0; i < LPC31_EHCI_NRHPORT; i++)
@ -5051,6 +5057,7 @@ struct usbhost_connection_s *lpc31_ehci_initialize(int controller)
rhport->drvr.connect = lpc31_connect;
#endif
rhport->drvr.disconnect = lpc31_disconnect;
rhport->hport.pdevgen = &g_ehci.devgen;
/* Initialize EP0 */
@ -5070,10 +5077,6 @@ struct usbhost_connection_s *lpc31_ehci_initialize(int controller)
hport->ep0 = &rhport->ep0;
hport->port = i;
hport->speed = USB_SPEED_FULL;
/* Initialize function address generation logic */
usbhost_devaddr_initialize(&rhport->hport);
}
#ifndef CONFIG_LPC31_EHCI_PREALLOCATE

View File

@ -31,6 +31,8 @@
* Pre-processor Definitions
****************************************************************************/
#define LPC43_EHCI_NRHPORT 1
/* Register Offsets *********************************************************/
/* 0x000 - 0x0ff: Reserved */

View File

@ -293,6 +293,8 @@ struct lpc43_ehci_s
volatile struct usbhost_hubport_s *hport;
#endif
struct usbhost_devaddr_s devgen; /* Address generation data */
/* Root hub ports */
struct lpc43_rhport_s rhport[LPC43_EHCI_NRHPORT];
@ -4849,6 +4851,10 @@ struct usbhost_connection_s *lpc43_ehci_initialize(int controller)
usbhost_vtrace1(EHCI_VTRACE1_INITIALIZING, 0);
/* Initialize function address generation logic */
usbhost_devaddr_initialize(&g_ehci.devgen);
/* Initialize the root hub port structures */
for (i = 0; i < LPC43_EHCI_NRHPORT; i++)
@ -4875,6 +4881,7 @@ struct usbhost_connection_s *lpc43_ehci_initialize(int controller)
rhport->drvr.connect = lpc43_connect;
#endif
rhport->drvr.disconnect = lpc43_disconnect;
rhport->hport.pdevgen = &g_ehci.devgen;
/* Initialize EP0 */
@ -4893,10 +4900,6 @@ struct usbhost_connection_s *lpc43_ehci_initialize(int controller)
hport->ep0 = &rhport->ep0;
hport->port = i;
hport->speed = USB_SPEED_FULL;
/* Initialize function address generation logic */
usbhost_devaddr_initialize(&rhport->hport);
}
#ifndef CONFIG_LPC43_EHCI_PREALLOCATE

View File

@ -268,6 +268,8 @@ struct lpc54_usbhost_s
volatile struct usbhost_hubport_s *hport;
#endif
struct usbhost_devaddr_s devgen; /* Address generation data */
};
/* This structure describes one asynchronous transfer */
@ -3824,7 +3826,8 @@ struct usbhost_connection_s *lpc54_usbhost_initialize(int controller)
/* Initialize function address generation logic */
usbhost_devaddr_initialize(&priv->rhport);
usbhost_devaddr_initialize(&priv->devgen);
priv->rhport.pdevgen = &priv->devgen;
#ifndef CONFIG_OHCI_INT_DISABLE
priv->ininterval = MAX_PERINTERVAL;

View File

@ -256,6 +256,8 @@ struct sam_ehci_s
volatile struct usbhost_hubport_s *hport;
#endif
struct usbhost_devaddr_s devgen; /* Address generation data */
/* Root hub ports */
struct sam_rhport_s rhport[SAM_EHCI_NRHPORT];
@ -4827,6 +4829,10 @@ struct usbhost_connection_s *sam_ehci_initialize(int controller)
usbhost_vtrace1(EHCI_VTRACE1_INITIALIZING, 0);
/* Initialize function address generation logic */
usbhost_devaddr_initialize(&g_ehci.devgen);
/* Initialize the root hub port structures */
for (i = 0; i < SAM_EHCI_NRHPORT; i++)
@ -4853,6 +4859,7 @@ struct usbhost_connection_s *sam_ehci_initialize(int controller)
rhport->drvr.connect = sam_connect;
#endif
rhport->drvr.disconnect = sam_disconnect;
rhport->hport.pdevgen = &g_ehci.devgen;
/* Initialize EP0 */
@ -4871,10 +4878,6 @@ struct usbhost_connection_s *sam_ehci_initialize(int controller)
hport->ep0 = &rhport->ep0;
hport->port = i;
hport->speed = USB_SPEED_FULL;
/* Initialize function address generation logic */
usbhost_devaddr_initialize(&rhport->hport);
}
#ifndef CONFIG_SAMA5_EHCI_PREALLOCATE

View File

@ -266,6 +266,8 @@ struct sam_ohci_s
volatile struct usbhost_hubport_s *hport;
#endif
struct usbhost_devaddr_s devgen; /* Address generation data */
/* Root hub ports */
struct sam_rhport_s rhport[SAM_OHCI_NRHPORT];
@ -4068,6 +4070,10 @@ struct usbhost_connection_s *sam_ohci_initialize(int controller)
buffer += CONFIG_SAMA5_OHCI_TDBUFSIZE;
}
/* Initialize function address generation logic */
usbhost_devaddr_initialize(&g_ohci.devgen);
/* Initialize the root hub port structures */
for (i = 0; i < SAM_OHCI_NRHPORT; i++)
@ -4094,6 +4100,7 @@ struct usbhost_connection_s *sam_ohci_initialize(int controller)
rhport->drvr.connect = sam_connect;
#endif
rhport->drvr.disconnect = sam_disconnect;
rhport->hport.pdevgen = &g_ohci.devgen;
/* Initialize the public port representation */
@ -4106,10 +4113,6 @@ struct usbhost_connection_s *sam_ohci_initialize(int controller)
hport->port = i;
hport->speed = USB_SPEED_FULL;
hport->funcaddr = 0;
/* Initialize function address generation logic */
usbhost_devaddr_initialize(&rhport->hport);
}
/* Wait 50MS then perform hardware reset */

View File

@ -664,6 +664,8 @@ struct sam_usbhost_s
volatile struct usbhost_hubport_s *hport;
#endif
struct usbhost_devaddr_s devgen; /* Address generation data */
/* The pipe list */
aligned_data(4)
@ -1294,7 +1296,7 @@ static void sam_putreg32(uint32_t regval, uintptr_t regaddr)
putreg32(regval, regaddr);
}
#else
static inline void sam_putreg32(uint32_t regval, uint32_t regaddr)
static inline void sam_putreg32(uint32_t regval, uintptr_t regaddr)
{
putreg32(regval, regaddr);
}
@ -1347,7 +1349,7 @@ static void sam_putreg16(uint16_t regval, uintptr_t regaddr)
putreg16(regval, regaddr);
}
#else
static inline void sam_putreg16(uint16_t regval, uint32_t regaddr)
static inline void sam_putreg16(uint16_t regval, uintptr_t regaddr)
{
putreg16(regval, regaddr);
}
@ -1400,7 +1402,7 @@ static void sam_putreg8(uint8_t regval, uintptr_t regaddr)
putreg8(regval, regaddr);
}
#else
static inline void sam_putreg8(uint8_t regval, uint32_t regaddr)
static inline void sam_putreg8(uint8_t regval, uintptr_t regaddr)
{
putreg8(regval, regaddr);
}
@ -6043,7 +6045,7 @@ static int sam_ctrl_recvdata(struct sam_usbhost_s *priv,
uinfo("pipe%d buffer:%p buflen:%d ADDR=0x%x PKTSIZE=0x%x\n",
pipe->idx, buffer, buflen,
pipe->descb[0]->addr,
pipe->descb[0]->pktsize)
pipe->descb[0]->pktsize);
uinfo("EXTREG=0x%x STATUSBK=0x%x CTRLPIPE=0x%x STATUSPIPE=0x%x\n",
pipe->descb[0]->extreg,
@ -8477,7 +8479,8 @@ static inline void sam_sw_initialize(struct sam_usbhost_s *priv)
/* Initialize function address generation logic */
usbhost_devaddr_initialize(&priv->rhport);
usbhost_devaddr_initialize(&priv->devgen);
priv->rhport.pdevgen = &priv->devgen;
/* Initialize the pipe list */

View File

@ -256,6 +256,8 @@ struct stm32_usbhost_s
volatile struct usbhost_hubport_s *hport;
#endif
struct usbhost_devaddr_s devgen; /* Address generation data */
/* The state of each host channel */
struct stm32_chan_s chan[STM32_MAX_TX_FIFOS];
@ -5243,7 +5245,8 @@ static inline void stm32_sw_initialize(struct stm32_usbhost_s *priv)
/* Initialize function address generation logic */
usbhost_devaddr_initialize(&priv->rhport);
usbhost_devaddr_initialize(&priv->devgen);
priv->rhport.pdevgen = &priv->devgen;
/* Initialize the driver state data */

View File

@ -261,6 +261,8 @@ struct stm32_usbhost_s
volatile struct usbhost_hubport_s *hport;
#endif
struct usbhost_devaddr_s devgen; /* Address generation data */
/* The state of each host channel */
struct stm32_chan_s chan[STM32_MAX_TX_FIFOS];
@ -5242,7 +5244,8 @@ static inline void stm32_sw_initialize(struct stm32_usbhost_s *priv)
/* Initialize function address generation logic */
usbhost_devaddr_initialize(&priv->rhport);
usbhost_devaddr_initialize(&priv->devgen);
priv->rhport.pdevgen = &priv->devgen;
/* Initialize the driver state data */

View File

@ -257,6 +257,8 @@ struct stm32_usbhost_s
volatile struct usbhost_hubport_s *hport;
#endif
struct usbhost_devaddr_s devgen; /* Address generation data */
/* The state of each host channel */
struct stm32_chan_s chan[STM32_MAX_TX_FIFOS];
@ -5217,7 +5219,8 @@ static inline void stm32_sw_initialize(struct stm32_usbhost_s *priv)
/* Initialize function address generation logic */
usbhost_devaddr_initialize(&priv->rhport);
usbhost_devaddr_initialize(&priv->devgen);
priv->rhport.pdevgen = &priv->devgen;
/* Initialize the driver state data */

View File

@ -257,6 +257,8 @@ struct stm32_usbhost_s
volatile struct usbhost_hubport_s *hport;
#endif
struct usbhost_devaddr_s devgen; /* Address generation data */
/* The state of each host channel */
struct stm32_chan_s chan[STM32_MAX_TX_FIFOS];
@ -5219,7 +5221,8 @@ static inline void stm32_sw_initialize(struct stm32_usbhost_s *priv)
/* Initialize function address generation logic */
usbhost_devaddr_initialize(&priv->rhport);
usbhost_devaddr_initialize(&priv->devgen);
priv->rhport.pdevgen = &priv->devgen;
/* Initialize the driver state data */

View File

@ -254,6 +254,8 @@ struct stm32l4_usbhost_s
volatile struct usbhost_hubport_s *hport;
#endif
struct usbhost_devaddr_s devgen; /* Address generation data */
/* The state of each host channel */
struct stm32l4_chan_s chan[STM32L4_MAX_TX_FIFOS];
@ -5256,7 +5258,8 @@ static inline void stm32l4_sw_initialize(struct stm32l4_usbhost_s *priv)
/* Initialize function address generation logic */
usbhost_devaddr_initialize(&priv->rhport);
usbhost_devaddr_initialize(&priv->devgen);
priv->rhport.pdevgen = &priv->devgen;
/* Initialize the driver state data */

View File

@ -150,6 +150,8 @@ struct rx65n_usbhost_s
volatile struct usbhost_hubport_s *hport;
#endif
struct usbhost_devaddr_s devgen; /* Address generation data */
};
/* This structure describes one asynchronous transfer */
@ -8350,7 +8352,8 @@ struct usbhost_connection_s *rx65n_usbhost_initialize(int controller)
/* Initialize function address generation logic */
usbhost_devaddr_initialize(&priv->rhport);
usbhost_devaddr_initialize(&priv->devgen);
priv->rhport.pdevgen = &priv->devgen;
#ifndef CONFIG_USBHOST_INT_DISABLE
priv->ininterval = MAX_PERINTERVAL;

View File

@ -106,6 +106,8 @@ struct sim_usbhost_s
mutex_t lock; /* Support mutually exclusive access */
sem_t pscsem; /* Semaphore to wait for port status change events */
struct usbhost_devaddr_s devgen; /* Address generation data */
};
/****************************************************************************
@ -700,7 +702,8 @@ int sim_usbhost_initialize(void)
/* Initialize function address generation logic */
usbhost_devaddr_initialize(&priv->hport);
usbhost_devaddr_initialize(&priv->devgen);
priv->hport.pdevgen = &priv->devgen;
/* Initialize host usb controller */

View File

@ -182,7 +182,7 @@ usbhost_devaddr_gen(FAR struct usbhost_hubport_s *hport)
rhport = usbhost_roothubport(hport);
if (rhport != NULL)
{
return &rhport->devgen;
return rhport->pdevgen;
}
return NULL;
@ -201,23 +201,29 @@ usbhost_devaddr_gen(FAR struct usbhost_hubport_s *hport)
* hub port.
*
* Input Parameters:
* rhport - A reference to a roothubport structure.
* devgen - A reference to a usbhost_devaddr_s structure.
*
* Returned Value:
* None
* On success, zero (OK) is returned. On a failure, a negated errno value
* is returned indicating the nature of the failure.
*
****************************************************************************/
void usbhost_devaddr_initialize(FAR struct usbhost_roothubport_s *rhport)
int usbhost_devaddr_initialize(FAR struct usbhost_devaddr_s *devgen)
{
FAR struct usbhost_devaddr_s *devgen;
int ret = -EINVAL;
DEBUGASSERT(rhport);
devgen = &rhport->devgen;
DEBUGASSERT(devgen);
memset(devgen, 0, sizeof(struct usbhost_devaddr_s));
nxmutex_init(&devgen->lock);
devgen->next = 1;
if (devgen)
{
memset(devgen, 0, sizeof(struct usbhost_devaddr_s));
nxmutex_init(&devgen->lock);
devgen->next = 1;
ret = OK;
}
return ret;
}
/****************************************************************************

View File

@ -113,8 +113,6 @@
#define MAX3421E_DATANAK_DELAY SEC2TICK(5) /* 5 seconds in system ticks */
#define MAX3421E_RETRY_COUNT 5 /* Number of tries before giving up */
#define NO_HOLDER (INVALID_PROCESS_ID)
/* Debug ********************************************************************/
#define TR_FMT1 false
@ -221,6 +219,8 @@ struct max3421e_usbhost_s
FAR struct usbhost_hubport_s *hport;
#endif
struct usbhost_devaddr_s devgen; /* Address generation data */
/* The channel waiting for the next event (there will only be one in
* this design)
*/
@ -4683,7 +4683,8 @@ static inline int max3421e_sw_initialize(FAR struct max3421e_usbhost_s *priv,
/* Initialize function address generation logic */
usbhost_devaddr_initialize(&priv->rhport);
usbhost_devaddr_initialize(&priv->devgen);
priv->rhport.pdevgen = &priv->devgen;
/* Initialize semaphores */
@ -4701,7 +4702,6 @@ static inline int max3421e_sw_initialize(FAR struct max3421e_usbhost_s *priv,
priv->connected = false;
priv->irqset = 0;
priv->change = false;
priv->holder = NO_HOLDER;
/* Put all of the channels back in their initial, allocated state */

View File

@ -734,7 +734,7 @@ struct usbhost_roothubport_s
*/
struct usbhost_hubport_s hport; /* Common hub port definitions */
struct usbhost_devaddr_s devgen; /* Address generation data */
struct usbhost_devaddr_s *pdevgen; /* Address generation data pointer */
};
/* struct usbhost_class_s provides access from the USB host driver to the

View File

@ -81,14 +81,15 @@ struct usbhost_roothubport_s; /* Forward reference */
* hub port.
*
* Input Parameters:
* rhport - A reference to a roothubport structure.
* devgen - A reference to a usbhost_devaddr_s structure.
*
* Returned Value:
* None
* On success, zero (OK) is returned. On a failure, a negated errno value
* is returned indicating the nature of the failure.
*
****************************************************************************/
void usbhost_devaddr_initialize(FAR struct usbhost_roothubport_s *rhport);
int usbhost_devaddr_initialize(FAR struct usbhost_devaddr_s *devgen);
/****************************************************************************
* Name: usbhost_devaddr_create