1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 // Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES.
3 
4 #include "rss.h"
5 
6 #define mlx5e_rss_warn(__dev, format, ...)			\
7 	dev_warn((__dev)->device, "%s:%d:(pid %d): " format,	\
8 		 __func__, __LINE__, current->pid,		\
9 		 ##__VA_ARGS__)
10 
11 static const struct mlx5e_rss_params_traffic_type rss_default_config[MLX5E_NUM_INDIR_TIRS] = {
12 	[MLX5_TT_IPV4_TCP] = {
13 		.l3_prot_type = MLX5_L3_PROT_TYPE_IPV4,
14 		.l4_prot_type = MLX5_L4_PROT_TYPE_TCP,
15 		.rx_hash_fields = MLX5_HASH_IP_L4PORTS,
16 	},
17 	[MLX5_TT_IPV6_TCP] = {
18 		.l3_prot_type = MLX5_L3_PROT_TYPE_IPV6,
19 		.l4_prot_type = MLX5_L4_PROT_TYPE_TCP,
20 		.rx_hash_fields = MLX5_HASH_IP_L4PORTS,
21 	},
22 	[MLX5_TT_IPV4_UDP] = {
23 		.l3_prot_type = MLX5_L3_PROT_TYPE_IPV4,
24 		.l4_prot_type = MLX5_L4_PROT_TYPE_UDP,
25 		.rx_hash_fields = MLX5_HASH_IP_L4PORTS,
26 	},
27 	[MLX5_TT_IPV6_UDP] = {
28 		.l3_prot_type = MLX5_L3_PROT_TYPE_IPV6,
29 		.l4_prot_type = MLX5_L4_PROT_TYPE_UDP,
30 		.rx_hash_fields = MLX5_HASH_IP_L4PORTS,
31 	},
32 	[MLX5_TT_IPV4_IPSEC_AH] = {
33 		.l3_prot_type = MLX5_L3_PROT_TYPE_IPV4,
34 		.l4_prot_type = 0,
35 		.rx_hash_fields = MLX5_HASH_IP_IPSEC_SPI,
36 	},
37 	[MLX5_TT_IPV6_IPSEC_AH] = {
38 		.l3_prot_type = MLX5_L3_PROT_TYPE_IPV6,
39 		.l4_prot_type = 0,
40 		.rx_hash_fields = MLX5_HASH_IP_IPSEC_SPI,
41 	},
42 	[MLX5_TT_IPV4_IPSEC_ESP] = {
43 		.l3_prot_type = MLX5_L3_PROT_TYPE_IPV4,
44 		.l4_prot_type = 0,
45 		.rx_hash_fields = MLX5_HASH_IP_IPSEC_SPI,
46 	},
47 	[MLX5_TT_IPV6_IPSEC_ESP] = {
48 		.l3_prot_type = MLX5_L3_PROT_TYPE_IPV6,
49 		.l4_prot_type = 0,
50 		.rx_hash_fields = MLX5_HASH_IP_IPSEC_SPI,
51 	},
52 	[MLX5_TT_IPV4] = {
53 		.l3_prot_type = MLX5_L3_PROT_TYPE_IPV4,
54 		.l4_prot_type = 0,
55 		.rx_hash_fields = MLX5_HASH_IP,
56 	},
57 	[MLX5_TT_IPV6] = {
58 		.l3_prot_type = MLX5_L3_PROT_TYPE_IPV6,
59 		.l4_prot_type = 0,
60 		.rx_hash_fields = MLX5_HASH_IP,
61 	},
62 };
63 
64 struct mlx5e_rss_params_traffic_type
mlx5e_rss_get_default_tt_config(enum mlx5_traffic_types tt)65 mlx5e_rss_get_default_tt_config(enum mlx5_traffic_types tt)
66 {
67 	return rss_default_config[tt];
68 }
69 
70 struct mlx5e_rss {
71 	struct mlx5e_rss_params_hash hash;
72 	struct mlx5e_rss_params_indir indir;
73 	u32 rx_hash_fields[MLX5E_NUM_INDIR_TIRS];
74 	struct mlx5e_tir *tir[MLX5E_NUM_INDIR_TIRS];
75 	struct mlx5e_tir *inner_tir[MLX5E_NUM_INDIR_TIRS];
76 	struct mlx5e_rqt rqt;
77 	struct mlx5_core_dev *mdev;
78 	u32 drop_rqn;
79 	bool inner_ft_support;
80 	bool enabled;
81 	refcount_t refcnt;
82 };
83 
mlx5e_rss_alloc(void)84 struct mlx5e_rss *mlx5e_rss_alloc(void)
85 {
86 	return kvzalloc(sizeof(struct mlx5e_rss), GFP_KERNEL);
87 }
88 
mlx5e_rss_free(struct mlx5e_rss * rss)89 void mlx5e_rss_free(struct mlx5e_rss *rss)
90 {
91 	kvfree(rss);
92 }
93 
mlx5e_rss_params_init(struct mlx5e_rss * rss)94 static void mlx5e_rss_params_init(struct mlx5e_rss *rss)
95 {
96 	enum mlx5_traffic_types tt;
97 
98 	rss->hash.hfunc = ETH_RSS_HASH_TOP;
99 	netdev_rss_key_fill(rss->hash.toeplitz_hash_key,
100 			    sizeof(rss->hash.toeplitz_hash_key));
101 	for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++)
102 		rss->rx_hash_fields[tt] =
103 			mlx5e_rss_get_default_tt_config(tt).rx_hash_fields;
104 }
105 
rss_get_tirp(struct mlx5e_rss * rss,enum mlx5_traffic_types tt,bool inner)106 static struct mlx5e_tir **rss_get_tirp(struct mlx5e_rss *rss, enum mlx5_traffic_types tt,
107 				       bool inner)
108 {
109 	return inner ? &rss->inner_tir[tt] : &rss->tir[tt];
110 }
111 
rss_get_tir(struct mlx5e_rss * rss,enum mlx5_traffic_types tt,bool inner)112 static struct mlx5e_tir *rss_get_tir(struct mlx5e_rss *rss, enum mlx5_traffic_types tt,
113 				     bool inner)
114 {
115 	return *rss_get_tirp(rss, tt, inner);
116 }
117 
118 static struct mlx5e_rss_params_traffic_type
mlx5e_rss_get_tt_config(struct mlx5e_rss * rss,enum mlx5_traffic_types tt)119 mlx5e_rss_get_tt_config(struct mlx5e_rss *rss, enum mlx5_traffic_types tt)
120 {
121 	struct mlx5e_rss_params_traffic_type rss_tt;
122 
123 	rss_tt = mlx5e_rss_get_default_tt_config(tt);
124 	rss_tt.rx_hash_fields = rss->rx_hash_fields[tt];
125 	return rss_tt;
126 }
127 
mlx5e_rss_create_tir(struct mlx5e_rss * rss,enum mlx5_traffic_types tt,const struct mlx5e_lro_param * init_lro_param,bool inner)128 static int mlx5e_rss_create_tir(struct mlx5e_rss *rss,
129 				enum mlx5_traffic_types tt,
130 				const struct mlx5e_lro_param *init_lro_param,
131 				bool inner)
132 {
133 	struct mlx5e_rss_params_traffic_type rss_tt;
134 	struct mlx5e_tir_builder *builder;
135 	struct mlx5e_tir **tir_p;
136 	struct mlx5e_tir *tir;
137 	u32 rqtn;
138 	int err;
139 
140 	if (inner && !rss->inner_ft_support) {
141 		mlx5e_rss_warn(rss->mdev,
142 			       "Cannot create inner indirect TIR[%d], RSS inner FT is not supported.\n",
143 			       tt);
144 		return -EINVAL;
145 	}
146 
147 	tir_p = rss_get_tirp(rss, tt, inner);
148 	if (*tir_p)
149 		return -EINVAL;
150 
151 	tir = kvzalloc(sizeof(*tir), GFP_KERNEL);
152 	if (!tir)
153 		return -ENOMEM;
154 
155 	builder = mlx5e_tir_builder_alloc(false);
156 	if (!builder) {
157 		err = -ENOMEM;
158 		goto free_tir;
159 	}
160 
161 	rqtn = mlx5e_rqt_get_rqtn(&rss->rqt);
162 	mlx5e_tir_builder_build_rqt(builder, rss->mdev->mlx5e_res.hw_objs.td.tdn,
163 				    rqtn, rss->inner_ft_support);
164 	mlx5e_tir_builder_build_lro(builder, init_lro_param);
165 	rss_tt = mlx5e_rss_get_tt_config(rss, tt);
166 	mlx5e_tir_builder_build_rss(builder, &rss->hash, &rss_tt, inner);
167 
168 	err = mlx5e_tir_init(tir, builder, rss->mdev, true);
169 	mlx5e_tir_builder_free(builder);
170 	if (err) {
171 		mlx5e_rss_warn(rss->mdev, "Failed to create %sindirect TIR: err = %d, tt = %d\n",
172 			       inner ? "inner " : "", err, tt);
173 		goto free_tir;
174 	}
175 
176 	*tir_p = tir;
177 	return 0;
178 
179 free_tir:
180 	kvfree(tir);
181 	return err;
182 }
183 
mlx5e_rss_destroy_tir(struct mlx5e_rss * rss,enum mlx5_traffic_types tt,bool inner)184 static void mlx5e_rss_destroy_tir(struct mlx5e_rss *rss, enum mlx5_traffic_types tt,
185 				  bool inner)
186 {
187 	struct mlx5e_tir **tir_p;
188 	struct mlx5e_tir *tir;
189 
190 	tir_p = rss_get_tirp(rss, tt, inner);
191 	if (!*tir_p)
192 		return;
193 
194 	tir = *tir_p;
195 	mlx5e_tir_destroy(tir);
196 	kvfree(tir);
197 	*tir_p = NULL;
198 }
199 
mlx5e_rss_create_tirs(struct mlx5e_rss * rss,const struct mlx5e_lro_param * init_lro_param,bool inner)200 static int mlx5e_rss_create_tirs(struct mlx5e_rss *rss,
201 				 const struct mlx5e_lro_param *init_lro_param,
202 				 bool inner)
203 {
204 	enum mlx5_traffic_types tt, max_tt;
205 	int err;
206 
207 	for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++) {
208 		err = mlx5e_rss_create_tir(rss, tt, init_lro_param, inner);
209 		if (err)
210 			goto err_destroy_tirs;
211 	}
212 
213 	return 0;
214 
215 err_destroy_tirs:
216 	max_tt = tt;
217 	for (tt = 0; tt < max_tt; tt++)
218 		mlx5e_rss_destroy_tir(rss, tt, inner);
219 	return err;
220 }
221 
mlx5e_rss_destroy_tirs(struct mlx5e_rss * rss,bool inner)222 static void mlx5e_rss_destroy_tirs(struct mlx5e_rss *rss, bool inner)
223 {
224 	enum mlx5_traffic_types tt;
225 
226 	for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++)
227 		mlx5e_rss_destroy_tir(rss, tt, inner);
228 }
229 
mlx5e_rss_update_tir(struct mlx5e_rss * rss,enum mlx5_traffic_types tt,bool inner)230 static int mlx5e_rss_update_tir(struct mlx5e_rss *rss, enum mlx5_traffic_types tt,
231 				bool inner)
232 {
233 	struct mlx5e_rss_params_traffic_type rss_tt;
234 	struct mlx5e_tir_builder *builder;
235 	struct mlx5e_tir *tir;
236 	int err;
237 
238 	tir = rss_get_tir(rss, tt, inner);
239 	if (!tir)
240 		return 0;
241 
242 	builder = mlx5e_tir_builder_alloc(true);
243 	if (!builder)
244 		return -ENOMEM;
245 
246 	rss_tt = mlx5e_rss_get_tt_config(rss, tt);
247 
248 	mlx5e_tir_builder_build_rss(builder, &rss->hash, &rss_tt, inner);
249 	err = mlx5e_tir_modify(tir, builder);
250 
251 	mlx5e_tir_builder_free(builder);
252 	return err;
253 }
254 
mlx5e_rss_update_tirs(struct mlx5e_rss * rss)255 static int mlx5e_rss_update_tirs(struct mlx5e_rss *rss)
256 {
257 	enum mlx5_traffic_types tt;
258 	int err, retval;
259 
260 	retval = 0;
261 
262 	for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++) {
263 		err = mlx5e_rss_update_tir(rss, tt, false);
264 		if (err) {
265 			retval = retval ? : err;
266 			mlx5e_rss_warn(rss->mdev,
267 				       "Failed to update RSS hash of indirect TIR for traffic type %d: err = %d\n",
268 				       tt, err);
269 		}
270 
271 		if (!rss->inner_ft_support)
272 			continue;
273 
274 		err = mlx5e_rss_update_tir(rss, tt, true);
275 		if (err) {
276 			retval = retval ? : err;
277 			mlx5e_rss_warn(rss->mdev,
278 				       "Failed to update RSS hash of inner indirect TIR for traffic type %d: err = %d\n",
279 				       tt, err);
280 		}
281 	}
282 	return retval;
283 }
284 
mlx5e_rss_init_no_tirs(struct mlx5e_rss * rss,struct mlx5_core_dev * mdev,bool inner_ft_support,u32 drop_rqn)285 int mlx5e_rss_init_no_tirs(struct mlx5e_rss *rss, struct mlx5_core_dev *mdev,
286 			   bool inner_ft_support, u32 drop_rqn)
287 {
288 	rss->mdev = mdev;
289 	rss->inner_ft_support = inner_ft_support;
290 	rss->drop_rqn = drop_rqn;
291 
292 	mlx5e_rss_params_init(rss);
293 	refcount_set(&rss->refcnt, 1);
294 
295 	return mlx5e_rqt_init_direct(&rss->rqt, mdev, true, drop_rqn);
296 }
297 
mlx5e_rss_init(struct mlx5e_rss * rss,struct mlx5_core_dev * mdev,bool inner_ft_support,u32 drop_rqn,const struct mlx5e_lro_param * init_lro_param)298 int mlx5e_rss_init(struct mlx5e_rss *rss, struct mlx5_core_dev *mdev,
299 		   bool inner_ft_support, u32 drop_rqn,
300 		   const struct mlx5e_lro_param *init_lro_param)
301 {
302 	int err;
303 
304 	err = mlx5e_rss_init_no_tirs(rss, mdev, inner_ft_support, drop_rqn);
305 	if (err)
306 		goto err_out;
307 
308 	err = mlx5e_rss_create_tirs(rss, init_lro_param, false);
309 	if (err)
310 		goto err_destroy_rqt;
311 
312 	if (inner_ft_support) {
313 		err = mlx5e_rss_create_tirs(rss, init_lro_param, true);
314 		if (err)
315 			goto err_destroy_tirs;
316 	}
317 
318 	return 0;
319 
320 err_destroy_tirs:
321 	mlx5e_rss_destroy_tirs(rss, false);
322 err_destroy_rqt:
323 	mlx5e_rqt_destroy(&rss->rqt);
324 err_out:
325 	return err;
326 }
327 
mlx5e_rss_cleanup(struct mlx5e_rss * rss)328 int mlx5e_rss_cleanup(struct mlx5e_rss *rss)
329 {
330 	if (!refcount_dec_if_one(&rss->refcnt))
331 		return -EBUSY;
332 
333 	mlx5e_rss_destroy_tirs(rss, false);
334 
335 	if (rss->inner_ft_support)
336 		mlx5e_rss_destroy_tirs(rss, true);
337 
338 	mlx5e_rqt_destroy(&rss->rqt);
339 
340 	return 0;
341 }
342 
mlx5e_rss_refcnt_inc(struct mlx5e_rss * rss)343 void mlx5e_rss_refcnt_inc(struct mlx5e_rss *rss)
344 {
345 	refcount_inc(&rss->refcnt);
346 }
347 
mlx5e_rss_refcnt_dec(struct mlx5e_rss * rss)348 void mlx5e_rss_refcnt_dec(struct mlx5e_rss *rss)
349 {
350 	refcount_dec(&rss->refcnt);
351 }
352 
mlx5e_rss_refcnt_read(struct mlx5e_rss * rss)353 unsigned int mlx5e_rss_refcnt_read(struct mlx5e_rss *rss)
354 {
355 	return refcount_read(&rss->refcnt);
356 }
357 
mlx5e_rss_get_tirn(struct mlx5e_rss * rss,enum mlx5_traffic_types tt,bool inner)358 u32 mlx5e_rss_get_tirn(struct mlx5e_rss *rss, enum mlx5_traffic_types tt,
359 		       bool inner)
360 {
361 	struct mlx5e_tir *tir;
362 
363 	WARN_ON(inner && !rss->inner_ft_support);
364 	tir = rss_get_tir(rss, tt, inner);
365 	WARN_ON(!tir);
366 
367 	return mlx5e_tir_get_tirn(tir);
368 }
369 
370 /* Fill the "tirn" output parameter.
371  * Create the requested TIR if it's its first usage.
372  */
mlx5e_rss_obtain_tirn(struct mlx5e_rss * rss,enum mlx5_traffic_types tt,const struct mlx5e_lro_param * init_lro_param,bool inner,u32 * tirn)373 int mlx5e_rss_obtain_tirn(struct mlx5e_rss *rss,
374 			  enum mlx5_traffic_types tt,
375 			  const struct mlx5e_lro_param *init_lro_param,
376 			  bool inner, u32 *tirn)
377 {
378 	struct mlx5e_tir *tir;
379 
380 	tir = rss_get_tir(rss, tt, inner);
381 	if (!tir) { /* TIR doesn't exist, create one */
382 		int err;
383 
384 		err = mlx5e_rss_create_tir(rss, tt, init_lro_param, inner);
385 		if (err)
386 			return err;
387 		tir = rss_get_tir(rss, tt, inner);
388 	}
389 
390 	*tirn = mlx5e_tir_get_tirn(tir);
391 	return 0;
392 }
393 
mlx5e_rss_apply(struct mlx5e_rss * rss,u32 * rqns,unsigned int num_rqns)394 static void mlx5e_rss_apply(struct mlx5e_rss *rss, u32 *rqns, unsigned int num_rqns)
395 {
396 	int err;
397 
398 	err = mlx5e_rqt_redirect_indir(&rss->rqt, rqns, num_rqns, rss->hash.hfunc, &rss->indir);
399 	if (err)
400 		mlx5e_rss_warn(rss->mdev, "Failed to redirect RQT %#x to channels: err = %d\n",
401 			       mlx5e_rqt_get_rqtn(&rss->rqt), err);
402 }
403 
mlx5e_rss_enable(struct mlx5e_rss * rss,u32 * rqns,unsigned int num_rqns)404 void mlx5e_rss_enable(struct mlx5e_rss *rss, u32 *rqns, unsigned int num_rqns)
405 {
406 	rss->enabled = true;
407 	mlx5e_rss_apply(rss, rqns, num_rqns);
408 }
409 
mlx5e_rss_disable(struct mlx5e_rss * rss)410 void mlx5e_rss_disable(struct mlx5e_rss *rss)
411 {
412 	int err;
413 
414 	rss->enabled = false;
415 	err = mlx5e_rqt_redirect_direct(&rss->rqt, rss->drop_rqn);
416 	if (err)
417 		mlx5e_rss_warn(rss->mdev, "Failed to redirect RQT %#x to drop RQ %#x: err = %d\n",
418 			       mlx5e_rqt_get_rqtn(&rss->rqt), rss->drop_rqn, err);
419 }
420 
mlx5e_rss_lro_set_param(struct mlx5e_rss * rss,struct mlx5e_lro_param * lro_param)421 int mlx5e_rss_lro_set_param(struct mlx5e_rss *rss, struct mlx5e_lro_param *lro_param)
422 {
423 	struct mlx5e_tir_builder *builder;
424 	enum mlx5_traffic_types tt;
425 	int err, final_err;
426 
427 	builder = mlx5e_tir_builder_alloc(true);
428 	if (!builder)
429 		return -ENOMEM;
430 
431 	mlx5e_tir_builder_build_lro(builder, lro_param);
432 
433 	final_err = 0;
434 
435 	for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++) {
436 		struct mlx5e_tir *tir;
437 
438 		tir = rss_get_tir(rss, tt, false);
439 		if (!tir)
440 			goto inner_tir;
441 		err = mlx5e_tir_modify(tir, builder);
442 		if (err) {
443 			mlx5e_rss_warn(rss->mdev, "Failed to update LRO state of indirect TIR %#x for traffic type %d: err = %d\n",
444 				       mlx5e_tir_get_tirn(tir), tt, err);
445 			if (!final_err)
446 				final_err = err;
447 		}
448 
449 inner_tir:
450 		if (!rss->inner_ft_support)
451 			continue;
452 
453 		tir = rss_get_tir(rss, tt, true);
454 		if (!tir)
455 			continue;
456 		err = mlx5e_tir_modify(tir, builder);
457 		if (err) {
458 			mlx5e_rss_warn(rss->mdev, "Failed to update LRO state of inner indirect TIR %#x for traffic type %d: err = %d\n",
459 				       mlx5e_tir_get_tirn(tir), tt, err);
460 			if (!final_err)
461 				final_err = err;
462 		}
463 	}
464 
465 	mlx5e_tir_builder_free(builder);
466 	return final_err;
467 }
468 
mlx5e_rss_get_rxfh(struct mlx5e_rss * rss,u32 * indir,u8 * key,u8 * hfunc)469 int mlx5e_rss_get_rxfh(struct mlx5e_rss *rss, u32 *indir, u8 *key, u8 *hfunc)
470 {
471 	unsigned int i;
472 
473 	if (indir)
474 		for (i = 0; i < MLX5E_INDIR_RQT_SIZE; i++)
475 			indir[i] = rss->indir.table[i];
476 
477 	if (key)
478 		memcpy(key, rss->hash.toeplitz_hash_key,
479 		       sizeof(rss->hash.toeplitz_hash_key));
480 
481 	if (hfunc)
482 		*hfunc = rss->hash.hfunc;
483 
484 	return 0;
485 }
486 
mlx5e_rss_set_rxfh(struct mlx5e_rss * rss,const u32 * indir,const u8 * key,const u8 * hfunc,u32 * rqns,unsigned int num_rqns)487 int mlx5e_rss_set_rxfh(struct mlx5e_rss *rss, const u32 *indir,
488 		       const u8 *key, const u8 *hfunc,
489 		       u32 *rqns, unsigned int num_rqns)
490 {
491 	bool changed_indir = false;
492 	bool changed_hash = false;
493 
494 	if (hfunc && *hfunc != rss->hash.hfunc) {
495 		switch (*hfunc) {
496 		case ETH_RSS_HASH_XOR:
497 		case ETH_RSS_HASH_TOP:
498 			break;
499 		default:
500 			return -EINVAL;
501 		}
502 		changed_hash = true;
503 		changed_indir = true;
504 		rss->hash.hfunc = *hfunc;
505 	}
506 
507 	if (key) {
508 		if (rss->hash.hfunc == ETH_RSS_HASH_TOP)
509 			changed_hash = true;
510 		memcpy(rss->hash.toeplitz_hash_key, key,
511 		       sizeof(rss->hash.toeplitz_hash_key));
512 	}
513 
514 	if (indir) {
515 		unsigned int i;
516 
517 		changed_indir = true;
518 
519 		for (i = 0; i < MLX5E_INDIR_RQT_SIZE; i++)
520 			rss->indir.table[i] = indir[i];
521 	}
522 
523 	if (changed_indir && rss->enabled)
524 		mlx5e_rss_apply(rss, rqns, num_rqns);
525 
526 	if (changed_hash)
527 		mlx5e_rss_update_tirs(rss);
528 
529 	return 0;
530 }
531 
mlx5e_rss_get_hash(struct mlx5e_rss * rss)532 struct mlx5e_rss_params_hash mlx5e_rss_get_hash(struct mlx5e_rss *rss)
533 {
534 	return rss->hash;
535 }
536 
mlx5e_rss_get_hash_fields(struct mlx5e_rss * rss,enum mlx5_traffic_types tt)537 u8 mlx5e_rss_get_hash_fields(struct mlx5e_rss *rss, enum mlx5_traffic_types tt)
538 {
539 	return rss->rx_hash_fields[tt];
540 }
541 
mlx5e_rss_set_hash_fields(struct mlx5e_rss * rss,enum mlx5_traffic_types tt,u8 rx_hash_fields)542 int mlx5e_rss_set_hash_fields(struct mlx5e_rss *rss, enum mlx5_traffic_types tt,
543 			      u8 rx_hash_fields)
544 {
545 	u8 old_rx_hash_fields;
546 	int err;
547 
548 	old_rx_hash_fields = rss->rx_hash_fields[tt];
549 
550 	if (old_rx_hash_fields == rx_hash_fields)
551 		return 0;
552 
553 	rss->rx_hash_fields[tt] = rx_hash_fields;
554 
555 	err = mlx5e_rss_update_tir(rss, tt, false);
556 	if (err) {
557 		rss->rx_hash_fields[tt] = old_rx_hash_fields;
558 		mlx5e_rss_warn(rss->mdev,
559 			       "Failed to update RSS hash fields of indirect TIR for traffic type %d: err = %d\n",
560 			       tt, err);
561 		return err;
562 	}
563 
564 	if (!(rss->inner_ft_support))
565 		return 0;
566 
567 	err = mlx5e_rss_update_tir(rss, tt, true);
568 	if (err) {
569 		/* Partial update happened. Try to revert - it may fail too, but
570 		 * there is nothing more we can do.
571 		 */
572 		rss->rx_hash_fields[tt] = old_rx_hash_fields;
573 		mlx5e_rss_warn(rss->mdev,
574 			       "Failed to update RSS hash fields of inner indirect TIR for traffic type %d: err = %d\n",
575 			       tt, err);
576 		if (mlx5e_rss_update_tir(rss, tt, false))
577 			mlx5e_rss_warn(rss->mdev,
578 				       "Partial update of RSS hash fields happened: failed to revert indirect TIR for traffic type %d to the old values\n",
579 				       tt);
580 	}
581 
582 	return err;
583 }
584 
mlx5e_rss_set_indir_uniform(struct mlx5e_rss * rss,unsigned int nch)585 void mlx5e_rss_set_indir_uniform(struct mlx5e_rss *rss, unsigned int nch)
586 {
587 	mlx5e_rss_params_indir_init_uniform(&rss->indir, nch);
588 }
589