1// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2/* Copyright (c) 2021, Mellanox Technologies inc. All rights reserved. */
3
4#include "rx_res.h"
5#include "channels.h"
6#include "params.h"
7
8#define MLX5E_MAX_NUM_RSS 16
9
10struct mlx5e_rx_res {
11 struct mlx5_core_dev *mdev; /* primary */
12 enum mlx5e_rx_res_features features;
13 unsigned int max_nch;
14 u32 drop_rqn;
15
16 struct mlx5e_packet_merge_param pkt_merge_param;
17 struct rw_semaphore pkt_merge_param_sem;
18
19 struct mlx5e_rss *rss[MLX5E_MAX_NUM_RSS];
20 bool rss_active;
21 u32 *rss_rqns;
22 u32 *rss_vhca_ids;
23 unsigned int rss_nch;
24
25 struct {
26 struct mlx5e_rqt direct_rqt;
27 struct mlx5e_tir direct_tir;
28 } *channels;
29
30 struct {
31 struct mlx5e_rqt rqt;
32 struct mlx5e_tir tir;
33 } ptp;
34};
35
36/* API for rx_res_rss_* */
37
38static u32 *get_vhca_ids(struct mlx5e_rx_res *res, int offset)
39{
40 bool multi_vhca = res->features & MLX5E_RX_RES_FEATURE_MULTI_VHCA;
41
42 return multi_vhca ? res->rss_vhca_ids + offset : NULL;
43}
44
45void mlx5e_rx_res_rss_update_num_channels(struct mlx5e_rx_res *res, u32 nch)
46{
47 int i;
48
49 for (i = 0; i < MLX5E_MAX_NUM_RSS; i++) {
50 if (res->rss[i])
51 mlx5e_rss_params_indir_modify_actual_size(rss: res->rss[i], num_channels: nch);
52 }
53}
54
55static int mlx5e_rx_res_rss_init_def(struct mlx5e_rx_res *res,
56 unsigned int init_nch)
57{
58 bool inner_ft_support = res->features & MLX5E_RX_RES_FEATURE_INNER_FT;
59 struct mlx5e_rss *rss;
60
61 if (WARN_ON(res->rss[0]))
62 return -EINVAL;
63
64 rss = mlx5e_rss_init(mdev: res->mdev, inner_ft_support, drop_rqn: res->drop_rqn,
65 init_pkt_merge_param: &res->pkt_merge_param, type: MLX5E_RSS_INIT_TIRS, nch: init_nch, max_nch: res->max_nch);
66 if (IS_ERR(ptr: rss))
67 return PTR_ERR(ptr: rss);
68
69 mlx5e_rss_set_indir_uniform(rss, nch: init_nch);
70
71 res->rss[0] = rss;
72
73 return 0;
74}
75
76int mlx5e_rx_res_rss_init(struct mlx5e_rx_res *res, u32 *rss_idx, unsigned int init_nch)
77{
78 bool inner_ft_support = res->features & MLX5E_RX_RES_FEATURE_INNER_FT;
79 struct mlx5e_rss *rss;
80 int i;
81
82 for (i = 1; i < MLX5E_MAX_NUM_RSS; i++)
83 if (!res->rss[i])
84 break;
85
86 if (i == MLX5E_MAX_NUM_RSS)
87 return -ENOSPC;
88
89 rss = mlx5e_rss_init(mdev: res->mdev, inner_ft_support, drop_rqn: res->drop_rqn,
90 init_pkt_merge_param: &res->pkt_merge_param, type: MLX5E_RSS_INIT_NO_TIRS, nch: init_nch,
91 max_nch: res->max_nch);
92 if (IS_ERR(ptr: rss))
93 return PTR_ERR(ptr: rss);
94
95 mlx5e_rss_set_indir_uniform(rss, nch: init_nch);
96 if (res->rss_active) {
97 u32 *vhca_ids = get_vhca_ids(res, offset: 0);
98
99 mlx5e_rss_enable(rss, rqns: res->rss_rqns, vhca_ids, num_rqns: res->rss_nch);
100 }
101
102 res->rss[i] = rss;
103 *rss_idx = i;
104
105 return 0;
106}
107
108static int __mlx5e_rx_res_rss_destroy(struct mlx5e_rx_res *res, u32 rss_idx)
109{
110 struct mlx5e_rss *rss = res->rss[rss_idx];
111 int err;
112
113 err = mlx5e_rss_cleanup(rss);
114 if (err)
115 return err;
116
117 res->rss[rss_idx] = NULL;
118
119 return 0;
120}
121
122int mlx5e_rx_res_rss_destroy(struct mlx5e_rx_res *res, u32 rss_idx)
123{
124 struct mlx5e_rss *rss;
125
126 if (rss_idx >= MLX5E_MAX_NUM_RSS)
127 return -EINVAL;
128
129 rss = res->rss[rss_idx];
130 if (!rss)
131 return -EINVAL;
132
133 return __mlx5e_rx_res_rss_destroy(res, rss_idx);
134}
135
136static void mlx5e_rx_res_rss_destroy_all(struct mlx5e_rx_res *res)
137{
138 int i;
139
140 for (i = 0; i < MLX5E_MAX_NUM_RSS; i++) {
141 struct mlx5e_rss *rss = res->rss[i];
142 int err;
143
144 if (!rss)
145 continue;
146
147 err = __mlx5e_rx_res_rss_destroy(res, rss_idx: i);
148 if (err) {
149 unsigned int refcount;
150
151 refcount = mlx5e_rss_refcnt_read(rss);
152 mlx5_core_warn(res->mdev,
153 "Failed to destroy RSS context %d, refcount = %u, err = %d\n",
154 i, refcount, err);
155 }
156 }
157}
158
159static void mlx5e_rx_res_rss_enable(struct mlx5e_rx_res *res)
160{
161 int i;
162
163 res->rss_active = true;
164
165 for (i = 0; i < MLX5E_MAX_NUM_RSS; i++) {
166 struct mlx5e_rss *rss = res->rss[i];
167 u32 *vhca_ids;
168
169 if (!rss)
170 continue;
171 vhca_ids = get_vhca_ids(res, offset: 0);
172 mlx5e_rss_enable(rss, rqns: res->rss_rqns, vhca_ids, num_rqns: res->rss_nch);
173 }
174}
175
176static void mlx5e_rx_res_rss_disable(struct mlx5e_rx_res *res)
177{
178 int i;
179
180 res->rss_active = false;
181
182 for (i = 0; i < MLX5E_MAX_NUM_RSS; i++) {
183 struct mlx5e_rss *rss = res->rss[i];
184
185 if (!rss)
186 continue;
187 mlx5e_rss_disable(rss);
188 }
189}
190
191/* Updates the indirection table SW shadow, does not update the HW resources yet */
192void mlx5e_rx_res_rss_set_indir_uniform(struct mlx5e_rx_res *res, unsigned int nch)
193{
194 WARN_ON_ONCE(res->rss_active);
195 mlx5e_rss_set_indir_uniform(rss: res->rss[0], nch);
196}
197
198int mlx5e_rx_res_rss_get_rxfh(struct mlx5e_rx_res *res, u32 rss_idx,
199 u32 *indir, u8 *key, u8 *hfunc)
200{
201 struct mlx5e_rss *rss;
202
203 if (rss_idx >= MLX5E_MAX_NUM_RSS)
204 return -EINVAL;
205
206 rss = res->rss[rss_idx];
207 if (!rss)
208 return -ENOENT;
209
210 return mlx5e_rss_get_rxfh(rss, indir, key, hfunc);
211}
212
213int mlx5e_rx_res_rss_set_rxfh(struct mlx5e_rx_res *res, u32 rss_idx,
214 const u32 *indir, const u8 *key, const u8 *hfunc)
215{
216 u32 *vhca_ids = get_vhca_ids(res, offset: 0);
217 struct mlx5e_rss *rss;
218
219 if (rss_idx >= MLX5E_MAX_NUM_RSS)
220 return -EINVAL;
221
222 rss = res->rss[rss_idx];
223 if (!rss)
224 return -ENOENT;
225
226 return mlx5e_rss_set_rxfh(rss, indir, key, hfunc, rqns: res->rss_rqns, vhca_ids,
227 num_rqns: res->rss_nch);
228}
229
230int mlx5e_rx_res_rss_get_hash_fields(struct mlx5e_rx_res *res, u32 rss_idx,
231 enum mlx5_traffic_types tt)
232{
233 struct mlx5e_rss *rss;
234
235 if (rss_idx >= MLX5E_MAX_NUM_RSS)
236 return -EINVAL;
237
238 rss = res->rss[rss_idx];
239 if (!rss)
240 return -ENOENT;
241
242 return mlx5e_rss_get_hash_fields(rss, tt);
243}
244
245int mlx5e_rx_res_rss_set_hash_fields(struct mlx5e_rx_res *res, u32 rss_idx,
246 enum mlx5_traffic_types tt, u8 rx_hash_fields)
247{
248 struct mlx5e_rss *rss;
249
250 if (rss_idx >= MLX5E_MAX_NUM_RSS)
251 return -EINVAL;
252
253 rss = res->rss[rss_idx];
254 if (!rss)
255 return -ENOENT;
256
257 return mlx5e_rss_set_hash_fields(rss, tt, rx_hash_fields);
258}
259
260int mlx5e_rx_res_rss_cnt(struct mlx5e_rx_res *res)
261{
262 int i, cnt;
263
264 cnt = 0;
265 for (i = 0; i < MLX5E_MAX_NUM_RSS; i++)
266 if (res->rss[i])
267 cnt++;
268
269 return cnt;
270}
271
272int mlx5e_rx_res_rss_index(struct mlx5e_rx_res *res, struct mlx5e_rss *rss)
273{
274 int i;
275
276 if (!rss)
277 return -EINVAL;
278
279 for (i = 0; i < MLX5E_MAX_NUM_RSS; i++)
280 if (rss == res->rss[i])
281 return i;
282
283 return -ENOENT;
284}
285
286struct mlx5e_rss *mlx5e_rx_res_rss_get(struct mlx5e_rx_res *res, u32 rss_idx)
287{
288 if (rss_idx >= MLX5E_MAX_NUM_RSS)
289 return NULL;
290
291 return res->rss[rss_idx];
292}
293
294/* End of API rx_res_rss_* */
295
296static void mlx5e_rx_res_free(struct mlx5e_rx_res *res)
297{
298 kvfree(addr: res->rss_vhca_ids);
299 kvfree(addr: res->rss_rqns);
300 kvfree(addr: res);
301}
302
303static struct mlx5e_rx_res *mlx5e_rx_res_alloc(struct mlx5_core_dev *mdev, unsigned int max_nch,
304 bool multi_vhca)
305{
306 struct mlx5e_rx_res *rx_res;
307
308 rx_res = kvzalloc(size: sizeof(*rx_res), GFP_KERNEL);
309 if (!rx_res)
310 return NULL;
311
312 rx_res->rss_rqns = kvcalloc(n: max_nch, size: sizeof(*rx_res->rss_rqns), GFP_KERNEL);
313 if (!rx_res->rss_rqns) {
314 kvfree(addr: rx_res);
315 return NULL;
316 }
317
318 if (multi_vhca) {
319 rx_res->rss_vhca_ids = kvcalloc(n: max_nch, size: sizeof(*rx_res->rss_vhca_ids), GFP_KERNEL);
320 if (!rx_res->rss_vhca_ids) {
321 kvfree(addr: rx_res->rss_rqns);
322 kvfree(addr: rx_res);
323 return NULL;
324 }
325 }
326
327 return rx_res;
328}
329
330static int mlx5e_rx_res_channels_init(struct mlx5e_rx_res *res)
331{
332 bool inner_ft_support = res->features & MLX5E_RX_RES_FEATURE_INNER_FT;
333 struct mlx5e_tir_builder *builder;
334 int err = 0;
335 int ix;
336
337 builder = mlx5e_tir_builder_alloc(modify: false);
338 if (!builder)
339 return -ENOMEM;
340
341 res->channels = kvcalloc(n: res->max_nch, size: sizeof(*res->channels), GFP_KERNEL);
342 if (!res->channels) {
343 err = -ENOMEM;
344 goto out;
345 }
346
347 for (ix = 0; ix < res->max_nch; ix++) {
348 err = mlx5e_rqt_init_direct(rqt: &res->channels[ix].direct_rqt,
349 mdev: res->mdev, indir_enabled: false, init_rqn: res->drop_rqn,
350 indir_table_size: mlx5e_rqt_size(mdev: res->mdev, num_channels: res->max_nch));
351 if (err) {
352 mlx5_core_warn(res->mdev, "Failed to create a direct RQT: err = %d, ix = %u\n",
353 err, ix);
354 goto err_destroy_direct_rqts;
355 }
356 }
357
358 for (ix = 0; ix < res->max_nch; ix++) {
359 mlx5e_tir_builder_build_rqt(builder, tdn: res->mdev->mlx5e_res.hw_objs.td.tdn,
360 rqtn: mlx5e_rqt_get_rqtn(rqt: &res->channels[ix].direct_rqt),
361 inner_ft_support);
362 mlx5e_tir_builder_build_packet_merge(builder, pkt_merge_param: &res->pkt_merge_param);
363 mlx5e_tir_builder_build_direct(builder);
364
365 err = mlx5e_tir_init(tir: &res->channels[ix].direct_tir, builder, mdev: res->mdev, reg: true);
366 if (err) {
367 mlx5_core_warn(res->mdev, "Failed to create a direct TIR: err = %d, ix = %u\n",
368 err, ix);
369 goto err_destroy_direct_tirs;
370 }
371
372 mlx5e_tir_builder_clear(builder);
373 }
374
375 goto out;
376
377err_destroy_direct_tirs:
378 while (--ix >= 0)
379 mlx5e_tir_destroy(tir: &res->channels[ix].direct_tir);
380
381 ix = res->max_nch;
382err_destroy_direct_rqts:
383 while (--ix >= 0)
384 mlx5e_rqt_destroy(rqt: &res->channels[ix].direct_rqt);
385
386 kvfree(addr: res->channels);
387
388out:
389 mlx5e_tir_builder_free(builder);
390
391 return err;
392}
393
394static int mlx5e_rx_res_ptp_init(struct mlx5e_rx_res *res)
395{
396 bool inner_ft_support = res->features & MLX5E_RX_RES_FEATURE_INNER_FT;
397 struct mlx5e_tir_builder *builder;
398 int err;
399
400 builder = mlx5e_tir_builder_alloc(modify: false);
401 if (!builder)
402 return -ENOMEM;
403
404 err = mlx5e_rqt_init_direct(rqt: &res->ptp.rqt, mdev: res->mdev, indir_enabled: false, init_rqn: res->drop_rqn,
405 indir_table_size: mlx5e_rqt_size(mdev: res->mdev, num_channels: res->max_nch));
406 if (err)
407 goto out;
408
409 /* Separated from the channels RQs, does not share pkt_merge state with them */
410 mlx5e_tir_builder_build_rqt(builder, tdn: res->mdev->mlx5e_res.hw_objs.td.tdn,
411 rqtn: mlx5e_rqt_get_rqtn(rqt: &res->ptp.rqt),
412 inner_ft_support);
413 mlx5e_tir_builder_build_direct(builder);
414
415 err = mlx5e_tir_init(tir: &res->ptp.tir, builder, mdev: res->mdev, reg: true);
416 if (err)
417 goto err_destroy_ptp_rqt;
418
419 goto out;
420
421err_destroy_ptp_rqt:
422 mlx5e_rqt_destroy(rqt: &res->ptp.rqt);
423
424out:
425 mlx5e_tir_builder_free(builder);
426 return err;
427}
428
429static void mlx5e_rx_res_channels_destroy(struct mlx5e_rx_res *res)
430{
431 unsigned int ix;
432
433 for (ix = 0; ix < res->max_nch; ix++) {
434 mlx5e_tir_destroy(tir: &res->channels[ix].direct_tir);
435 mlx5e_rqt_destroy(rqt: &res->channels[ix].direct_rqt);
436 }
437
438 kvfree(addr: res->channels);
439}
440
441static void mlx5e_rx_res_ptp_destroy(struct mlx5e_rx_res *res)
442{
443 mlx5e_tir_destroy(tir: &res->ptp.tir);
444 mlx5e_rqt_destroy(rqt: &res->ptp.rqt);
445}
446
447struct mlx5e_rx_res *
448mlx5e_rx_res_create(struct mlx5_core_dev *mdev, enum mlx5e_rx_res_features features,
449 unsigned int max_nch, u32 drop_rqn,
450 const struct mlx5e_packet_merge_param *init_pkt_merge_param,
451 unsigned int init_nch)
452{
453 bool multi_vhca = features & MLX5E_RX_RES_FEATURE_MULTI_VHCA;
454 struct mlx5e_rx_res *res;
455 int err;
456
457 res = mlx5e_rx_res_alloc(mdev, max_nch, multi_vhca);
458 if (!res)
459 return ERR_PTR(error: -ENOMEM);
460
461 res->mdev = mdev;
462 res->features = features;
463 res->max_nch = max_nch;
464 res->drop_rqn = drop_rqn;
465
466 res->pkt_merge_param = *init_pkt_merge_param;
467 init_rwsem(&res->pkt_merge_param_sem);
468
469 err = mlx5e_rx_res_rss_init_def(res, init_nch);
470 if (err)
471 goto err_rx_res_free;
472
473 err = mlx5e_rx_res_channels_init(res);
474 if (err)
475 goto err_rss_destroy;
476
477 err = mlx5e_rx_res_ptp_init(res);
478 if (err)
479 goto err_channels_destroy;
480
481 return res;
482
483err_channels_destroy:
484 mlx5e_rx_res_channels_destroy(res);
485err_rss_destroy:
486 __mlx5e_rx_res_rss_destroy(res, rss_idx: 0);
487err_rx_res_free:
488 mlx5e_rx_res_free(res);
489 return ERR_PTR(error: err);
490}
491
492void mlx5e_rx_res_destroy(struct mlx5e_rx_res *res)
493{
494 mlx5e_rx_res_ptp_destroy(res);
495 mlx5e_rx_res_channels_destroy(res);
496 mlx5e_rx_res_rss_destroy_all(res);
497 mlx5e_rx_res_free(res);
498}
499
500u32 mlx5e_rx_res_get_tirn_direct(struct mlx5e_rx_res *res, unsigned int ix)
501{
502 return mlx5e_tir_get_tirn(tir: &res->channels[ix].direct_tir);
503}
504
505u32 mlx5e_rx_res_get_tirn_rss(struct mlx5e_rx_res *res, enum mlx5_traffic_types tt)
506{
507 struct mlx5e_rss *rss = res->rss[0];
508
509 return mlx5e_rss_get_tirn(rss, tt, inner: false);
510}
511
512u32 mlx5e_rx_res_get_tirn_rss_inner(struct mlx5e_rx_res *res, enum mlx5_traffic_types tt)
513{
514 struct mlx5e_rss *rss = res->rss[0];
515
516 return mlx5e_rss_get_tirn(rss, tt, inner: true);
517}
518
519u32 mlx5e_rx_res_get_tirn_ptp(struct mlx5e_rx_res *res)
520{
521 WARN_ON(!(res->features & MLX5E_RX_RES_FEATURE_PTP));
522 return mlx5e_tir_get_tirn(tir: &res->ptp.tir);
523}
524
525static u32 mlx5e_rx_res_get_rqtn_direct(struct mlx5e_rx_res *res, unsigned int ix)
526{
527 return mlx5e_rqt_get_rqtn(rqt: &res->channels[ix].direct_rqt);
528}
529
530static void mlx5e_rx_res_channel_activate_direct(struct mlx5e_rx_res *res,
531 struct mlx5e_channels *chs,
532 unsigned int ix)
533{
534 u32 *vhca_id = get_vhca_ids(res, offset: ix);
535 u32 rqn = res->rss_rqns[ix];
536 int err;
537
538 err = mlx5e_rqt_redirect_direct(rqt: &res->channels[ix].direct_rqt, rqn, vhca_id);
539 if (err)
540 mlx5_core_warn(res->mdev, "Failed to redirect direct RQT %#x to RQ %#x (channel %u): err = %d\n",
541 mlx5e_rqt_get_rqtn(&res->channels[ix].direct_rqt),
542 rqn, ix, err);
543}
544
545static void mlx5e_rx_res_channel_deactivate_direct(struct mlx5e_rx_res *res,
546 unsigned int ix)
547{
548 int err;
549
550 err = mlx5e_rqt_redirect_direct(rqt: &res->channels[ix].direct_rqt, rqn: res->drop_rqn, NULL);
551 if (err)
552 mlx5_core_warn(res->mdev, "Failed to redirect direct RQT %#x to drop RQ %#x (channel %u): err = %d\n",
553 mlx5e_rqt_get_rqtn(&res->channels[ix].direct_rqt),
554 res->drop_rqn, ix, err);
555}
556
557void mlx5e_rx_res_channels_activate(struct mlx5e_rx_res *res, struct mlx5e_channels *chs)
558{
559 unsigned int nch, ix;
560 int err;
561
562 nch = mlx5e_channels_get_num(chs);
563
564 for (ix = 0; ix < chs->num; ix++) {
565 u32 *vhca_id = get_vhca_ids(res, offset: ix);
566
567 if (mlx5e_channels_is_xsk(chs, ix))
568 mlx5e_channels_get_xsk_rqn(chs, ix, rqn: &res->rss_rqns[ix], vhca_id);
569 else
570 mlx5e_channels_get_regular_rqn(chs, ix, rqn: &res->rss_rqns[ix], vhca_id);
571 }
572 res->rss_nch = chs->num;
573
574 mlx5e_rx_res_rss_enable(res);
575
576 for (ix = 0; ix < nch; ix++)
577 mlx5e_rx_res_channel_activate_direct(res, chs, ix);
578 for (ix = nch; ix < res->max_nch; ix++)
579 mlx5e_rx_res_channel_deactivate_direct(res, ix);
580
581 if (res->features & MLX5E_RX_RES_FEATURE_PTP) {
582 u32 rqn;
583
584 if (!mlx5e_channels_get_ptp_rqn(chs, rqn: &rqn))
585 rqn = res->drop_rqn;
586
587 err = mlx5e_rqt_redirect_direct(rqt: &res->ptp.rqt, rqn, NULL);
588 if (err)
589 mlx5_core_warn(res->mdev, "Failed to redirect direct RQT %#x to RQ %#x (PTP): err = %d\n",
590 mlx5e_rqt_get_rqtn(&res->ptp.rqt),
591 rqn, err);
592 }
593}
594
595void mlx5e_rx_res_channels_deactivate(struct mlx5e_rx_res *res)
596{
597 unsigned int ix;
598 int err;
599
600 mlx5e_rx_res_rss_disable(res);
601
602 for (ix = 0; ix < res->max_nch; ix++)
603 mlx5e_rx_res_channel_deactivate_direct(res, ix);
604
605 if (res->features & MLX5E_RX_RES_FEATURE_PTP) {
606 err = mlx5e_rqt_redirect_direct(rqt: &res->ptp.rqt, rqn: res->drop_rqn, NULL);
607 if (err)
608 mlx5_core_warn(res->mdev, "Failed to redirect direct RQT %#x to drop RQ %#x (PTP): err = %d\n",
609 mlx5e_rqt_get_rqtn(&res->ptp.rqt),
610 res->drop_rqn, err);
611 }
612}
613
614void mlx5e_rx_res_xsk_update(struct mlx5e_rx_res *res, struct mlx5e_channels *chs,
615 unsigned int ix, bool xsk)
616{
617 u32 *vhca_id = get_vhca_ids(res, offset: ix);
618
619 if (xsk)
620 mlx5e_channels_get_xsk_rqn(chs, ix, rqn: &res->rss_rqns[ix], vhca_id);
621 else
622 mlx5e_channels_get_regular_rqn(chs, ix, rqn: &res->rss_rqns[ix], vhca_id);
623
624 mlx5e_rx_res_rss_enable(res);
625
626 mlx5e_rx_res_channel_activate_direct(res, chs, ix);
627}
628
629int mlx5e_rx_res_packet_merge_set_param(struct mlx5e_rx_res *res,
630 struct mlx5e_packet_merge_param *pkt_merge_param)
631{
632 struct mlx5e_tir_builder *builder;
633 int err, final_err;
634 unsigned int ix;
635
636 builder = mlx5e_tir_builder_alloc(modify: true);
637 if (!builder)
638 return -ENOMEM;
639
640 down_write(sem: &res->pkt_merge_param_sem);
641 res->pkt_merge_param = *pkt_merge_param;
642
643 mlx5e_tir_builder_build_packet_merge(builder, pkt_merge_param);
644
645 final_err = 0;
646
647 for (ix = 0; ix < MLX5E_MAX_NUM_RSS; ix++) {
648 struct mlx5e_rss *rss = res->rss[ix];
649
650 if (!rss)
651 continue;
652
653 err = mlx5e_rss_packet_merge_set_param(rss, pkt_merge_param);
654 if (err)
655 final_err = final_err ? : err;
656 }
657
658 for (ix = 0; ix < res->max_nch; ix++) {
659 err = mlx5e_tir_modify(tir: &res->channels[ix].direct_tir, builder);
660 if (err) {
661 mlx5_core_warn(res->mdev, "Failed to update packet merge state of direct TIR %#x for channel %u: err = %d\n",
662 mlx5e_tir_get_tirn(&res->channels[ix].direct_tir), ix, err);
663 if (!final_err)
664 final_err = err;
665 }
666 }
667
668 up_write(sem: &res->pkt_merge_param_sem);
669 mlx5e_tir_builder_free(builder);
670 return final_err;
671}
672
673struct mlx5e_rss_params_hash mlx5e_rx_res_get_current_hash(struct mlx5e_rx_res *res)
674{
675 return mlx5e_rss_get_hash(rss: res->rss[0]);
676}
677
678int mlx5e_rx_res_tls_tir_create(struct mlx5e_rx_res *res, unsigned int rxq,
679 struct mlx5e_tir *tir)
680{
681 bool inner_ft_support = res->features & MLX5E_RX_RES_FEATURE_INNER_FT;
682 struct mlx5e_tir_builder *builder;
683 u32 rqtn;
684 int err;
685
686 builder = mlx5e_tir_builder_alloc(modify: false);
687 if (!builder)
688 return -ENOMEM;
689
690 rqtn = mlx5e_rx_res_get_rqtn_direct(res, ix: rxq);
691
692 mlx5e_tir_builder_build_rqt(builder, tdn: res->mdev->mlx5e_res.hw_objs.td.tdn, rqtn,
693 inner_ft_support);
694 mlx5e_tir_builder_build_direct(builder);
695 mlx5e_tir_builder_build_tls(builder);
696 down_read(sem: &res->pkt_merge_param_sem);
697 mlx5e_tir_builder_build_packet_merge(builder, pkt_merge_param: &res->pkt_merge_param);
698 err = mlx5e_tir_init(tir, builder, mdev: res->mdev, reg: false);
699 up_read(sem: &res->pkt_merge_param_sem);
700
701 mlx5e_tir_builder_free(builder);
702
703 return err;
704}
705

source code of linux/drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.c