Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'mlx5e-xdp'

Tariq Toukan says:

====================
mlx5e XDP support

This series adds XDP support in mlx5e driver.
This includes the use cases: XDP_DROP, XDP_PASS, and XDP_TX.

Single stream performance tests show 16.5 Mpps for XDP_DROP,
and 12.4 Mpps for XDP_TX, with nice scalability for multiple streams/rings.

This rate of XDP_DROP is lower than the 32 Mpps we got in previous
implementation, when Striding RQ was used.

We moved to non-Striding RQ, as some XDP_TX requirements (like headroom,
packet-per-page) cannot be satisfied with the current Striding RQ HW,
and we decided to fully support both DROP/TX.

Few directions are considered in order to enable the faster rate for XDP_DROP,
e.g a possibility for users to enable Striding RQ so they choose optimized
XDP_DROP on the price of partial XDP_TX functionality, or some HW changes.

Series generated against net-next commit:
cf714ac147e0 'ipvlan: Fix dependency issue'

Thanks,
Tariq

V2:
* patch 8:
- when XDP_TX fails, call mlx5e_page_release and drop the packet.
- update xdp_tx counter within mlx5e_xmit_xdp_frame.
(mlx5e_xmit_xdp_frame return value becomes obsolete, change it to void)
- drop the packet for unknown XDP return code.
* patch 9:
- use a boolean for xdp_doorbell in SQ struct, instead of dragging it
throughout the functions calls.
- handle doorbell and counters within mlx5e_xmit_xdp_frame.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+759 -265
+56 -13
drivers/net/ethernet/mellanox/mlx5/core/en.h
··· 65 65 #define MLX5E_PARAMS_DEFAULT_LOG_RQ_SIZE_MPW 0x3 66 66 #define MLX5E_PARAMS_MAXIMUM_LOG_RQ_SIZE_MPW 0x6 67 67 68 + #define MLX5_RX_HEADROOM NET_SKB_PAD 69 + 68 70 #define MLX5_MPWRQ_LOG_STRIDE_SIZE 6 /* >= 6, HW restriction */ 69 71 #define MLX5_MPWRQ_LOG_STRIDE_SIZE_CQE_COMPRESS 8 /* >= 6, HW restriction */ 70 72 #define MLX5_MPWRQ_LOG_WQE_SZ 18 ··· 100 98 #define MLX5E_TX_CQ_POLL_BUDGET 128 101 99 #define MLX5E_UPDATE_STATS_INTERVAL 200 /* msecs */ 102 100 #define MLX5E_SQ_BF_BUDGET 16 101 + 102 + #define MLX5E_ICOSQ_MAX_WQEBBS \ 103 + (DIV_ROUND_UP(sizeof(struct mlx5e_umr_wqe), MLX5_SEND_WQE_BB)) 104 + 105 + #define MLX5E_XDP_MIN_INLINE (ETH_HLEN + VLAN_HLEN) 106 + #define MLX5E_XDP_IHS_DS_COUNT \ 107 + DIV_ROUND_UP(MLX5E_XDP_MIN_INLINE - 2, MLX5_SEND_WQE_DS) 108 + #define MLX5E_XDP_TX_DS_COUNT \ 109 + (MLX5E_XDP_IHS_DS_COUNT + \ 110 + (sizeof(struct mlx5e_tx_wqe) / MLX5_SEND_WQE_DS) + 1 /* SG DS */) 111 + #define MLX5E_XDP_TX_WQEBBS \ 112 + DIV_ROUND_UP(MLX5E_XDP_TX_DS_COUNT, MLX5_SEND_WQEBB_NUM_DS) 103 113 104 114 #define MLX5E_NUM_MAIN_GROUPS 9 105 115 ··· 316 302 struct mlx5e_rq { 317 303 /* data path */ 318 304 struct mlx5_wq_ll wq; 319 - u32 wqe_sz; 320 - struct sk_buff **skb; 321 - struct mlx5e_mpw_info *wqe_info; 322 - void *mtt_no_align; 305 + 306 + union { 307 + struct mlx5e_dma_info *dma_info; 308 + struct { 309 + struct mlx5e_mpw_info *info; 310 + void *mtt_no_align; 311 + u32 mtt_offset; 312 + } mpwqe; 313 + }; 314 + struct { 315 + u8 page_order; 316 + u32 wqe_sz; /* wqe data buffer size */ 317 + u8 map_dir; /* dma map direction */ 318 + } buff; 323 319 __be32 mkey_be; 324 320 325 321 struct device *pdev; ··· 345 321 346 322 unsigned long state; 347 323 int ix; 348 - u32 mpwqe_mtt_offset; 349 324 350 325 struct mlx5e_rx_am am; /* Adaptive Moderation */ 326 + struct bpf_prog *xdp_prog; 351 327 352 328 /* control */ 353 329 struct mlx5_wq_ctrl wq_ctrl; ··· 394 370 MLX5E_SQ_STATE_BF_ENABLE, 395 371 }; 396 372 397 - struct mlx5e_ico_wqe_info { 373 + struct mlx5e_sq_wqe_info { 398 374 u8 opcode; 399 375 u8 num_wqebbs; 376 + }; 377 + 378 + enum mlx5e_sq_type { 379 + MLX5E_SQ_TXQ, 380 + MLX5E_SQ_ICO, 381 + MLX5E_SQ_XDP 400 382 }; 401 383 402 384 struct mlx5e_sq { ··· 422 392 423 393 struct mlx5e_cq cq; 424 394 425 - /* pointers to per packet info: write@xmit, read@completion */ 426 - struct sk_buff **skb; 427 - struct mlx5e_sq_dma *dma_fifo; 428 - struct mlx5e_tx_wqe_info *wqe_info; 395 + /* pointers to per tx element info: write@xmit, read@completion */ 396 + union { 397 + struct { 398 + struct sk_buff **skb; 399 + struct mlx5e_sq_dma *dma_fifo; 400 + struct mlx5e_tx_wqe_info *wqe_info; 401 + } txq; 402 + struct mlx5e_sq_wqe_info *ico_wqe; 403 + struct { 404 + struct mlx5e_sq_wqe_info *wqe_info; 405 + struct mlx5e_dma_info *di; 406 + bool doorbell; 407 + } xdp; 408 + } db; 429 409 430 410 /* read only */ 431 411 struct mlx5_wq_cyc wq; ··· 457 417 struct mlx5_uar uar; 458 418 struct mlx5e_channel *channel; 459 419 int tc; 460 - struct mlx5e_ico_wqe_info *ico_wqe_info; 461 420 u32 rate_limit; 421 + u8 type; 462 422 } ____cacheline_aligned_in_smp; 463 423 464 424 static inline bool mlx5e_sq_has_room_for(struct mlx5e_sq *sq, u16 n) ··· 474 434 struct mlx5e_channel { 475 435 /* data path */ 476 436 struct mlx5e_rq rq; 437 + struct mlx5e_sq xdp_sq; 477 438 struct mlx5e_sq sq[MLX5E_MAX_NUM_TC]; 478 439 struct mlx5e_sq icosq; /* internal control operations */ 440 + bool xdp; 479 441 struct napi_struct napi; 480 442 struct device *pdev; 481 443 struct net_device *netdev; ··· 659 617 /* priv data path fields - start */ 660 618 struct mlx5e_sq **txq_to_sq_map; 661 619 int channeltc_to_txq_map[MLX5E_MAX_NUM_CHANNELS][MLX5E_MAX_NUM_TC]; 620 + struct bpf_prog *xdp_prog; 662 621 /* priv data path fields - end */ 663 622 664 623 unsigned long state; ··· 706 663 int mlx5e_napi_poll(struct napi_struct *napi, int budget); 707 664 bool mlx5e_poll_tx_cq(struct mlx5e_cq *cq, int napi_budget); 708 665 int mlx5e_poll_rx_cq(struct mlx5e_cq *cq, int budget); 709 - void mlx5e_free_tx_descs(struct mlx5e_sq *sq); 666 + void mlx5e_free_sq_descs(struct mlx5e_sq *sq); 710 667 711 668 void mlx5e_page_release(struct mlx5e_rq *rq, struct mlx5e_dma_info *dma_info, 712 669 bool recycle); ··· 807 764 808 765 static inline u32 mlx5e_get_wqe_mtt_offset(struct mlx5e_rq *rq, u16 wqe_ix) 809 766 { 810 - return rq->mpwqe_mtt_offset + 767 + return rq->mpwqe.mtt_offset + 811 768 wqe_ix * ALIGN(MLX5_MPWRQ_PAGES_PER_WQE, 8); 812 769 } 813 770
+349 -113
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
··· 34 34 #include <net/pkt_cls.h> 35 35 #include <linux/mlx5/fs.h> 36 36 #include <net/vxlan.h> 37 + #include <linux/bpf.h> 37 38 #include "en.h" 38 39 #include "en_tc.h" 39 40 #include "eswitch.h" ··· 51 50 struct mlx5_wq_param wq; 52 51 u16 max_inline; 53 52 u8 min_inline_mode; 54 - bool icosq; 53 + enum mlx5e_sq_type type; 55 54 }; 56 55 57 56 struct mlx5e_cq_param { ··· 64 63 struct mlx5e_channel_param { 65 64 struct mlx5e_rq_param rq; 66 65 struct mlx5e_sq_param sq; 66 + struct mlx5e_sq_param xdp_sq; 67 67 struct mlx5e_sq_param icosq; 68 68 struct mlx5e_cq_param rx_cq; 69 69 struct mlx5e_cq_param tx_cq; 70 70 struct mlx5e_cq_param icosq_cq; 71 71 }; 72 + 73 + static bool mlx5e_check_fragmented_striding_rq_cap(struct mlx5_core_dev *mdev) 74 + { 75 + return MLX5_CAP_GEN(mdev, striding_rq) && 76 + MLX5_CAP_GEN(mdev, umr_ptr_rlky) && 77 + MLX5_CAP_ETH(mdev, reg_umr_sq); 78 + } 79 + 80 + static void mlx5e_set_rq_type_params(struct mlx5e_priv *priv, u8 rq_type) 81 + { 82 + priv->params.rq_wq_type = rq_type; 83 + switch (priv->params.rq_wq_type) { 84 + case MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ: 85 + priv->params.log_rq_size = MLX5E_PARAMS_DEFAULT_LOG_RQ_SIZE_MPW; 86 + priv->params.mpwqe_log_stride_sz = priv->params.rx_cqe_compress ? 87 + MLX5_MPWRQ_LOG_STRIDE_SIZE_CQE_COMPRESS : 88 + MLX5_MPWRQ_LOG_STRIDE_SIZE; 89 + priv->params.mpwqe_log_num_strides = MLX5_MPWRQ_LOG_WQE_SZ - 90 + priv->params.mpwqe_log_stride_sz; 91 + break; 92 + default: /* MLX5_WQ_TYPE_LINKED_LIST */ 93 + priv->params.log_rq_size = MLX5E_PARAMS_DEFAULT_LOG_RQ_SIZE; 94 + } 95 + priv->params.min_rx_wqes = mlx5_min_rx_wqes(priv->params.rq_wq_type, 96 + BIT(priv->params.log_rq_size)); 97 + 98 + mlx5_core_info(priv->mdev, 99 + "MLX5E: StrdRq(%d) RqSz(%ld) StrdSz(%ld) RxCqeCmprss(%d)\n", 100 + priv->params.rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ, 101 + BIT(priv->params.log_rq_size), 102 + BIT(priv->params.mpwqe_log_stride_sz), 103 + priv->params.rx_cqe_compress_admin); 104 + } 105 + 106 + static void mlx5e_set_rq_priv_params(struct mlx5e_priv *priv) 107 + { 108 + u8 rq_type = mlx5e_check_fragmented_striding_rq_cap(priv->mdev) && 109 + !priv->xdp_prog ? 110 + MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ : 111 + MLX5_WQ_TYPE_LINKED_LIST; 112 + mlx5e_set_rq_type_params(priv, rq_type); 113 + } 72 114 73 115 static void mlx5e_update_carrier(struct mlx5e_priv *priv) 74 116 { ··· 180 136 s->rx_csum_none += rq_stats->csum_none; 181 137 s->rx_csum_complete += rq_stats->csum_complete; 182 138 s->rx_csum_unnecessary_inner += rq_stats->csum_unnecessary_inner; 139 + s->rx_xdp_drop += rq_stats->xdp_drop; 140 + s->rx_xdp_tx += rq_stats->xdp_tx; 141 + s->rx_xdp_tx_full += rq_stats->xdp_tx_full; 183 142 s->rx_wqe_err += rq_stats->wqe_err; 184 143 s->rx_mpwqe_filler += rq_stats->mpwqe_filler; 185 144 s->rx_buff_alloc_err += rq_stats->buff_alloc_err; ··· 361 314 struct mlx5_wqe_ctrl_seg *cseg = &wqe->ctrl; 362 315 struct mlx5_wqe_umr_ctrl_seg *ucseg = &wqe->uctrl; 363 316 struct mlx5_wqe_data_seg *dseg = &wqe->data; 364 - struct mlx5e_mpw_info *wi = &rq->wqe_info[ix]; 317 + struct mlx5e_mpw_info *wi = &rq->mpwqe.info[ix]; 365 318 u8 ds_cnt = DIV_ROUND_UP(sizeof(*wqe), MLX5_SEND_WQE_DS); 366 319 u32 umr_wqe_mtt_offset = mlx5e_get_wqe_mtt_offset(rq, ix); 367 320 ··· 389 342 int mtt_alloc = mtt_sz + MLX5_UMR_ALIGN - 1; 390 343 int i; 391 344 392 - rq->wqe_info = kzalloc_node(wq_sz * sizeof(*rq->wqe_info), 393 - GFP_KERNEL, cpu_to_node(c->cpu)); 394 - if (!rq->wqe_info) 345 + rq->mpwqe.info = kzalloc_node(wq_sz * sizeof(*rq->mpwqe.info), 346 + GFP_KERNEL, cpu_to_node(c->cpu)); 347 + if (!rq->mpwqe.info) 395 348 goto err_out; 396 349 397 350 /* We allocate more than mtt_sz as we will align the pointer */ 398 - rq->mtt_no_align = kzalloc_node(mtt_alloc * wq_sz, GFP_KERNEL, 351 + rq->mpwqe.mtt_no_align = kzalloc_node(mtt_alloc * wq_sz, GFP_KERNEL, 399 352 cpu_to_node(c->cpu)); 400 - if (unlikely(!rq->mtt_no_align)) 353 + if (unlikely(!rq->mpwqe.mtt_no_align)) 401 354 goto err_free_wqe_info; 402 355 403 356 for (i = 0; i < wq_sz; i++) { 404 - struct mlx5e_mpw_info *wi = &rq->wqe_info[i]; 357 + struct mlx5e_mpw_info *wi = &rq->mpwqe.info[i]; 405 358 406 - wi->umr.mtt = PTR_ALIGN(rq->mtt_no_align + i * mtt_alloc, 359 + wi->umr.mtt = PTR_ALIGN(rq->mpwqe.mtt_no_align + i * mtt_alloc, 407 360 MLX5_UMR_ALIGN); 408 361 wi->umr.mtt_addr = dma_map_single(c->pdev, wi->umr.mtt, mtt_sz, 409 362 PCI_DMA_TODEVICE); ··· 417 370 418 371 err_unmap_mtts: 419 372 while (--i >= 0) { 420 - struct mlx5e_mpw_info *wi = &rq->wqe_info[i]; 373 + struct mlx5e_mpw_info *wi = &rq->mpwqe.info[i]; 421 374 422 375 dma_unmap_single(c->pdev, wi->umr.mtt_addr, mtt_sz, 423 376 PCI_DMA_TODEVICE); 424 377 } 425 - kfree(rq->mtt_no_align); 378 + kfree(rq->mpwqe.mtt_no_align); 426 379 err_free_wqe_info: 427 - kfree(rq->wqe_info); 380 + kfree(rq->mpwqe.info); 428 381 429 382 err_out: 430 383 return -ENOMEM; ··· 437 390 int i; 438 391 439 392 for (i = 0; i < wq_sz; i++) { 440 - struct mlx5e_mpw_info *wi = &rq->wqe_info[i]; 393 + struct mlx5e_mpw_info *wi = &rq->mpwqe.info[i]; 441 394 442 395 dma_unmap_single(rq->pdev, wi->umr.mtt_addr, mtt_sz, 443 396 PCI_DMA_TODEVICE); 444 397 } 445 - kfree(rq->mtt_no_align); 446 - kfree(rq->wqe_info); 398 + kfree(rq->mpwqe.mtt_no_align); 399 + kfree(rq->mpwqe.info); 447 400 } 448 401 449 402 static int mlx5e_create_rq(struct mlx5e_channel *c, ··· 455 408 void *rqc = param->rqc; 456 409 void *rqc_wq = MLX5_ADDR_OF(rqc, rqc, wq); 457 410 u32 byte_count; 411 + u32 frag_sz; 412 + int npages; 458 413 int wq_sz; 459 414 int err; 460 415 int i; ··· 479 430 rq->channel = c; 480 431 rq->ix = c->ix; 481 432 rq->priv = c->priv; 433 + rq->xdp_prog = priv->xdp_prog; 434 + 435 + rq->buff.map_dir = DMA_FROM_DEVICE; 436 + if (rq->xdp_prog) 437 + rq->buff.map_dir = DMA_BIDIRECTIONAL; 482 438 483 439 switch (priv->params.rq_wq_type) { 484 440 case MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ: ··· 491 437 rq->alloc_wqe = mlx5e_alloc_rx_mpwqe; 492 438 rq->dealloc_wqe = mlx5e_dealloc_rx_mpwqe; 493 439 494 - rq->mpwqe_mtt_offset = c->ix * 440 + rq->mpwqe.mtt_offset = c->ix * 495 441 MLX5E_REQUIRED_MTTS(1, BIT(priv->params.log_rq_size)); 496 442 497 443 rq->mpwqe_stride_sz = BIT(priv->params.mpwqe_log_stride_sz); 498 444 rq->mpwqe_num_strides = BIT(priv->params.mpwqe_log_num_strides); 499 - rq->wqe_sz = rq->mpwqe_stride_sz * rq->mpwqe_num_strides; 500 - byte_count = rq->wqe_sz; 445 + 446 + rq->buff.wqe_sz = rq->mpwqe_stride_sz * rq->mpwqe_num_strides; 447 + byte_count = rq->buff.wqe_sz; 501 448 rq->mkey_be = cpu_to_be32(c->priv->umr_mkey.key); 502 449 err = mlx5e_rq_alloc_mpwqe_info(rq, c); 503 450 if (err) 504 451 goto err_rq_wq_destroy; 505 452 break; 506 453 default: /* MLX5_WQ_TYPE_LINKED_LIST */ 507 - rq->skb = kzalloc_node(wq_sz * sizeof(*rq->skb), GFP_KERNEL, 508 - cpu_to_node(c->cpu)); 509 - if (!rq->skb) { 454 + rq->dma_info = kzalloc_node(wq_sz * sizeof(*rq->dma_info), 455 + GFP_KERNEL, cpu_to_node(c->cpu)); 456 + if (!rq->dma_info) { 510 457 err = -ENOMEM; 511 458 goto err_rq_wq_destroy; 512 459 } 460 + 513 461 rq->handle_rx_cqe = mlx5e_handle_rx_cqe; 514 462 rq->alloc_wqe = mlx5e_alloc_rx_wqe; 515 463 rq->dealloc_wqe = mlx5e_dealloc_rx_wqe; 516 464 517 - rq->wqe_sz = (priv->params.lro_en) ? 465 + rq->buff.wqe_sz = (priv->params.lro_en) ? 518 466 priv->params.lro_wqe_sz : 519 467 MLX5E_SW2HW_MTU(priv->netdev->mtu); 520 - rq->wqe_sz = SKB_DATA_ALIGN(rq->wqe_sz); 521 - byte_count = rq->wqe_sz; 468 + byte_count = rq->buff.wqe_sz; 469 + 470 + /* calc the required page order */ 471 + frag_sz = MLX5_RX_HEADROOM + 472 + byte_count /* packet data */ + 473 + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); 474 + frag_sz = SKB_DATA_ALIGN(frag_sz); 475 + 476 + npages = DIV_ROUND_UP(frag_sz, PAGE_SIZE); 477 + rq->buff.page_order = order_base_2(npages); 478 + 522 479 byte_count |= MLX5_HW_START_PADDING; 523 480 rq->mkey_be = c->mkey_be; 524 481 } ··· 547 482 rq->page_cache.head = 0; 548 483 rq->page_cache.tail = 0; 549 484 485 + if (rq->xdp_prog) 486 + bpf_prog_add(rq->xdp_prog, 1); 487 + 550 488 return 0; 551 489 552 490 err_rq_wq_destroy: ··· 562 494 { 563 495 int i; 564 496 497 + if (rq->xdp_prog) 498 + bpf_prog_put(rq->xdp_prog); 499 + 565 500 switch (rq->wq_type) { 566 501 case MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ: 567 502 mlx5e_rq_free_mpwqe_info(rq); 568 503 break; 569 504 default: /* MLX5_WQ_TYPE_LINKED_LIST */ 570 - kfree(rq->skb); 505 + kfree(rq->dma_info); 571 506 } 572 507 573 508 for (i = rq->page_cache.head; i != rq->page_cache.tail; ··· 712 641 713 642 /* UMR WQE (if in progress) is always at wq->head */ 714 643 if (test_bit(MLX5E_RQ_STATE_UMR_WQE_IN_PROGRESS, &rq->state)) 715 - mlx5e_free_rx_mpwqe(rq, &rq->wqe_info[wq->head]); 644 + mlx5e_free_rx_mpwqe(rq, &rq->mpwqe.info[wq->head]); 716 645 717 646 while (!mlx5_wq_ll_is_empty(wq)) { 718 647 wqe_ix_be = *wq->tail_next; ··· 747 676 if (param->am_enabled) 748 677 set_bit(MLX5E_RQ_STATE_AM, &c->rq.state); 749 678 750 - sq->ico_wqe_info[pi].opcode = MLX5_OPCODE_NOP; 751 - sq->ico_wqe_info[pi].num_wqebbs = 1; 679 + sq->db.ico_wqe[pi].opcode = MLX5_OPCODE_NOP; 680 + sq->db.ico_wqe[pi].num_wqebbs = 1; 752 681 mlx5e_send_nop(sq, true); /* trigger mlx5e_post_rx_wqes() */ 753 682 754 683 return 0; ··· 772 701 mlx5e_destroy_rq(rq); 773 702 } 774 703 775 - static void mlx5e_free_sq_db(struct mlx5e_sq *sq) 704 + static void mlx5e_free_sq_xdp_db(struct mlx5e_sq *sq) 776 705 { 777 - kfree(sq->wqe_info); 778 - kfree(sq->dma_fifo); 779 - kfree(sq->skb); 706 + kfree(sq->db.xdp.di); 707 + kfree(sq->db.xdp.wqe_info); 780 708 } 781 709 782 - static int mlx5e_alloc_sq_db(struct mlx5e_sq *sq, int numa) 710 + static int mlx5e_alloc_sq_xdp_db(struct mlx5e_sq *sq, int numa) 711 + { 712 + int wq_sz = mlx5_wq_cyc_get_size(&sq->wq); 713 + 714 + sq->db.xdp.di = kzalloc_node(sizeof(*sq->db.xdp.di) * wq_sz, 715 + GFP_KERNEL, numa); 716 + sq->db.xdp.wqe_info = kzalloc_node(sizeof(*sq->db.xdp.wqe_info) * wq_sz, 717 + GFP_KERNEL, numa); 718 + if (!sq->db.xdp.di || !sq->db.xdp.wqe_info) { 719 + mlx5e_free_sq_xdp_db(sq); 720 + return -ENOMEM; 721 + } 722 + 723 + return 0; 724 + } 725 + 726 + static void mlx5e_free_sq_ico_db(struct mlx5e_sq *sq) 727 + { 728 + kfree(sq->db.ico_wqe); 729 + } 730 + 731 + static int mlx5e_alloc_sq_ico_db(struct mlx5e_sq *sq, int numa) 732 + { 733 + u8 wq_sz = mlx5_wq_cyc_get_size(&sq->wq); 734 + 735 + sq->db.ico_wqe = kzalloc_node(sizeof(*sq->db.ico_wqe) * wq_sz, 736 + GFP_KERNEL, numa); 737 + if (!sq->db.ico_wqe) 738 + return -ENOMEM; 739 + 740 + return 0; 741 + } 742 + 743 + static void mlx5e_free_sq_txq_db(struct mlx5e_sq *sq) 744 + { 745 + kfree(sq->db.txq.wqe_info); 746 + kfree(sq->db.txq.dma_fifo); 747 + kfree(sq->db.txq.skb); 748 + } 749 + 750 + static int mlx5e_alloc_sq_txq_db(struct mlx5e_sq *sq, int numa) 783 751 { 784 752 int wq_sz = mlx5_wq_cyc_get_size(&sq->wq); 785 753 int df_sz = wq_sz * MLX5_SEND_WQEBB_NUM_DS; 786 754 787 - sq->skb = kzalloc_node(wq_sz * sizeof(*sq->skb), GFP_KERNEL, numa); 788 - sq->dma_fifo = kzalloc_node(df_sz * sizeof(*sq->dma_fifo), GFP_KERNEL, 789 - numa); 790 - sq->wqe_info = kzalloc_node(wq_sz * sizeof(*sq->wqe_info), GFP_KERNEL, 791 - numa); 792 - 793 - if (!sq->skb || !sq->dma_fifo || !sq->wqe_info) { 794 - mlx5e_free_sq_db(sq); 755 + sq->db.txq.skb = kzalloc_node(wq_sz * sizeof(*sq->db.txq.skb), 756 + GFP_KERNEL, numa); 757 + sq->db.txq.dma_fifo = kzalloc_node(df_sz * sizeof(*sq->db.txq.dma_fifo), 758 + GFP_KERNEL, numa); 759 + sq->db.txq.wqe_info = kzalloc_node(wq_sz * sizeof(*sq->db.txq.wqe_info), 760 + GFP_KERNEL, numa); 761 + if (!sq->db.txq.skb || !sq->db.txq.dma_fifo || !sq->db.txq.wqe_info) { 762 + mlx5e_free_sq_txq_db(sq); 795 763 return -ENOMEM; 796 764 } 797 765 798 766 sq->dma_fifo_mask = df_sz - 1; 799 767 800 768 return 0; 769 + } 770 + 771 + static void mlx5e_free_sq_db(struct mlx5e_sq *sq) 772 + { 773 + switch (sq->type) { 774 + case MLX5E_SQ_TXQ: 775 + mlx5e_free_sq_txq_db(sq); 776 + break; 777 + case MLX5E_SQ_ICO: 778 + mlx5e_free_sq_ico_db(sq); 779 + break; 780 + case MLX5E_SQ_XDP: 781 + mlx5e_free_sq_xdp_db(sq); 782 + break; 783 + } 784 + } 785 + 786 + static int mlx5e_alloc_sq_db(struct mlx5e_sq *sq, int numa) 787 + { 788 + switch (sq->type) { 789 + case MLX5E_SQ_TXQ: 790 + return mlx5e_alloc_sq_txq_db(sq, numa); 791 + case MLX5E_SQ_ICO: 792 + return mlx5e_alloc_sq_ico_db(sq, numa); 793 + case MLX5E_SQ_XDP: 794 + return mlx5e_alloc_sq_xdp_db(sq, numa); 795 + } 796 + 797 + return 0; 798 + } 799 + 800 + static int mlx5e_sq_get_max_wqebbs(u8 sq_type) 801 + { 802 + switch (sq_type) { 803 + case MLX5E_SQ_ICO: 804 + return MLX5E_ICOSQ_MAX_WQEBBS; 805 + case MLX5E_SQ_XDP: 806 + return MLX5E_XDP_TX_WQEBBS; 807 + } 808 + return MLX5_SEND_WQE_MAX_WQEBBS; 801 809 } 802 810 803 811 static int mlx5e_create_sq(struct mlx5e_channel *c, ··· 890 740 void *sqc = param->sqc; 891 741 void *sqc_wq = MLX5_ADDR_OF(sqc, sqc, wq); 892 742 int err; 743 + 744 + sq->type = param->type; 745 + sq->pdev = c->pdev; 746 + sq->tstamp = &priv->tstamp; 747 + sq->mkey_be = c->mkey_be; 748 + sq->channel = c; 749 + sq->tc = tc; 893 750 894 751 err = mlx5_alloc_map_uar(mdev, &sq->uar, !!MLX5_CAP_GEN(mdev, bf)); 895 752 if (err) ··· 926 769 if (err) 927 770 goto err_sq_wq_destroy; 928 771 929 - if (param->icosq) { 930 - u8 wq_sz = mlx5_wq_cyc_get_size(&sq->wq); 931 - 932 - sq->ico_wqe_info = kzalloc_node(sizeof(*sq->ico_wqe_info) * 933 - wq_sz, 934 - GFP_KERNEL, 935 - cpu_to_node(c->cpu)); 936 - if (!sq->ico_wqe_info) { 937 - err = -ENOMEM; 938 - goto err_free_sq_db; 939 - } 940 - } else { 772 + if (sq->type == MLX5E_SQ_TXQ) { 941 773 int txq_ix; 942 774 943 775 txq_ix = c->ix + tc * priv->params.num_channels; ··· 934 788 priv->txq_to_sq_map[txq_ix] = sq; 935 789 } 936 790 937 - sq->pdev = c->pdev; 938 - sq->tstamp = &priv->tstamp; 939 - sq->mkey_be = c->mkey_be; 940 - sq->channel = c; 941 - sq->tc = tc; 942 - sq->edge = (sq->wq.sz_m1 + 1) - MLX5_SEND_WQE_MAX_WQEBBS; 791 + sq->edge = (sq->wq.sz_m1 + 1) - mlx5e_sq_get_max_wqebbs(sq->type); 943 792 sq->bf_budget = MLX5E_SQ_BF_BUDGET; 944 793 945 794 return 0; 946 - 947 - err_free_sq_db: 948 - mlx5e_free_sq_db(sq); 949 795 950 796 err_sq_wq_destroy: 951 797 mlx5_wq_destroy(&sq->wq_ctrl); ··· 953 815 struct mlx5e_channel *c = sq->channel; 954 816 struct mlx5e_priv *priv = c->priv; 955 817 956 - kfree(sq->ico_wqe_info); 957 818 mlx5e_free_sq_db(sq); 958 819 mlx5_wq_destroy(&sq->wq_ctrl); 959 820 mlx5_unmap_free_uar(priv->mdev, &sq->uar); ··· 981 844 982 845 memcpy(sqc, param->sqc, sizeof(param->sqc)); 983 846 984 - MLX5_SET(sqc, sqc, tis_num_0, param->icosq ? 0 : priv->tisn[sq->tc]); 847 + MLX5_SET(sqc, sqc, tis_num_0, param->type == MLX5E_SQ_ICO ? 848 + 0 : priv->tisn[sq->tc]); 985 849 MLX5_SET(sqc, sqc, cqn, sq->cq.mcq.cqn); 986 850 MLX5_SET(sqc, sqc, min_wqe_inline_mode, sq->min_inline_mode); 987 851 MLX5_SET(sqc, sqc, state, MLX5_SQC_STATE_RST); 988 - MLX5_SET(sqc, sqc, tis_lst_sz, param->icosq ? 0 : 1); 852 + MLX5_SET(sqc, sqc, tis_lst_sz, param->type == MLX5E_SQ_ICO ? 0 : 1); 989 853 MLX5_SET(sqc, sqc, flush_in_error_en, 1); 990 854 991 855 MLX5_SET(wq, wq, wq_type, MLX5_WQ_TYPE_CYCLIC); ··· 1101 963 netif_tx_disable_queue(sq->txq); 1102 964 1103 965 /* last doorbell out, godspeed .. */ 1104 - if (mlx5e_sq_has_room_for(sq, 1)) 966 + if (mlx5e_sq_has_room_for(sq, 1)) { 967 + sq->db.txq.skb[(sq->pc & sq->wq.sz_m1)] = NULL; 1105 968 mlx5e_send_nop(sq, true); 969 + } 1106 970 } 1107 971 1108 972 mlx5e_disable_sq(sq); 1109 - mlx5e_free_tx_descs(sq); 973 + mlx5e_free_sq_descs(sq); 1110 974 mlx5e_destroy_sq(sq); 1111 975 } 1112 976 ··· 1469 1329 } 1470 1330 } 1471 1331 1332 + if (priv->xdp_prog) { 1333 + /* XDP SQ CQ params are same as normal TXQ sq CQ params */ 1334 + err = mlx5e_open_cq(c, &cparam->tx_cq, &c->xdp_sq.cq, 1335 + priv->params.tx_cq_moderation); 1336 + if (err) 1337 + goto err_close_sqs; 1338 + 1339 + err = mlx5e_open_sq(c, 0, &cparam->xdp_sq, &c->xdp_sq); 1340 + if (err) { 1341 + mlx5e_close_cq(&c->xdp_sq.cq); 1342 + goto err_close_sqs; 1343 + } 1344 + } 1345 + 1346 + c->xdp = !!priv->xdp_prog; 1472 1347 err = mlx5e_open_rq(c, &cparam->rq, &c->rq); 1473 1348 if (err) 1474 - goto err_close_sqs; 1349 + goto err_close_xdp_sq; 1475 1350 1476 1351 netif_set_xps_queue(netdev, get_cpu_mask(c->cpu), ix); 1477 1352 *cp = c; 1478 1353 1479 1354 return 0; 1355 + err_close_xdp_sq: 1356 + mlx5e_close_sq(&c->xdp_sq); 1480 1357 1481 1358 err_close_sqs: 1482 1359 mlx5e_close_sqs(c); ··· 1522 1365 static void mlx5e_close_channel(struct mlx5e_channel *c) 1523 1366 { 1524 1367 mlx5e_close_rq(&c->rq); 1368 + if (c->xdp) 1369 + mlx5e_close_sq(&c->xdp_sq); 1525 1370 mlx5e_close_sqs(c); 1526 1371 mlx5e_close_sq(&c->icosq); 1527 1372 napi_disable(&c->napi); 1373 + if (c->xdp) 1374 + mlx5e_close_cq(&c->xdp_sq.cq); 1528 1375 mlx5e_close_cq(&c->rq.cq); 1529 1376 mlx5e_close_tx_cqs(c); 1530 1377 mlx5e_close_cq(&c->icosq.cq); ··· 1602 1441 1603 1442 param->max_inline = priv->params.tx_max_inline; 1604 1443 param->min_inline_mode = priv->params.tx_min_inline_mode; 1444 + param->type = MLX5E_SQ_TXQ; 1605 1445 } 1606 1446 1607 1447 static void mlx5e_build_common_cq_param(struct mlx5e_priv *priv, ··· 1676 1514 MLX5_SET(wq, wq, log_wq_sz, log_wq_size); 1677 1515 MLX5_SET(sqc, sqc, reg_umr, MLX5_CAP_ETH(priv->mdev, reg_umr_sq)); 1678 1516 1679 - param->icosq = true; 1517 + param->type = MLX5E_SQ_ICO; 1518 + } 1519 + 1520 + static void mlx5e_build_xdpsq_param(struct mlx5e_priv *priv, 1521 + struct mlx5e_sq_param *param) 1522 + { 1523 + void *sqc = param->sqc; 1524 + void *wq = MLX5_ADDR_OF(sqc, sqc, wq); 1525 + 1526 + mlx5e_build_sq_param_common(priv, param); 1527 + MLX5_SET(wq, wq, log_wq_sz, priv->params.log_sq_size); 1528 + 1529 + param->max_inline = priv->params.tx_max_inline; 1530 + /* FOR XDP SQs will support only L2 inline mode */ 1531 + param->min_inline_mode = MLX5_INLINE_MODE_NONE; 1532 + param->type = MLX5E_SQ_XDP; 1680 1533 } 1681 1534 1682 1535 static void mlx5e_build_channel_param(struct mlx5e_priv *priv, struct mlx5e_channel_param *cparam) ··· 1700 1523 1701 1524 mlx5e_build_rq_param(priv, &cparam->rq); 1702 1525 mlx5e_build_sq_param(priv, &cparam->sq); 1526 + mlx5e_build_xdpsq_param(priv, &cparam->xdp_sq); 1703 1527 mlx5e_build_icosq_param(priv, &cparam->icosq, icosq_log_wq_sz); 1704 1528 mlx5e_build_rx_cq_param(priv, &cparam->rx_cq); 1705 1529 mlx5e_build_tx_cq_param(priv, &cparam->tx_cq); ··· 3079 2901 schedule_work(&priv->tx_timeout_work); 3080 2902 } 3081 2903 2904 + static int mlx5e_xdp_set(struct net_device *netdev, struct bpf_prog *prog) 2905 + { 2906 + struct mlx5e_priv *priv = netdev_priv(netdev); 2907 + struct bpf_prog *old_prog; 2908 + int err = 0; 2909 + bool reset, was_opened; 2910 + int i; 2911 + 2912 + mutex_lock(&priv->state_lock); 2913 + 2914 + if ((netdev->features & NETIF_F_LRO) && prog) { 2915 + netdev_warn(netdev, "can't set XDP while LRO is on, disable LRO first\n"); 2916 + err = -EINVAL; 2917 + goto unlock; 2918 + } 2919 + 2920 + was_opened = test_bit(MLX5E_STATE_OPENED, &priv->state); 2921 + /* no need for full reset when exchanging programs */ 2922 + reset = (!priv->xdp_prog || !prog); 2923 + 2924 + if (was_opened && reset) 2925 + mlx5e_close_locked(netdev); 2926 + 2927 + /* exchange programs */ 2928 + old_prog = xchg(&priv->xdp_prog, prog); 2929 + if (prog) 2930 + bpf_prog_add(prog, 1); 2931 + if (old_prog) 2932 + bpf_prog_put(old_prog); 2933 + 2934 + if (reset) /* change RQ type according to priv->xdp_prog */ 2935 + mlx5e_set_rq_priv_params(priv); 2936 + 2937 + if (was_opened && reset) 2938 + mlx5e_open_locked(netdev); 2939 + 2940 + if (!test_bit(MLX5E_STATE_OPENED, &priv->state) || reset) 2941 + goto unlock; 2942 + 2943 + /* exchanging programs w/o reset, we update ref counts on behalf 2944 + * of the channels RQs here. 2945 + */ 2946 + bpf_prog_add(prog, priv->params.num_channels); 2947 + for (i = 0; i < priv->params.num_channels; i++) { 2948 + struct mlx5e_channel *c = priv->channel[i]; 2949 + 2950 + set_bit(MLX5E_RQ_STATE_FLUSH, &c->rq.state); 2951 + napi_synchronize(&c->napi); 2952 + /* prevent mlx5e_poll_rx_cq from accessing rq->xdp_prog */ 2953 + 2954 + old_prog = xchg(&c->rq.xdp_prog, prog); 2955 + 2956 + clear_bit(MLX5E_RQ_STATE_FLUSH, &c->rq.state); 2957 + /* napi_schedule in case we have missed anything */ 2958 + set_bit(MLX5E_CHANNEL_NAPI_SCHED, &c->flags); 2959 + napi_schedule(&c->napi); 2960 + 2961 + if (old_prog) 2962 + bpf_prog_put(old_prog); 2963 + } 2964 + 2965 + unlock: 2966 + mutex_unlock(&priv->state_lock); 2967 + return err; 2968 + } 2969 + 2970 + static bool mlx5e_xdp_attached(struct net_device *dev) 2971 + { 2972 + struct mlx5e_priv *priv = netdev_priv(dev); 2973 + 2974 + return !!priv->xdp_prog; 2975 + } 2976 + 2977 + static int mlx5e_xdp(struct net_device *dev, struct netdev_xdp *xdp) 2978 + { 2979 + switch (xdp->command) { 2980 + case XDP_SETUP_PROG: 2981 + return mlx5e_xdp_set(dev, xdp->prog); 2982 + case XDP_QUERY_PROG: 2983 + xdp->prog_attached = mlx5e_xdp_attached(dev); 2984 + return 0; 2985 + default: 2986 + return -EINVAL; 2987 + } 2988 + } 2989 + 3082 2990 static const struct net_device_ops mlx5e_netdev_ops_basic = { 3083 2991 .ndo_open = mlx5e_open, 3084 2992 .ndo_stop = mlx5e_close, ··· 3184 2920 .ndo_rx_flow_steer = mlx5e_rx_flow_steer, 3185 2921 #endif 3186 2922 .ndo_tx_timeout = mlx5e_tx_timeout, 2923 + .ndo_xdp = mlx5e_xdp, 3187 2924 }; 3188 2925 3189 2926 static const struct net_device_ops mlx5e_netdev_ops_sriov = { ··· 3216 2951 .ndo_set_vf_link_state = mlx5e_set_vf_link_state, 3217 2952 .ndo_get_vf_stats = mlx5e_get_vf_stats, 3218 2953 .ndo_tx_timeout = mlx5e_tx_timeout, 2954 + .ndo_xdp = mlx5e_xdp, 3219 2955 }; 3220 2956 3221 2957 static int mlx5e_check_required_hca_cap(struct mlx5_core_dev *mdev) ··· 3289 3023 3290 3024 for (i = 0; i < len; i++) 3291 3025 indirection_rqt[i] = i % num_channels; 3292 - } 3293 - 3294 - static bool mlx5e_check_fragmented_striding_rq_cap(struct mlx5_core_dev *mdev) 3295 - { 3296 - return MLX5_CAP_GEN(mdev, striding_rq) && 3297 - MLX5_CAP_GEN(mdev, umr_ptr_rlky) && 3298 - MLX5_CAP_ETH(mdev, reg_umr_sq); 3299 3026 } 3300 3027 3301 3028 static int mlx5e_get_pci_bw(struct mlx5_core_dev *mdev, u32 *pci_bw) ··· 3370 3111 MLX5_CQ_PERIOD_MODE_START_FROM_CQE : 3371 3112 MLX5_CQ_PERIOD_MODE_START_FROM_EQE; 3372 3113 3373 - priv->params.log_sq_size = 3374 - MLX5E_PARAMS_DEFAULT_LOG_SQ_SIZE; 3375 - priv->params.rq_wq_type = mlx5e_check_fragmented_striding_rq_cap(mdev) ? 3376 - MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ : 3377 - MLX5_WQ_TYPE_LINKED_LIST; 3114 + priv->mdev = mdev; 3115 + priv->netdev = netdev; 3116 + priv->params.num_channels = profile->max_nch(mdev); 3117 + priv->profile = profile; 3118 + priv->ppriv = ppriv; 3119 + 3120 + priv->params.log_sq_size = MLX5E_PARAMS_DEFAULT_LOG_SQ_SIZE; 3378 3121 3379 3122 /* set CQE compression */ 3380 3123 priv->params.rx_cqe_compress_admin = false; ··· 3389 3128 priv->params.rx_cqe_compress_admin = 3390 3129 cqe_compress_heuristic(link_speed, pci_bw); 3391 3130 } 3392 - 3393 3131 priv->params.rx_cqe_compress = priv->params.rx_cqe_compress_admin; 3394 3132 3395 - switch (priv->params.rq_wq_type) { 3396 - case MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ: 3397 - priv->params.log_rq_size = MLX5E_PARAMS_DEFAULT_LOG_RQ_SIZE_MPW; 3398 - priv->params.mpwqe_log_stride_sz = 3399 - priv->params.rx_cqe_compress ? 3400 - MLX5_MPWRQ_LOG_STRIDE_SIZE_CQE_COMPRESS : 3401 - MLX5_MPWRQ_LOG_STRIDE_SIZE; 3402 - priv->params.mpwqe_log_num_strides = MLX5_MPWRQ_LOG_WQE_SZ - 3403 - priv->params.mpwqe_log_stride_sz; 3133 + mlx5e_set_rq_priv_params(priv); 3134 + if (priv->params.rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ) 3404 3135 priv->params.lro_en = true; 3405 - break; 3406 - default: /* MLX5_WQ_TYPE_LINKED_LIST */ 3407 - priv->params.log_rq_size = MLX5E_PARAMS_DEFAULT_LOG_RQ_SIZE; 3408 - } 3409 - 3410 - mlx5_core_info(mdev, 3411 - "MLX5E: StrdRq(%d) RqSz(%ld) StrdSz(%ld) RxCqeCmprss(%d)\n", 3412 - priv->params.rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ, 3413 - BIT(priv->params.log_rq_size), 3414 - BIT(priv->params.mpwqe_log_stride_sz), 3415 - priv->params.rx_cqe_compress_admin); 3416 - 3417 - priv->params.min_rx_wqes = mlx5_min_rx_wqes(priv->params.rq_wq_type, 3418 - BIT(priv->params.log_rq_size)); 3419 3136 3420 3137 priv->params.rx_am_enabled = MLX5_CAP_GEN(mdev, cq_moderation); 3421 3138 mlx5e_set_rx_cq_mode_params(&priv->params, cq_period_mode); ··· 3413 3174 mlx5e_build_default_indir_rqt(mdev, priv->params.indirection_rqt, 3414 3175 MLX5E_INDIR_RQT_SIZE, profile->max_nch(mdev)); 3415 3176 3416 - priv->params.lro_wqe_sz = 3417 - MLX5E_PARAMS_DEFAULT_LRO_WQE_SZ; 3177 + priv->params.lro_wqe_sz = 3178 + MLX5E_PARAMS_DEFAULT_LRO_WQE_SZ - 3179 + /* Extra room needed for build_skb */ 3180 + MLX5_RX_HEADROOM - 3181 + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); 3418 3182 3419 3183 /* Initialize pflags */ 3420 3184 MLX5E_SET_PRIV_FLAG(priv, MLX5E_PFLAG_RX_CQE_BASED_MODER, 3421 3185 priv->params.rx_cq_period_mode == MLX5_CQ_PERIOD_MODE_START_FROM_CQE); 3422 - 3423 - priv->mdev = mdev; 3424 - priv->netdev = netdev; 3425 - priv->params.num_channels = profile->max_nch(mdev); 3426 - priv->profile = profile; 3427 - priv->ppriv = ppriv; 3428 3186 3429 3187 #ifdef CONFIG_MLX5_CORE_EN_DCB 3430 3188 mlx5e_ets_init(priv);
+228 -125
drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
··· 179 179 mutex_unlock(&priv->state_lock); 180 180 } 181 181 182 - int mlx5e_alloc_rx_wqe(struct mlx5e_rq *rq, struct mlx5e_rx_wqe *wqe, u16 ix) 183 - { 184 - struct sk_buff *skb; 185 - dma_addr_t dma_addr; 182 + #define RQ_PAGE_SIZE(rq) ((1 << rq->buff.page_order) << PAGE_SHIFT) 186 183 187 - skb = napi_alloc_skb(rq->cq.napi, rq->wqe_sz); 188 - if (unlikely(!skb)) 184 + static inline bool mlx5e_rx_cache_put(struct mlx5e_rq *rq, 185 + struct mlx5e_dma_info *dma_info) 186 + { 187 + struct mlx5e_page_cache *cache = &rq->page_cache; 188 + u32 tail_next = (cache->tail + 1) & (MLX5E_CACHE_SIZE - 1); 189 + 190 + if (tail_next == cache->head) { 191 + rq->stats.cache_full++; 192 + return false; 193 + } 194 + 195 + cache->page_cache[cache->tail] = *dma_info; 196 + cache->tail = tail_next; 197 + return true; 198 + } 199 + 200 + static inline bool mlx5e_rx_cache_get(struct mlx5e_rq *rq, 201 + struct mlx5e_dma_info *dma_info) 202 + { 203 + struct mlx5e_page_cache *cache = &rq->page_cache; 204 + 205 + if (unlikely(cache->head == cache->tail)) { 206 + rq->stats.cache_empty++; 207 + return false; 208 + } 209 + 210 + if (page_ref_count(cache->page_cache[cache->head].page) != 1) { 211 + rq->stats.cache_busy++; 212 + return false; 213 + } 214 + 215 + *dma_info = cache->page_cache[cache->head]; 216 + cache->head = (cache->head + 1) & (MLX5E_CACHE_SIZE - 1); 217 + rq->stats.cache_reuse++; 218 + 219 + dma_sync_single_for_device(rq->pdev, dma_info->addr, 220 + RQ_PAGE_SIZE(rq), 221 + DMA_FROM_DEVICE); 222 + return true; 223 + } 224 + 225 + static inline int mlx5e_page_alloc_mapped(struct mlx5e_rq *rq, 226 + struct mlx5e_dma_info *dma_info) 227 + { 228 + struct page *page; 229 + 230 + if (mlx5e_rx_cache_get(rq, dma_info)) 231 + return 0; 232 + 233 + page = dev_alloc_pages(rq->buff.page_order); 234 + if (unlikely(!page)) 189 235 return -ENOMEM; 190 236 191 - dma_addr = dma_map_single(rq->pdev, 192 - /* hw start padding */ 193 - skb->data, 194 - /* hw end padding */ 195 - rq->wqe_sz, 196 - DMA_FROM_DEVICE); 197 - 198 - if (unlikely(dma_mapping_error(rq->pdev, dma_addr))) 199 - goto err_free_skb; 200 - 201 - *((dma_addr_t *)skb->cb) = dma_addr; 202 - wqe->data.addr = cpu_to_be64(dma_addr); 203 - 204 - rq->skb[ix] = skb; 237 + dma_info->page = page; 238 + dma_info->addr = dma_map_page(rq->pdev, page, 0, 239 + RQ_PAGE_SIZE(rq), rq->buff.map_dir); 240 + if (unlikely(dma_mapping_error(rq->pdev, dma_info->addr))) { 241 + put_page(page); 242 + return -ENOMEM; 243 + } 205 244 206 245 return 0; 246 + } 207 247 208 - err_free_skb: 209 - dev_kfree_skb(skb); 248 + void mlx5e_page_release(struct mlx5e_rq *rq, struct mlx5e_dma_info *dma_info, 249 + bool recycle) 250 + { 251 + if (likely(recycle) && mlx5e_rx_cache_put(rq, dma_info)) 252 + return; 210 253 211 - return -ENOMEM; 254 + dma_unmap_page(rq->pdev, dma_info->addr, RQ_PAGE_SIZE(rq), 255 + rq->buff.map_dir); 256 + put_page(dma_info->page); 257 + } 258 + 259 + int mlx5e_alloc_rx_wqe(struct mlx5e_rq *rq, struct mlx5e_rx_wqe *wqe, u16 ix) 260 + { 261 + struct mlx5e_dma_info *di = &rq->dma_info[ix]; 262 + 263 + if (unlikely(mlx5e_page_alloc_mapped(rq, di))) 264 + return -ENOMEM; 265 + 266 + wqe->data.addr = cpu_to_be64(di->addr + MLX5_RX_HEADROOM); 267 + return 0; 212 268 } 213 269 214 270 void mlx5e_dealloc_rx_wqe(struct mlx5e_rq *rq, u16 ix) 215 271 { 216 - struct sk_buff *skb = rq->skb[ix]; 272 + struct mlx5e_dma_info *di = &rq->dma_info[ix]; 217 273 218 - if (skb) { 219 - rq->skb[ix] = NULL; 220 - dma_unmap_single(rq->pdev, 221 - *((dma_addr_t *)skb->cb), 222 - rq->wqe_sz, 223 - DMA_FROM_DEVICE); 224 - dev_kfree_skb(skb); 225 - } 274 + mlx5e_page_release(rq, di, true); 226 275 } 227 276 228 277 static inline int mlx5e_mpwqe_strides_per_page(struct mlx5e_rq *rq) ··· 328 279 329 280 static inline void mlx5e_post_umr_wqe(struct mlx5e_rq *rq, u16 ix) 330 281 { 331 - struct mlx5e_mpw_info *wi = &rq->wqe_info[ix]; 282 + struct mlx5e_mpw_info *wi = &rq->mpwqe.info[ix]; 332 283 struct mlx5e_sq *sq = &rq->channel->icosq; 333 284 struct mlx5_wq_cyc *wq = &sq->wq; 334 285 struct mlx5e_umr_wqe *wqe; ··· 337 288 338 289 /* fill sq edge with nops to avoid wqe wrap around */ 339 290 while ((pi = (sq->pc & wq->sz_m1)) > sq->edge) { 340 - sq->ico_wqe_info[pi].opcode = MLX5_OPCODE_NOP; 341 - sq->ico_wqe_info[pi].num_wqebbs = 1; 291 + sq->db.ico_wqe[pi].opcode = MLX5_OPCODE_NOP; 292 + sq->db.ico_wqe[pi].num_wqebbs = 1; 342 293 mlx5e_send_nop(sq, true); 343 294 } 344 295 ··· 348 299 cpu_to_be32((sq->pc << MLX5_WQE_CTRL_WQE_INDEX_SHIFT) | 349 300 MLX5_OPCODE_UMR); 350 301 351 - sq->ico_wqe_info[pi].opcode = MLX5_OPCODE_UMR; 352 - sq->ico_wqe_info[pi].num_wqebbs = num_wqebbs; 302 + sq->db.ico_wqe[pi].opcode = MLX5_OPCODE_UMR; 303 + sq->db.ico_wqe[pi].num_wqebbs = num_wqebbs; 353 304 sq->pc += num_wqebbs; 354 305 mlx5e_tx_notify_hw(sq, &wqe->ctrl, 0); 355 - } 356 - 357 - static inline bool mlx5e_rx_cache_put(struct mlx5e_rq *rq, 358 - struct mlx5e_dma_info *dma_info) 359 - { 360 - struct mlx5e_page_cache *cache = &rq->page_cache; 361 - u32 tail_next = (cache->tail + 1) & (MLX5E_CACHE_SIZE - 1); 362 - 363 - if (tail_next == cache->head) { 364 - rq->stats.cache_full++; 365 - return false; 366 - } 367 - 368 - cache->page_cache[cache->tail] = *dma_info; 369 - cache->tail = tail_next; 370 - return true; 371 - } 372 - 373 - static inline bool mlx5e_rx_cache_get(struct mlx5e_rq *rq, 374 - struct mlx5e_dma_info *dma_info) 375 - { 376 - struct mlx5e_page_cache *cache = &rq->page_cache; 377 - 378 - if (unlikely(cache->head == cache->tail)) { 379 - rq->stats.cache_empty++; 380 - return false; 381 - } 382 - 383 - if (page_ref_count(cache->page_cache[cache->head].page) != 1) { 384 - rq->stats.cache_busy++; 385 - return false; 386 - } 387 - 388 - *dma_info = cache->page_cache[cache->head]; 389 - cache->head = (cache->head + 1) & (MLX5E_CACHE_SIZE - 1); 390 - rq->stats.cache_reuse++; 391 - 392 - dma_sync_single_for_device(rq->pdev, dma_info->addr, PAGE_SIZE, 393 - DMA_FROM_DEVICE); 394 - return true; 395 - } 396 - 397 - static inline int mlx5e_page_alloc_mapped(struct mlx5e_rq *rq, 398 - struct mlx5e_dma_info *dma_info) 399 - { 400 - struct page *page; 401 - 402 - if (mlx5e_rx_cache_get(rq, dma_info)) 403 - return 0; 404 - 405 - page = dev_alloc_page(); 406 - if (unlikely(!page)) 407 - return -ENOMEM; 408 - 409 - dma_info->page = page; 410 - dma_info->addr = dma_map_page(rq->pdev, page, 0, PAGE_SIZE, 411 - DMA_FROM_DEVICE); 412 - if (unlikely(dma_mapping_error(rq->pdev, dma_info->addr))) { 413 - put_page(page); 414 - return -ENOMEM; 415 - } 416 - 417 - return 0; 418 - } 419 - 420 - void mlx5e_page_release(struct mlx5e_rq *rq, struct mlx5e_dma_info *dma_info, 421 - bool recycle) 422 - { 423 - if (likely(recycle) && mlx5e_rx_cache_put(rq, dma_info)) 424 - return; 425 - 426 - dma_unmap_page(rq->pdev, dma_info->addr, PAGE_SIZE, DMA_FROM_DEVICE); 427 - put_page(dma_info->page); 428 306 } 429 307 430 308 static int mlx5e_alloc_rx_umr_mpwqe(struct mlx5e_rq *rq, 431 309 struct mlx5e_rx_wqe *wqe, 432 310 u16 ix) 433 311 { 434 - struct mlx5e_mpw_info *wi = &rq->wqe_info[ix]; 312 + struct mlx5e_mpw_info *wi = &rq->mpwqe.info[ix]; 435 313 u64 dma_offset = (u64)mlx5e_get_wqe_mtt_offset(rq, ix) << PAGE_SHIFT; 436 314 int pg_strides = mlx5e_mpwqe_strides_per_page(rq); 437 315 int err; ··· 412 436 clear_bit(MLX5E_RQ_STATE_UMR_WQE_IN_PROGRESS, &rq->state); 413 437 414 438 if (unlikely(test_bit(MLX5E_RQ_STATE_FLUSH, &rq->state))) { 415 - mlx5e_free_rx_mpwqe(rq, &rq->wqe_info[wq->head]); 439 + mlx5e_free_rx_mpwqe(rq, &rq->mpwqe.info[wq->head]); 416 440 return; 417 441 } 418 442 ··· 424 448 mlx5_wq_ll_update_db_record(wq); 425 449 } 426 450 427 - int mlx5e_alloc_rx_mpwqe(struct mlx5e_rq *rq, struct mlx5e_rx_wqe *wqe, u16 ix) 451 + int mlx5e_alloc_rx_mpwqe(struct mlx5e_rq *rq, struct mlx5e_rx_wqe *wqe, u16 ix) 428 452 { 429 453 int err; 430 454 ··· 438 462 439 463 void mlx5e_dealloc_rx_mpwqe(struct mlx5e_rq *rq, u16 ix) 440 464 { 441 - struct mlx5e_mpw_info *wi = &rq->wqe_info[ix]; 465 + struct mlx5e_mpw_info *wi = &rq->mpwqe.info[ix]; 442 466 443 467 mlx5e_free_rx_mpwqe(rq, wi); 444 468 } ··· 632 656 napi_gro_receive(rq->cq.napi, skb); 633 657 } 634 658 659 + static inline void mlx5e_xmit_xdp_doorbell(struct mlx5e_sq *sq) 660 + { 661 + struct mlx5_wq_cyc *wq = &sq->wq; 662 + struct mlx5e_tx_wqe *wqe; 663 + u16 pi = (sq->pc - MLX5E_XDP_TX_WQEBBS) & wq->sz_m1; /* last pi */ 664 + 665 + wqe = mlx5_wq_cyc_get_wqe(wq, pi); 666 + 667 + wqe->ctrl.fm_ce_se = MLX5_WQE_CTRL_CQ_UPDATE; 668 + mlx5e_tx_notify_hw(sq, &wqe->ctrl, 0); 669 + } 670 + 671 + static inline void mlx5e_xmit_xdp_frame(struct mlx5e_rq *rq, 672 + struct mlx5e_dma_info *di, 673 + unsigned int data_offset, 674 + int len) 675 + { 676 + struct mlx5e_sq *sq = &rq->channel->xdp_sq; 677 + struct mlx5_wq_cyc *wq = &sq->wq; 678 + u16 pi = sq->pc & wq->sz_m1; 679 + struct mlx5e_tx_wqe *wqe = mlx5_wq_cyc_get_wqe(wq, pi); 680 + struct mlx5e_sq_wqe_info *wi = &sq->db.xdp.wqe_info[pi]; 681 + 682 + struct mlx5_wqe_ctrl_seg *cseg = &wqe->ctrl; 683 + struct mlx5_wqe_eth_seg *eseg = &wqe->eth; 684 + struct mlx5_wqe_data_seg *dseg; 685 + 686 + dma_addr_t dma_addr = di->addr + data_offset + MLX5E_XDP_MIN_INLINE; 687 + unsigned int dma_len = len - MLX5E_XDP_MIN_INLINE; 688 + void *data = page_address(di->page) + data_offset; 689 + 690 + if (unlikely(!mlx5e_sq_has_room_for(sq, MLX5E_XDP_TX_WQEBBS))) { 691 + if (sq->db.xdp.doorbell) { 692 + /* SQ is full, ring doorbell */ 693 + mlx5e_xmit_xdp_doorbell(sq); 694 + sq->db.xdp.doorbell = false; 695 + } 696 + rq->stats.xdp_tx_full++; 697 + mlx5e_page_release(rq, di, true); 698 + return; 699 + } 700 + 701 + dma_sync_single_for_device(sq->pdev, dma_addr, dma_len, 702 + PCI_DMA_TODEVICE); 703 + 704 + memset(wqe, 0, sizeof(*wqe)); 705 + 706 + /* copy the inline part */ 707 + memcpy(eseg->inline_hdr_start, data, MLX5E_XDP_MIN_INLINE); 708 + eseg->inline_hdr_sz = cpu_to_be16(MLX5E_XDP_MIN_INLINE); 709 + 710 + dseg = (struct mlx5_wqe_data_seg *)cseg + (MLX5E_XDP_TX_DS_COUNT - 1); 711 + 712 + /* write the dma part */ 713 + dseg->addr = cpu_to_be64(dma_addr); 714 + dseg->byte_count = cpu_to_be32(dma_len); 715 + dseg->lkey = sq->mkey_be; 716 + 717 + cseg->opmod_idx_opcode = cpu_to_be32((sq->pc << 8) | MLX5_OPCODE_SEND); 718 + cseg->qpn_ds = cpu_to_be32((sq->sqn << 8) | MLX5E_XDP_TX_DS_COUNT); 719 + 720 + sq->db.xdp.di[pi] = *di; 721 + wi->opcode = MLX5_OPCODE_SEND; 722 + wi->num_wqebbs = MLX5E_XDP_TX_WQEBBS; 723 + sq->pc += MLX5E_XDP_TX_WQEBBS; 724 + 725 + sq->db.xdp.doorbell = true; 726 + rq->stats.xdp_tx++; 727 + } 728 + 729 + /* returns true if packet was consumed by xdp */ 730 + static inline bool mlx5e_xdp_handle(struct mlx5e_rq *rq, 731 + const struct bpf_prog *prog, 732 + struct mlx5e_dma_info *di, 733 + void *data, u16 len) 734 + { 735 + struct xdp_buff xdp; 736 + u32 act; 737 + 738 + if (!prog) 739 + return false; 740 + 741 + xdp.data = data; 742 + xdp.data_end = xdp.data + len; 743 + act = bpf_prog_run_xdp(prog, &xdp); 744 + switch (act) { 745 + case XDP_PASS: 746 + return false; 747 + case XDP_TX: 748 + mlx5e_xmit_xdp_frame(rq, di, MLX5_RX_HEADROOM, len); 749 + return true; 750 + default: 751 + bpf_warn_invalid_xdp_action(act); 752 + case XDP_ABORTED: 753 + case XDP_DROP: 754 + rq->stats.xdp_drop++; 755 + mlx5e_page_release(rq, di, true); 756 + return true; 757 + } 758 + } 759 + 635 760 void mlx5e_handle_rx_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe) 636 761 { 762 + struct bpf_prog *xdp_prog = READ_ONCE(rq->xdp_prog); 763 + struct mlx5e_dma_info *di; 637 764 struct mlx5e_rx_wqe *wqe; 638 - struct sk_buff *skb; 639 765 __be16 wqe_counter_be; 766 + struct sk_buff *skb; 640 767 u16 wqe_counter; 768 + void *va, *data; 641 769 u32 cqe_bcnt; 642 770 643 771 wqe_counter_be = cqe->wqe_counter; 644 772 wqe_counter = be16_to_cpu(wqe_counter_be); 645 773 wqe = mlx5_wq_ll_get_wqe(&rq->wq, wqe_counter); 646 - skb = rq->skb[wqe_counter]; 647 - prefetch(skb->data); 648 - rq->skb[wqe_counter] = NULL; 774 + di = &rq->dma_info[wqe_counter]; 775 + va = page_address(di->page); 776 + data = va + MLX5_RX_HEADROOM; 649 777 650 - dma_unmap_single(rq->pdev, 651 - *((dma_addr_t *)skb->cb), 652 - rq->wqe_sz, 653 - DMA_FROM_DEVICE); 778 + dma_sync_single_range_for_cpu(rq->pdev, 779 + di->addr, 780 + MLX5_RX_HEADROOM, 781 + rq->buff.wqe_sz, 782 + DMA_FROM_DEVICE); 783 + prefetch(data); 784 + cqe_bcnt = be32_to_cpu(cqe->byte_cnt); 654 785 655 786 if (unlikely((cqe->op_own >> 4) != MLX5_CQE_RESP_SEND)) { 656 787 rq->stats.wqe_err++; 657 - dev_kfree_skb(skb); 788 + mlx5e_page_release(rq, di, true); 658 789 goto wq_ll_pop; 659 790 } 660 791 661 - cqe_bcnt = be32_to_cpu(cqe->byte_cnt); 792 + if (mlx5e_xdp_handle(rq, xdp_prog, di, data, cqe_bcnt)) 793 + goto wq_ll_pop; /* page/packet was consumed by XDP */ 794 + 795 + skb = build_skb(va, RQ_PAGE_SIZE(rq)); 796 + if (unlikely(!skb)) { 797 + rq->stats.buff_alloc_err++; 798 + mlx5e_page_release(rq, di, true); 799 + goto wq_ll_pop; 800 + } 801 + 802 + /* queue up for recycling ..*/ 803 + page_ref_inc(di->page); 804 + mlx5e_page_release(rq, di, true); 805 + 806 + skb_reserve(skb, MLX5_RX_HEADROOM); 662 807 skb_put(skb, cqe_bcnt); 663 808 664 809 mlx5e_complete_rx_cqe(rq, cqe, cqe_bcnt, skb); ··· 831 734 { 832 735 u16 cstrides = mpwrq_get_cqe_consumed_strides(cqe); 833 736 u16 wqe_id = be16_to_cpu(cqe->wqe_id); 834 - struct mlx5e_mpw_info *wi = &rq->wqe_info[wqe_id]; 737 + struct mlx5e_mpw_info *wi = &rq->mpwqe.info[wqe_id]; 835 738 struct mlx5e_rx_wqe *wqe = mlx5_wq_ll_get_wqe(&rq->wq, wqe_id); 836 739 struct sk_buff *skb; 837 740 u16 cqe_bcnt; ··· 873 776 int mlx5e_poll_rx_cq(struct mlx5e_cq *cq, int budget) 874 777 { 875 778 struct mlx5e_rq *rq = container_of(cq, struct mlx5e_rq, cq); 779 + struct mlx5e_sq *xdp_sq = &rq->channel->xdp_sq; 876 780 int work_done = 0; 877 781 878 782 if (unlikely(test_bit(MLX5E_RQ_STATE_FLUSH, &rq->state))) ··· 898 800 mlx5_cqwq_pop(&cq->wq); 899 801 900 802 rq->handle_rx_cqe(rq, cqe); 803 + } 804 + 805 + if (xdp_sq->db.xdp.doorbell) { 806 + mlx5e_xmit_xdp_doorbell(xdp_sq); 807 + xdp_sq->db.xdp.doorbell = false; 901 808 } 902 809 903 810 mlx5_cqwq_update_db_record(&cq->wq);
+12
drivers/net/ethernet/mellanox/mlx5/core/en_stats.h
··· 65 65 u64 rx_csum_none; 66 66 u64 rx_csum_complete; 67 67 u64 rx_csum_unnecessary_inner; 68 + u64 rx_xdp_drop; 69 + u64 rx_xdp_tx; 70 + u64 rx_xdp_tx_full; 68 71 u64 tx_csum_partial; 69 72 u64 tx_csum_partial_inner; 70 73 u64 tx_queue_stopped; ··· 103 100 { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_csum_none) }, 104 101 { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_csum_complete) }, 105 102 { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_csum_unnecessary_inner) }, 103 + { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_xdp_drop) }, 104 + { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_xdp_tx) }, 105 + { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_xdp_tx_full) }, 106 106 { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_csum_partial) }, 107 107 { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_csum_partial_inner) }, 108 108 { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_queue_stopped) }, ··· 284 278 u64 csum_none; 285 279 u64 lro_packets; 286 280 u64 lro_bytes; 281 + u64 xdp_drop; 282 + u64 xdp_tx; 283 + u64 xdp_tx_full; 287 284 u64 wqe_err; 288 285 u64 mpwqe_filler; 289 286 u64 buff_alloc_err; ··· 304 295 { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, csum_complete) }, 305 296 { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, csum_unnecessary_inner) }, 306 297 { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, csum_none) }, 298 + { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, xdp_drop) }, 299 + { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, xdp_tx) }, 300 + { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, xdp_tx_full) }, 307 301 { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, lro_packets) }, 308 302 { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, lro_bytes) }, 309 303 { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, wqe_err) },
+50 -13
drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
··· 52 52 cseg->opmod_idx_opcode = cpu_to_be32((sq->pc << 8) | MLX5_OPCODE_NOP); 53 53 cseg->qpn_ds = cpu_to_be32((sq->sqn << 8) | 0x01); 54 54 55 - sq->skb[pi] = NULL; 56 55 sq->pc++; 57 56 sq->stats.nop++; 58 57 ··· 81 82 u32 size, 82 83 enum mlx5e_dma_map_type map_type) 83 84 { 84 - sq->dma_fifo[sq->dma_fifo_pc & sq->dma_fifo_mask].addr = addr; 85 - sq->dma_fifo[sq->dma_fifo_pc & sq->dma_fifo_mask].size = size; 86 - sq->dma_fifo[sq->dma_fifo_pc & sq->dma_fifo_mask].type = map_type; 85 + u32 i = sq->dma_fifo_pc & sq->dma_fifo_mask; 86 + 87 + sq->db.txq.dma_fifo[i].addr = addr; 88 + sq->db.txq.dma_fifo[i].size = size; 89 + sq->db.txq.dma_fifo[i].type = map_type; 87 90 sq->dma_fifo_pc++; 88 91 } 89 92 90 93 static inline struct mlx5e_sq_dma *mlx5e_dma_get(struct mlx5e_sq *sq, u32 i) 91 94 { 92 - return &sq->dma_fifo[i & sq->dma_fifo_mask]; 95 + return &sq->db.txq.dma_fifo[i & sq->dma_fifo_mask]; 93 96 } 94 97 95 98 static void mlx5e_dma_unmap_wqe_err(struct mlx5e_sq *sq, u8 num_dma) ··· 222 221 223 222 u16 pi = sq->pc & wq->sz_m1; 224 223 struct mlx5e_tx_wqe *wqe = mlx5_wq_cyc_get_wqe(wq, pi); 225 - struct mlx5e_tx_wqe_info *wi = &sq->wqe_info[pi]; 224 + struct mlx5e_tx_wqe_info *wi = &sq->db.txq.wqe_info[pi]; 226 225 227 226 struct mlx5_wqe_ctrl_seg *cseg = &wqe->ctrl; 228 227 struct mlx5_wqe_eth_seg *eseg = &wqe->eth; ··· 342 341 cseg->opmod_idx_opcode = cpu_to_be32((sq->pc << 8) | opcode); 343 342 cseg->qpn_ds = cpu_to_be32((sq->sqn << 8) | ds_cnt); 344 343 345 - sq->skb[pi] = skb; 344 + sq->db.txq.skb[pi] = skb; 346 345 347 346 wi->num_wqebbs = DIV_ROUND_UP(ds_cnt, MLX5_SEND_WQEBB_NUM_DS); 348 347 sq->pc += wi->num_wqebbs; ··· 369 368 } 370 369 371 370 /* fill sq edge with nops to avoid wqe wrap around */ 372 - while ((sq->pc & wq->sz_m1) > sq->edge) 371 + while ((pi = (sq->pc & wq->sz_m1)) > sq->edge) { 372 + sq->db.txq.skb[pi] = NULL; 373 373 mlx5e_send_nop(sq, false); 374 + } 374 375 375 376 if (bf) 376 377 sq->bf_budget--; ··· 445 442 last_wqe = (sqcc == wqe_counter); 446 443 447 444 ci = sqcc & sq->wq.sz_m1; 448 - skb = sq->skb[ci]; 449 - wi = &sq->wqe_info[ci]; 445 + skb = sq->db.txq.skb[ci]; 446 + wi = &sq->db.txq.wqe_info[ci]; 450 447 451 448 if (unlikely(!skb)) { /* nop */ 452 449 sqcc++; ··· 495 492 return (i == MLX5E_TX_CQ_POLL_BUDGET); 496 493 } 497 494 498 - void mlx5e_free_tx_descs(struct mlx5e_sq *sq) 495 + static void mlx5e_free_txq_sq_descs(struct mlx5e_sq *sq) 499 496 { 500 497 struct mlx5e_tx_wqe_info *wi; 501 498 struct sk_buff *skb; ··· 504 501 505 502 while (sq->cc != sq->pc) { 506 503 ci = sq->cc & sq->wq.sz_m1; 507 - skb = sq->skb[ci]; 508 - wi = &sq->wqe_info[ci]; 504 + skb = sq->db.txq.skb[ci]; 505 + wi = &sq->db.txq.wqe_info[ci]; 509 506 510 507 if (!skb) { /* nop */ 511 508 sq->cc++; ··· 521 518 522 519 dev_kfree_skb_any(skb); 523 520 sq->cc += wi->num_wqebbs; 521 + } 522 + } 523 + 524 + static void mlx5e_free_xdp_sq_descs(struct mlx5e_sq *sq) 525 + { 526 + struct mlx5e_sq_wqe_info *wi; 527 + struct mlx5e_dma_info *di; 528 + u16 ci; 529 + 530 + while (sq->cc != sq->pc) { 531 + ci = sq->cc & sq->wq.sz_m1; 532 + di = &sq->db.xdp.di[ci]; 533 + wi = &sq->db.xdp.wqe_info[ci]; 534 + 535 + if (wi->opcode == MLX5_OPCODE_NOP) { 536 + sq->cc++; 537 + continue; 538 + } 539 + 540 + sq->cc += wi->num_wqebbs; 541 + 542 + mlx5e_page_release(&sq->channel->rq, di, false); 543 + } 544 + } 545 + 546 + void mlx5e_free_sq_descs(struct mlx5e_sq *sq) 547 + { 548 + switch (sq->type) { 549 + case MLX5E_SQ_TXQ: 550 + mlx5e_free_txq_sq_descs(sq); 551 + break; 552 + case MLX5E_SQ_XDP: 553 + mlx5e_free_xdp_sq_descs(sq); 554 + break; 524 555 } 525 556 }
+64 -1
drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c
··· 72 72 73 73 do { 74 74 u16 ci = be16_to_cpu(cqe->wqe_counter) & wq->sz_m1; 75 - struct mlx5e_ico_wqe_info *icowi = &sq->ico_wqe_info[ci]; 75 + struct mlx5e_sq_wqe_info *icowi = &sq->db.ico_wqe[ci]; 76 76 77 77 mlx5_cqwq_pop(&cq->wq); 78 78 sqcc += icowi->num_wqebbs; ··· 105 105 sq->cc = sqcc; 106 106 } 107 107 108 + static inline bool mlx5e_poll_xdp_tx_cq(struct mlx5e_cq *cq) 109 + { 110 + struct mlx5e_sq *sq; 111 + u16 sqcc; 112 + int i; 113 + 114 + sq = container_of(cq, struct mlx5e_sq, cq); 115 + 116 + if (unlikely(test_bit(MLX5E_SQ_STATE_FLUSH, &sq->state))) 117 + return false; 118 + 119 + /* sq->cc must be updated only after mlx5_cqwq_update_db_record(), 120 + * otherwise a cq overrun may occur 121 + */ 122 + sqcc = sq->cc; 123 + 124 + for (i = 0; i < MLX5E_TX_CQ_POLL_BUDGET; i++) { 125 + struct mlx5_cqe64 *cqe; 126 + u16 wqe_counter; 127 + bool last_wqe; 128 + 129 + cqe = mlx5e_get_cqe(cq); 130 + if (!cqe) 131 + break; 132 + 133 + mlx5_cqwq_pop(&cq->wq); 134 + 135 + wqe_counter = be16_to_cpu(cqe->wqe_counter); 136 + 137 + do { 138 + struct mlx5e_sq_wqe_info *wi; 139 + struct mlx5e_dma_info *di; 140 + u16 ci; 141 + 142 + last_wqe = (sqcc == wqe_counter); 143 + 144 + ci = sqcc & sq->wq.sz_m1; 145 + di = &sq->db.xdp.di[ci]; 146 + wi = &sq->db.xdp.wqe_info[ci]; 147 + 148 + if (unlikely(wi->opcode == MLX5_OPCODE_NOP)) { 149 + sqcc++; 150 + continue; 151 + } 152 + 153 + sqcc += wi->num_wqebbs; 154 + /* Recycle RX page */ 155 + mlx5e_page_release(&sq->channel->rq, di, true); 156 + } while (!last_wqe); 157 + } 158 + 159 + mlx5_cqwq_update_db_record(&cq->wq); 160 + 161 + /* ensure cq space is freed before enabling more cqes */ 162 + wmb(); 163 + 164 + sq->cc = sqcc; 165 + return (i == MLX5E_TX_CQ_POLL_BUDGET); 166 + } 167 + 108 168 int mlx5e_napi_poll(struct napi_struct *napi, int budget) 109 169 { 110 170 struct mlx5e_channel *c = container_of(napi, struct mlx5e_channel, ··· 180 120 181 121 work_done = mlx5e_poll_rx_cq(&c->rq.cq, budget); 182 122 busy |= work_done == budget; 123 + 124 + if (c->xdp) 125 + busy |= mlx5e_poll_xdp_tx_cq(&c->xdp_sq.cq); 183 126 184 127 mlx5e_poll_ico_cq(&c->icosq.cq); 185 128