aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTariq Toukan <tariqt@mellanox.com>2017-11-28 04:03:37 -0500
committerSaeed Mahameed <saeedm@mellanox.com>2018-03-30 19:55:06 -0400
commit9f9e9cd50eac6ad09cb053509f2e764bddc05f18 (patch)
tree8b3a3f9c6a1e07c13ef23ec1cebd960fc4ddfad7
parent22f4539881944a8acc9c6f5afa7aa7f028898002 (diff)
net/mlx5e: Remove page_ref bulking in Striding RQ
When many packets reside on the same page, the bulking of page_ref modifications reduces the total number of atomic operations executed. Besides the necessary 2 operations on page alloc/free, we have the following extra ops per page: - one on WQE allocation (bump refcnt to maximum possible), - zero ops for SKBs, - one on WQE free, a constant of two operations in total, no matter how many packets/SKBs actually populate the page. Without this bulking, we have: - no ops on WQE allocation or free, - one op per SKB, Comparing the two methods when PAGE_SIZE is 4K: - As mentioned above, bulking method always executes 2 operations, not more, but not less. - In the default MTU configuration (1500, stride size is 2K), the non-bulking method execute 2 ops as well. - For larger MTUs with stride size of 4K, non-bulking method executes only a single op. - For XDP (stride size of 4K, no SKBs), non-bulking method executes no ops at all! Hence, to optimize the flows with linear SKB and XDP over Striding RQ, we here remove the page_ref bulking method. Performance testing: ConnectX-5, Intel(R) Xeon(R) CPU E5-2680 v3 @ 2.50GHz. Single core packet rate (64 bytes). Early drop in TC: no degradation. XDP_DROP: before: 14,270,188 pps after: 20,503,603 pps, 43% improvement. Signed-off-by: Tariq Toukan <tariqt@mellanox.com> Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en.h1
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_rx.c47
2 files changed, 16 insertions, 32 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h
index 7997d7c159db..5853de4e4fc7 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h
@@ -456,7 +456,6 @@ struct mlx5e_umr_dma_info {
456struct mlx5e_mpw_info { 456struct mlx5e_mpw_info {
457 struct mlx5e_umr_dma_info umr; 457 struct mlx5e_umr_dma_info umr;
458 u16 consumed_strides; 458 u16 consumed_strides;
459 u16 skbs_frags[MLX5_MPWRQ_PAGES_PER_WQE];
460 DECLARE_BITMAP(xdp_xmit_bitmap, MLX5_MPWRQ_PAGES_PER_WQE); 459 DECLARE_BITMAP(xdp_xmit_bitmap, MLX5_MPWRQ_PAGES_PER_WQE);
461}; 460};
462 461
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
index 1da79cab1838..9bb47a6d40f1 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
@@ -296,37 +296,28 @@ void mlx5e_dealloc_rx_wqe(struct mlx5e_rq *rq, u16 ix)
296 mlx5e_free_rx_wqe(rq, wi); 296 mlx5e_free_rx_wqe(rq, wi);
297} 297}
298 298
299static inline int mlx5e_mpwqe_strides_per_page(struct mlx5e_rq *rq)
300{
301 return rq->mpwqe.num_strides >> MLX5_MPWRQ_WQE_PAGE_ORDER;
302}
303
304static inline void mlx5e_add_skb_frag_mpwqe(struct mlx5e_rq *rq, 299static inline void mlx5e_add_skb_frag_mpwqe(struct mlx5e_rq *rq,
305 struct sk_buff *skb, 300 struct sk_buff *skb,
306 struct mlx5e_mpw_info *wi, 301 struct mlx5e_dma_info *di,
307 u32 page_idx, u32 frag_offset, 302 u32 frag_offset, u32 len)
308 u32 len)
309{ 303{
310 unsigned int truesize = ALIGN(len, BIT(rq->mpwqe.log_stride_sz)); 304 unsigned int truesize = ALIGN(len, BIT(rq->mpwqe.log_stride_sz));
311 305
312 dma_sync_single_for_cpu(rq->pdev, 306 dma_sync_single_for_cpu(rq->pdev,
313 wi->umr.dma_info[page_idx].addr + frag_offset, 307 di->addr + frag_offset,
314 len, DMA_FROM_DEVICE); 308 len, DMA_FROM_DEVICE);
315 wi->skbs_frags[page_idx]++; 309 page_ref_inc(di->page);
316 skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, 310 skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
317 wi->umr.dma_info[page_idx].page, frag_offset, 311 di->page, frag_offset, len, truesize);
318 len, truesize);
319} 312}
320 313
321static inline void 314static inline void
322mlx5e_copy_skb_header_mpwqe(struct device *pdev, 315mlx5e_copy_skb_header_mpwqe(struct device *pdev,
323 struct sk_buff *skb, 316 struct sk_buff *skb,
324 struct mlx5e_mpw_info *wi, 317 struct mlx5e_dma_info *dma_info,
325 u32 page_idx, u32 offset, 318 u32 offset, u32 headlen)
326 u32 headlen)
327{ 319{
328 u16 headlen_pg = min_t(u32, headlen, PAGE_SIZE - offset); 320 u16 headlen_pg = min_t(u32, headlen, PAGE_SIZE - offset);
329 struct mlx5e_dma_info *dma_info = &wi->umr.dma_info[page_idx];
330 unsigned int len; 321 unsigned int len;
331 322
332 /* Aligning len to sizeof(long) optimizes memcpy performance */ 323 /* Aligning len to sizeof(long) optimizes memcpy performance */
@@ -351,15 +342,12 @@ void mlx5e_free_rx_mpwqe(struct mlx5e_rq *rq, struct mlx5e_mpw_info *wi)
351{ 342{
352 const bool no_xdp_xmit = 343 const bool no_xdp_xmit =
353 bitmap_empty(wi->xdp_xmit_bitmap, MLX5_MPWRQ_PAGES_PER_WQE); 344 bitmap_empty(wi->xdp_xmit_bitmap, MLX5_MPWRQ_PAGES_PER_WQE);
354 int pg_strides = mlx5e_mpwqe_strides_per_page(rq);
355 struct mlx5e_dma_info *dma_info = wi->umr.dma_info; 345 struct mlx5e_dma_info *dma_info = wi->umr.dma_info;
356 int i; 346 int i;
357 347
358 for (i = 0; i < MLX5_MPWRQ_PAGES_PER_WQE; i++) { 348 for (i = 0; i < MLX5_MPWRQ_PAGES_PER_WQE; i++)
359 page_ref_sub(dma_info[i].page, pg_strides - wi->skbs_frags[i]);
360 if (no_xdp_xmit || !test_bit(i, wi->xdp_xmit_bitmap)) 349 if (no_xdp_xmit || !test_bit(i, wi->xdp_xmit_bitmap))
361 mlx5e_page_release(rq, &dma_info[i], true); 350 mlx5e_page_release(rq, &dma_info[i], true);
362 }
363} 351}
364 352
365static void mlx5e_post_rx_mpwqe(struct mlx5e_rq *rq) 353static void mlx5e_post_rx_mpwqe(struct mlx5e_rq *rq)
@@ -380,7 +368,6 @@ static void mlx5e_post_rx_mpwqe(struct mlx5e_rq *rq)
380static int mlx5e_alloc_rx_mpwqe(struct mlx5e_rq *rq, u16 ix) 368static int mlx5e_alloc_rx_mpwqe(struct mlx5e_rq *rq, u16 ix)
381{ 369{
382 struct mlx5e_mpw_info *wi = &rq->mpwqe.info[ix]; 370 struct mlx5e_mpw_info *wi = &rq->mpwqe.info[ix];
383 int pg_strides = mlx5e_mpwqe_strides_per_page(rq);
384 struct mlx5e_dma_info *dma_info = &wi->umr.dma_info[0]; 371 struct mlx5e_dma_info *dma_info = &wi->umr.dma_info[0];
385 struct mlx5e_icosq *sq = &rq->channel->icosq; 372 struct mlx5e_icosq *sq = &rq->channel->icosq;
386 struct mlx5_wq_cyc *wq = &sq->wq; 373 struct mlx5_wq_cyc *wq = &sq->wq;
@@ -403,10 +390,8 @@ static int mlx5e_alloc_rx_mpwqe(struct mlx5e_rq *rq, u16 ix)
403 if (unlikely(err)) 390 if (unlikely(err))
404 goto err_unmap; 391 goto err_unmap;
405 umr_wqe->inline_mtts[i].ptag = cpu_to_be64(dma_info->addr | MLX5_EN_WR); 392 umr_wqe->inline_mtts[i].ptag = cpu_to_be64(dma_info->addr | MLX5_EN_WR);
406 page_ref_add(dma_info->page, pg_strides);
407 } 393 }
408 394
409 memset(wi->skbs_frags, 0, sizeof(*wi->skbs_frags) * MLX5_MPWRQ_PAGES_PER_WQE);
410 bitmap_zero(wi->xdp_xmit_bitmap, MLX5_MPWRQ_PAGES_PER_WQE); 395 bitmap_zero(wi->xdp_xmit_bitmap, MLX5_MPWRQ_PAGES_PER_WQE);
411 wi->consumed_strides = 0; 396 wi->consumed_strides = 0;
412 397
@@ -425,7 +410,6 @@ static int mlx5e_alloc_rx_mpwqe(struct mlx5e_rq *rq, u16 ix)
425err_unmap: 410err_unmap:
426 while (--i >= 0) { 411 while (--i >= 0) {
427 dma_info--; 412 dma_info--;
428 page_ref_sub(dma_info->page, pg_strides);
429 mlx5e_page_release(rq, dma_info, true); 413 mlx5e_page_release(rq, dma_info, true);
430 } 414 }
431 rq->stats.buff_alloc_err++; 415 rq->stats.buff_alloc_err++;
@@ -987,9 +971,10 @@ mlx5e_skb_from_cqe_mpwrq_nonlinear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *w
987 u16 cqe_bcnt, u32 head_offset, u32 page_idx) 971 u16 cqe_bcnt, u32 head_offset, u32 page_idx)
988{ 972{
989 u16 headlen = min_t(u16, MLX5_MPWRQ_SMALL_PACKET_THRESHOLD, cqe_bcnt); 973 u16 headlen = min_t(u16, MLX5_MPWRQ_SMALL_PACKET_THRESHOLD, cqe_bcnt);
974 struct mlx5e_dma_info *di = &wi->umr.dma_info[page_idx];
990 u32 frag_offset = head_offset + headlen; 975 u32 frag_offset = head_offset + headlen;
991 u16 byte_cnt = cqe_bcnt - headlen; 976 u32 byte_cnt = cqe_bcnt - headlen;
992 u32 head_page_idx = page_idx; 977 struct mlx5e_dma_info *head_di = di;
993 struct sk_buff *skb; 978 struct sk_buff *skb;
994 979
995 skb = napi_alloc_skb(rq->cq.napi, 980 skb = napi_alloc_skb(rq->cq.napi,
@@ -1002,7 +987,7 @@ mlx5e_skb_from_cqe_mpwrq_nonlinear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *w
1002 prefetchw(skb->data); 987 prefetchw(skb->data);
1003 988
1004 if (unlikely(frag_offset >= PAGE_SIZE)) { 989 if (unlikely(frag_offset >= PAGE_SIZE)) {
1005 page_idx++; 990 di++;
1006 frag_offset -= PAGE_SIZE; 991 frag_offset -= PAGE_SIZE;
1007 } 992 }
1008 993
@@ -1010,14 +995,14 @@ mlx5e_skb_from_cqe_mpwrq_nonlinear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *w
1010 u32 pg_consumed_bytes = 995 u32 pg_consumed_bytes =
1011 min_t(u32, PAGE_SIZE - frag_offset, byte_cnt); 996 min_t(u32, PAGE_SIZE - frag_offset, byte_cnt);
1012 997
1013 mlx5e_add_skb_frag_mpwqe(rq, skb, wi, page_idx, frag_offset, 998 mlx5e_add_skb_frag_mpwqe(rq, skb, di, frag_offset,
1014 pg_consumed_bytes); 999 pg_consumed_bytes);
1015 byte_cnt -= pg_consumed_bytes; 1000 byte_cnt -= pg_consumed_bytes;
1016 frag_offset = 0; 1001 frag_offset = 0;
1017 page_idx++; 1002 di++;
1018 } 1003 }
1019 /* copy header */ 1004 /* copy header */
1020 mlx5e_copy_skb_header_mpwqe(rq->pdev, skb, wi, head_page_idx, 1005 mlx5e_copy_skb_header_mpwqe(rq->pdev, skb, head_di,
1021 head_offset, headlen); 1006 head_offset, headlen);
1022 /* skb linear part was allocated with headlen and aligned to long */ 1007 /* skb linear part was allocated with headlen and aligned to long */
1023 skb->tail += headlen; 1008 skb->tail += headlen;
@@ -1060,7 +1045,7 @@ mlx5e_skb_from_cqe_mpwrq_linear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *wi,
1060 return NULL; 1045 return NULL;
1061 1046
1062 /* queue up for recycling/reuse */ 1047 /* queue up for recycling/reuse */
1063 wi->skbs_frags[page_idx]++; 1048 page_ref_inc(di->page);
1064 1049
1065 return skb; 1050 return skb;
1066} 1051}