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_packet_merge_param * init_pkt_merge_param,bool inner)128 static int mlx5e_rss_create_tir(struct mlx5e_rss *rss,
129 				enum mlx5_traffic_types tt,
130 				const struct mlx5e_packet_merge_param *init_pkt_merge_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_packet_merge(builder, init_pkt_merge_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_packet_merge_param * init_pkt_merge_param,bool inner)200 static int mlx5e_rss_create_tirs(struct mlx5e_rss *rss,
201 				 const struct mlx5e_packet_merge_param *init_pkt_merge_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_pkt_merge_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_packet_merge_param * init_pkt_merge_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_packet_merge_param *init_pkt_merge_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_pkt_merge_param, false);
309 	if (err)
310 		goto err_destroy_rqt;
311 
312 	if (inner_ft_support) {
313 		err = mlx5e_rss_create_tirs(rss, init_pkt_merge_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_packet_merge_param * init_pkt_merge_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_packet_merge_param *init_pkt_merge_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_pkt_merge_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 int 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 	return err;
403 }
404 
mlx5e_rss_enable(struct mlx5e_rss * rss,u32 * rqns,unsigned int num_rqns)405 void mlx5e_rss_enable(struct mlx5e_rss *rss, u32 *rqns, unsigned int num_rqns)
406 {
407 	rss->enabled = true;
408 	mlx5e_rss_apply(rss, rqns, num_rqns);
409 }
410 
mlx5e_rss_disable(struct mlx5e_rss * rss)411 void mlx5e_rss_disable(struct mlx5e_rss *rss)
412 {
413 	int err;
414 
415 	rss->enabled = false;
416 	err = mlx5e_rqt_redirect_direct(&rss->rqt, rss->drop_rqn);
417 	if (err)
418 		mlx5e_rss_warn(rss->mdev, "Failed to redirect RQT %#x to drop RQ %#x: err = %d\n",
419 			       mlx5e_rqt_get_rqtn(&rss->rqt), rss->drop_rqn, err);
420 }
421 
mlx5e_rss_packet_merge_set_param(struct mlx5e_rss * rss,struct mlx5e_packet_merge_param * pkt_merge_param)422 int mlx5e_rss_packet_merge_set_param(struct mlx5e_rss *rss,
423 				     struct mlx5e_packet_merge_param *pkt_merge_param)
424 {
425 	struct mlx5e_tir_builder *builder;
426 	enum mlx5_traffic_types tt;
427 	int err, final_err;
428 
429 	builder = mlx5e_tir_builder_alloc(true);
430 	if (!builder)
431 		return -ENOMEM;
432 
433 	mlx5e_tir_builder_build_packet_merge(builder, pkt_merge_param);
434 
435 	final_err = 0;
436 
437 	for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++) {
438 		struct mlx5e_tir *tir;
439 
440 		tir = rss_get_tir(rss, tt, false);
441 		if (!tir)
442 			goto inner_tir;
443 		err = mlx5e_tir_modify(tir, builder);
444 		if (err) {
445 			mlx5e_rss_warn(rss->mdev, "Failed to update packet merge state of indirect TIR %#x for traffic type %d: err = %d\n",
446 				       mlx5e_tir_get_tirn(tir), tt, err);
447 			if (!final_err)
448 				final_err = err;
449 		}
450 
451 inner_tir:
452 		if (!rss->inner_ft_support)
453 			continue;
454 
455 		tir = rss_get_tir(rss, tt, true);
456 		if (!tir)
457 			continue;
458 		err = mlx5e_tir_modify(tir, builder);
459 		if (err) {
460 			mlx5e_rss_warn(rss->mdev, "Failed to update packet merge state of inner indirect TIR %#x for traffic type %d: err = %d\n",
461 				       mlx5e_tir_get_tirn(tir), tt, err);
462 			if (!final_err)
463 				final_err = err;
464 		}
465 	}
466 
467 	mlx5e_tir_builder_free(builder);
468 	return final_err;
469 }
470 
mlx5e_rss_get_rxfh(struct mlx5e_rss * rss,u32 * indir,u8 * key,u8 * hfunc)471 int mlx5e_rss_get_rxfh(struct mlx5e_rss *rss, u32 *indir, u8 *key, u8 *hfunc)
472 {
473 	unsigned int i;
474 
475 	if (indir)
476 		for (i = 0; i < MLX5E_INDIR_RQT_SIZE; i++)
477 			indir[i] = rss->indir.table[i];
478 
479 	if (key)
480 		memcpy(key, rss->hash.toeplitz_hash_key,
481 		       sizeof(rss->hash.toeplitz_hash_key));
482 
483 	if (hfunc)
484 		*hfunc = rss->hash.hfunc;
485 
486 	return 0;
487 }
488 
mlx5e_rss_set_rxfh(struct mlx5e_rss * rss,const u32 * indir,const u8 * key,const u8 * hfunc,u32 * rqns,unsigned int num_rqns)489 int mlx5e_rss_set_rxfh(struct mlx5e_rss *rss, const u32 *indir,
490 		       const u8 *key, const u8 *hfunc,
491 		       u32 *rqns, unsigned int num_rqns)
492 {
493 	bool changed_indir = false;
494 	bool changed_hash = false;
495 	struct mlx5e_rss *old_rss;
496 	int err = 0;
497 
498 	old_rss = mlx5e_rss_alloc();
499 	if (!old_rss)
500 		return -ENOMEM;
501 
502 	*old_rss = *rss;
503 
504 	if (hfunc && *hfunc != rss->hash.hfunc) {
505 		switch (*hfunc) {
506 		case ETH_RSS_HASH_XOR:
507 		case ETH_RSS_HASH_TOP:
508 			break;
509 		default:
510 			err = -EINVAL;
511 			goto out;
512 		}
513 		changed_hash = true;
514 		changed_indir = true;
515 		rss->hash.hfunc = *hfunc;
516 	}
517 
518 	if (key) {
519 		if (rss->hash.hfunc == ETH_RSS_HASH_TOP)
520 			changed_hash = true;
521 		memcpy(rss->hash.toeplitz_hash_key, key,
522 		       sizeof(rss->hash.toeplitz_hash_key));
523 	}
524 
525 	if (indir) {
526 		unsigned int i;
527 
528 		changed_indir = true;
529 
530 		for (i = 0; i < MLX5E_INDIR_RQT_SIZE; i++)
531 			rss->indir.table[i] = indir[i];
532 	}
533 
534 	if (changed_indir && rss->enabled) {
535 		err = mlx5e_rss_apply(rss, rqns, num_rqns);
536 		if (err) {
537 			*rss = *old_rss;
538 			goto out;
539 		}
540 	}
541 
542 	if (changed_hash)
543 		mlx5e_rss_update_tirs(rss);
544 
545 out:
546 	mlx5e_rss_free(old_rss);
547 	return err;
548 }
549 
mlx5e_rss_get_hash(struct mlx5e_rss * rss)550 struct mlx5e_rss_params_hash mlx5e_rss_get_hash(struct mlx5e_rss *rss)
551 {
552 	return rss->hash;
553 }
554 
mlx5e_rss_get_hash_fields(struct mlx5e_rss * rss,enum mlx5_traffic_types tt)555 u8 mlx5e_rss_get_hash_fields(struct mlx5e_rss *rss, enum mlx5_traffic_types tt)
556 {
557 	return rss->rx_hash_fields[tt];
558 }
559 
mlx5e_rss_set_hash_fields(struct mlx5e_rss * rss,enum mlx5_traffic_types tt,u8 rx_hash_fields)560 int mlx5e_rss_set_hash_fields(struct mlx5e_rss *rss, enum mlx5_traffic_types tt,
561 			      u8 rx_hash_fields)
562 {
563 	u8 old_rx_hash_fields;
564 	int err;
565 
566 	old_rx_hash_fields = rss->rx_hash_fields[tt];
567 
568 	if (old_rx_hash_fields == rx_hash_fields)
569 		return 0;
570 
571 	rss->rx_hash_fields[tt] = rx_hash_fields;
572 
573 	err = mlx5e_rss_update_tir(rss, tt, false);
574 	if (err) {
575 		rss->rx_hash_fields[tt] = old_rx_hash_fields;
576 		mlx5e_rss_warn(rss->mdev,
577 			       "Failed to update RSS hash fields of indirect TIR for traffic type %d: err = %d\n",
578 			       tt, err);
579 		return err;
580 	}
581 
582 	if (!(rss->inner_ft_support))
583 		return 0;
584 
585 	err = mlx5e_rss_update_tir(rss, tt, true);
586 	if (err) {
587 		/* Partial update happened. Try to revert - it may fail too, but
588 		 * there is nothing more we can do.
589 		 */
590 		rss->rx_hash_fields[tt] = old_rx_hash_fields;
591 		mlx5e_rss_warn(rss->mdev,
592 			       "Failed to update RSS hash fields of inner indirect TIR for traffic type %d: err = %d\n",
593 			       tt, err);
594 		if (mlx5e_rss_update_tir(rss, tt, false))
595 			mlx5e_rss_warn(rss->mdev,
596 				       "Partial update of RSS hash fields happened: failed to revert indirect TIR for traffic type %d to the old values\n",
597 				       tt);
598 	}
599 
600 	return err;
601 }
602 
mlx5e_rss_set_indir_uniform(struct mlx5e_rss * rss,unsigned int nch)603 void mlx5e_rss_set_indir_uniform(struct mlx5e_rss *rss, unsigned int nch)
604 {
605 	mlx5e_rss_params_indir_init_uniform(&rss->indir, nch);
606 }
607