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