net: zynq_gem: reinitialize RX BDs on every init

Reinitialize RX BDs and rewrite rxqbase on every init instead of only
on the first init. This ensures a clean BD state on every init for all
GEM configurations.
For AMD Versal Gen 2 10GBE this is required since the USX block
resets the RX DMA pointer to rxqbase on each init, so BDs must be
rebuilt each time to stay in sync with hardware.

Signed-off-by: Pranav Tilak <pranav.vinaytilak@amd.com>
Signed-off-by: Michal Simek <michal.simek@amd.com>
Link: https://lore.kernel.org/r/20260410093018.1461732-4-pranav.vinaytilak@amd.com
This commit is contained in:
Pranav Tilak 2026-04-10 15:00:18 +05:30 committed by Michal Simek
parent 0443deb428
commit 89c269154b

View File

@ -474,28 +474,6 @@ static int zynq_gem_init(struct udevice *dev)
for (i = 0; i < STAT_SIZE; i++)
readl(&regs->stat[i]);
/* Setup RxBD space */
memset(priv->rx_bd, 0, RX_BUF * sizeof(struct emac_bd));
for (i = 0; i < RX_BUF; i++) {
priv->rx_bd[i].status = 0xF0000000;
priv->rx_bd[i].addr =
(lower_32_bits((ulong)(priv->rxbuffers)
+ (i * PKTSIZE_ALIGN)));
#if defined(CONFIG_PHYS_64BIT)
priv->rx_bd[i].addr_hi =
(upper_32_bits((ulong)(priv->rxbuffers)
+ (i * PKTSIZE_ALIGN)));
#endif
}
/* WRAP bit to last BD */
priv->rx_bd[--i].addr |= ZYNQ_GEM_RXBUF_WRAP_MASK;
/* Write RxBDs to IP */
writel(lower_32_bits((ulong)priv->rx_bd), &regs->rxqbase);
#if defined(CONFIG_PHYS_64BIT)
writel(upper_32_bits((ulong)priv->rx_bd), &regs->upper_rxqbase);
#endif
/* Setup for DMA Configuration register */
writel(ZYNQ_GEM_DMACR_INIT, &regs->dmacr);
@ -524,6 +502,35 @@ static int zynq_gem_init(struct udevice *dev)
priv->init++;
}
/*
* Reinitialize RX BDs on every init. The 10GBE USX block asserts
* RX_SYNC_RESET during setup which resets the GEM RX DMA pointer
* back to rxqbase, so BDs and rxqbase must be refreshed each time
* to keep the hardware and driver ring indices in sync.
*/
priv->rxbd_current = 0;
priv->rx_first_buf = 0;
memset(priv->rx_bd, 0, RX_BUF * sizeof(struct emac_bd));
for (i = 0; i < RX_BUF; i++) {
priv->rx_bd[i].status = 0xF0000000;
priv->rx_bd[i].addr =
(lower_32_bits((ulong)(priv->rxbuffers)
+ (i * PKTSIZE_ALIGN)));
#if defined(CONFIG_PHYS_64BIT)
priv->rx_bd[i].addr_hi =
(upper_32_bits((ulong)(priv->rxbuffers)
+ (i * PKTSIZE_ALIGN)));
#endif
}
/* WRAP bit to last BD */
priv->rx_bd[--i].addr |= ZYNQ_GEM_RXBUF_WRAP_MASK;
/* Write RxBDs to IP */
writel(lower_32_bits((ulong)priv->rx_bd), &regs->rxqbase);
#if defined(CONFIG_PHYS_64BIT)
writel(upper_32_bits((ulong)priv->rx_bd), &regs->upper_rxqbase);
#endif
ret = phy_startup(priv->phydev);
if (ret)
return ret;