net/mlx5e: XDP Tx, no inline copy on ConnectX-5
authorSaeed Mahameed <saeedm@mellanox.com>
Tue, 6 Dec 2016 12:04:05 +0000 (14:04 +0200)
committerSaeed Mahameed <saeedm@mellanox.com>
Mon, 6 Feb 2017 16:20:18 +0000 (18:20 +0200)
ConnectX-5 and later HW generations will report min inline mode ==
MLX5_INLINE_MODE_NONE, which means driver is not required to copy packet
headers to inline fields of TX WQE.

Avoid copy to inline segment in XDP TX routine when HW inline mode doesn't
require it.

This will improve CPU utilization and boost XDP TX performance.

Tested with xdp2 single flow:
CPU: Intel(R) Xeon(R) CPU E5-2680 v3 @ 2.50GHz
HCA: Mellanox Technologies MT28800 Family [ConnectX-5 Ex]

Before: 7.4Mpps
After:  7.8Mpps
Improvement: 5%

Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
Reviewed-by: Tariq Toukan <tariqt@mellanox.com>
drivers/net/ethernet/mellanox/mlx5/core/en.h
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/en_rx.c

index 9b23d3329847e7662b3664d80f252b7d3a6133a9..8be4b12b55454beff3a2fa330649862f27a9abe7 100644 (file)
 #define MLX5E_XDP_IHS_DS_COUNT \
        DIV_ROUND_UP(MLX5E_XDP_MIN_INLINE - 2, MLX5_SEND_WQE_DS)
 #define MLX5E_XDP_TX_DS_COUNT \
-       (MLX5E_XDP_IHS_DS_COUNT + \
-        (sizeof(struct mlx5e_tx_wqe) / MLX5_SEND_WQE_DS) + 1 /* SG DS */)
+       ((sizeof(struct mlx5e_tx_wqe) / MLX5_SEND_WQE_DS) + 1 /* SG DS */)
 #define MLX5E_XDP_TX_WQEBBS \
        DIV_ROUND_UP(MLX5E_XDP_TX_DS_COUNT, MLX5_SEND_WQEBB_NUM_DS)
 
index 9cd38401fdc92d7dd595ea9219de01d179709cdf..ed230757d9c5fecfbbb94f8cfec5cb3a86f9db60 100644 (file)
@@ -1806,8 +1806,7 @@ static void mlx5e_build_xdpsq_param(struct mlx5e_priv *priv,
        MLX5_SET(wq, wq, log_wq_sz,     priv->params.log_sq_size);
 
        param->max_inline = priv->params.tx_max_inline;
-       /* FOR XDP SQs will support only L2 inline mode */
-       param->min_inline_mode = MLX5_INLINE_MODE_NONE;
+       param->min_inline_mode = priv->params.tx_min_inline_mode;
        param->type = MLX5E_SQ_XDP;
 }
 
index 965e69e9ff1e519e778927b9247488858c0f1997..b039b87742a64422454ea105a8073b6451977253 100644 (file)
@@ -657,9 +657,10 @@ static inline bool mlx5e_xmit_xdp_frame(struct mlx5e_rq *rq,
        struct mlx5_wqe_ctrl_seg *cseg = &wqe->ctrl;
        struct mlx5_wqe_eth_seg  *eseg = &wqe->eth;
        struct mlx5_wqe_data_seg *dseg;
+       u8 ds_cnt = MLX5E_XDP_TX_DS_COUNT;
 
        ptrdiff_t data_offset = xdp->data - xdp->data_hard_start;
-       dma_addr_t dma_addr  = di->addr + data_offset + MLX5E_XDP_MIN_INLINE;
+       dma_addr_t dma_addr  = di->addr + data_offset;
        unsigned int dma_len = xdp->data_end - xdp->data;
 
        if (unlikely(dma_len < MLX5E_XDP_MIN_INLINE ||
@@ -680,17 +681,22 @@ static inline bool mlx5e_xmit_xdp_frame(struct mlx5e_rq *rq,
                return false;
        }
 
-       dma_len -= MLX5E_XDP_MIN_INLINE;
        dma_sync_single_for_device(sq->pdev, dma_addr, dma_len,
                                   PCI_DMA_TODEVICE);
 
        memset(wqe, 0, sizeof(*wqe));
 
-       /* copy the inline part */
-       memcpy(eseg->inline_hdr.start, xdp->data, MLX5E_XDP_MIN_INLINE);
-       eseg->inline_hdr.sz = cpu_to_be16(MLX5E_XDP_MIN_INLINE);
+       dseg = (struct mlx5_wqe_data_seg *)eseg + 1;
+       /* copy the inline part if required */
+       if (sq->min_inline_mode != MLX5_INLINE_MODE_NONE) {
+               memcpy(eseg->inline_hdr.start, xdp->data, MLX5E_XDP_MIN_INLINE);
+               eseg->inline_hdr.sz = cpu_to_be16(MLX5E_XDP_MIN_INLINE);
+               dma_len  -= MLX5E_XDP_MIN_INLINE;
+               dma_addr += MLX5E_XDP_MIN_INLINE;
 
-       dseg = (struct mlx5_wqe_data_seg *)cseg + (MLX5E_XDP_TX_DS_COUNT - 1);
+               ds_cnt   += MLX5E_XDP_IHS_DS_COUNT;
+               dseg++;
+       }
 
        /* write the dma part */
        dseg->addr       = cpu_to_be64(dma_addr);
@@ -698,7 +704,7 @@ static inline bool mlx5e_xmit_xdp_frame(struct mlx5e_rq *rq,
        dseg->lkey       = sq->mkey_be;
 
        cseg->opmod_idx_opcode = cpu_to_be32((sq->pc << 8) | MLX5_OPCODE_SEND);
-       cseg->qpn_ds = cpu_to_be32((sq->sqn << 8) | MLX5E_XDP_TX_DS_COUNT);
+       cseg->qpn_ds = cpu_to_be32((sq->sqn << 8) | ds_cnt);
 
        sq->db.xdp.di[pi] = *di;
        wi->opcode     = MLX5_OPCODE_SEND;