Skip to content

Commit 3f93f82

Browse files
dtatuleaSaeed Mahameed
authored andcommitted
net/mlx5e: RX, Defer page release in legacy rq for better recycling
Currently, fragmented pages from the page pool can be released in two ways: 1) In the mlx5e driver when trimming off the unused fragments AND the associated skb fragments have been released. This path allows recycling of pages to the page pool cache (allow_direct == true). 2) On the skb release path (last fragment release), which will always release pages to the page pool ring (allow_direct == false). Whichever is releasing the last fragment will be decisive on where the page gets released: the cache or the ring. So we obviously want to maximize for doing the release from 1. This patch does that by deferring the release of page fragments right before requesting new ones from the page pool. A flag is added to make sure that there's no release before first alloc and that XDP_TX fragments are not released prematurely. This is a preparation patch that doesn't unlock the performance improvements yet. A followup patch will do that. Signed-off-by: Dragos Tatulea <[email protected]> Reviewed-by: Tariq Toukan <[email protected]> Signed-off-by: Saeed Mahameed <[email protected]>
1 parent 625dff2 commit 3f93f82

File tree

4 files changed

+66
-23
lines changed

4 files changed

+66
-23
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -607,6 +607,7 @@ struct mlx5e_frag_page {
607607

608608
enum mlx5e_wqe_frag_flag {
609609
MLX5E_WQE_FRAG_LAST_IN_PAGE,
610+
MLX5E_WQE_FRAG_SKIP_RELEASE,
610611
};
611612

612613
struct mlx5e_wqe_frag_info {

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ int mlx5e_xsk_alloc_rx_wqes_batched(struct mlx5e_rq *rq, u16 ix, int wqe_bulk)
189189

190190
addr = xsk_buff_xdp_get_frame_dma(*frag->xskp);
191191
wqe->data[0].addr = cpu_to_be64(addr + rq->buff.headroom);
192+
frag->flags &= ~BIT(MLX5E_WQE_FRAG_SKIP_RELEASE);
192193
}
193194

194195
return alloc;
@@ -215,6 +216,7 @@ int mlx5e_xsk_alloc_rx_wqes(struct mlx5e_rq *rq, u16 ix, int wqe_bulk)
215216

216217
addr = xsk_buff_xdp_get_frame_dma(*frag->xskp);
217218
wqe->data[0].addr = cpu_to_be64(addr + rq->buff.headroom);
219+
frag->flags &= ~BIT(MLX5E_WQE_FRAG_SKIP_RELEASE);
218220
}
219221

220222
return wqe_bulk;

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

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,9 @@ static void mlx5e_init_frags_partition(struct mlx5e_rq *rq)
520520

521521
next_frag.frag_page = &rq->wqe.alloc_units->frag_pages[0];
522522

523+
/* Skip first release due to deferred release. */
524+
next_frag.flags = BIT(MLX5E_WQE_FRAG_SKIP_RELEASE);
525+
523526
for (i = 0; i < mlx5_wq_cyc_get_size(&rq->wqe.wq); i++) {
524527
struct mlx5e_rq_frag_info *frag_info = &rq->wqe.info.arr[0];
525528
struct mlx5e_wqe_frag_info *frag =
@@ -558,8 +561,14 @@ static void mlx5e_init_xsk_buffs(struct mlx5e_rq *rq)
558561
/* Considering the above assumptions a fragment maps to a single
559562
* xsk_buff.
560563
*/
561-
for (i = 0; i < mlx5_wq_cyc_get_size(&rq->wqe.wq); i++)
564+
for (i = 0; i < mlx5_wq_cyc_get_size(&rq->wqe.wq); i++) {
562565
rq->wqe.frags[i].xskp = &rq->wqe.alloc_units->xsk_buffs[i];
566+
567+
/* Skip first release due to deferred release as WQES are
568+
* not allocated yet.
569+
*/
570+
rq->wqe.frags[i].flags |= BIT(MLX5E_WQE_FRAG_SKIP_RELEASE);
571+
}
563572
}
564573

565574
static int mlx5e_init_wqe_alloc_info(struct mlx5e_rq *rq, int node)
@@ -1183,12 +1192,21 @@ void mlx5e_free_rx_descs(struct mlx5e_rq *rq)
11831192
0, true);
11841193
} else {
11851194
struct mlx5_wq_cyc *wq = &rq->wqe.wq;
1195+
u16 missing = mlx5_wq_cyc_missing(wq);
1196+
u16 head = mlx5_wq_cyc_get_head(wq);
11861197

11871198
while (!mlx5_wq_cyc_is_empty(wq)) {
11881199
wqe_ix = mlx5_wq_cyc_get_tail(wq);
11891200
rq->dealloc_wqe(rq, wqe_ix);
11901201
mlx5_wq_cyc_pop(wq);
11911202
}
1203+
/* Missing slots might also contain unreleased pages due to
1204+
* deferred release.
1205+
*/
1206+
while (missing--) {
1207+
wqe_ix = mlx5_wq_cyc_ctr2ix(wq, head++);
1208+
rq->dealloc_wqe(rq, wqe_ix);
1209+
}
11921210
}
11931211

11941212
}

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

Lines changed: 44 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -319,11 +319,21 @@ static inline int mlx5e_get_rx_frag(struct mlx5e_rq *rq,
319319
return err;
320320
}
321321

322+
static bool mlx5e_frag_can_release(struct mlx5e_wqe_frag_info *frag)
323+
{
324+
#define CAN_RELEASE_MASK \
325+
(BIT(MLX5E_WQE_FRAG_LAST_IN_PAGE) | BIT(MLX5E_WQE_FRAG_SKIP_RELEASE))
326+
327+
#define CAN_RELEASE_VALUE BIT(MLX5E_WQE_FRAG_LAST_IN_PAGE)
328+
329+
return (frag->flags & CAN_RELEASE_MASK) == CAN_RELEASE_VALUE;
330+
}
331+
322332
static inline void mlx5e_put_rx_frag(struct mlx5e_rq *rq,
323333
struct mlx5e_wqe_frag_info *frag,
324334
bool recycle)
325335
{
326-
if (frag->flags & BIT(MLX5E_WQE_FRAG_LAST_IN_PAGE))
336+
if (mlx5e_frag_can_release(frag))
327337
mlx5e_page_release_fragmented(rq, frag->frag_page, recycle);
328338
}
329339

@@ -347,6 +357,8 @@ static int mlx5e_alloc_rx_wqe(struct mlx5e_rq *rq, struct mlx5e_rx_wqe_cyc *wqe,
347357
if (unlikely(err))
348358
goto free_frags;
349359

360+
frag->flags &= ~BIT(MLX5E_WQE_FRAG_SKIP_RELEASE);
361+
350362
headroom = i == 0 ? rq->buff.headroom : 0;
351363
addr = page_pool_get_dma_addr(frag->frag_page->page);
352364
wqe->data[i].addr = cpu_to_be64(addr + frag->offset + headroom);
@@ -367,7 +379,7 @@ static inline void mlx5e_free_rx_wqe(struct mlx5e_rq *rq,
367379
{
368380
int i;
369381

370-
if (rq->xsk_pool) {
382+
if (rq->xsk_pool && !(wi->flags & BIT(MLX5E_WQE_FRAG_SKIP_RELEASE))) {
371383
/* The `recycle` parameter is ignored, and the page is always
372384
* put into the Reuse Ring, because there is no way to return
373385
* the page to the userspace when the interface goes down.
@@ -387,6 +399,20 @@ static void mlx5e_dealloc_rx_wqe(struct mlx5e_rq *rq, u16 ix)
387399
mlx5e_free_rx_wqe(rq, wi, false);
388400
}
389401

402+
static void mlx5e_free_rx_wqes(struct mlx5e_rq *rq, u16 ix, int wqe_bulk)
403+
{
404+
struct mlx5_wq_cyc *wq = &rq->wqe.wq;
405+
int i;
406+
407+
for (i = 0; i < wqe_bulk; i++) {
408+
int j = mlx5_wq_cyc_ctr2ix(wq, ix + i);
409+
struct mlx5e_wqe_frag_info *wi;
410+
411+
wi = get_frag(rq, j);
412+
mlx5e_free_rx_wqe(rq, wi, true);
413+
}
414+
}
415+
390416
static int mlx5e_alloc_rx_wqes(struct mlx5e_rq *rq, u16 ix, int wqe_bulk)
391417
{
392418
struct mlx5_wq_cyc *wq = &rq->wqe.wq;
@@ -792,6 +818,8 @@ INDIRECT_CALLABLE_SCOPE bool mlx5e_post_rx_wqes(struct mlx5e_rq *rq)
792818
*/
793819
wqe_bulk -= (head + wqe_bulk) & rq->wqe.info.wqe_index_mask;
794820

821+
mlx5e_free_rx_wqes(rq, head, wqe_bulk);
822+
795823
if (!rq->xsk_pool)
796824
count = mlx5e_alloc_rx_wqes(rq, head, wqe_bulk);
797825
else if (likely(!rq->xsk_pool->dma_need_sync))
@@ -1727,7 +1755,7 @@ static void mlx5e_handle_rx_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe)
17271755

17281756
if (unlikely(MLX5E_RX_ERR_CQE(cqe))) {
17291757
mlx5e_handle_rx_err_cqe(rq, cqe);
1730-
goto free_wqe;
1758+
goto wq_cyc_pop;
17311759
}
17321760

17331761
skb = INDIRECT_CALL_3(rq->wqe.skb_from_cqe,
@@ -1741,23 +1769,21 @@ static void mlx5e_handle_rx_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe)
17411769
/* do not return page to cache,
17421770
* it will be returned on XDP_TX completion.
17431771
*/
1744-
goto wq_cyc_pop;
1772+
wi->flags |= BIT(MLX5E_WQE_FRAG_SKIP_RELEASE);
17451773
}
1746-
goto free_wqe;
1774+
goto wq_cyc_pop;
17471775
}
17481776

17491777
mlx5e_complete_rx_cqe(rq, cqe, cqe_bcnt, skb);
17501778

17511779
if (mlx5e_cqe_regb_chain(cqe))
17521780
if (!mlx5e_tc_update_skb_nic(cqe, skb)) {
17531781
dev_kfree_skb_any(skb);
1754-
goto free_wqe;
1782+
goto wq_cyc_pop;
17551783
}
17561784

17571785
napi_gro_receive(rq->cq.napi, skb);
17581786

1759-
free_wqe:
1760-
mlx5e_free_rx_wqe(rq, wi, true);
17611787
wq_cyc_pop:
17621788
mlx5_wq_cyc_pop(wq);
17631789
}
@@ -1781,7 +1807,7 @@ static void mlx5e_handle_rx_cqe_rep(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe)
17811807

17821808
if (unlikely(MLX5E_RX_ERR_CQE(cqe))) {
17831809
mlx5e_handle_rx_err_cqe(rq, cqe);
1784-
goto free_wqe;
1810+
goto wq_cyc_pop;
17851811
}
17861812

17871813
skb = INDIRECT_CALL_2(rq->wqe.skb_from_cqe,
@@ -1794,9 +1820,9 @@ static void mlx5e_handle_rx_cqe_rep(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe)
17941820
/* do not return page to cache,
17951821
* it will be returned on XDP_TX completion.
17961822
*/
1797-
goto wq_cyc_pop;
1823+
wi->flags |= BIT(MLX5E_WQE_FRAG_SKIP_RELEASE);
17981824
}
1799-
goto free_wqe;
1825+
goto wq_cyc_pop;
18001826
}
18011827

18021828
mlx5e_complete_rx_cqe(rq, cqe, cqe_bcnt, skb);
@@ -1806,8 +1832,6 @@ static void mlx5e_handle_rx_cqe_rep(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe)
18061832

18071833
mlx5e_rep_tc_receive(cqe, rq, skb);
18081834

1809-
free_wqe:
1810-
mlx5e_free_rx_wqe(rq, wi, true);
18111835
wq_cyc_pop:
18121836
mlx5_wq_cyc_pop(wq);
18131837
}
@@ -2454,25 +2478,24 @@ static void mlx5i_handle_rx_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe)
24542478

24552479
if (unlikely(MLX5E_RX_ERR_CQE(cqe))) {
24562480
rq->stats->wqe_err++;
2457-
goto wq_free_wqe;
2481+
goto wq_cyc_pop;
24582482
}
24592483

24602484
skb = INDIRECT_CALL_2(rq->wqe.skb_from_cqe,
24612485
mlx5e_skb_from_cqe_linear,
24622486
mlx5e_skb_from_cqe_nonlinear,
24632487
rq, wi, cqe, cqe_bcnt);
24642488
if (!skb)
2465-
goto wq_free_wqe;
2489+
goto wq_cyc_pop;
24662490

24672491
mlx5i_complete_rx_cqe(rq, cqe, cqe_bcnt, skb);
24682492
if (unlikely(!skb->dev)) {
24692493
dev_kfree_skb_any(skb);
2470-
goto wq_free_wqe;
2494+
goto wq_cyc_pop;
24712495
}
24722496
napi_gro_receive(rq->cq.napi, skb);
24732497

2474-
wq_free_wqe:
2475-
mlx5e_free_rx_wqe(rq, wi, true);
2498+
wq_cyc_pop:
24762499
mlx5_wq_cyc_pop(wq);
24772500
}
24782501

@@ -2547,12 +2570,12 @@ static void mlx5e_trap_handle_rx_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe
25472570

25482571
if (unlikely(MLX5E_RX_ERR_CQE(cqe))) {
25492572
rq->stats->wqe_err++;
2550-
goto free_wqe;
2573+
goto wq_cyc_pop;
25512574
}
25522575

25532576
skb = mlx5e_skb_from_cqe_nonlinear(rq, wi, cqe, cqe_bcnt);
25542577
if (!skb)
2555-
goto free_wqe;
2578+
goto wq_cyc_pop;
25562579

25572580
mlx5e_complete_rx_cqe(rq, cqe, cqe_bcnt, skb);
25582581
skb_push(skb, ETH_HLEN);
@@ -2561,8 +2584,7 @@ static void mlx5e_trap_handle_rx_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe
25612584
rq->netdev->devlink_port);
25622585
dev_kfree_skb_any(skb);
25632586

2564-
free_wqe:
2565-
mlx5e_free_rx_wqe(rq, wi, false);
2587+
wq_cyc_pop:
25662588
mlx5_wq_cyc_pop(wq);
25672589
}
25682590

0 commit comments

Comments
 (0)