305 lines
11 KiB
Diff
305 lines
11 KiB
Diff
From 65f74d0b4614133bc8ed318ed25a4532182f50fc Mon Sep 17 00:00:00 2001
|
|
From: Kamal Heib <kheib@redhat.com>
|
|
Date: Thu, 16 Apr 2026 18:03:18 -0400
|
|
Subject: [PATCH] net/mlx5e: SHAMPO: Separate pool for headers
|
|
|
|
JIRA: https://redhat.atlassian.net/browse/RHEL-169055
|
|
|
|
commit e225d9bd93ed0bb84014f5f8e241e8e456533e30
|
|
Author: Saeed Mahameed <saeedm@nvidia.com>
|
|
Date: Mon Jun 16 17:14:36 2025 +0300
|
|
|
|
net/mlx5e: SHAMPO: Separate pool for headers
|
|
|
|
Allow allocating a separate page pool for headers when SHAMPO is on.
|
|
This will be useful for adding support to zc page pool, which has to be
|
|
different from the headers page pool.
|
|
For now, the pools are the same.
|
|
|
|
Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
|
|
Reviewed-by: Dragos Tatulea <dtatulea@nvidia.com>
|
|
Signed-off-by: Cosmin Ratiu <cratiu@nvidia.com>
|
|
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
|
|
Signed-off-by: Mark Bloch <mbloch@nvidia.com>
|
|
Link: https://patch.msgid.link/20250616141441.1243044-8-mbloch@nvidia.com
|
|
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
|
|
|
Signed-off-by: Kamal Heib <kheib@redhat.com>
|
|
|
|
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h
|
|
index 581eef34f512..c329de1d4f0a 100644
|
|
--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
|
|
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h
|
|
@@ -716,7 +716,11 @@ struct mlx5e_rq {
|
|
struct bpf_prog __rcu *xdp_prog;
|
|
struct mlx5e_xdpsq *xdpsq;
|
|
DECLARE_BITMAP(flags, 8);
|
|
+
|
|
+ /* page pools */
|
|
struct page_pool *page_pool;
|
|
+ struct page_pool *hd_page_pool;
|
|
+
|
|
struct mlx5e_xdp_buff mxbuf;
|
|
|
|
/* AF_XDP zero-copy */
|
|
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
|
|
index e552dcf8f13a..59e845367cfd 100644
|
|
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
|
|
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
|
|
@@ -40,6 +40,7 @@
|
|
#include <linux/if_bridge.h>
|
|
#include <linux/filter.h>
|
|
#include <net/netdev_queues.h>
|
|
+#include <net/netdev_rx_queue.h>
|
|
#include <net/page_pool/types.h>
|
|
#include <net/pkt_sched.h>
|
|
#include <net/xdp_sock_drv.h>
|
|
@@ -745,6 +746,11 @@ static void mlx5e_rq_shampo_hd_info_free(struct mlx5e_rq *rq)
|
|
bitmap_free(rq->mpwqe.shampo->bitmap);
|
|
}
|
|
|
|
+static bool mlx5_rq_needs_separate_hd_pool(struct mlx5e_rq *rq)
|
|
+{
|
|
+ return false;
|
|
+}
|
|
+
|
|
static int mlx5_rq_shampo_alloc(struct mlx5_core_dev *mdev,
|
|
struct mlx5e_params *params,
|
|
struct mlx5e_rq_param *rqp,
|
|
@@ -753,6 +759,7 @@ static int mlx5_rq_shampo_alloc(struct mlx5_core_dev *mdev,
|
|
int node)
|
|
{
|
|
void *wqc = MLX5_ADDR_OF(rqc, rqp->rqc, wq);
|
|
+ u32 hd_pool_size;
|
|
u16 hd_per_wq;
|
|
int wq_size;
|
|
int err;
|
|
@@ -780,8 +787,34 @@ static int mlx5_rq_shampo_alloc(struct mlx5_core_dev *mdev,
|
|
rq->mpwqe.shampo->hd_per_wqe =
|
|
mlx5e_shampo_hd_per_wqe(mdev, params, rqp);
|
|
wq_size = BIT(MLX5_GET(wq, wqc, log_wq_sz));
|
|
- *pool_size += (rq->mpwqe.shampo->hd_per_wqe * wq_size) /
|
|
- MLX5E_SHAMPO_WQ_HEADER_PER_PAGE;
|
|
+ hd_pool_size = (rq->mpwqe.shampo->hd_per_wqe * wq_size) /
|
|
+ MLX5E_SHAMPO_WQ_HEADER_PER_PAGE;
|
|
+
|
|
+ if (mlx5_rq_needs_separate_hd_pool(rq)) {
|
|
+ /* Separate page pool for shampo headers */
|
|
+ struct page_pool_params pp_params = { };
|
|
+
|
|
+ pp_params.order = 0;
|
|
+ pp_params.flags = PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV;
|
|
+ pp_params.pool_size = hd_pool_size;
|
|
+ pp_params.nid = node;
|
|
+ pp_params.dev = rq->pdev;
|
|
+ pp_params.napi = rq->cq.napi;
|
|
+ pp_params.netdev = rq->netdev;
|
|
+ pp_params.dma_dir = rq->buff.map_dir;
|
|
+ pp_params.max_len = PAGE_SIZE;
|
|
+
|
|
+ rq->hd_page_pool = page_pool_create(&pp_params);
|
|
+ if (IS_ERR(rq->hd_page_pool)) {
|
|
+ err = PTR_ERR(rq->hd_page_pool);
|
|
+ rq->hd_page_pool = NULL;
|
|
+ goto err_hds_page_pool;
|
|
+ }
|
|
+ } else {
|
|
+ /* Common page pool, reserve space for headers. */
|
|
+ *pool_size += hd_pool_size;
|
|
+ rq->hd_page_pool = NULL;
|
|
+ }
|
|
|
|
/* gro only data structures */
|
|
rq->hw_gro_data = kvzalloc_node(sizeof(*rq->hw_gro_data), GFP_KERNEL, node);
|
|
@@ -793,6 +826,8 @@ static int mlx5_rq_shampo_alloc(struct mlx5_core_dev *mdev,
|
|
return 0;
|
|
|
|
err_hw_gro_data:
|
|
+ page_pool_destroy(rq->hd_page_pool);
|
|
+err_hds_page_pool:
|
|
mlx5_core_destroy_mkey(mdev, rq->mpwqe.shampo->mkey);
|
|
err_umr_mkey:
|
|
mlx5e_rq_shampo_hd_info_free(rq);
|
|
@@ -807,6 +842,8 @@ static void mlx5e_rq_free_shampo(struct mlx5e_rq *rq)
|
|
return;
|
|
|
|
kvfree(rq->hw_gro_data);
|
|
+ if (rq->hd_page_pool != rq->page_pool)
|
|
+ page_pool_destroy(rq->hd_page_pool);
|
|
mlx5e_rq_shampo_hd_info_free(rq);
|
|
mlx5_core_destroy_mkey(rq->mdev, rq->mpwqe.shampo->mkey);
|
|
kvfree(rq->mpwqe.shampo);
|
|
@@ -938,6 +975,8 @@ static int mlx5e_alloc_rq(struct mlx5e_params *params,
|
|
rq->page_pool = NULL;
|
|
goto err_free_by_rq_type;
|
|
}
|
|
+ if (!rq->hd_page_pool)
|
|
+ rq->hd_page_pool = rq->page_pool;
|
|
if (xdp_rxq_info_is_reg(&rq->xdp_rxq))
|
|
err = xdp_rxq_info_reg_mem_model(&rq->xdp_rxq,
|
|
MEM_TYPE_PAGE_POOL, rq->page_pool);
|
|
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
|
|
index 382679838113..36a4780332d7 100644
|
|
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
|
|
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
|
|
@@ -273,12 +273,12 @@ static inline u32 mlx5e_decompress_cqes_start(struct mlx5e_rq *rq,
|
|
|
|
#define MLX5E_PAGECNT_BIAS_MAX (PAGE_SIZE / 64)
|
|
|
|
-static int mlx5e_page_alloc_fragmented(struct mlx5e_rq *rq,
|
|
+static int mlx5e_page_alloc_fragmented(struct page_pool *pool,
|
|
struct mlx5e_frag_page *frag_page)
|
|
{
|
|
struct page *page;
|
|
|
|
- page = page_pool_dev_alloc_pages(rq->page_pool);
|
|
+ page = page_pool_dev_alloc_pages(pool);
|
|
if (unlikely(!page))
|
|
return -ENOMEM;
|
|
|
|
@@ -292,14 +292,14 @@ static int mlx5e_page_alloc_fragmented(struct mlx5e_rq *rq,
|
|
return 0;
|
|
}
|
|
|
|
-static void mlx5e_page_release_fragmented(struct mlx5e_rq *rq,
|
|
+static void mlx5e_page_release_fragmented(struct page_pool *pool,
|
|
struct mlx5e_frag_page *frag_page)
|
|
{
|
|
u16 drain_count = MLX5E_PAGECNT_BIAS_MAX - frag_page->frags;
|
|
struct page *page = frag_page->page;
|
|
|
|
if (page_pool_unref_page(page, drain_count) == 0)
|
|
- page_pool_put_unrefed_page(rq->page_pool, page, -1, true);
|
|
+ page_pool_put_unrefed_page(pool, page, -1, true);
|
|
}
|
|
|
|
static inline int mlx5e_get_rx_frag(struct mlx5e_rq *rq,
|
|
@@ -313,7 +313,8 @@ static inline int mlx5e_get_rx_frag(struct mlx5e_rq *rq,
|
|
* offset) should just use the new one without replenishing again
|
|
* by themselves.
|
|
*/
|
|
- err = mlx5e_page_alloc_fragmented(rq, frag->frag_page);
|
|
+ err = mlx5e_page_alloc_fragmented(rq->page_pool,
|
|
+ frag->frag_page);
|
|
|
|
return err;
|
|
}
|
|
@@ -332,7 +333,7 @@ static inline void mlx5e_put_rx_frag(struct mlx5e_rq *rq,
|
|
struct mlx5e_wqe_frag_info *frag)
|
|
{
|
|
if (mlx5e_frag_can_release(frag))
|
|
- mlx5e_page_release_fragmented(rq, frag->frag_page);
|
|
+ mlx5e_page_release_fragmented(rq->page_pool, frag->frag_page);
|
|
}
|
|
|
|
static inline struct mlx5e_wqe_frag_info *get_frag(struct mlx5e_rq *rq, u16 ix)
|
|
@@ -586,7 +587,8 @@ mlx5e_free_rx_mpwqe(struct mlx5e_rq *rq, struct mlx5e_mpw_info *wi)
|
|
struct mlx5e_frag_page *frag_page;
|
|
|
|
frag_page = &wi->alloc_units.frag_pages[i];
|
|
- mlx5e_page_release_fragmented(rq, frag_page);
|
|
+ mlx5e_page_release_fragmented(rq->page_pool,
|
|
+ frag_page);
|
|
}
|
|
}
|
|
}
|
|
@@ -681,11 +683,10 @@ static int mlx5e_build_shampo_hd_umr(struct mlx5e_rq *rq,
|
|
struct mlx5e_frag_page *frag_page = mlx5e_shampo_hd_to_frag_page(rq, index);
|
|
u64 addr;
|
|
|
|
- err = mlx5e_page_alloc_fragmented(rq, frag_page);
|
|
+ err = mlx5e_page_alloc_fragmented(rq->hd_page_pool, frag_page);
|
|
if (unlikely(err))
|
|
goto err_unmap;
|
|
|
|
-
|
|
addr = page_pool_get_dma_addr(frag_page->page);
|
|
|
|
for (int j = 0; j < MLX5E_SHAMPO_WQ_HEADER_PER_PAGE; j++) {
|
|
@@ -717,7 +718,8 @@ static int mlx5e_build_shampo_hd_umr(struct mlx5e_rq *rq,
|
|
if (!header_offset) {
|
|
struct mlx5e_frag_page *frag_page = mlx5e_shampo_hd_to_frag_page(rq, index);
|
|
|
|
- mlx5e_page_release_fragmented(rq, frag_page);
|
|
+ mlx5e_page_release_fragmented(rq->hd_page_pool,
|
|
+ frag_page);
|
|
}
|
|
}
|
|
|
|
@@ -793,7 +795,7 @@ static int mlx5e_alloc_rx_mpwqe(struct mlx5e_rq *rq, u16 ix)
|
|
for (i = 0; i < rq->mpwqe.pages_per_wqe; i++, frag_page++) {
|
|
dma_addr_t addr;
|
|
|
|
- err = mlx5e_page_alloc_fragmented(rq, frag_page);
|
|
+ err = mlx5e_page_alloc_fragmented(rq->page_pool, frag_page);
|
|
if (unlikely(err))
|
|
goto err_unmap;
|
|
addr = page_pool_get_dma_addr(frag_page->page);
|
|
@@ -838,7 +840,7 @@ static int mlx5e_alloc_rx_mpwqe(struct mlx5e_rq *rq, u16 ix)
|
|
err_unmap:
|
|
while (--i >= 0) {
|
|
frag_page--;
|
|
- mlx5e_page_release_fragmented(rq, frag_page);
|
|
+ mlx5e_page_release_fragmented(rq->page_pool, frag_page);
|
|
}
|
|
|
|
bitmap_fill(wi->skip_release_bitmap, rq->mpwqe.pages_per_wqe);
|
|
@@ -857,7 +859,7 @@ mlx5e_free_rx_shampo_hd_entry(struct mlx5e_rq *rq, u16 header_index)
|
|
if (((header_index + 1) & (MLX5E_SHAMPO_WQ_HEADER_PER_PAGE - 1)) == 0) {
|
|
struct mlx5e_frag_page *frag_page = mlx5e_shampo_hd_to_frag_page(rq, header_index);
|
|
|
|
- mlx5e_page_release_fragmented(rq, frag_page);
|
|
+ mlx5e_page_release_fragmented(rq->hd_page_pool, frag_page);
|
|
}
|
|
clear_bit(header_index, shampo->bitmap);
|
|
}
|
|
@@ -1102,6 +1104,8 @@ INDIRECT_CALLABLE_SCOPE bool mlx5e_post_rx_mpwqes(struct mlx5e_rq *rq)
|
|
|
|
if (rq->page_pool)
|
|
page_pool_nid_changed(rq->page_pool, numa_mem_id());
|
|
+ if (rq->hd_page_pool)
|
|
+ page_pool_nid_changed(rq->hd_page_pool, numa_mem_id());
|
|
|
|
head = rq->mpwqe.actual_wq_head;
|
|
i = missing;
|
|
@@ -2010,7 +2014,8 @@ mlx5e_skb_from_cqe_mpwrq_nonlinear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *w
|
|
if (prog) {
|
|
/* area for bpf_xdp_[store|load]_bytes */
|
|
net_prefetchw(page_address(frag_page->page) + frag_offset);
|
|
- if (unlikely(mlx5e_page_alloc_fragmented(rq, &wi->linear_page))) {
|
|
+ if (unlikely(mlx5e_page_alloc_fragmented(rq->page_pool,
|
|
+ &wi->linear_page))) {
|
|
rq->stats->buff_alloc_err++;
|
|
return NULL;
|
|
}
|
|
@@ -2074,7 +2079,8 @@ mlx5e_skb_from_cqe_mpwrq_nonlinear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *w
|
|
|
|
wi->linear_page.frags++;
|
|
}
|
|
- mlx5e_page_release_fragmented(rq, &wi->linear_page);
|
|
+ mlx5e_page_release_fragmented(rq->page_pool,
|
|
+ &wi->linear_page);
|
|
return NULL; /* page/packet was consumed by XDP */
|
|
}
|
|
|
|
@@ -2083,13 +2089,14 @@ mlx5e_skb_from_cqe_mpwrq_nonlinear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *w
|
|
mxbuf->xdp.data - mxbuf->xdp.data_hard_start, 0,
|
|
mxbuf->xdp.data - mxbuf->xdp.data_meta);
|
|
if (unlikely(!skb)) {
|
|
- mlx5e_page_release_fragmented(rq, &wi->linear_page);
|
|
+ mlx5e_page_release_fragmented(rq->page_pool,
|
|
+ &wi->linear_page);
|
|
return NULL;
|
|
}
|
|
|
|
skb_mark_for_recycle(skb);
|
|
wi->linear_page.frags++;
|
|
- mlx5e_page_release_fragmented(rq, &wi->linear_page);
|
|
+ mlx5e_page_release_fragmented(rq->page_pool, &wi->linear_page);
|
|
|
|
if (xdp_buff_has_frags(&mxbuf->xdp)) {
|
|
struct mlx5e_frag_page *pagep;
|
|
--
|
|
2.50.1 (Apple Git-155)
|
|
|