Skip to content

Commit 2c925db

Browse files
ofer70Saeed Mahameed
authored andcommitted
net/mlx5e: Support enhanced CQE compression
CQE compression feature improves performance by reducing PCI bandwidth bottleneck on CQEs write. Enhanced CQE compression introduced in ConnectX-6 and it aims to reduce CPU utilization of SW side packets decompression by eliminating the need to rewrite ownership bit, which is likely to cost a cache-miss, is replaced by validity byte handled solely by HW. Another advantage of the enhanced feature is that session packets are available to SW as soon as a single CQE slot is filled, instead of waiting for session to close, this improves packet latency from NIC to host. Performance: Following are tested scenarios and reults comparing basic and enahnced CQE compression. setup: IXIA 100GbE connected directly to port 0 and port 1 of ConnectX-6 Dx 100GbE dual port. Case #1 RX only, single flow goes to single queue: IRQ rate reduced by ~ 30%, CPU utilization improved by 2%. Case #2 IP forwarding from port 1 to port 0 single flow goes to single queue: Avg latency improved from 60us to 21us, frame loss improved from 0.5% to 0.0%. Case #3 IP forwarding from port 1 to port 0 Max Throughput IXIA sends 100%, 8192 UDP flows, goes to 24 queues: Enhanced is equal or slightly better than basic. Testing the basic compression feature with this patch shows there is no perfrormance degradation of the basic compression feature. Signed-off-by: Ofer Levi <oferle@nvidia.com> Reviewed-by: Tariq Toukan <tariqt@nvidia.com> Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
1 parent 9458108 commit 2c925db

6 files changed

Lines changed: 170 additions & 23 deletions

File tree

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,7 @@ enum {
344344
MLX5E_RQ_STATE_CSUM_FULL, /* cqe_csum_full hw bit is set */
345345
MLX5E_RQ_STATE_MINI_CQE_HW_STRIDX, /* set when mini_cqe_resp_stride_index cap is used */
346346
MLX5E_RQ_STATE_SHAMPO, /* set when SHAMPO cap is used */
347+
MLX5E_RQ_STATE_MINI_CQE_ENHANCED, /* set when enhanced mini_cqe_cap is used */
347348
};
348349

349350
struct mlx5e_cq {
@@ -370,6 +371,7 @@ struct mlx5e_cq_decomp {
370371
u8 mini_arr_idx;
371372
u16 left;
372373
u16 wqe_counter;
374+
bool last_cqe_title;
373375
} ____cacheline_aligned_in_smp;
374376

375377
enum mlx5e_dma_map_type {

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -608,13 +608,15 @@ void mlx5e_init_rq_type_params(struct mlx5_core_dev *mdev,
608608
MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE :
609609
MLX5E_PARAMS_DEFAULT_LOG_RQ_SIZE;
610610

611-
mlx5_core_info(mdev, "MLX5E: StrdRq(%d) RqSz(%ld) StrdSz(%ld) RxCqeCmprss(%d)\n",
611+
mlx5_core_info(mdev, "MLX5E: StrdRq(%d) RqSz(%ld) StrdSz(%ld) RxCqeCmprss(%d %s)\n",
612612
params->rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ,
613613
params->rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ ?
614614
BIT(mlx5e_mpwqe_get_log_rq_size(mdev, params, NULL)) :
615615
BIT(params->log_rq_mtu_frames),
616616
BIT(mlx5e_mpwqe_get_log_stride_size(mdev, params, NULL)),
617-
MLX5E_GET_PFLAG(params, MLX5E_PFLAG_RX_CQE_COMPRESS));
617+
MLX5E_GET_PFLAG(params, MLX5E_PFLAG_RX_CQE_COMPRESS),
618+
MLX5_CAP_GEN(mdev, enhanced_cqe_compression) ?
619+
"enhanced" : "basic");
618620
}
619621

620622
void mlx5e_set_rq_type(struct mlx5_core_dev *mdev, struct mlx5e_params *params)
@@ -852,6 +854,10 @@ static void mlx5e_build_rx_cq_param(struct mlx5_core_dev *mdev,
852854
if (MLX5E_GET_PFLAG(params, MLX5E_PFLAG_RX_CQE_COMPRESS)) {
853855
MLX5_SET(cqc, cqc, mini_cqe_res_format, hw_stridx ?
854856
MLX5_CQE_FORMAT_CSUM_STRIDX : MLX5_CQE_FORMAT_CSUM);
857+
MLX5_SET(cqc, cqc, cqe_compression_layout,
858+
MLX5_CAP_GEN(mdev, enhanced_cqe_compression) ?
859+
MLX5_CQE_COMPRESS_LAYOUT_ENHANCED :
860+
MLX5_CQE_COMPRESS_LAYOUT_BASIC);
855861
MLX5_SET(cqc, cqc, cqe_comp_en, 1);
856862
}
857863

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1205,6 +1205,13 @@ int mlx5e_open_rq(struct mlx5e_params *params, struct mlx5e_rq_param *param,
12051205
MLX5_CAP_GEN(mdev, mini_cqe_resp_stride_index))
12061206
__set_bit(MLX5E_RQ_STATE_MINI_CQE_HW_STRIDX, &rq->state);
12071207

1208+
/* For enhanced CQE compression packet processing. decompress
1209+
* session according to the enhanced layout.
1210+
*/
1211+
if (MLX5E_GET_PFLAG(params, MLX5E_PFLAG_RX_CQE_COMPRESS) &&
1212+
MLX5_CAP_GEN(mdev, enhanced_cqe_compression))
1213+
__set_bit(MLX5E_RQ_STATE_MINI_CQE_ENHANCED, &rq->state);
1214+
12081215
return 0;
12091216

12101217
err_destroy_rq:
@@ -1895,6 +1902,7 @@ static int mlx5e_alloc_cq_common(struct mlx5e_priv *priv,
18951902
struct mlx5_cqe64 *cqe = mlx5_cqwq_get_wqe(&cq->wq, i);
18961903

18971904
cqe->op_own = 0xf1;
1905+
cqe->validity_iteration_count = 0xff;
18981906
}
18991907

19001908
cq->mdev = mdev;

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

Lines changed: 129 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,25 @@ static inline void mlx5e_read_cqe_slot(struct mlx5_cqwq *wq,
8989
memcpy(data, mlx5_cqwq_get_wqe(wq, ci), sizeof(struct mlx5_cqe64));
9090
}
9191

92+
static void mlx5e_read_enhanced_title_slot(struct mlx5e_rq *rq,
93+
struct mlx5_cqe64 *cqe)
94+
{
95+
struct mlx5e_cq_decomp *cqd = &rq->cqd;
96+
struct mlx5_cqe64 *title = &cqd->title;
97+
98+
memcpy(title, cqe, sizeof(struct mlx5_cqe64));
99+
100+
if (likely(test_bit(MLX5E_RQ_STATE_MINI_CQE_HW_STRIDX, &rq->state)))
101+
return;
102+
103+
if (rq->wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ)
104+
cqd->wqe_counter = mpwrq_get_cqe_stride_index(title) +
105+
mpwrq_get_cqe_consumed_strides(title);
106+
else
107+
cqd->wqe_counter =
108+
mlx5_wq_cyc_ctr2ix(&rq->wqe.wq, be16_to_cpu(title->wqe_counter) + 1);
109+
}
110+
92111
static inline void mlx5e_read_title_slot(struct mlx5e_rq *rq,
93112
struct mlx5_cqwq *wq,
94113
u32 cqcc)
@@ -175,6 +194,38 @@ static inline void mlx5e_decompress_cqe_no_hash(struct mlx5e_rq *rq,
175194
cqd->title.rss_hash_result = 0;
176195
}
177196

197+
static u32 mlx5e_decompress_enhanced_cqe(struct mlx5e_rq *rq,
198+
struct mlx5_cqwq *wq,
199+
struct mlx5_cqe64 *cqe,
200+
int budget_rem)
201+
{
202+
struct mlx5e_cq_decomp *cqd = &rq->cqd;
203+
u32 cqcc, left;
204+
u32 i;
205+
206+
left = get_cqe_enhanced_num_mini_cqes(cqe);
207+
/* Here we avoid breaking the cqe compression session in the middle
208+
* in case budget is not sufficient to handle all of it. In this case
209+
* we return work_done == budget_rem to give 'busy' napi indication.
210+
*/
211+
if (unlikely(left > budget_rem))
212+
return budget_rem;
213+
214+
cqcc = wq->cc;
215+
cqd->mini_arr_idx = 0;
216+
memcpy(cqd->mini_arr, cqe, sizeof(struct mlx5_cqe64));
217+
for (i = 0; i < left; i++, cqd->mini_arr_idx++, cqcc++) {
218+
mlx5e_decompress_cqe_no_hash(rq, wq, cqcc);
219+
INDIRECT_CALL_3(rq->handle_rx_cqe, mlx5e_handle_rx_cqe_mpwrq,
220+
mlx5e_handle_rx_cqe, mlx5e_handle_rx_cqe_mpwrq_shampo,
221+
rq, &cqd->title);
222+
}
223+
wq->cc = cqcc;
224+
rq->stats->cqe_compress_pkts += left;
225+
226+
return left;
227+
}
228+
178229
static inline u32 mlx5e_decompress_cqes_cont(struct mlx5e_rq *rq,
179230
struct mlx5_cqwq *wq,
180231
int update_owner_only,
@@ -220,7 +271,7 @@ static inline u32 mlx5e_decompress_cqes_start(struct mlx5e_rq *rq,
220271
rq, &cqd->title);
221272
cqd->mini_arr_idx++;
222273

223-
return mlx5e_decompress_cqes_cont(rq, wq, 1, budget_rem) - 1;
274+
return mlx5e_decompress_cqes_cont(rq, wq, 1, budget_rem);
224275
}
225276

226277
static inline bool mlx5e_rx_cache_put(struct mlx5e_rq *rq, struct page *page)
@@ -2211,45 +2262,102 @@ static void mlx5e_handle_rx_cqe_mpwrq(struct mlx5e_rq *rq, struct mlx5_cqe64 *cq
22112262
mlx5_wq_ll_pop(wq, cqe->wqe_id, &wqe->next.next_wqe_index);
22122263
}
22132264

2214-
int mlx5e_poll_rx_cq(struct mlx5e_cq *cq, int budget)
2265+
static int mlx5e_rx_cq_process_enhanced_cqe_comp(struct mlx5e_rq *rq,
2266+
struct mlx5_cqwq *cqwq,
2267+
int budget_rem)
22152268
{
2216-
struct mlx5e_rq *rq = container_of(cq, struct mlx5e_rq, cq);
2217-
struct mlx5_cqwq *cqwq = &cq->wq;
2218-
struct mlx5_cqe64 *cqe;
2269+
struct mlx5_cqe64 *cqe, *title_cqe = NULL;
2270+
struct mlx5e_cq_decomp *cqd = &rq->cqd;
22192271
int work_done = 0;
22202272

2221-
if (unlikely(!test_bit(MLX5E_RQ_STATE_ENABLED, &rq->state)))
2222-
return 0;
2273+
cqe = mlx5_cqwq_get_cqe_enahnced_comp(cqwq);
2274+
if (!cqe)
2275+
return work_done;
22232276

2224-
if (rq->cqd.left) {
2225-
work_done += mlx5e_decompress_cqes_cont(rq, cqwq, 0, budget);
2226-
if (work_done >= budget)
2227-
goto out;
2277+
if (cqd->last_cqe_title &&
2278+
(mlx5_get_cqe_format(cqe) == MLX5_COMPRESSED)) {
2279+
rq->stats->cqe_compress_blks++;
2280+
cqd->last_cqe_title = false;
22282281
}
22292282

2230-
cqe = mlx5_cqwq_get_cqe(cqwq);
2231-
if (!cqe) {
2232-
if (unlikely(work_done))
2233-
goto out;
2234-
return 0;
2283+
do {
2284+
if (mlx5_get_cqe_format(cqe) == MLX5_COMPRESSED) {
2285+
if (title_cqe) {
2286+
mlx5e_read_enhanced_title_slot(rq, title_cqe);
2287+
title_cqe = NULL;
2288+
rq->stats->cqe_compress_blks++;
2289+
}
2290+
work_done +=
2291+
mlx5e_decompress_enhanced_cqe(rq, cqwq, cqe,
2292+
budget_rem - work_done);
2293+
continue;
2294+
}
2295+
title_cqe = cqe;
2296+
mlx5_cqwq_pop(cqwq);
2297+
2298+
INDIRECT_CALL_3(rq->handle_rx_cqe, mlx5e_handle_rx_cqe_mpwrq,
2299+
mlx5e_handle_rx_cqe, mlx5e_handle_rx_cqe_mpwrq_shampo,
2300+
rq, cqe);
2301+
work_done++;
2302+
} while (work_done < budget_rem &&
2303+
(cqe = mlx5_cqwq_get_cqe_enahnced_comp(cqwq)));
2304+
2305+
/* last cqe might be title on next poll bulk */
2306+
if (title_cqe) {
2307+
mlx5e_read_enhanced_title_slot(rq, title_cqe);
2308+
cqd->last_cqe_title = true;
22352309
}
22362310

2237-
do {
2311+
return work_done;
2312+
}
2313+
2314+
static int mlx5e_rx_cq_process_basic_cqe_comp(struct mlx5e_rq *rq,
2315+
struct mlx5_cqwq *cqwq,
2316+
int budget_rem)
2317+
{
2318+
struct mlx5_cqe64 *cqe;
2319+
int work_done = 0;
2320+
2321+
if (rq->cqd.left)
2322+
work_done += mlx5e_decompress_cqes_cont(rq, cqwq, 0, budget_rem);
2323+
2324+
while (work_done < budget_rem && (cqe = mlx5_cqwq_get_cqe(cqwq))) {
22382325
if (mlx5_get_cqe_format(cqe) == MLX5_COMPRESSED) {
22392326
work_done +=
22402327
mlx5e_decompress_cqes_start(rq, cqwq,
2241-
budget - work_done);
2328+
budget_rem - work_done);
22422329
continue;
22432330
}
22442331

22452332
mlx5_cqwq_pop(cqwq);
2246-
22472333
INDIRECT_CALL_3(rq->handle_rx_cqe, mlx5e_handle_rx_cqe_mpwrq,
22482334
mlx5e_handle_rx_cqe, mlx5e_handle_rx_cqe_mpwrq_shampo,
22492335
rq, cqe);
2250-
} while ((++work_done < budget) && (cqe = mlx5_cqwq_get_cqe(cqwq)));
2336+
work_done++;
2337+
}
2338+
2339+
return work_done;
2340+
}
2341+
2342+
int mlx5e_poll_rx_cq(struct mlx5e_cq *cq, int budget)
2343+
{
2344+
struct mlx5e_rq *rq = container_of(cq, struct mlx5e_rq, cq);
2345+
struct mlx5_cqwq *cqwq = &cq->wq;
2346+
int work_done;
2347+
2348+
if (unlikely(!test_bit(MLX5E_RQ_STATE_ENABLED, &rq->state)))
2349+
return 0;
2350+
2351+
if (test_bit(MLX5E_RQ_STATE_MINI_CQE_ENHANCED, &rq->state))
2352+
work_done = mlx5e_rx_cq_process_enhanced_cqe_comp(rq, cqwq,
2353+
budget);
2354+
else
2355+
work_done = mlx5e_rx_cq_process_basic_cqe_comp(rq, cqwq,
2356+
budget);
2357+
2358+
if (work_done == 0)
2359+
return 0;
22512360

2252-
out:
22532361
if (test_bit(MLX5E_RQ_STATE_SHAMPO, &rq->state) && rq->hw_gro_data->skb)
22542362
mlx5e_shampo_flush_skb(rq, NULL, false);
22552363

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,23 @@ static inline struct mlx5_cqe64 *mlx5_cqwq_get_cqe(struct mlx5_cqwq *wq)
243243
return cqe;
244244
}
245245

246+
static inline
247+
struct mlx5_cqe64 *mlx5_cqwq_get_cqe_enahnced_comp(struct mlx5_cqwq *wq)
248+
{
249+
u8 sw_validity_iteration_count = mlx5_cqwq_get_wrap_cnt(wq) & 0xff;
250+
u32 ci = mlx5_cqwq_get_ci(wq);
251+
struct mlx5_cqe64 *cqe;
252+
253+
cqe = mlx5_cqwq_get_wqe(wq, ci);
254+
if (cqe->validity_iteration_count != sw_validity_iteration_count)
255+
return NULL;
256+
257+
/* ensure cqe content is read after cqe ownership bit/validity byte */
258+
dma_rmb();
259+
260+
return cqe;
261+
}
262+
246263
static inline u32 mlx5_wq_ll_get_size(struct mlx5_wq_ll *wq)
247264
{
248265
return (u32)wq->fbc.sz_m1 + 1;

include/linux/mlx5/device.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -882,6 +882,12 @@ static inline u8 get_cqe_opcode(struct mlx5_cqe64 *cqe)
882882
return cqe->op_own >> 4;
883883
}
884884

885+
static inline u8 get_cqe_enhanced_num_mini_cqes(struct mlx5_cqe64 *cqe)
886+
{
887+
/* num_of_mini_cqes is zero based */
888+
return get_cqe_opcode(cqe) + 1;
889+
}
890+
885891
static inline u8 get_cqe_lro_tcppsh(struct mlx5_cqe64 *cqe)
886892
{
887893
return (cqe->lro.tcppsh_abort_dupack >> 6) & 1;

0 commit comments

Comments
 (0)