[PATCH 3/3] net: zynq_gem: reinitialize RX BDs on every init
Pranav Tilak
pranav.vinaytilak at amd.com
Fri Apr 10 11:30:18 CEST 2026
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 at amd.com>
---
drivers/net/zynq_gem.c | 51 ++++++++++++++++++++++++------------------
1 file changed, 29 insertions(+), 22 deletions(-)
diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c
index e9210d42438..e3f9fd72d2f 100644
--- a/drivers/net/zynq_gem.c
+++ b/drivers/net/zynq_gem.c
@@ -474,28 +474,6 @@ static int zynq_gem_init(struct udevice *dev)
for (i = 0; i < STAT_SIZE; i++)
readl(®s->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), ®s->rxqbase);
-#if defined(CONFIG_PHYS_64BIT)
- writel(upper_32_bits((ulong)priv->rx_bd), ®s->upper_rxqbase);
-#endif
-
/* Setup for DMA Configuration register */
writel(ZYNQ_GEM_DMACR_INIT, ®s->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), ®s->rxqbase);
+#if defined(CONFIG_PHYS_64BIT)
+ writel(upper_32_bits((ulong)priv->rx_bd), ®s->upper_rxqbase);
+#endif
+
ret = phy_startup(priv->phydev);
if (ret)
return ret;
--
2.43.0
More information about the U-Boot
mailing list