On Tue, 30 Mar 2021 10:49:47 +0800 Ong Boon Leong wrote: > + if (!skb) { > + dma_sync_single_for_cpu(priv->device, buf->addr, > + buf1_len, dma_dir); > + > + xdp.data = page_address(buf->page) + buf->page_offset; > + xdp.data_end = xdp.data + len; > + xdp.data_hard_start = page_address(buf->page); > + xdp_set_data_meta_invalid(&xdp); > + xdp.frame_sz = buf_sz; > + > + skb = stmmac_xdp_run_prog(priv, &xdp); > + > + /* For Not XDP_PASS verdict */ > + if (IS_ERR(skb)) { > + unsigned int xdp_res = -PTR_ERR(skb); > + > + if (xdp_res & STMMAC_XDP_CONSUMED) { > + page_pool_recycle_direct(rx_q->page_pool, > + buf->page); > + buf->page = NULL; > + priv->dev->stats.rx_dropped++; > + > + /* Clear skb as it was set as > + * status by XDP program. > + */ > + skb = NULL; > + > + if (unlikely((status & rx_not_ls))) > + goto read_again; > + > + count++; > + continue; > + } > + } > + } > + > if (!skb) { > skb = napi_alloc_skb(&ch->rx_napi, buf1_len); > if (!skb) { > @@ -4322,9 +4400,8 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue) > goto drain_data; > } > > - dma_sync_single_for_cpu(priv->device, buf->addr, > - buf1_len, DMA_FROM_DEVICE); > - skb_copy_to_linear_data(skb, page_address(buf->page), > + skb_copy_to_linear_data(skb, page_address(buf->page) + > + buf->page_offset, > buf1_len); XDP can prepend or remove headers (using the bpf_xdp_adjust_head() helper), so the start of data may no longer be page + HEADROOM, and the length of the frame may have changed. Are you accounting for this?