The Rx descriptors are chained by hand, one assignment per descriptor
and per field. Adding a descriptor means adding another block of
next_desc/buf_addr/cntrl assignments, so the number of Rx descriptors
is effectively frozen at two.

Build the same chain in a loop over RX_DESC instead. Each descriptor
points at its successor, the last one wraps back to the first, and each
gets its own PKTSIZE_ALIGN slice of the Rx buffer pool. The tail
descriptor is now the last one of the ring rather than a hardcoded
rx_bd[1]. The resulting ring is identical to the hand-written one for
RX_DESC = 2, but the descriptor count is now a single constant to
change.

Signed-off-by: Padmarao Begari <[email protected]>
---
 drivers/net/xilinx_axi_mrmac.c | 34 +++++++++++++++++++---------------
 1 file changed, 19 insertions(+), 15 deletions(-)

diff --git a/drivers/net/xilinx_axi_mrmac.c b/drivers/net/xilinx_axi_mrmac.c
index d77b0e3445b..2c97e9576c9 100644
--- a/drivers/net/xilinx_axi_mrmac.c
+++ b/drivers/net/xilinx_axi_mrmac.c
@@ -162,6 +162,7 @@ static int axi_mrmac_start(struct udevice *dev)
 {
        struct axi_mrmac_priv *priv = dev_get_priv(dev);
        struct mrmac_regs *regs = priv->iobase;
+       int i;
 
        /*
         * Initialize MCDMA engine. MCDMA engine must be initialized before
@@ -181,27 +182,30 @@ static int axi_mrmac_start(struct udevice *dev)
        /* Update current descriptor */
        axi_mrmac_dma_write(&priv->rx_bd[0], &priv->mcdma_rx->current);
 
-       /* Setup Rx BD. MRMAC needs atleast two descriptors */
+       /*
+        * Setup Rx BDs as a closed ring: every descriptor points at the next
+        * one and the last one wraps back to the first, each with its own
+        * slice of the Rx buffer pool. MRMAC needs at least two descriptors.
+        */
        memset(priv->rx_bd, 0, RX_BD_TOTAL_SIZE);
 
-       priv->rx_bd[0].next_desc = lower_32_bits((u64)&priv->rx_bd[1]);
-       priv->rx_bd[0].buf_addr = lower_32_bits((u64)priv->rx_buf);
+       for (i = 0; i < RX_DESC; i++) {
+               struct mcdma_bd *next = &priv->rx_bd[(i + 1) % RX_DESC];
+               u8 *buf = priv->rx_buf + i * PKTSIZE_ALIGN;
+               struct mcdma_bd *bd = &priv->rx_bd[i];
 
-       priv->rx_bd[1].next_desc = lower_32_bits((u64)&priv->rx_bd[0]);
-       priv->rx_bd[1].buf_addr = lower_32_bits((u64)priv->rx_buf + 
PKTSIZE_ALIGN);
+               bd->next_desc = lower_32_bits((u64)next);
+               bd->buf_addr = lower_32_bits((u64)buf);
 
-       if (IS_ENABLED(CONFIG_PHYS_64BIT)) {
-               priv->rx_bd[0].next_desc_msb = 
upper_32_bits((u64)&priv->rx_bd[1]);
-               priv->rx_bd[0].buf_addr_msb = upper_32_bits((u64)priv->rx_buf);
+               if (IS_ENABLED(CONFIG_PHYS_64BIT)) {
+                       bd->next_desc_msb = upper_32_bits((u64)next);
+                       bd->buf_addr_msb = upper_32_bits((u64)buf);
+               }
 
-               priv->rx_bd[1].next_desc_msb = 
upper_32_bits((u64)&priv->rx_bd[0]);
-               priv->rx_bd[1].buf_addr_msb = upper_32_bits((u64)priv->rx_buf + 
PKTSIZE_ALIGN);
+               bd->cntrl = PKTSIZE_ALIGN;
        }
 
-       priv->rx_bd[0].cntrl = PKTSIZE_ALIGN;
-       priv->rx_bd[1].cntrl = PKTSIZE_ALIGN;
-
-       /* Flush the last BD so DMA core could see the updates */
+       /* Flush the BDs so DMA core could see the updates */
        flush_cache((phys_addr_t)priv->rx_bd, RX_BD_TOTAL_SIZE);
 
        /* It is necessary to flush rx buffers because if you don't do it
@@ -218,7 +222,7 @@ static int axi_mrmac_start(struct udevice *dev)
        setbits_le32(&priv->mcdma_rx->control, XMCDMA_CR_RUNSTOP_MASK);
 
        /* Update tail descriptor. Now it's ready to receive data */
-       axi_mrmac_dma_write(&priv->rx_bd[1], &priv->mcdma_rx->tail);
+       axi_mrmac_dma_write(&priv->rx_bd[RX_DESC - 1], &priv->mcdma_rx->tail);
 
        /* Enable Tx */
        setbits_le32(&regs->tx_config, MRMAC_TX_EN_MASK);
-- 
2.34.1

Reply via email to