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