Subject: Re: [PATCH net-next v6 02/12] net: airoha: Reserve RX headroom to avoid skb reallocation

From: Lorenzo Bianconi <[email-masked]>
Date: Tue, 12 May 2026 22:31:48 +0200

On May 11, Lorenzo Bianconi wrote:
> 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 <[email-masked]>
> Signed-off-by: Lorenzo Bianconi <[email-masked]>
> ---
>  drivers/net/ethernet/airoha/airoha_eth.c | 12 ++++++++----
>  drivers/net/ethernet/airoha/airoha_eth.h |  2 ++
>  2 files changed, 10 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
> index f71fb18197ec..3fe2561c85f1 100644
> --- a/drivers/net/ethernet/airoha/airoha_eth.c
> +++ b/drivers/net/ethernet/airoha/airoha_eth.c
> @@ -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));
> @@ -616,8 +617,9 @@ static int airoha_qdma_rx_process(struct airoha_queue *q, int budget)
>  
>  		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)
> +			   : SKB_WITH_OVERHEAD(AIROHA_RX_LEN(q->buf_size));
>  		if (!len || data_len < len)
>  			goto free_frag;
>  
> @@ -627,10 +629,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;
> diff --git a/drivers/net/ethernet/airoha/airoha_eth.h b/drivers/net/ethernet/airoha/airoha_eth.h
> index 58530d096de7..d3781103abb5 100644
> --- a/drivers/net/ethernet/airoha/airoha_eth.h
> +++ b/drivers/net/ethernet/airoha/airoha_eth.h
> @@ -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
> 
> -- 
> 2.54.0
> 

commenting on sashiko's report:
https://sashiko.dev/#/patchset/20260511-airoha-eth-multi-serdes-v6-0-c899462c4f75%40kernel.org

- Does the length passed to dma_sync_single_for_cpu() also need to be updated
  to match the new DMA length?
  I will fix it in v7.

Regards,
Lorenzo