[RFC: DMA_PMD 19/22] net/mlx5e: Use DMA_PMD memory for tx header bounce buffers
flat view
From: Luigi Rizzo <hidden>
Date: 2026-10-03 21:23:15
Also in:
driver-core, linux-doc, linux-iommu, linux-mm, lkml
Subsystem:
mellanox ethernet driver (mlx5e), mellanox mlx5 core vpi driver, networking drivers, the rest · Maintainers:
Saeed Mahameed, Tariq Toukan, Mark Bloch, Leon Romanovsky, Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
When dev->dma_pmd_tx_hdrs is enabled, allocate a MAX_TCP_HEADER bounce buffer per TX DMA FIFO slot out of the DMA_PMD arena. When the linear portion of a transmitted packet is at most MAX_TCP_HEADER bytes, copy it into the pre-mapped bounce buffer instead of calling dma_map_single()/dma_unmap_single() on every packet. Signed-off-by: Luigi Rizzo <redacted> --- drivers/net/ethernet/mellanox/mlx5/core/en.h | 2 ++ .../net/ethernet/mellanox/mlx5/core/en/txrx.h | 4 ++- .../net/ethernet/mellanox/mlx5/core/en_main.c | 14 ++++++++++ .../net/ethernet/mellanox/mlx5/core/en_tx.c | 28 +++++++++++++++---- 4 files changed, 42 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h
index a3945195f454e..d762ad1c1ffaf 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h@@ -442,6 +442,8 @@ struct mlx5e_txqsq { struct mlx5e_sq_dma *dma_fifo; struct mlx5e_skb_fifo skb_fifo; struct mlx5e_tx_wqe_info *wqe_info; + void *tx_hdr_bufs; + dma_addr_t tx_hdr_bufs_dma; } db; void __iomem *uar_map; struct netdev_queue *txq;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h b/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h
index f2a8453d8dce0..6de7a2a430d72 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h@@ -365,7 +365,9 @@ mlx5e_tx_dma_unmap(struct device *pdev, struct mlx5e_sq_dma *dma) { switch (dma->type) { case MLX5E_DMA_MAP_SINGLE: - dma_unmap_single(pdev, dma->addr, dma->size, DMA_TO_DEVICE); + if (dma->size) + dma_unmap_single(pdev, dma->addr, dma->size, + DMA_TO_DEVICE); break; case MLX5E_DMA_MAP_PAGE: netmem_dma_unmap_page_attrs(pdev, dma->addr, dma->size,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index 4c6060d54fbed..efd766aa43a02 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c@@ -1666,6 +1666,13 @@ static void mlx5e_free_icosq(struct mlx5e_icosq *sq) void mlx5e_free_txqsq_db(struct mlx5e_txqsq *sq) { + if (sq->db.tx_hdr_bufs) { + int wq_sz = mlx5_wq_cyc_get_size(&sq->wq); + int df_sz = wq_sz * MLX5_SEND_WQEBB_NUM_DS; + + dma_free_coherent(sq->pdev, df_sz * MAX_TCP_HEADER, + sq->db.tx_hdr_bufs, sq->db.tx_hdr_bufs_dma); + } kvfree(sq->db.wqe_info); kvfree(sq->db.skb_fifo.fifo); kvfree(sq->db.dma_fifo);
@@ -1690,6 +1697,13 @@ int mlx5e_alloc_txqsq_db(struct mlx5e_txqsq *sq, int numa) return -ENOMEM; } + if (sq->pdev->dma_pmd_tx_hdrs) + sq->db.tx_hdr_bufs = + dma_alloc_coherent(sq->pdev, + df_sz * MAX_TCP_HEADER, + &sq->db.tx_hdr_bufs_dma, + GFP_KERNEL | __GFP_NOWARN); + sq->dma_fifo_mask = df_sz - 1; sq->db.skb_fifo.pc = &sq->skb_fifo_pc;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
index 0b5e600e4a6a9..3b6a7a8b0128e 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c@@ -177,6 +177,27 @@ mlx5e_tx_get_gso_ihs(struct mlx5e_txqsq *sq, struct sk_buff *skb) return ihs; } +static inline dma_addr_t +mlx5e_tx_map_hdr(struct mlx5e_txqsq *sq, unsigned char *data, u32 len) +{ + dma_addr_t dma_addr; + + if (sq->db.tx_hdr_bufs && len <= MAX_TCP_HEADER) { + u32 off = (sq->dma_fifo_pc & sq->dma_fifo_mask) * + MAX_TCP_HEADER; + + memcpy(sq->db.tx_hdr_bufs + off, data, len); + dma_addr = sq->db.tx_hdr_bufs_dma + off; + mlx5e_dma_push_single(sq, dma_addr, 0); + return dma_addr; + } + + dma_addr = dma_map_single(sq->pdev, data, len, DMA_TO_DEVICE); + if (likely(!dma_mapping_error(sq->pdev, dma_addr))) + mlx5e_dma_push_single(sq, dma_addr, len); + return dma_addr; +} + static inline int mlx5e_txwqe_build_dsegs(struct mlx5e_txqsq *sq, struct sk_buff *skb, unsigned char *skb_data, u16 headlen,
@@ -187,8 +208,7 @@ mlx5e_txwqe_build_dsegs(struct mlx5e_txqsq *sq, struct sk_buff *skb, int i; if (headlen) { - dma_addr = dma_map_single(sq->pdev, skb_data, headlen, - DMA_TO_DEVICE); + dma_addr = mlx5e_tx_map_hdr(sq, skb_data, headlen); if (unlikely(dma_mapping_error(sq->pdev, dma_addr))) goto dma_unmap_wqe_err;
@@ -196,7 +216,6 @@ mlx5e_txwqe_build_dsegs(struct mlx5e_txqsq *sq, struct sk_buff *skb, dseg->lkey = sq->mkey_be; dseg->byte_count = cpu_to_be32(headlen); - mlx5e_dma_push_single(sq, dma_addr, headlen); num_dma++; dseg++; }
@@ -578,7 +597,7 @@ mlx5e_sq_xmit_mpwqe(struct mlx5e_txqsq *sq, struct sk_buff *skb, txd.data = skb->data; txd.len = skb->len; - txd.dma_addr = dma_map_single(sq->pdev, txd.data, txd.len, DMA_TO_DEVICE); + txd.dma_addr = mlx5e_tx_map_hdr(sq, txd.data, txd.len); if (unlikely(dma_mapping_error(sq->pdev, txd.dma_addr))) goto err_unmap;
@@ -591,7 +610,6 @@ mlx5e_sq_xmit_mpwqe(struct mlx5e_txqsq *sq, struct sk_buff *skb, sq->stats->xmit_more += xmit_more; - mlx5e_dma_push_single(sq, txd.dma_addr, txd.len); mlx5e_skb_fifo_push(&sq->db.skb_fifo, skb); mlx5e_tx_mpwqe_add_dseg(sq, &txd); mlx5e_tx_skb_update_ts_flags(skb);
--
2.56.0.rc1.315.gc6ed9934b7-goog