]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
net: ethernet: ti: am65-cpsw: fix memleak in certain XDP cases
authorRoger Quadros <rogerq@kernel.org>
Mon, 10 Feb 2025 14:52:15 +0000 (16:52 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 21 Feb 2025 13:01:18 +0000 (14:01 +0100)
[ Upstream commit 5db843258de1e4e6b1ef1cbd1797923c9e3de548 ]

If the XDP program doesn't result in XDP_PASS then we leak the
memory allocated by am65_cpsw_build_skb().

It is pointless to allocate SKB memory before running the XDP
program as we would be wasting CPU cycles for cases other than XDP_PASS.
Move the SKB allocation after evaluating the XDP program result.

This fixes the memleak. A performance boost is seen for XDP_DROP test.

XDP_DROP test:
Before: 460256 rx/s                  0 err/s
After:  784130 rx/s                  0 err/s

Fixes: 8acacc40f733 ("net: ethernet: ti: am65-cpsw: Add minimal XDP support")
Signed-off-by: Roger Quadros <rogerq@kernel.org>
Link: https://patch.msgid.link/20250210-am65-cpsw-xdp-fixes-v1-1-ec6b1f7f1aca@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/net/ethernet/ti/am65-cpsw-nuss.c

index 3c0d067c36099207045e2e51188c42f33244673d..14df3c0141679abe6179fc8a483b3ad066ef4c34 100644 (file)
@@ -599,7 +599,8 @@ static void am65_cpsw_nuss_tx_cleanup(void *data, dma_addr_t desc_dma)
 
 static struct sk_buff *am65_cpsw_build_skb(void *page_addr,
                                           struct net_device *ndev,
-                                          unsigned int len)
+                                          unsigned int len,
+                                          unsigned int headroom)
 {
        struct sk_buff *skb;
 
@@ -609,7 +610,7 @@ static struct sk_buff *am65_cpsw_build_skb(void *page_addr,
        if (unlikely(!skb))
                return NULL;
 
-       skb_reserve(skb, AM65_CPSW_HEADROOM);
+       skb_reserve(skb, headroom);
        skb->dev = ndev;
 
        return skb;
@@ -1191,16 +1192,8 @@ static int am65_cpsw_nuss_rx_packets(struct am65_cpsw_rx_flow *flow,
        dev_dbg(dev, "%s rx csum_info:%#x\n", __func__, csum_info);
 
        dma_unmap_single(rx_chn->dma_dev, buf_dma, buf_dma_len, DMA_FROM_DEVICE);
-
        k3_cppi_desc_pool_free(rx_chn->desc_pool, desc_rx);
 
-       skb = am65_cpsw_build_skb(page_addr, ndev,
-                                 AM65_CPSW_MAX_PACKET_SIZE);
-       if (unlikely(!skb)) {
-               new_page = page;
-               goto requeue;
-       }
-
        if (port->xdp_prog) {
                xdp_init_buff(&xdp, PAGE_SIZE, &port->xdp_rxq[flow->id]);
                xdp_prepare_buff(&xdp, page_addr, AM65_CPSW_HEADROOM,
@@ -1210,9 +1203,16 @@ static int am65_cpsw_nuss_rx_packets(struct am65_cpsw_rx_flow *flow,
                if (*xdp_state != AM65_CPSW_XDP_PASS)
                        goto allocate;
 
-               /* Compute additional headroom to be reserved */
-               headroom = (xdp.data - xdp.data_hard_start) - skb_headroom(skb);
-               skb_reserve(skb, headroom);
+               headroom = xdp.data - xdp.data_hard_start;
+       } else {
+               headroom = AM65_CPSW_HEADROOM;
+       }
+
+       skb = am65_cpsw_build_skb(page_addr, ndev,
+                                 AM65_CPSW_MAX_PACKET_SIZE, headroom);
+       if (unlikely(!skb)) {
+               new_page = page;
+               goto requeue;
        }
 
        ndev_priv = netdev_priv(ndev);