]> git.ipfire.org Git - thirdparty/u-boot.git/commitdiff
net: zynq_gem: reinitialize RX BDs on every init
authorPranav Tilak <pranav.vinaytilak@amd.com>
Fri, 10 Apr 2026 09:30:18 +0000 (15:00 +0530)
committerMichal Simek <michal.simek@amd.com>
Thu, 23 Apr 2026 09:49:48 +0000 (11:49 +0200)
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
drivers/net/zynq_gem.c

index e9210d42438dd2e19ce861c64e20bd21e1bf7137..e3f9fd72d2fc5350a6a641319405eecec4eec14c 100644 (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;