dpaa2-eth: recycle the RX buffer only after all processing done
authorIoana Ciornei <ioana.ciornei@nxp.com>
Fri, 24 Nov 2023 10:28:05 +0000 (12:28 +0200)
committerDavid S. Miller <davem@davemloft.net>
Sun, 26 Nov 2023 15:18:57 +0000 (15:18 +0000)
The blamed commit added support for Rx copybreak. This meant that for
certain frame sizes, a new skb was allocated and the initial data buffer
was recycled. Instead of waiting to recycle the Rx buffer only after all
processing was done on it (like accessing the parse results or timestamp
information), the code path just went ahead and re-used the buffer right
away.

This sometimes lead to corrupted HW and SW annotation areas.
Fix this by delaying the moment when the buffer is recycled.

Fixes: 50f826999a80 ("dpaa2-eth: add rx copybreak support")
Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c

index 774377db0b4bdd3a413dd999b40a0ee6263ebe0d..888509cf1f210ecb1ff6771542e85df76c07ce2e 100644 (file)
@@ -516,8 +516,6 @@ struct sk_buff *dpaa2_eth_alloc_skb(struct dpaa2_eth_priv *priv,
 
        memcpy(skb->data, fd_vaddr + fd_offset, fd_length);
 
-       dpaa2_eth_recycle_buf(priv, ch, dpaa2_fd_get_addr(fd));
-
        return skb;
 }
 
@@ -589,6 +587,7 @@ void dpaa2_eth_rx(struct dpaa2_eth_priv *priv,
        struct rtnl_link_stats64 *percpu_stats;
        struct dpaa2_eth_drv_stats *percpu_extras;
        struct device *dev = priv->net_dev->dev.parent;
+       bool recycle_rx_buf = false;
        void *buf_data;
        u32 xdp_act;
 
@@ -618,6 +617,8 @@ void dpaa2_eth_rx(struct dpaa2_eth_priv *priv,
                        dma_unmap_page(dev, addr, priv->rx_buf_size,
                                       DMA_BIDIRECTIONAL);
                        skb = dpaa2_eth_build_linear_skb(ch, fd, vaddr);
+               } else {
+                       recycle_rx_buf = true;
                }
        } else if (fd_format == dpaa2_fd_sg) {
                WARN_ON(priv->xdp_prog);
@@ -637,6 +638,9 @@ void dpaa2_eth_rx(struct dpaa2_eth_priv *priv,
                goto err_build_skb;
 
        dpaa2_eth_receive_skb(priv, ch, fd, vaddr, fq, percpu_stats, skb);
+
+       if (recycle_rx_buf)
+               dpaa2_eth_recycle_buf(priv, ch, dpaa2_fd_get_addr(fd));
        return;
 
 err_build_skb: