]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
net: airoha: Reserve RX headroom to avoid skb reallocation
authorLorenzo Bianconi <lorenzo@kernel.org>
Wed, 13 May 2026 15:03:59 +0000 (17:03 +0200)
committerJakub Kicinski <kuba@kernel.org>
Sat, 16 May 2026 00:25:08 +0000 (17:25 -0700)
Reserve NET_SKB_PAD + NET_IP_ALIGN bytes of headroom for received packets
to avoid skb head reallocation when pushing protocol headers into the skb.

Tested-by: Xuegang Lu <xuegang.lu@airoha.com>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Link: https://patch.msgid.link/20260513-airoha-rx-headroom-v1-1-bd87798e422d@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/airoha/airoha_eth.c
drivers/net/ethernet/airoha/airoha_eth.h

index f71fb18197ecdcee58d8ca624382a4888bdee40e..5a027cc7ffcb10e4649be5268e828a26b5d95877 100644 (file)
@@ -543,9 +543,10 @@ static int airoha_qdma_fill_rx_queue(struct airoha_queue *q)
                q->queued++;
                nframes++;
 
+               offset += AIROHA_RX_HEADROOM;
                e->buf = page_address(page) + offset;
                e->dma_addr = page_pool_get_dma_addr(page) + offset;
-               e->dma_len = SKB_WITH_OVERHEAD(q->buf_size);
+               e->dma_len = SKB_WITH_OVERHEAD(AIROHA_RX_LEN(q->buf_size));
 
                val = FIELD_PREP(QDMA_DESC_LEN_MASK, e->dma_len);
                WRITE_ONCE(desc->ctrl, cpu_to_le32(val));
@@ -611,13 +612,12 @@ static int airoha_qdma_rx_process(struct airoha_queue *q, int budget)
                q->tail = (q->tail + 1) % q->ndesc;
                q->queued--;
 
-               dma_sync_single_for_cpu(eth->dev, e->dma_addr,
-                                       SKB_WITH_OVERHEAD(q->buf_size), dir);
+               dma_sync_single_for_cpu(eth->dev, e->dma_addr, e->dma_len,
+                                       dir);
 
                page = virt_to_head_page(e->buf);
                len = FIELD_GET(QDMA_DESC_LEN_MASK, desc_ctrl);
-               data_len = q->skb ? q->buf_size
-                                 : SKB_WITH_OVERHEAD(q->buf_size);
+               data_len = q->skb ? AIROHA_RX_LEN(q->buf_size) : e->dma_len;
                if (!len || data_len < len)
                        goto free_frag;
 
@@ -627,10 +627,12 @@ static int airoha_qdma_rx_process(struct airoha_queue *q, int budget)
 
                port = eth->ports[p];
                if (!q->skb) { /* first buffer */
-                       q->skb = napi_build_skb(e->buf, q->buf_size);
+                       q->skb = napi_build_skb(e->buf - AIROHA_RX_HEADROOM,
+                                               q->buf_size);
                        if (!q->skb)
                                goto free_frag;
 
+                       skb_reserve(q->skb, AIROHA_RX_HEADROOM);
                        __skb_put(q->skb, len);
                        skb_mark_for_recycle(q->skb);
                        q->skb->dev = port->dev;
index 58530d096de76475225d6f5d6cbda62e97203341..d3781103abb5d29d1d3ba019abe7fdc46fd8c9d4 100644 (file)
@@ -32,6 +32,8 @@
 #define AIROHA_FE_MC_MAX_VLAN_TABLE    64
 #define AIROHA_FE_MC_MAX_VLAN_PORT     16
 #define AIROHA_NUM_TX_IRQ              2
+#define AIROHA_RX_HEADROOM             (NET_SKB_PAD + NET_IP_ALIGN)
+#define AIROHA_RX_LEN(_n)              ((_n) - AIROHA_RX_HEADROOM)
 #define HW_DSCP_NUM                    2048
 #define IRQ_QUEUE_LEN(_n)              ((_n) ? 1024 : 2048)
 #define TX_DSCP_NUM                    1024