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);
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;