]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
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)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 10 Jan 2024 16:10:32 +0000 (17:10 +0100)
[ Upstream commit beb1930f966d1517921488bd5d64147f58f79abf ]

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>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c

index b58162ce81d87a8ae05d33e7bc9cb168abb4d26b..de62eee58a00e4d1f0de17c3c90461b0a688e2a5 100644 (file)
@@ -509,8 +509,6 @@ static struct sk_buff *dpaa2_eth_copybreak(struct dpaa2_eth_channel *ch,
 
        memcpy(skb->data, fd_vaddr + fd_offset, fd_length);
 
-       dpaa2_eth_recycle_buf(priv, ch, dpaa2_fd_get_addr(fd));
-
        return skb;
 }
 
@@ -528,6 +526,7 @@ static void dpaa2_eth_rx(struct dpaa2_eth_priv *priv,
        struct dpaa2_eth_drv_stats *percpu_extras;
        struct device *dev = priv->net_dev->dev.parent;
        struct dpaa2_fas *fas;
+       bool recycle_rx_buf = false;
        void *buf_data;
        u32 status = 0;
        u32 xdp_act;
@@ -560,6 +559,8 @@ static 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);
@@ -607,6 +608,8 @@ static void dpaa2_eth_rx(struct dpaa2_eth_priv *priv,
 
        list_add_tail(&skb->list, ch->rx_list);
 
+       if (recycle_rx_buf)
+               dpaa2_eth_recycle_buf(priv, ch, dpaa2_fd_get_addr(fd));
        return;
 
 err_build_skb: