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