Skip to content

Commit c2c9e31

Browse files
nvmmaxkuba-moo
authored andcommitted
net/mlx5e: xsk: Optimize for unaligned mode with 3072-byte frames
When XSK frame size is 3072 (or another power of two multiplied by 3), KLM mechanism for NIC virtual memory page mapping can be optimized by replacing it with KSM. Before this change, two KLM entries were needed to map an XSK frame that is not a power of two: one entry maps the UMEM memory up to the frame length, the other maps the rest of the stride to the garbage page. When the frame length divided by 3 is a power of two, it can be mapped using 3 KSM entries, and the fourth will map the rest of the stride to the garbage page. All 4 KSM entries are of the same size, which allows for a much faster lookup. Frame size 3072 is useful in certain use cases, because it allows packing 4 frames into 3 pages. Generally speaking, other frame sizes equal to PAGE_SIZE minus a power of two can be optimized in a similar way, but it will require many more KSMs per frame, which slows down UMRs a little bit, but more importantly may hit the limit for the maximum number of KSM entries. Signed-off-by: Maxim Mikityanskiy <[email protected]> Reviewed-by: Tariq Toukan <[email protected]> Signed-off-by: Saeed Mahameed <[email protected]> Signed-off-by: Jakub Kicinski <[email protected]>
1 parent c6f0420 commit c2c9e31

File tree

4 files changed

+61
-3
lines changed

4 files changed

+61
-3
lines changed

drivers/net/ethernet/mellanox/mlx5/core/en.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -681,6 +681,7 @@ enum mlx5e_mpwrq_umr_mode {
681681
MLX5E_MPWRQ_UMR_MODE_ALIGNED,
682682
MLX5E_MPWRQ_UMR_MODE_UNALIGNED,
683683
MLX5E_MPWRQ_UMR_MODE_OVERSIZED,
684+
MLX5E_MPWRQ_UMR_MODE_TRIPLE,
684685
};
685686

686687
struct mlx5e_rq {

drivers/net/ethernet/mellanox/mlx5/core/en/params.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,16 @@ mlx5e_mpwrq_umr_mode(struct mlx5_core_dev *mdev, struct mlx5e_xsk_param *xsk)
5656
* stride is mapped to a garbage page, resulting in two mappings of
5757
* different sizes per frame.
5858
*/
59-
if (oversized)
59+
if (oversized) {
60+
/* An optimization for frame sizes equal to 3 * power_of_two.
61+
* 3 KSMs point to the frame, and one KSM points to the garbage
62+
* page, which works faster than KLM.
63+
*/
64+
if (xsk->chunk_size % 3 == 0 && is_power_of_2(xsk->chunk_size / 3))
65+
return MLX5E_MPWRQ_UMR_MODE_TRIPLE;
66+
6067
return MLX5E_MPWRQ_UMR_MODE_OVERSIZED;
68+
}
6169

6270
/* XSK frames can start at arbitrary unaligned locations, but they all
6371
* have the same size which is a power of two. It allows to optimize to
@@ -82,6 +90,8 @@ u8 mlx5e_mpwrq_umr_entry_size(enum mlx5e_mpwrq_umr_mode mode)
8290
return sizeof(struct mlx5_ksm);
8391
case MLX5E_MPWRQ_UMR_MODE_OVERSIZED:
8492
return sizeof(struct mlx5_klm) * 2;
93+
case MLX5E_MPWRQ_UMR_MODE_TRIPLE:
94+
return sizeof(struct mlx5_ksm) * 4;
8595
}
8696
WARN_ONCE(1, "MPWRQ UMR mode %d is not known\n", mode);
8797
return 0;
@@ -179,6 +189,9 @@ u32 mlx5e_mpwrq_max_num_entries(struct mlx5_core_dev *mdev,
179189
case MLX5E_MPWRQ_UMR_MODE_OVERSIZED:
180190
/* Each entry is two KLMs. */
181191
return klm_limit / 2;
192+
case MLX5E_MPWRQ_UMR_MODE_TRIPLE:
193+
/* Each entry is four KSMs. */
194+
return klm_limit / 4;
182195
}
183196
WARN_ONCE(1, "MPWRQ UMR mode %d is not known\n", umr_mode);
184197
return 0;
@@ -1121,6 +1134,11 @@ static u8 mlx5e_build_icosq_log_wq_sz(struct mlx5_core_dev *mdev,
11211134
xsk.chunk_size -= 1;
11221135
max_xsk_wqebbs = max(max_xsk_wqebbs,
11231136
mlx5e_mpwrq_total_umr_wqebbs(mdev, params, &xsk));
1137+
1138+
/* XSK unaligned mode, frame size is a triple power of two. */
1139+
xsk.chunk_size = (1 << frame_shift) / 4 * 3;
1140+
max_xsk_wqebbs = max(max_xsk_wqebbs,
1141+
mlx5e_mpwrq_total_umr_wqebbs(mdev, params, &xsk));
11241142
}
11251143

11261144
wqebbs += max_xsk_wqebbs;

drivers/net/ethernet/mellanox/mlx5/core/en/xsk/rx.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,29 @@ int mlx5e_xsk_alloc_rx_mpwqe(struct mlx5e_rq *rq, u16 ix)
5858
.va = cpu_to_be64(addr),
5959
};
6060
}
61+
} else if (likely(rq->mpwqe.umr_mode == MLX5E_MPWRQ_UMR_MODE_TRIPLE)) {
62+
u32 mapping_size = 1 << (rq->mpwqe.page_shift - 2);
63+
64+
for (i = 0; i < batch; i++) {
65+
dma_addr_t addr = xsk_buff_xdp_get_frame_dma(wi->alloc_units[i].xsk);
66+
67+
umr_wqe->inline_ksms[i << 2] = (struct mlx5_ksm) {
68+
.key = rq->mkey_be,
69+
.va = cpu_to_be64(addr),
70+
};
71+
umr_wqe->inline_ksms[(i << 2) + 1] = (struct mlx5_ksm) {
72+
.key = rq->mkey_be,
73+
.va = cpu_to_be64(addr + mapping_size),
74+
};
75+
umr_wqe->inline_ksms[(i << 2) + 2] = (struct mlx5_ksm) {
76+
.key = rq->mkey_be,
77+
.va = cpu_to_be64(addr + mapping_size * 2),
78+
};
79+
umr_wqe->inline_ksms[(i << 2) + 3] = (struct mlx5_ksm) {
80+
.key = rq->mkey_be,
81+
.va = cpu_to_be64(rq->wqe_overflow.addr),
82+
};
83+
}
6184
} else {
6285
__be32 pad_size = cpu_to_be32((1 << rq->mpwqe.page_shift) -
6386
rq->xsk_pool->chunk_size);
@@ -91,6 +114,8 @@ int mlx5e_xsk_alloc_rx_mpwqe(struct mlx5e_rq *rq, u16 ix)
91114
offset = offset * sizeof(struct mlx5_mtt) / MLX5_OCTWORD;
92115
else if (unlikely(rq->mpwqe.umr_mode == MLX5E_MPWRQ_UMR_MODE_OVERSIZED))
93116
offset = offset * sizeof(struct mlx5_klm) * 2 / MLX5_OCTWORD;
117+
else if (unlikely(rq->mpwqe.umr_mode == MLX5E_MPWRQ_UMR_MODE_TRIPLE))
118+
offset = offset * sizeof(struct mlx5_ksm) * 4 / MLX5_OCTWORD;
94119
umr_wqe->uctrl.xlt_offset = cpu_to_be16(offset);
95120

96121
icosq->db.wqe_info[pi] = (struct mlx5e_icosq_wqe_info) {

drivers/net/ethernet/mellanox/mlx5/core/en_main.c

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,8 @@ static u8 mlx5e_mpwrq_access_mode(enum mlx5e_mpwrq_umr_mode umr_mode)
301301
return MLX5_MKC_ACCESS_MODE_KSM;
302302
case MLX5E_MPWRQ_UMR_MODE_OVERSIZED:
303303
return MLX5_MKC_ACCESS_MODE_KLMS;
304+
case MLX5E_MPWRQ_UMR_MODE_TRIPLE:
305+
return MLX5_MKC_ACCESS_MODE_KSM;
304306
}
305307
WARN_ONCE(1, "MPWRQ UMR mode %d is not known\n", umr_mode);
306308
return 0;
@@ -322,7 +324,8 @@ static int mlx5e_create_umr_mkey(struct mlx5_core_dev *mdev,
322324
int err;
323325
int i;
324326

325-
if (umr_mode == MLX5E_MPWRQ_UMR_MODE_UNALIGNED &&
327+
if ((umr_mode == MLX5E_MPWRQ_UMR_MODE_UNALIGNED ||
328+
umr_mode == MLX5E_MPWRQ_UMR_MODE_TRIPLE) &&
326329
!MLX5_CAP_GEN(mdev, fixed_buffer_size)) {
327330
mlx5_core_warn(mdev, "Unaligned AF_XDP requires fixed_buffer_size capability\n");
328331
return -EINVAL;
@@ -351,7 +354,9 @@ static int mlx5e_create_umr_mkey(struct mlx5_core_dev *mdev,
351354
MLX5_SET(mkc, mkc, pd, mdev->mlx5e_res.hw_objs.pdn);
352355
MLX5_SET64(mkc, mkc, len, npages << page_shift);
353356
MLX5_SET(mkc, mkc, translations_octword_size, octwords);
354-
if (umr_mode != MLX5E_MPWRQ_UMR_MODE_OVERSIZED)
357+
if (umr_mode == MLX5E_MPWRQ_UMR_MODE_TRIPLE)
358+
MLX5_SET(mkc, mkc, log_page_size, page_shift - 2);
359+
else if (umr_mode != MLX5E_MPWRQ_UMR_MODE_OVERSIZED)
355360
MLX5_SET(mkc, mkc, log_page_size, page_shift);
356361
MLX5_SET(create_mkey_in, in, translations_octword_actual_size, octwords);
357362

@@ -392,6 +397,15 @@ static int mlx5e_create_umr_mkey(struct mlx5_core_dev *mdev,
392397
.ptag = cpu_to_be64(filler_addr),
393398
};
394399
break;
400+
case MLX5E_MPWRQ_UMR_MODE_TRIPLE:
401+
ksm = MLX5_ADDR_OF(create_mkey_in, in, klm_pas_mtt);
402+
for (i = 0; i < npages * 4; i++) {
403+
ksm[i] = (struct mlx5_ksm) {
404+
.key = cpu_to_be32(mdev->mlx5e_res.hw_objs.mkey),
405+
.va = cpu_to_be64(filler_addr),
406+
};
407+
}
408+
break;
395409
}
396410

397411
err = mlx5_core_create_mkey(mdev, umr_mkey, in, inlen);

0 commit comments

Comments
 (0)