[PATCH net 1/3] net/mlx5e: SHAMPO, Fix header mapping for 64K pages

Tariq Toukan posted 3 patches 3 months, 1 week ago
There is a newer version of this series
[PATCH net 1/3] net/mlx5e: SHAMPO, Fix header mapping for 64K pages
Posted by Tariq Toukan 3 months, 1 week ago
From: Dragos Tatulea <dtatulea@nvidia.com>

HW-GRO is broken on mlx5 for 64K page sizes. The patch in the fixes tag
didn't take into account larger page sizes when doing an align down
of max_ksm_entries. For 64K page size, max_ksm_entries is 0 which will skip
mapping header pages via WQE UMR. This breaks header-data split
and will result in the following syndrome:

mlx5_core 0000:00:08.0 eth2: Error cqe on cqn 0x4c9, ci 0x0, qn 0x1133, opcode 0xe, syndrome 0x4, vendor syndrome 0x32
00000000: 00 00 00 00 04 4a 00 00 00 00 00 00 20 00 93 32
00000010: 55 00 00 00 fb cc 00 00 00 00 00 00 07 18 00 00
00000020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 4a
00000030: 00 00 3b c7 93 01 32 04 00 00 00 00 00 00 bf e0
mlx5_core 0000:00:08.0 eth2: ERR CQE on RQ: 0x1133

Furthermore, the function that fills in WQE UMRs for the headers
(mlx5e_build_shampo_hd_umr()) only supports mapping page sizes that
fit in a single UMR WQE.

This patch goes back to the old non-aligned max_ksm_entries value and it
changes mlx5e_build_shampo_hd_umr() to support mapping a large page over
multiple UMR WQEs.

This means that mlx5e_build_shampo_hd_umr() can now leave a page only
partially mapped. The caller, mlx5e_build_shampo_hd_umr(), ensures that
there are enough UMR WQEs to cover complete pages by working on
ksm_entries that are multiples of MLX5E_SHAMPO_WQ_HEADER_PER_PAGE.

Fixes: 8a0ee54027b1 ("net/mlx5e: SHAMPO, Simplify UMR allocation for headers")
Signed-off-by: Dragos Tatulea <dtatulea@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
---
 .../net/ethernet/mellanox/mlx5/core/en_rx.c   | 34 +++++++++----------
 1 file changed, 16 insertions(+), 18 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
index 1c79adc51a04..77f7a1ca091d 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
@@ -679,25 +679,24 @@ static int mlx5e_build_shampo_hd_umr(struct mlx5e_rq *rq,
 	umr_wqe = mlx5_wq_cyc_get_wqe(&sq->wq, pi);
 	build_ksm_umr(sq, umr_wqe, shampo->mkey_be, index, ksm_entries);
 
-	WARN_ON_ONCE(ksm_entries & (MLX5E_SHAMPO_WQ_HEADER_PER_PAGE - 1));
-	while (i < ksm_entries) {
-		struct mlx5e_frag_page *frag_page = mlx5e_shampo_hd_to_frag_page(rq, index);
+	for ( ; i < ksm_entries; i++, index++) {
+		struct mlx5e_frag_page *frag_page;
 		u64 addr;
 
-		err = mlx5e_page_alloc_fragmented(rq->hd_page_pool, frag_page);
-		if (unlikely(err))
-			goto err_unmap;
+		frag_page = mlx5e_shampo_hd_to_frag_page(rq, index);
+		header_offset = mlx5e_shampo_hd_offset(index);
+		if (!header_offset) {
+			err = mlx5e_page_alloc_fragmented(rq->hd_page_pool,
+							  frag_page);
+			if (err)
+				goto err_unmap;
+		}
 
 		addr = page_pool_get_dma_addr_netmem(frag_page->netmem);
-
-		for (int j = 0; j < MLX5E_SHAMPO_WQ_HEADER_PER_PAGE; j++) {
-			header_offset = mlx5e_shampo_hd_offset(index++);
-
-			umr_wqe->inline_ksms[i++] = (struct mlx5_ksm) {
-				.key = cpu_to_be32(lkey),
-				.va  = cpu_to_be64(addr + header_offset + headroom),
-			};
-		}
+		umr_wqe->inline_ksms[i] = (struct mlx5_ksm) {
+			.key = cpu_to_be32(lkey),
+			.va  = cpu_to_be64(addr + header_offset + headroom),
+		};
 	}
 
 	sq->db.wqe_info[pi] = (struct mlx5e_icosq_wqe_info) {
@@ -713,7 +712,7 @@ static int mlx5e_build_shampo_hd_umr(struct mlx5e_rq *rq,
 	return 0;
 
 err_unmap:
-	while (--i) {
+	while (--i >= 0) {
 		--index;
 		header_offset = mlx5e_shampo_hd_offset(index);
 		if (!header_offset) {
@@ -735,8 +734,7 @@ static int mlx5e_alloc_rx_hd_mpwqe(struct mlx5e_rq *rq)
 	struct mlx5e_icosq *sq = rq->icosq;
 	int i, err, max_ksm_entries, len;
 
-	max_ksm_entries = ALIGN_DOWN(MLX5E_MAX_KSM_PER_WQE(rq->mdev),
-				     MLX5E_SHAMPO_WQ_HEADER_PER_PAGE);
+	max_ksm_entries = MLX5E_MAX_KSM_PER_WQE(rq->mdev);
 	ksm_entries = bitmap_find_window(shampo->bitmap,
 					 shampo->hd_per_wqe,
 					 shampo->hd_per_wq, shampo->pi);
-- 
2.31.1
Re: [PATCH net 1/3] net/mlx5e: SHAMPO, Fix header mapping for 64K pages
Posted by Simon Horman 3 months, 1 week ago
On Tue, Oct 28, 2025 at 08:47:17AM +0200, Tariq Toukan wrote:
> From: Dragos Tatulea <dtatulea@nvidia.com>
> 
> HW-GRO is broken on mlx5 for 64K page sizes. The patch in the fixes tag
> didn't take into account larger page sizes when doing an align down
> of max_ksm_entries. For 64K page size, max_ksm_entries is 0 which will skip
> mapping header pages via WQE UMR. This breaks header-data split
> and will result in the following syndrome:
> 
> mlx5_core 0000:00:08.0 eth2: Error cqe on cqn 0x4c9, ci 0x0, qn 0x1133, opcode 0xe, syndrome 0x4, vendor syndrome 0x32
> 00000000: 00 00 00 00 04 4a 00 00 00 00 00 00 20 00 93 32
> 00000010: 55 00 00 00 fb cc 00 00 00 00 00 00 07 18 00 00
> 00000020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 4a
> 00000030: 00 00 3b c7 93 01 32 04 00 00 00 00 00 00 bf e0
> mlx5_core 0000:00:08.0 eth2: ERR CQE on RQ: 0x1133
> 
> Furthermore, the function that fills in WQE UMRs for the headers
> (mlx5e_build_shampo_hd_umr()) only supports mapping page sizes that
> fit in a single UMR WQE.
> 
> This patch goes back to the old non-aligned max_ksm_entries value and it
> changes mlx5e_build_shampo_hd_umr() to support mapping a large page over
> multiple UMR WQEs.
> 
> This means that mlx5e_build_shampo_hd_umr() can now leave a page only
> partially mapped. The caller, mlx5e_build_shampo_hd_umr(), ensures that

It's not particularly important, but I think the caller is
mlx5e_alloc_rx_hd_mpwqe().

> there are enough UMR WQEs to cover complete pages by working on
> ksm_entries that are multiples of MLX5E_SHAMPO_WQ_HEADER_PER_PAGE.
> 
> Fixes: 8a0ee54027b1 ("net/mlx5e: SHAMPO, Simplify UMR allocation for headers")
> Signed-off-by: Dragos Tatulea <dtatulea@nvidia.com>
> Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
> ---
>  .../net/ethernet/mellanox/mlx5/core/en_rx.c   | 34 +++++++++----------
>  1 file changed, 16 insertions(+), 18 deletions(-)
> 
> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
> index 1c79adc51a04..77f7a1ca091d 100644
> --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
> +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
> @@ -679,25 +679,24 @@ static int mlx5e_build_shampo_hd_umr(struct mlx5e_rq *rq,
>  	umr_wqe = mlx5_wq_cyc_get_wqe(&sq->wq, pi);
>  	build_ksm_umr(sq, umr_wqe, shampo->mkey_be, index, ksm_entries);
>  
> -	WARN_ON_ONCE(ksm_entries & (MLX5E_SHAMPO_WQ_HEADER_PER_PAGE - 1));
> -	while (i < ksm_entries) {
> -		struct mlx5e_frag_page *frag_page = mlx5e_shampo_hd_to_frag_page(rq, index);
> +	for ( ; i < ksm_entries; i++, index++) {

Also, if you have to respin for some reason, I would move the
initialisation of i to 0 from it's declaration to the for loop.

...
Re: [PATCH net 1/3] net/mlx5e: SHAMPO, Fix header mapping for 64K pages
Posted by Dragos Tatulea 3 months, 1 week ago
On Wed, Oct 29, 2025 at 03:51:18PM +0000, Simon Horman wrote:
> On Tue, Oct 28, 2025 at 08:47:17AM +0200, Tariq Toukan wrote:
> > From: Dragos Tatulea <dtatulea@nvidia.com>
> > 
> > HW-GRO is broken on mlx5 for 64K page sizes. The patch in the fixes tag
> > didn't take into account larger page sizes when doing an align down
> > of max_ksm_entries. For 64K page size, max_ksm_entries is 0 which will skip
> > mapping header pages via WQE UMR. This breaks header-data split
> > and will result in the following syndrome:
> > 
> > mlx5_core 0000:00:08.0 eth2: Error cqe on cqn 0x4c9, ci 0x0, qn 0x1133, opcode 0xe, syndrome 0x4, vendor syndrome 0x32
> > 00000000: 00 00 00 00 04 4a 00 00 00 00 00 00 20 00 93 32
> > 00000010: 55 00 00 00 fb cc 00 00 00 00 00 00 07 18 00 00
> > 00000020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 4a
> > 00000030: 00 00 3b c7 93 01 32 04 00 00 00 00 00 00 bf e0
> > mlx5_core 0000:00:08.0 eth2: ERR CQE on RQ: 0x1133
> > 
> > Furthermore, the function that fills in WQE UMRs for the headers
> > (mlx5e_build_shampo_hd_umr()) only supports mapping page sizes that
> > fit in a single UMR WQE.
> > 
> > This patch goes back to the old non-aligned max_ksm_entries value and it
> > changes mlx5e_build_shampo_hd_umr() to support mapping a large page over
> > multiple UMR WQEs.
> > 
> > This means that mlx5e_build_shampo_hd_umr() can now leave a page only
> > partially mapped. The caller, mlx5e_build_shampo_hd_umr(), ensures that
> 
> It's not particularly important, but I think the caller is
> mlx5e_alloc_rx_hd_mpwqe().
>
Right. Sorry. Will fix it.

> > there are enough UMR WQEs to cover complete pages by working on
> > ksm_entries that are multiples of MLX5E_SHAMPO_WQ_HEADER_PER_PAGE.
> > 
> > Fixes: 8a0ee54027b1 ("net/mlx5e: SHAMPO, Simplify UMR allocation for headers")
> > Signed-off-by: Dragos Tatulea <dtatulea@nvidia.com>
> > Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
> > ---
> >  .../net/ethernet/mellanox/mlx5/core/en_rx.c   | 34 +++++++++----------
> >  1 file changed, 16 insertions(+), 18 deletions(-)
> > 
> > diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
> > index 1c79adc51a04..77f7a1ca091d 100644
> > --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
> > +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
> > @@ -679,25 +679,24 @@ static int mlx5e_build_shampo_hd_umr(struct mlx5e_rq *rq,
> >  	umr_wqe = mlx5_wq_cyc_get_wqe(&sq->wq, pi);
> >  	build_ksm_umr(sq, umr_wqe, shampo->mkey_be, index, ksm_entries);
> >  
> > -	WARN_ON_ONCE(ksm_entries & (MLX5E_SHAMPO_WQ_HEADER_PER_PAGE - 1));
> > -	while (i < ksm_entries) {
> > -		struct mlx5e_frag_page *frag_page = mlx5e_shampo_hd_to_frag_page(rq, index);
> > +	for ( ; i < ksm_entries; i++, index++) {
> 
> Also, if you have to respin for some reason, I would move the
> initialisation of i to 0 from it's declaration to the for loop.
> 
> ...
If Tariq respins, I will change it.

Thanks,
Dragos