165d6b6e5SMaxim Mikityanskiy // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
265d6b6e5SMaxim Mikityanskiy /* Copyright (c) 2021, Mellanox Technologies inc. All rights reserved. */
365d6b6e5SMaxim Mikityanskiy 
465d6b6e5SMaxim Mikityanskiy #include "rx_res.h"
5*43ec0f41SMaxim Mikityanskiy #include "channels.h"
6*43ec0f41SMaxim Mikityanskiy #include "params.h"
765d6b6e5SMaxim Mikityanskiy 
865d6b6e5SMaxim Mikityanskiy static const struct mlx5e_rss_params_traffic_type rss_default_config[MLX5E_NUM_INDIR_TIRS] = {
965d6b6e5SMaxim Mikityanskiy 	[MLX5E_TT_IPV4_TCP] = {
1065d6b6e5SMaxim Mikityanskiy 		.l3_prot_type = MLX5_L3_PROT_TYPE_IPV4,
1165d6b6e5SMaxim Mikityanskiy 		.l4_prot_type = MLX5_L4_PROT_TYPE_TCP,
1265d6b6e5SMaxim Mikityanskiy 		.rx_hash_fields = MLX5_HASH_IP_L4PORTS,
1365d6b6e5SMaxim Mikityanskiy 	},
1465d6b6e5SMaxim Mikityanskiy 	[MLX5E_TT_IPV6_TCP] = {
1565d6b6e5SMaxim Mikityanskiy 		.l3_prot_type = MLX5_L3_PROT_TYPE_IPV6,
1665d6b6e5SMaxim Mikityanskiy 		.l4_prot_type = MLX5_L4_PROT_TYPE_TCP,
1765d6b6e5SMaxim Mikityanskiy 		.rx_hash_fields = MLX5_HASH_IP_L4PORTS,
1865d6b6e5SMaxim Mikityanskiy 	},
1965d6b6e5SMaxim Mikityanskiy 	[MLX5E_TT_IPV4_UDP] = {
2065d6b6e5SMaxim Mikityanskiy 		.l3_prot_type = MLX5_L3_PROT_TYPE_IPV4,
2165d6b6e5SMaxim Mikityanskiy 		.l4_prot_type = MLX5_L4_PROT_TYPE_UDP,
2265d6b6e5SMaxim Mikityanskiy 		.rx_hash_fields = MLX5_HASH_IP_L4PORTS,
2365d6b6e5SMaxim Mikityanskiy 	},
2465d6b6e5SMaxim Mikityanskiy 	[MLX5E_TT_IPV6_UDP] = {
2565d6b6e5SMaxim Mikityanskiy 		.l3_prot_type = MLX5_L3_PROT_TYPE_IPV6,
2665d6b6e5SMaxim Mikityanskiy 		.l4_prot_type = MLX5_L4_PROT_TYPE_UDP,
2765d6b6e5SMaxim Mikityanskiy 		.rx_hash_fields = MLX5_HASH_IP_L4PORTS,
2865d6b6e5SMaxim Mikityanskiy 	},
2965d6b6e5SMaxim Mikityanskiy 	[MLX5E_TT_IPV4_IPSEC_AH] = {
3065d6b6e5SMaxim Mikityanskiy 		.l3_prot_type = MLX5_L3_PROT_TYPE_IPV4,
3165d6b6e5SMaxim Mikityanskiy 		.l4_prot_type = 0,
3265d6b6e5SMaxim Mikityanskiy 		.rx_hash_fields = MLX5_HASH_IP_IPSEC_SPI,
3365d6b6e5SMaxim Mikityanskiy 	},
3465d6b6e5SMaxim Mikityanskiy 	[MLX5E_TT_IPV6_IPSEC_AH] = {
3565d6b6e5SMaxim Mikityanskiy 		.l3_prot_type = MLX5_L3_PROT_TYPE_IPV6,
3665d6b6e5SMaxim Mikityanskiy 		.l4_prot_type = 0,
3765d6b6e5SMaxim Mikityanskiy 		.rx_hash_fields = MLX5_HASH_IP_IPSEC_SPI,
3865d6b6e5SMaxim Mikityanskiy 	},
3965d6b6e5SMaxim Mikityanskiy 	[MLX5E_TT_IPV4_IPSEC_ESP] = {
4065d6b6e5SMaxim Mikityanskiy 		.l3_prot_type = MLX5_L3_PROT_TYPE_IPV4,
4165d6b6e5SMaxim Mikityanskiy 		.l4_prot_type = 0,
4265d6b6e5SMaxim Mikityanskiy 		.rx_hash_fields = MLX5_HASH_IP_IPSEC_SPI,
4365d6b6e5SMaxim Mikityanskiy 	},
4465d6b6e5SMaxim Mikityanskiy 	[MLX5E_TT_IPV6_IPSEC_ESP] = {
4565d6b6e5SMaxim Mikityanskiy 		.l3_prot_type = MLX5_L3_PROT_TYPE_IPV6,
4665d6b6e5SMaxim Mikityanskiy 		.l4_prot_type = 0,
4765d6b6e5SMaxim Mikityanskiy 		.rx_hash_fields = MLX5_HASH_IP_IPSEC_SPI,
4865d6b6e5SMaxim Mikityanskiy 	},
4965d6b6e5SMaxim Mikityanskiy 	[MLX5E_TT_IPV4] = {
5065d6b6e5SMaxim Mikityanskiy 		.l3_prot_type = MLX5_L3_PROT_TYPE_IPV4,
5165d6b6e5SMaxim Mikityanskiy 		.l4_prot_type = 0,
5265d6b6e5SMaxim Mikityanskiy 		.rx_hash_fields = MLX5_HASH_IP,
5365d6b6e5SMaxim Mikityanskiy 	},
5465d6b6e5SMaxim Mikityanskiy 	[MLX5E_TT_IPV6] = {
5565d6b6e5SMaxim Mikityanskiy 		.l3_prot_type = MLX5_L3_PROT_TYPE_IPV6,
5665d6b6e5SMaxim Mikityanskiy 		.l4_prot_type = 0,
5765d6b6e5SMaxim Mikityanskiy 		.rx_hash_fields = MLX5_HASH_IP,
5865d6b6e5SMaxim Mikityanskiy 	},
5965d6b6e5SMaxim Mikityanskiy };
6065d6b6e5SMaxim Mikityanskiy 
6165d6b6e5SMaxim Mikityanskiy struct mlx5e_rss_params_traffic_type
6265d6b6e5SMaxim Mikityanskiy mlx5e_rss_get_default_tt_config(enum mlx5e_traffic_types tt)
6365d6b6e5SMaxim Mikityanskiy {
6465d6b6e5SMaxim Mikityanskiy 	return rss_default_config[tt];
6565d6b6e5SMaxim Mikityanskiy }
6665d6b6e5SMaxim Mikityanskiy 
67*43ec0f41SMaxim Mikityanskiy struct mlx5e_rx_res {
68*43ec0f41SMaxim Mikityanskiy 	struct mlx5_core_dev *mdev;
69*43ec0f41SMaxim Mikityanskiy 	enum mlx5e_rx_res_features features;
70*43ec0f41SMaxim Mikityanskiy 	unsigned int max_nch;
71*43ec0f41SMaxim Mikityanskiy 	u32 drop_rqn;
72*43ec0f41SMaxim Mikityanskiy 
73*43ec0f41SMaxim Mikityanskiy 	struct {
74*43ec0f41SMaxim Mikityanskiy 		struct mlx5e_rss_params_hash hash;
75*43ec0f41SMaxim Mikityanskiy 		struct mlx5e_rss_params_indir indir;
76*43ec0f41SMaxim Mikityanskiy 		u32 rx_hash_fields[MLX5E_NUM_INDIR_TIRS];
77*43ec0f41SMaxim Mikityanskiy 	} rss_params;
78*43ec0f41SMaxim Mikityanskiy 
79*43ec0f41SMaxim Mikityanskiy 	struct mlx5e_rqt indir_rqt;
80*43ec0f41SMaxim Mikityanskiy 	struct {
81*43ec0f41SMaxim Mikityanskiy 		struct mlx5e_tir indir_tir;
82*43ec0f41SMaxim Mikityanskiy 		struct mlx5e_tir inner_indir_tir;
83*43ec0f41SMaxim Mikityanskiy 	} rss[MLX5E_NUM_INDIR_TIRS];
84*43ec0f41SMaxim Mikityanskiy 
85*43ec0f41SMaxim Mikityanskiy 	bool rss_active;
86*43ec0f41SMaxim Mikityanskiy 	u32 rss_rqns[MLX5E_INDIR_RQT_SIZE];
87*43ec0f41SMaxim Mikityanskiy 	unsigned int rss_nch;
88*43ec0f41SMaxim Mikityanskiy 
89*43ec0f41SMaxim Mikityanskiy 	struct {
90*43ec0f41SMaxim Mikityanskiy 		struct mlx5e_rqt direct_rqt;
91*43ec0f41SMaxim Mikityanskiy 		struct mlx5e_tir direct_tir;
92*43ec0f41SMaxim Mikityanskiy 		struct mlx5e_rqt xsk_rqt;
93*43ec0f41SMaxim Mikityanskiy 		struct mlx5e_tir xsk_tir;
94*43ec0f41SMaxim Mikityanskiy 	} channels[MLX5E_MAX_NUM_CHANNELS];
95*43ec0f41SMaxim Mikityanskiy 
96*43ec0f41SMaxim Mikityanskiy 	struct {
97*43ec0f41SMaxim Mikityanskiy 		struct mlx5e_rqt rqt;
98*43ec0f41SMaxim Mikityanskiy 		struct mlx5e_tir tir;
99*43ec0f41SMaxim Mikityanskiy 	} ptp;
100*43ec0f41SMaxim Mikityanskiy };
101*43ec0f41SMaxim Mikityanskiy 
102*43ec0f41SMaxim Mikityanskiy struct mlx5e_rx_res *mlx5e_rx_res_alloc(void)
103*43ec0f41SMaxim Mikityanskiy {
104*43ec0f41SMaxim Mikityanskiy 	return kvzalloc(sizeof(struct mlx5e_rx_res), GFP_KERNEL);
105*43ec0f41SMaxim Mikityanskiy }
106*43ec0f41SMaxim Mikityanskiy 
107*43ec0f41SMaxim Mikityanskiy static void mlx5e_rx_res_rss_params_init(struct mlx5e_rx_res *res, unsigned int init_nch)
108*43ec0f41SMaxim Mikityanskiy {
109*43ec0f41SMaxim Mikityanskiy 	enum mlx5e_traffic_types tt;
110*43ec0f41SMaxim Mikityanskiy 
111*43ec0f41SMaxim Mikityanskiy 	res->rss_params.hash.hfunc = ETH_RSS_HASH_TOP;
112*43ec0f41SMaxim Mikityanskiy 	netdev_rss_key_fill(res->rss_params.hash.toeplitz_hash_key,
113*43ec0f41SMaxim Mikityanskiy 			    sizeof(res->rss_params.hash.toeplitz_hash_key));
114*43ec0f41SMaxim Mikityanskiy 	mlx5e_rss_params_indir_init_uniform(&res->rss_params.indir, init_nch);
115*43ec0f41SMaxim Mikityanskiy 	for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++)
116*43ec0f41SMaxim Mikityanskiy 		res->rss_params.rx_hash_fields[tt] =
117*43ec0f41SMaxim Mikityanskiy 			mlx5e_rss_get_default_tt_config(tt).rx_hash_fields;
118*43ec0f41SMaxim Mikityanskiy }
119*43ec0f41SMaxim Mikityanskiy 
120*43ec0f41SMaxim Mikityanskiy static int mlx5e_rx_res_rss_init(struct mlx5e_rx_res *res,
121*43ec0f41SMaxim Mikityanskiy 				 const struct mlx5e_lro_param *init_lro_param)
122*43ec0f41SMaxim Mikityanskiy {
123*43ec0f41SMaxim Mikityanskiy 	bool inner_ft_support = res->features & MLX5E_RX_RES_FEATURE_INNER_FT;
124*43ec0f41SMaxim Mikityanskiy 	enum mlx5e_traffic_types tt, max_tt;
125*43ec0f41SMaxim Mikityanskiy 	struct mlx5e_tir_builder *builder;
126*43ec0f41SMaxim Mikityanskiy 	u32 indir_rqtn;
127*43ec0f41SMaxim Mikityanskiy 	int err;
128*43ec0f41SMaxim Mikityanskiy 
129*43ec0f41SMaxim Mikityanskiy 	builder = mlx5e_tir_builder_alloc(false);
130*43ec0f41SMaxim Mikityanskiy 	if (!builder)
131*43ec0f41SMaxim Mikityanskiy 		return -ENOMEM;
132*43ec0f41SMaxim Mikityanskiy 
133*43ec0f41SMaxim Mikityanskiy 	err = mlx5e_rqt_init_direct(&res->indir_rqt, res->mdev, true, res->drop_rqn);
134*43ec0f41SMaxim Mikityanskiy 	if (err)
135*43ec0f41SMaxim Mikityanskiy 		goto out;
136*43ec0f41SMaxim Mikityanskiy 
137*43ec0f41SMaxim Mikityanskiy 	indir_rqtn = mlx5e_rqt_get_rqtn(&res->indir_rqt);
138*43ec0f41SMaxim Mikityanskiy 
139*43ec0f41SMaxim Mikityanskiy 	for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++) {
140*43ec0f41SMaxim Mikityanskiy 		struct mlx5e_rss_params_traffic_type rss_tt;
141*43ec0f41SMaxim Mikityanskiy 
142*43ec0f41SMaxim Mikityanskiy 		mlx5e_tir_builder_build_rqt(builder, res->mdev->mlx5e_res.hw_objs.td.tdn,
143*43ec0f41SMaxim Mikityanskiy 					    indir_rqtn, inner_ft_support);
144*43ec0f41SMaxim Mikityanskiy 		mlx5e_tir_builder_build_lro(builder, init_lro_param);
145*43ec0f41SMaxim Mikityanskiy 		rss_tt = mlx5e_rx_res_rss_get_current_tt_config(res, tt);
146*43ec0f41SMaxim Mikityanskiy 		mlx5e_tir_builder_build_rss(builder, &res->rss_params.hash, &rss_tt, false);
147*43ec0f41SMaxim Mikityanskiy 
148*43ec0f41SMaxim Mikityanskiy 		err = mlx5e_tir_init(&res->rss[tt].indir_tir, builder, res->mdev, true);
149*43ec0f41SMaxim Mikityanskiy 		if (err) {
150*43ec0f41SMaxim Mikityanskiy 			mlx5_core_warn(res->mdev, "Failed to create an indirect TIR: err = %d, tt = %d\n",
151*43ec0f41SMaxim Mikityanskiy 				       err, tt);
152*43ec0f41SMaxim Mikityanskiy 			goto err_destroy_tirs;
153*43ec0f41SMaxim Mikityanskiy 		}
154*43ec0f41SMaxim Mikityanskiy 
155*43ec0f41SMaxim Mikityanskiy 		mlx5e_tir_builder_clear(builder);
156*43ec0f41SMaxim Mikityanskiy 	}
157*43ec0f41SMaxim Mikityanskiy 
158*43ec0f41SMaxim Mikityanskiy 	if (!inner_ft_support)
159*43ec0f41SMaxim Mikityanskiy 		goto out;
160*43ec0f41SMaxim Mikityanskiy 
161*43ec0f41SMaxim Mikityanskiy 	for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++) {
162*43ec0f41SMaxim Mikityanskiy 		struct mlx5e_rss_params_traffic_type rss_tt;
163*43ec0f41SMaxim Mikityanskiy 
164*43ec0f41SMaxim Mikityanskiy 		mlx5e_tir_builder_build_rqt(builder, res->mdev->mlx5e_res.hw_objs.td.tdn,
165*43ec0f41SMaxim Mikityanskiy 					    indir_rqtn, inner_ft_support);
166*43ec0f41SMaxim Mikityanskiy 		mlx5e_tir_builder_build_lro(builder, init_lro_param);
167*43ec0f41SMaxim Mikityanskiy 		rss_tt = mlx5e_rx_res_rss_get_current_tt_config(res, tt);
168*43ec0f41SMaxim Mikityanskiy 		mlx5e_tir_builder_build_rss(builder, &res->rss_params.hash, &rss_tt, true);
169*43ec0f41SMaxim Mikityanskiy 
170*43ec0f41SMaxim Mikityanskiy 		err = mlx5e_tir_init(&res->rss[tt].inner_indir_tir, builder, res->mdev, true);
171*43ec0f41SMaxim Mikityanskiy 		if (err) {
172*43ec0f41SMaxim Mikityanskiy 			mlx5_core_warn(res->mdev, "Failed to create an inner indirect TIR: err = %d, tt = %d\n",
173*43ec0f41SMaxim Mikityanskiy 				       err, tt);
174*43ec0f41SMaxim Mikityanskiy 			goto err_destroy_inner_tirs;
175*43ec0f41SMaxim Mikityanskiy 		}
176*43ec0f41SMaxim Mikityanskiy 
177*43ec0f41SMaxim Mikityanskiy 		mlx5e_tir_builder_clear(builder);
178*43ec0f41SMaxim Mikityanskiy 	}
179*43ec0f41SMaxim Mikityanskiy 
180*43ec0f41SMaxim Mikityanskiy 	goto out;
181*43ec0f41SMaxim Mikityanskiy 
182*43ec0f41SMaxim Mikityanskiy err_destroy_inner_tirs:
183*43ec0f41SMaxim Mikityanskiy 	max_tt = tt;
184*43ec0f41SMaxim Mikityanskiy 	for (tt = 0; tt < max_tt; tt++)
185*43ec0f41SMaxim Mikityanskiy 		mlx5e_tir_destroy(&res->rss[tt].inner_indir_tir);
186*43ec0f41SMaxim Mikityanskiy 
187*43ec0f41SMaxim Mikityanskiy 	tt = MLX5E_NUM_INDIR_TIRS;
188*43ec0f41SMaxim Mikityanskiy err_destroy_tirs:
189*43ec0f41SMaxim Mikityanskiy 	max_tt = tt;
190*43ec0f41SMaxim Mikityanskiy 	for (tt = 0; tt < max_tt; tt++)
191*43ec0f41SMaxim Mikityanskiy 		mlx5e_tir_destroy(&res->rss[tt].indir_tir);
192*43ec0f41SMaxim Mikityanskiy 
193*43ec0f41SMaxim Mikityanskiy 	mlx5e_rqt_destroy(&res->indir_rqt);
194*43ec0f41SMaxim Mikityanskiy 
195*43ec0f41SMaxim Mikityanskiy out:
196*43ec0f41SMaxim Mikityanskiy 	mlx5e_tir_builder_free(builder);
197*43ec0f41SMaxim Mikityanskiy 
198*43ec0f41SMaxim Mikityanskiy 	return err;
199*43ec0f41SMaxim Mikityanskiy }
200*43ec0f41SMaxim Mikityanskiy 
201*43ec0f41SMaxim Mikityanskiy static int mlx5e_rx_res_channels_init(struct mlx5e_rx_res *res,
202*43ec0f41SMaxim Mikityanskiy 				      const struct mlx5e_lro_param *init_lro_param)
203*43ec0f41SMaxim Mikityanskiy {
204*43ec0f41SMaxim Mikityanskiy 	bool inner_ft_support = res->features & MLX5E_RX_RES_FEATURE_INNER_FT;
205*43ec0f41SMaxim Mikityanskiy 	struct mlx5e_tir_builder *builder;
206*43ec0f41SMaxim Mikityanskiy 	int err = 0;
207*43ec0f41SMaxim Mikityanskiy 	int ix;
208*43ec0f41SMaxim Mikityanskiy 
209*43ec0f41SMaxim Mikityanskiy 	builder = mlx5e_tir_builder_alloc(false);
210*43ec0f41SMaxim Mikityanskiy 	if (!builder)
211*43ec0f41SMaxim Mikityanskiy 		return -ENOMEM;
212*43ec0f41SMaxim Mikityanskiy 
213*43ec0f41SMaxim Mikityanskiy 	for (ix = 0; ix < res->max_nch; ix++) {
214*43ec0f41SMaxim Mikityanskiy 		err = mlx5e_rqt_init_direct(&res->channels[ix].direct_rqt,
215*43ec0f41SMaxim Mikityanskiy 					    res->mdev, false, res->drop_rqn);
216*43ec0f41SMaxim Mikityanskiy 		if (err) {
217*43ec0f41SMaxim Mikityanskiy 			mlx5_core_warn(res->mdev, "Failed to create a direct RQT: err = %d, ix = %u\n",
218*43ec0f41SMaxim Mikityanskiy 				       err, ix);
219*43ec0f41SMaxim Mikityanskiy 			goto err_destroy_direct_rqts;
220*43ec0f41SMaxim Mikityanskiy 		}
221*43ec0f41SMaxim Mikityanskiy 	}
222*43ec0f41SMaxim Mikityanskiy 
223*43ec0f41SMaxim Mikityanskiy 	for (ix = 0; ix < res->max_nch; ix++) {
224*43ec0f41SMaxim Mikityanskiy 		mlx5e_tir_builder_build_rqt(builder, res->mdev->mlx5e_res.hw_objs.td.tdn,
225*43ec0f41SMaxim Mikityanskiy 					    mlx5e_rqt_get_rqtn(&res->channels[ix].direct_rqt),
226*43ec0f41SMaxim Mikityanskiy 					    inner_ft_support);
227*43ec0f41SMaxim Mikityanskiy 		mlx5e_tir_builder_build_lro(builder, init_lro_param);
228*43ec0f41SMaxim Mikityanskiy 		mlx5e_tir_builder_build_direct(builder);
229*43ec0f41SMaxim Mikityanskiy 
230*43ec0f41SMaxim Mikityanskiy 		err = mlx5e_tir_init(&res->channels[ix].direct_tir, builder, res->mdev, true);
231*43ec0f41SMaxim Mikityanskiy 		if (err) {
232*43ec0f41SMaxim Mikityanskiy 			mlx5_core_warn(res->mdev, "Failed to create a direct TIR: err = %d, ix = %u\n",
233*43ec0f41SMaxim Mikityanskiy 				       err, ix);
234*43ec0f41SMaxim Mikityanskiy 			goto err_destroy_direct_tirs;
235*43ec0f41SMaxim Mikityanskiy 		}
236*43ec0f41SMaxim Mikityanskiy 
237*43ec0f41SMaxim Mikityanskiy 		mlx5e_tir_builder_clear(builder);
238*43ec0f41SMaxim Mikityanskiy 	}
239*43ec0f41SMaxim Mikityanskiy 
240*43ec0f41SMaxim Mikityanskiy 	if (!(res->features & MLX5E_RX_RES_FEATURE_XSK))
241*43ec0f41SMaxim Mikityanskiy 		goto out;
242*43ec0f41SMaxim Mikityanskiy 
243*43ec0f41SMaxim Mikityanskiy 	for (ix = 0; ix < res->max_nch; ix++) {
244*43ec0f41SMaxim Mikityanskiy 		err = mlx5e_rqt_init_direct(&res->channels[ix].xsk_rqt,
245*43ec0f41SMaxim Mikityanskiy 					    res->mdev, false, res->drop_rqn);
246*43ec0f41SMaxim Mikityanskiy 		if (err) {
247*43ec0f41SMaxim Mikityanskiy 			mlx5_core_warn(res->mdev, "Failed to create an XSK RQT: err = %d, ix = %u\n",
248*43ec0f41SMaxim Mikityanskiy 				       err, ix);
249*43ec0f41SMaxim Mikityanskiy 			goto err_destroy_xsk_rqts;
250*43ec0f41SMaxim Mikityanskiy 		}
251*43ec0f41SMaxim Mikityanskiy 	}
252*43ec0f41SMaxim Mikityanskiy 
253*43ec0f41SMaxim Mikityanskiy 	for (ix = 0; ix < res->max_nch; ix++) {
254*43ec0f41SMaxim Mikityanskiy 		mlx5e_tir_builder_build_rqt(builder, res->mdev->mlx5e_res.hw_objs.td.tdn,
255*43ec0f41SMaxim Mikityanskiy 					    mlx5e_rqt_get_rqtn(&res->channels[ix].xsk_rqt),
256*43ec0f41SMaxim Mikityanskiy 					    inner_ft_support);
257*43ec0f41SMaxim Mikityanskiy 		mlx5e_tir_builder_build_lro(builder, init_lro_param);
258*43ec0f41SMaxim Mikityanskiy 		mlx5e_tir_builder_build_direct(builder);
259*43ec0f41SMaxim Mikityanskiy 
260*43ec0f41SMaxim Mikityanskiy 		err = mlx5e_tir_init(&res->channels[ix].xsk_tir, builder, res->mdev, true);
261*43ec0f41SMaxim Mikityanskiy 		if (err) {
262*43ec0f41SMaxim Mikityanskiy 			mlx5_core_warn(res->mdev, "Failed to create an XSK TIR: err = %d, ix = %u\n",
263*43ec0f41SMaxim Mikityanskiy 				       err, ix);
264*43ec0f41SMaxim Mikityanskiy 			goto err_destroy_xsk_tirs;
265*43ec0f41SMaxim Mikityanskiy 		}
266*43ec0f41SMaxim Mikityanskiy 
267*43ec0f41SMaxim Mikityanskiy 		mlx5e_tir_builder_clear(builder);
268*43ec0f41SMaxim Mikityanskiy 	}
269*43ec0f41SMaxim Mikityanskiy 
270*43ec0f41SMaxim Mikityanskiy 	goto out;
271*43ec0f41SMaxim Mikityanskiy 
272*43ec0f41SMaxim Mikityanskiy err_destroy_xsk_tirs:
273*43ec0f41SMaxim Mikityanskiy 	while (--ix >= 0)
274*43ec0f41SMaxim Mikityanskiy 		mlx5e_tir_destroy(&res->channels[ix].xsk_tir);
275*43ec0f41SMaxim Mikityanskiy 
276*43ec0f41SMaxim Mikityanskiy 	ix = res->max_nch;
277*43ec0f41SMaxim Mikityanskiy err_destroy_xsk_rqts:
278*43ec0f41SMaxim Mikityanskiy 	while (--ix >= 0)
279*43ec0f41SMaxim Mikityanskiy 		mlx5e_rqt_destroy(&res->channels[ix].xsk_rqt);
280*43ec0f41SMaxim Mikityanskiy 
281*43ec0f41SMaxim Mikityanskiy 	ix = res->max_nch;
282*43ec0f41SMaxim Mikityanskiy err_destroy_direct_tirs:
283*43ec0f41SMaxim Mikityanskiy 	while (--ix >= 0)
284*43ec0f41SMaxim Mikityanskiy 		mlx5e_tir_destroy(&res->channels[ix].direct_tir);
285*43ec0f41SMaxim Mikityanskiy 
286*43ec0f41SMaxim Mikityanskiy 	ix = res->max_nch;
287*43ec0f41SMaxim Mikityanskiy err_destroy_direct_rqts:
288*43ec0f41SMaxim Mikityanskiy 	while (--ix >= 0)
289*43ec0f41SMaxim Mikityanskiy 		mlx5e_rqt_destroy(&res->channels[ix].direct_rqt);
290*43ec0f41SMaxim Mikityanskiy 
291*43ec0f41SMaxim Mikityanskiy out:
292*43ec0f41SMaxim Mikityanskiy 	mlx5e_tir_builder_free(builder);
293*43ec0f41SMaxim Mikityanskiy 
294*43ec0f41SMaxim Mikityanskiy 	return err;
295*43ec0f41SMaxim Mikityanskiy }
296*43ec0f41SMaxim Mikityanskiy 
297*43ec0f41SMaxim Mikityanskiy static int mlx5e_rx_res_ptp_init(struct mlx5e_rx_res *res)
298*43ec0f41SMaxim Mikityanskiy {
299*43ec0f41SMaxim Mikityanskiy 	bool inner_ft_support = res->features & MLX5E_RX_RES_FEATURE_INNER_FT;
300*43ec0f41SMaxim Mikityanskiy 	struct mlx5e_tir_builder *builder;
301*43ec0f41SMaxim Mikityanskiy 	int err;
302*43ec0f41SMaxim Mikityanskiy 
303*43ec0f41SMaxim Mikityanskiy 	builder = mlx5e_tir_builder_alloc(false);
304*43ec0f41SMaxim Mikityanskiy 	if (!builder)
305*43ec0f41SMaxim Mikityanskiy 		return -ENOMEM;
306*43ec0f41SMaxim Mikityanskiy 
307*43ec0f41SMaxim Mikityanskiy 	err = mlx5e_rqt_init_direct(&res->ptp.rqt, res->mdev, false, res->drop_rqn);
308*43ec0f41SMaxim Mikityanskiy 	if (err)
309*43ec0f41SMaxim Mikityanskiy 		goto out;
310*43ec0f41SMaxim Mikityanskiy 
311*43ec0f41SMaxim Mikityanskiy 	mlx5e_tir_builder_build_rqt(builder, res->mdev->mlx5e_res.hw_objs.td.tdn,
312*43ec0f41SMaxim Mikityanskiy 				    mlx5e_rqt_get_rqtn(&res->ptp.rqt),
313*43ec0f41SMaxim Mikityanskiy 				    inner_ft_support);
314*43ec0f41SMaxim Mikityanskiy 	mlx5e_tir_builder_build_direct(builder);
315*43ec0f41SMaxim Mikityanskiy 
316*43ec0f41SMaxim Mikityanskiy 	err = mlx5e_tir_init(&res->ptp.tir, builder, res->mdev, true);
317*43ec0f41SMaxim Mikityanskiy 	if (err)
318*43ec0f41SMaxim Mikityanskiy 		goto err_destroy_ptp_rqt;
319*43ec0f41SMaxim Mikityanskiy 
320*43ec0f41SMaxim Mikityanskiy 	goto out;
321*43ec0f41SMaxim Mikityanskiy 
322*43ec0f41SMaxim Mikityanskiy err_destroy_ptp_rqt:
323*43ec0f41SMaxim Mikityanskiy 	mlx5e_rqt_destroy(&res->ptp.rqt);
324*43ec0f41SMaxim Mikityanskiy 
325*43ec0f41SMaxim Mikityanskiy out:
326*43ec0f41SMaxim Mikityanskiy 	mlx5e_tir_builder_free(builder);
327*43ec0f41SMaxim Mikityanskiy 	return err;
328*43ec0f41SMaxim Mikityanskiy }
329*43ec0f41SMaxim Mikityanskiy 
330*43ec0f41SMaxim Mikityanskiy static void mlx5e_rx_res_rss_destroy(struct mlx5e_rx_res *res)
331*43ec0f41SMaxim Mikityanskiy {
332*43ec0f41SMaxim Mikityanskiy 	enum mlx5e_traffic_types tt;
333*43ec0f41SMaxim Mikityanskiy 
334*43ec0f41SMaxim Mikityanskiy 	for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++)
335*43ec0f41SMaxim Mikityanskiy 		mlx5e_tir_destroy(&res->rss[tt].indir_tir);
336*43ec0f41SMaxim Mikityanskiy 
337*43ec0f41SMaxim Mikityanskiy 	if (res->features & MLX5E_RX_RES_FEATURE_INNER_FT)
338*43ec0f41SMaxim Mikityanskiy 		for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++)
339*43ec0f41SMaxim Mikityanskiy 			mlx5e_tir_destroy(&res->rss[tt].inner_indir_tir);
340*43ec0f41SMaxim Mikityanskiy 
341*43ec0f41SMaxim Mikityanskiy 	mlx5e_rqt_destroy(&res->indir_rqt);
342*43ec0f41SMaxim Mikityanskiy }
343*43ec0f41SMaxim Mikityanskiy 
344*43ec0f41SMaxim Mikityanskiy static void mlx5e_rx_res_channels_destroy(struct mlx5e_rx_res *res)
345*43ec0f41SMaxim Mikityanskiy {
346*43ec0f41SMaxim Mikityanskiy 	unsigned int ix;
347*43ec0f41SMaxim Mikityanskiy 
348*43ec0f41SMaxim Mikityanskiy 	for (ix = 0; ix < res->max_nch; ix++) {
349*43ec0f41SMaxim Mikityanskiy 		mlx5e_tir_destroy(&res->channels[ix].direct_tir);
350*43ec0f41SMaxim Mikityanskiy 		mlx5e_rqt_destroy(&res->channels[ix].direct_rqt);
351*43ec0f41SMaxim Mikityanskiy 
352*43ec0f41SMaxim Mikityanskiy 		if (!(res->features & MLX5E_RX_RES_FEATURE_XSK))
353*43ec0f41SMaxim Mikityanskiy 			continue;
354*43ec0f41SMaxim Mikityanskiy 
355*43ec0f41SMaxim Mikityanskiy 		mlx5e_tir_destroy(&res->channels[ix].xsk_tir);
356*43ec0f41SMaxim Mikityanskiy 		mlx5e_rqt_destroy(&res->channels[ix].xsk_rqt);
357*43ec0f41SMaxim Mikityanskiy 	}
358*43ec0f41SMaxim Mikityanskiy }
359*43ec0f41SMaxim Mikityanskiy 
360*43ec0f41SMaxim Mikityanskiy static void mlx5e_rx_res_ptp_destroy(struct mlx5e_rx_res *res)
361*43ec0f41SMaxim Mikityanskiy {
362*43ec0f41SMaxim Mikityanskiy 	mlx5e_tir_destroy(&res->ptp.tir);
363*43ec0f41SMaxim Mikityanskiy 	mlx5e_rqt_destroy(&res->ptp.rqt);
364*43ec0f41SMaxim Mikityanskiy }
365*43ec0f41SMaxim Mikityanskiy 
366*43ec0f41SMaxim Mikityanskiy int mlx5e_rx_res_init(struct mlx5e_rx_res *res, struct mlx5_core_dev *mdev,
367*43ec0f41SMaxim Mikityanskiy 		      enum mlx5e_rx_res_features features, unsigned int max_nch,
368*43ec0f41SMaxim Mikityanskiy 		      u32 drop_rqn, const struct mlx5e_lro_param *init_lro_param,
369*43ec0f41SMaxim Mikityanskiy 		      unsigned int init_nch)
370*43ec0f41SMaxim Mikityanskiy {
371*43ec0f41SMaxim Mikityanskiy 	int err;
372*43ec0f41SMaxim Mikityanskiy 
373*43ec0f41SMaxim Mikityanskiy 	res->mdev = mdev;
374*43ec0f41SMaxim Mikityanskiy 	res->features = features;
375*43ec0f41SMaxim Mikityanskiy 	res->max_nch = max_nch;
376*43ec0f41SMaxim Mikityanskiy 	res->drop_rqn = drop_rqn;
377*43ec0f41SMaxim Mikityanskiy 
378*43ec0f41SMaxim Mikityanskiy 	mlx5e_rx_res_rss_params_init(res, init_nch);
379*43ec0f41SMaxim Mikityanskiy 
380*43ec0f41SMaxim Mikityanskiy 	err = mlx5e_rx_res_rss_init(res, init_lro_param);
381*43ec0f41SMaxim Mikityanskiy 	if (err)
382*43ec0f41SMaxim Mikityanskiy 		return err;
383*43ec0f41SMaxim Mikityanskiy 
384*43ec0f41SMaxim Mikityanskiy 	err = mlx5e_rx_res_channels_init(res, init_lro_param);
385*43ec0f41SMaxim Mikityanskiy 	if (err)
386*43ec0f41SMaxim Mikityanskiy 		goto err_rss_destroy;
387*43ec0f41SMaxim Mikityanskiy 
388*43ec0f41SMaxim Mikityanskiy 	err = mlx5e_rx_res_ptp_init(res);
389*43ec0f41SMaxim Mikityanskiy 	if (err)
390*43ec0f41SMaxim Mikityanskiy 		goto err_channels_destroy;
391*43ec0f41SMaxim Mikityanskiy 
392*43ec0f41SMaxim Mikityanskiy 	return 0;
393*43ec0f41SMaxim Mikityanskiy 
394*43ec0f41SMaxim Mikityanskiy err_channels_destroy:
395*43ec0f41SMaxim Mikityanskiy 	mlx5e_rx_res_channels_destroy(res);
396*43ec0f41SMaxim Mikityanskiy err_rss_destroy:
397*43ec0f41SMaxim Mikityanskiy 	mlx5e_rx_res_rss_destroy(res);
398*43ec0f41SMaxim Mikityanskiy 	return err;
399*43ec0f41SMaxim Mikityanskiy }
400*43ec0f41SMaxim Mikityanskiy 
401*43ec0f41SMaxim Mikityanskiy void mlx5e_rx_res_destroy(struct mlx5e_rx_res *res)
402*43ec0f41SMaxim Mikityanskiy {
403*43ec0f41SMaxim Mikityanskiy 	mlx5e_rx_res_ptp_destroy(res);
404*43ec0f41SMaxim Mikityanskiy 	mlx5e_rx_res_channels_destroy(res);
405*43ec0f41SMaxim Mikityanskiy 	mlx5e_rx_res_rss_destroy(res);
406*43ec0f41SMaxim Mikityanskiy }
407*43ec0f41SMaxim Mikityanskiy 
408*43ec0f41SMaxim Mikityanskiy void mlx5e_rx_res_free(struct mlx5e_rx_res *res)
409*43ec0f41SMaxim Mikityanskiy {
410*43ec0f41SMaxim Mikityanskiy 	kvfree(res);
411*43ec0f41SMaxim Mikityanskiy }
412*43ec0f41SMaxim Mikityanskiy 
413*43ec0f41SMaxim Mikityanskiy u32 mlx5e_rx_res_get_tirn_direct(struct mlx5e_rx_res *res, unsigned int ix)
414*43ec0f41SMaxim Mikityanskiy {
415*43ec0f41SMaxim Mikityanskiy 	return mlx5e_tir_get_tirn(&res->channels[ix].direct_tir);
416*43ec0f41SMaxim Mikityanskiy }
417*43ec0f41SMaxim Mikityanskiy 
418*43ec0f41SMaxim Mikityanskiy u32 mlx5e_rx_res_get_tirn_xsk(struct mlx5e_rx_res *res, unsigned int ix)
419*43ec0f41SMaxim Mikityanskiy {
420*43ec0f41SMaxim Mikityanskiy 	WARN_ON(!(res->features & MLX5E_RX_RES_FEATURE_XSK));
421*43ec0f41SMaxim Mikityanskiy 
422*43ec0f41SMaxim Mikityanskiy 	return mlx5e_tir_get_tirn(&res->channels[ix].xsk_tir);
423*43ec0f41SMaxim Mikityanskiy }
424*43ec0f41SMaxim Mikityanskiy 
425*43ec0f41SMaxim Mikityanskiy u32 mlx5e_rx_res_get_tirn_rss(struct mlx5e_rx_res *res, enum mlx5e_traffic_types tt)
426*43ec0f41SMaxim Mikityanskiy {
427*43ec0f41SMaxim Mikityanskiy 	return mlx5e_tir_get_tirn(&res->rss[tt].indir_tir);
428*43ec0f41SMaxim Mikityanskiy }
429*43ec0f41SMaxim Mikityanskiy 
430*43ec0f41SMaxim Mikityanskiy u32 mlx5e_rx_res_get_tirn_rss_inner(struct mlx5e_rx_res *res, enum mlx5e_traffic_types tt)
431*43ec0f41SMaxim Mikityanskiy {
432*43ec0f41SMaxim Mikityanskiy 	WARN_ON(!(res->features & MLX5E_RX_RES_FEATURE_INNER_FT));
433*43ec0f41SMaxim Mikityanskiy 	return mlx5e_tir_get_tirn(&res->rss[tt].inner_indir_tir);
434*43ec0f41SMaxim Mikityanskiy }
435*43ec0f41SMaxim Mikityanskiy 
436*43ec0f41SMaxim Mikityanskiy u32 mlx5e_rx_res_get_tirn_ptp(struct mlx5e_rx_res *res)
437*43ec0f41SMaxim Mikityanskiy {
438*43ec0f41SMaxim Mikityanskiy 	WARN_ON(!(res->features & MLX5E_RX_RES_FEATURE_PTP));
439*43ec0f41SMaxim Mikityanskiy 	return mlx5e_tir_get_tirn(&res->ptp.tir);
440*43ec0f41SMaxim Mikityanskiy }
441*43ec0f41SMaxim Mikityanskiy 
442*43ec0f41SMaxim Mikityanskiy u32 mlx5e_rx_res_get_rqtn_direct(struct mlx5e_rx_res *res, unsigned int ix)
443*43ec0f41SMaxim Mikityanskiy {
444*43ec0f41SMaxim Mikityanskiy 	return mlx5e_rqt_get_rqtn(&res->channels[ix].direct_rqt);
445*43ec0f41SMaxim Mikityanskiy }
446*43ec0f41SMaxim Mikityanskiy 
447*43ec0f41SMaxim Mikityanskiy static void mlx5e_rx_res_rss_enable(struct mlx5e_rx_res *res)
448*43ec0f41SMaxim Mikityanskiy {
449*43ec0f41SMaxim Mikityanskiy 	int err;
450*43ec0f41SMaxim Mikityanskiy 
451*43ec0f41SMaxim Mikityanskiy 	res->rss_active = true;
452*43ec0f41SMaxim Mikityanskiy 
453*43ec0f41SMaxim Mikityanskiy 	err = mlx5e_rqt_redirect_indir(&res->indir_rqt, res->rss_rqns, res->rss_nch,
454*43ec0f41SMaxim Mikityanskiy 				       res->rss_params.hash.hfunc,
455*43ec0f41SMaxim Mikityanskiy 				       &res->rss_params.indir);
456*43ec0f41SMaxim Mikityanskiy 	if (err)
457*43ec0f41SMaxim Mikityanskiy 		mlx5_core_warn(res->mdev, "Failed to redirect indirect RQT %#x to channels: err = %d\n",
458*43ec0f41SMaxim Mikityanskiy 			       mlx5e_rqt_get_rqtn(&res->indir_rqt), err);
459*43ec0f41SMaxim Mikityanskiy }
460*43ec0f41SMaxim Mikityanskiy 
461*43ec0f41SMaxim Mikityanskiy static void mlx5e_rx_res_rss_disable(struct mlx5e_rx_res *res)
462*43ec0f41SMaxim Mikityanskiy {
463*43ec0f41SMaxim Mikityanskiy 	int err;
464*43ec0f41SMaxim Mikityanskiy 
465*43ec0f41SMaxim Mikityanskiy 	res->rss_active = false;
466*43ec0f41SMaxim Mikityanskiy 
467*43ec0f41SMaxim Mikityanskiy 	err = mlx5e_rqt_redirect_direct(&res->indir_rqt, res->drop_rqn);
468*43ec0f41SMaxim Mikityanskiy 	if (err)
469*43ec0f41SMaxim Mikityanskiy 		mlx5_core_warn(res->mdev, "Failed to redirect indirect RQT %#x to drop RQ %#x: err = %d\n",
470*43ec0f41SMaxim Mikityanskiy 			       mlx5e_rqt_get_rqtn(&res->indir_rqt), res->drop_rqn, err);
471*43ec0f41SMaxim Mikityanskiy }
472*43ec0f41SMaxim Mikityanskiy 
473*43ec0f41SMaxim Mikityanskiy void mlx5e_rx_res_channels_activate(struct mlx5e_rx_res *res, struct mlx5e_channels *chs)
474*43ec0f41SMaxim Mikityanskiy {
475*43ec0f41SMaxim Mikityanskiy 	unsigned int nch, ix;
476*43ec0f41SMaxim Mikityanskiy 	int err;
477*43ec0f41SMaxim Mikityanskiy 
478*43ec0f41SMaxim Mikityanskiy 	nch = mlx5e_channels_get_num(chs);
479*43ec0f41SMaxim Mikityanskiy 
480*43ec0f41SMaxim Mikityanskiy 	for (ix = 0; ix < chs->num; ix++)
481*43ec0f41SMaxim Mikityanskiy 		mlx5e_channels_get_regular_rqn(chs, ix, &res->rss_rqns[ix]);
482*43ec0f41SMaxim Mikityanskiy 	res->rss_nch = chs->num;
483*43ec0f41SMaxim Mikityanskiy 
484*43ec0f41SMaxim Mikityanskiy 	mlx5e_rx_res_rss_enable(res);
485*43ec0f41SMaxim Mikityanskiy 
486*43ec0f41SMaxim Mikityanskiy 	for (ix = 0; ix < nch; ix++) {
487*43ec0f41SMaxim Mikityanskiy 		u32 rqn;
488*43ec0f41SMaxim Mikityanskiy 
489*43ec0f41SMaxim Mikityanskiy 		mlx5e_channels_get_regular_rqn(chs, ix, &rqn);
490*43ec0f41SMaxim Mikityanskiy 		err = mlx5e_rqt_redirect_direct(&res->channels[ix].direct_rqt, rqn);
491*43ec0f41SMaxim Mikityanskiy 		if (err)
492*43ec0f41SMaxim Mikityanskiy 			mlx5_core_warn(res->mdev, "Failed to redirect direct RQT %#x to RQ %#x (channel %u): err = %d\n",
493*43ec0f41SMaxim Mikityanskiy 				       mlx5e_rqt_get_rqtn(&res->channels[ix].direct_rqt),
494*43ec0f41SMaxim Mikityanskiy 				       rqn, ix, err);
495*43ec0f41SMaxim Mikityanskiy 
496*43ec0f41SMaxim Mikityanskiy 		if (!(res->features & MLX5E_RX_RES_FEATURE_XSK))
497*43ec0f41SMaxim Mikityanskiy 			continue;
498*43ec0f41SMaxim Mikityanskiy 
499*43ec0f41SMaxim Mikityanskiy 		if (!mlx5e_channels_get_xsk_rqn(chs, ix, &rqn))
500*43ec0f41SMaxim Mikityanskiy 			rqn = res->drop_rqn;
501*43ec0f41SMaxim Mikityanskiy 		err = mlx5e_rqt_redirect_direct(&res->channels[ix].xsk_rqt, rqn);
502*43ec0f41SMaxim Mikityanskiy 		if (err)
503*43ec0f41SMaxim Mikityanskiy 			mlx5_core_warn(res->mdev, "Failed to redirect XSK RQT %#x to RQ %#x (channel %u): err = %d\n",
504*43ec0f41SMaxim Mikityanskiy 				       mlx5e_rqt_get_rqtn(&res->channels[ix].xsk_rqt),
505*43ec0f41SMaxim Mikityanskiy 				       rqn, ix, err);
506*43ec0f41SMaxim Mikityanskiy 	}
507*43ec0f41SMaxim Mikityanskiy 	for (ix = nch; ix < res->max_nch; ix++) {
508*43ec0f41SMaxim Mikityanskiy 		err = mlx5e_rqt_redirect_direct(&res->channels[ix].direct_rqt, res->drop_rqn);
509*43ec0f41SMaxim Mikityanskiy 		if (err)
510*43ec0f41SMaxim Mikityanskiy 			mlx5_core_warn(res->mdev, "Failed to redirect direct RQT %#x to drop RQ %#x (channel %u): err = %d\n",
511*43ec0f41SMaxim Mikityanskiy 				       mlx5e_rqt_get_rqtn(&res->channels[ix].direct_rqt),
512*43ec0f41SMaxim Mikityanskiy 				       res->drop_rqn, ix, err);
513*43ec0f41SMaxim Mikityanskiy 
514*43ec0f41SMaxim Mikityanskiy 		if (!(res->features & MLX5E_RX_RES_FEATURE_XSK))
515*43ec0f41SMaxim Mikityanskiy 			continue;
516*43ec0f41SMaxim Mikityanskiy 
517*43ec0f41SMaxim Mikityanskiy 		err = mlx5e_rqt_redirect_direct(&res->channels[ix].xsk_rqt, res->drop_rqn);
518*43ec0f41SMaxim Mikityanskiy 		if (err)
519*43ec0f41SMaxim Mikityanskiy 			mlx5_core_warn(res->mdev, "Failed to redirect XSK RQT %#x to drop RQ %#x (channel %u): err = %d\n",
520*43ec0f41SMaxim Mikityanskiy 				       mlx5e_rqt_get_rqtn(&res->channels[ix].xsk_rqt),
521*43ec0f41SMaxim Mikityanskiy 				       res->drop_rqn, ix, err);
522*43ec0f41SMaxim Mikityanskiy 	}
523*43ec0f41SMaxim Mikityanskiy 
524*43ec0f41SMaxim Mikityanskiy 	if (res->features & MLX5E_RX_RES_FEATURE_PTP) {
525*43ec0f41SMaxim Mikityanskiy 		u32 rqn;
526*43ec0f41SMaxim Mikityanskiy 
527*43ec0f41SMaxim Mikityanskiy 		if (mlx5e_channels_get_ptp_rqn(chs, &rqn))
528*43ec0f41SMaxim Mikityanskiy 			rqn = res->drop_rqn;
529*43ec0f41SMaxim Mikityanskiy 
530*43ec0f41SMaxim Mikityanskiy 		err = mlx5e_rqt_redirect_direct(&res->ptp.rqt, rqn);
531*43ec0f41SMaxim Mikityanskiy 		if (err)
532*43ec0f41SMaxim Mikityanskiy 			mlx5_core_warn(res->mdev, "Failed to redirect direct RQT %#x to RQ %#x (PTP): err = %d\n",
533*43ec0f41SMaxim Mikityanskiy 				       mlx5e_rqt_get_rqtn(&res->ptp.rqt),
534*43ec0f41SMaxim Mikityanskiy 				       rqn, err);
535*43ec0f41SMaxim Mikityanskiy 	}
536*43ec0f41SMaxim Mikityanskiy }
537*43ec0f41SMaxim Mikityanskiy 
538*43ec0f41SMaxim Mikityanskiy void mlx5e_rx_res_channels_deactivate(struct mlx5e_rx_res *res)
539*43ec0f41SMaxim Mikityanskiy {
540*43ec0f41SMaxim Mikityanskiy 	unsigned int ix;
541*43ec0f41SMaxim Mikityanskiy 	int err;
542*43ec0f41SMaxim Mikityanskiy 
543*43ec0f41SMaxim Mikityanskiy 	mlx5e_rx_res_rss_disable(res);
544*43ec0f41SMaxim Mikityanskiy 
545*43ec0f41SMaxim Mikityanskiy 	for (ix = 0; ix < res->max_nch; ix++) {
546*43ec0f41SMaxim Mikityanskiy 		err = mlx5e_rqt_redirect_direct(&res->channels[ix].direct_rqt, res->drop_rqn);
547*43ec0f41SMaxim Mikityanskiy 		if (err)
548*43ec0f41SMaxim Mikityanskiy 			mlx5_core_warn(res->mdev, "Failed to redirect direct RQT %#x to drop RQ %#x (channel %u): err = %d\n",
549*43ec0f41SMaxim Mikityanskiy 				       mlx5e_rqt_get_rqtn(&res->channels[ix].direct_rqt),
550*43ec0f41SMaxim Mikityanskiy 				       res->drop_rqn, ix, err);
551*43ec0f41SMaxim Mikityanskiy 
552*43ec0f41SMaxim Mikityanskiy 		if (!(res->features & MLX5E_RX_RES_FEATURE_XSK))
553*43ec0f41SMaxim Mikityanskiy 			continue;
554*43ec0f41SMaxim Mikityanskiy 
555*43ec0f41SMaxim Mikityanskiy 		err = mlx5e_rqt_redirect_direct(&res->channels[ix].xsk_rqt, res->drop_rqn);
556*43ec0f41SMaxim Mikityanskiy 		if (err)
557*43ec0f41SMaxim Mikityanskiy 			mlx5_core_warn(res->mdev, "Failed to redirect XSK RQT %#x to drop RQ %#x (channel %u): err = %d\n",
558*43ec0f41SMaxim Mikityanskiy 				       mlx5e_rqt_get_rqtn(&res->channels[ix].xsk_rqt),
559*43ec0f41SMaxim Mikityanskiy 				       res->drop_rqn, ix, err);
560*43ec0f41SMaxim Mikityanskiy 	}
561*43ec0f41SMaxim Mikityanskiy 
562*43ec0f41SMaxim Mikityanskiy 	if (res->features & MLX5E_RX_RES_FEATURE_PTP) {
563*43ec0f41SMaxim Mikityanskiy 		err = mlx5e_rqt_redirect_direct(&res->ptp.rqt, res->drop_rqn);
564*43ec0f41SMaxim Mikityanskiy 		if (err)
565*43ec0f41SMaxim Mikityanskiy 			mlx5_core_warn(res->mdev, "Failed to redirect direct RQT %#x to drop RQ %#x (PTP): err = %d\n",
566*43ec0f41SMaxim Mikityanskiy 				       mlx5e_rqt_get_rqtn(&res->ptp.rqt),
567*43ec0f41SMaxim Mikityanskiy 				       res->drop_rqn, err);
568*43ec0f41SMaxim Mikityanskiy 	}
569*43ec0f41SMaxim Mikityanskiy }
570*43ec0f41SMaxim Mikityanskiy 
571*43ec0f41SMaxim Mikityanskiy int mlx5e_rx_res_xsk_activate(struct mlx5e_rx_res *res, struct mlx5e_channels *chs,
572*43ec0f41SMaxim Mikityanskiy 			      unsigned int ix)
573*43ec0f41SMaxim Mikityanskiy {
574*43ec0f41SMaxim Mikityanskiy 	u32 rqn;
575*43ec0f41SMaxim Mikityanskiy 	int err;
576*43ec0f41SMaxim Mikityanskiy 
577*43ec0f41SMaxim Mikityanskiy 	if (!mlx5e_channels_get_xsk_rqn(chs, ix, &rqn))
578*43ec0f41SMaxim Mikityanskiy 		return -EINVAL;
579*43ec0f41SMaxim Mikityanskiy 
580*43ec0f41SMaxim Mikityanskiy 	err = mlx5e_rqt_redirect_direct(&res->channels[ix].xsk_rqt, rqn);
581*43ec0f41SMaxim Mikityanskiy 	if (err)
582*43ec0f41SMaxim Mikityanskiy 		mlx5_core_warn(res->mdev, "Failed to redirect XSK RQT %#x to XSK RQ %#x (channel %u): err = %d\n",
583*43ec0f41SMaxim Mikityanskiy 			       mlx5e_rqt_get_rqtn(&res->channels[ix].xsk_rqt),
584*43ec0f41SMaxim Mikityanskiy 			       rqn, ix, err);
585*43ec0f41SMaxim Mikityanskiy 	return err;
586*43ec0f41SMaxim Mikityanskiy }
587*43ec0f41SMaxim Mikityanskiy 
588*43ec0f41SMaxim Mikityanskiy int mlx5e_rx_res_xsk_deactivate(struct mlx5e_rx_res *res, unsigned int ix)
589*43ec0f41SMaxim Mikityanskiy {
590*43ec0f41SMaxim Mikityanskiy 	int err;
591*43ec0f41SMaxim Mikityanskiy 
592*43ec0f41SMaxim Mikityanskiy 	err = mlx5e_rqt_redirect_direct(&res->channels[ix].xsk_rqt, res->drop_rqn);
593*43ec0f41SMaxim Mikityanskiy 	if (err)
594*43ec0f41SMaxim Mikityanskiy 		mlx5_core_warn(res->mdev, "Failed to redirect XSK RQT %#x to drop RQ %#x (channel %u): err = %d\n",
595*43ec0f41SMaxim Mikityanskiy 			       mlx5e_rqt_get_rqtn(&res->channels[ix].xsk_rqt),
596*43ec0f41SMaxim Mikityanskiy 			       res->drop_rqn, ix, err);
597*43ec0f41SMaxim Mikityanskiy 	return err;
598*43ec0f41SMaxim Mikityanskiy }
599*43ec0f41SMaxim Mikityanskiy 
60065d6b6e5SMaxim Mikityanskiy struct mlx5e_rss_params_traffic_type
60165d6b6e5SMaxim Mikityanskiy mlx5e_rx_res_rss_get_current_tt_config(struct mlx5e_rx_res *res, enum mlx5e_traffic_types tt)
60265d6b6e5SMaxim Mikityanskiy {
60365d6b6e5SMaxim Mikityanskiy 	struct mlx5e_rss_params_traffic_type rss_tt;
60465d6b6e5SMaxim Mikityanskiy 
60565d6b6e5SMaxim Mikityanskiy 	rss_tt = mlx5e_rss_get_default_tt_config(tt);
60665d6b6e5SMaxim Mikityanskiy 	rss_tt.rx_hash_fields = res->rss_params.rx_hash_fields[tt];
60765d6b6e5SMaxim Mikityanskiy 	return rss_tt;
60865d6b6e5SMaxim Mikityanskiy }
609*43ec0f41SMaxim Mikityanskiy 
610*43ec0f41SMaxim Mikityanskiy void mlx5e_rx_res_rss_set_indir_uniform(struct mlx5e_rx_res *res, unsigned int nch)
611*43ec0f41SMaxim Mikityanskiy {
612*43ec0f41SMaxim Mikityanskiy 	mlx5e_rss_params_indir_init_uniform(&res->rss_params.indir, nch);
613*43ec0f41SMaxim Mikityanskiy 
614*43ec0f41SMaxim Mikityanskiy 	if (!res->rss_active)
615*43ec0f41SMaxim Mikityanskiy 		return;
616*43ec0f41SMaxim Mikityanskiy 
617*43ec0f41SMaxim Mikityanskiy 	mlx5e_rx_res_rss_enable(res);
618*43ec0f41SMaxim Mikityanskiy }
619*43ec0f41SMaxim Mikityanskiy 
620*43ec0f41SMaxim Mikityanskiy void mlx5e_rx_res_rss_get_rxfh(struct mlx5e_rx_res *res, u32 *indir, u8 *key, u8 *hfunc)
621*43ec0f41SMaxim Mikityanskiy {
622*43ec0f41SMaxim Mikityanskiy 	unsigned int i;
623*43ec0f41SMaxim Mikityanskiy 
624*43ec0f41SMaxim Mikityanskiy 	if (indir)
625*43ec0f41SMaxim Mikityanskiy 		for (i = 0; i < MLX5E_INDIR_RQT_SIZE; i++)
626*43ec0f41SMaxim Mikityanskiy 			indir[i] = res->rss_params.indir.table[i];
627*43ec0f41SMaxim Mikityanskiy 
628*43ec0f41SMaxim Mikityanskiy 	if (key)
629*43ec0f41SMaxim Mikityanskiy 		memcpy(key, res->rss_params.hash.toeplitz_hash_key,
630*43ec0f41SMaxim Mikityanskiy 		       sizeof(res->rss_params.hash.toeplitz_hash_key));
631*43ec0f41SMaxim Mikityanskiy 
632*43ec0f41SMaxim Mikityanskiy 	if (hfunc)
633*43ec0f41SMaxim Mikityanskiy 		*hfunc = res->rss_params.hash.hfunc;
634*43ec0f41SMaxim Mikityanskiy }
635*43ec0f41SMaxim Mikityanskiy 
636*43ec0f41SMaxim Mikityanskiy static int mlx5e_rx_res_rss_update_tir(struct mlx5e_rx_res *res, enum mlx5e_traffic_types tt,
637*43ec0f41SMaxim Mikityanskiy 				       bool inner)
638*43ec0f41SMaxim Mikityanskiy {
639*43ec0f41SMaxim Mikityanskiy 	struct mlx5e_rss_params_traffic_type rss_tt;
640*43ec0f41SMaxim Mikityanskiy 	struct mlx5e_tir_builder *builder;
641*43ec0f41SMaxim Mikityanskiy 	struct mlx5e_tir *tir;
642*43ec0f41SMaxim Mikityanskiy 	int err;
643*43ec0f41SMaxim Mikityanskiy 
644*43ec0f41SMaxim Mikityanskiy 	builder = mlx5e_tir_builder_alloc(true);
645*43ec0f41SMaxim Mikityanskiy 	if (!builder)
646*43ec0f41SMaxim Mikityanskiy 		return -ENOMEM;
647*43ec0f41SMaxim Mikityanskiy 
648*43ec0f41SMaxim Mikityanskiy 	rss_tt = mlx5e_rx_res_rss_get_current_tt_config(res, tt);
649*43ec0f41SMaxim Mikityanskiy 
650*43ec0f41SMaxim Mikityanskiy 	mlx5e_tir_builder_build_rss(builder, &res->rss_params.hash, &rss_tt, inner);
651*43ec0f41SMaxim Mikityanskiy 	tir = inner ? &res->rss[tt].inner_indir_tir : &res->rss[tt].indir_tir;
652*43ec0f41SMaxim Mikityanskiy 	err = mlx5e_tir_modify(tir, builder);
653*43ec0f41SMaxim Mikityanskiy 
654*43ec0f41SMaxim Mikityanskiy 	mlx5e_tir_builder_free(builder);
655*43ec0f41SMaxim Mikityanskiy 	return err;
656*43ec0f41SMaxim Mikityanskiy }
657*43ec0f41SMaxim Mikityanskiy 
658*43ec0f41SMaxim Mikityanskiy int mlx5e_rx_res_rss_set_rxfh(struct mlx5e_rx_res *res, const u32 *indir,
659*43ec0f41SMaxim Mikityanskiy 			      const u8 *key, const u8 *hfunc)
660*43ec0f41SMaxim Mikityanskiy {
661*43ec0f41SMaxim Mikityanskiy 	enum mlx5e_traffic_types tt;
662*43ec0f41SMaxim Mikityanskiy 	bool changed_indir = false;
663*43ec0f41SMaxim Mikityanskiy 	bool changed_hash = false;
664*43ec0f41SMaxim Mikityanskiy 	int err;
665*43ec0f41SMaxim Mikityanskiy 
666*43ec0f41SMaxim Mikityanskiy 	if (hfunc && *hfunc != res->rss_params.hash.hfunc) {
667*43ec0f41SMaxim Mikityanskiy 		switch (*hfunc) {
668*43ec0f41SMaxim Mikityanskiy 		case ETH_RSS_HASH_XOR:
669*43ec0f41SMaxim Mikityanskiy 		case ETH_RSS_HASH_TOP:
670*43ec0f41SMaxim Mikityanskiy 			break;
671*43ec0f41SMaxim Mikityanskiy 		default:
672*43ec0f41SMaxim Mikityanskiy 			return -EINVAL;
673*43ec0f41SMaxim Mikityanskiy 		}
674*43ec0f41SMaxim Mikityanskiy 		changed_hash = true;
675*43ec0f41SMaxim Mikityanskiy 		changed_indir = true;
676*43ec0f41SMaxim Mikityanskiy 		res->rss_params.hash.hfunc = *hfunc;
677*43ec0f41SMaxim Mikityanskiy 	}
678*43ec0f41SMaxim Mikityanskiy 
679*43ec0f41SMaxim Mikityanskiy 	if (key) {
680*43ec0f41SMaxim Mikityanskiy 		if (res->rss_params.hash.hfunc == ETH_RSS_HASH_TOP)
681*43ec0f41SMaxim Mikityanskiy 			changed_hash = true;
682*43ec0f41SMaxim Mikityanskiy 		memcpy(res->rss_params.hash.toeplitz_hash_key, key,
683*43ec0f41SMaxim Mikityanskiy 		       sizeof(res->rss_params.hash.toeplitz_hash_key));
684*43ec0f41SMaxim Mikityanskiy 	}
685*43ec0f41SMaxim Mikityanskiy 
686*43ec0f41SMaxim Mikityanskiy 	if (indir) {
687*43ec0f41SMaxim Mikityanskiy 		unsigned int i;
688*43ec0f41SMaxim Mikityanskiy 
689*43ec0f41SMaxim Mikityanskiy 		changed_indir = true;
690*43ec0f41SMaxim Mikityanskiy 
691*43ec0f41SMaxim Mikityanskiy 		for (i = 0; i < MLX5E_INDIR_RQT_SIZE; i++)
692*43ec0f41SMaxim Mikityanskiy 			res->rss_params.indir.table[i] = indir[i];
693*43ec0f41SMaxim Mikityanskiy 	}
694*43ec0f41SMaxim Mikityanskiy 
695*43ec0f41SMaxim Mikityanskiy 	if (changed_indir && res->rss_active) {
696*43ec0f41SMaxim Mikityanskiy 		err = mlx5e_rqt_redirect_indir(&res->indir_rqt, res->rss_rqns, res->rss_nch,
697*43ec0f41SMaxim Mikityanskiy 					       res->rss_params.hash.hfunc,
698*43ec0f41SMaxim Mikityanskiy 					       &res->rss_params.indir);
699*43ec0f41SMaxim Mikityanskiy 		if (err)
700*43ec0f41SMaxim Mikityanskiy 			mlx5_core_warn(res->mdev, "Failed to redirect indirect RQT %#x to channels: err = %d\n",
701*43ec0f41SMaxim Mikityanskiy 				       mlx5e_rqt_get_rqtn(&res->indir_rqt), err);
702*43ec0f41SMaxim Mikityanskiy 	}
703*43ec0f41SMaxim Mikityanskiy 
704*43ec0f41SMaxim Mikityanskiy 	if (changed_hash)
705*43ec0f41SMaxim Mikityanskiy 		for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++) {
706*43ec0f41SMaxim Mikityanskiy 			err = mlx5e_rx_res_rss_update_tir(res, tt, false);
707*43ec0f41SMaxim Mikityanskiy 			if (err)
708*43ec0f41SMaxim Mikityanskiy 				mlx5_core_warn(res->mdev, "Failed to update RSS hash of indirect TIR for traffic type %d: err = %d\n",
709*43ec0f41SMaxim Mikityanskiy 					       tt, err);
710*43ec0f41SMaxim Mikityanskiy 
711*43ec0f41SMaxim Mikityanskiy 			if (!(res->features & MLX5E_RX_RES_FEATURE_INNER_FT))
712*43ec0f41SMaxim Mikityanskiy 				continue;
713*43ec0f41SMaxim Mikityanskiy 
714*43ec0f41SMaxim Mikityanskiy 			err = mlx5e_rx_res_rss_update_tir(res, tt, true);
715*43ec0f41SMaxim Mikityanskiy 			if (err)
716*43ec0f41SMaxim Mikityanskiy 				mlx5_core_warn(res->mdev, "Failed to update RSS hash of inner indirect TIR for traffic type %d: err = %d\n",
717*43ec0f41SMaxim Mikityanskiy 					       tt, err);
718*43ec0f41SMaxim Mikityanskiy 		}
719*43ec0f41SMaxim Mikityanskiy 
720*43ec0f41SMaxim Mikityanskiy 	return 0;
721*43ec0f41SMaxim Mikityanskiy }
722*43ec0f41SMaxim Mikityanskiy 
723*43ec0f41SMaxim Mikityanskiy u8 mlx5e_rx_res_rss_get_hash_fields(struct mlx5e_rx_res *res, enum mlx5e_traffic_types tt)
724*43ec0f41SMaxim Mikityanskiy {
725*43ec0f41SMaxim Mikityanskiy 	return res->rss_params.rx_hash_fields[tt];
726*43ec0f41SMaxim Mikityanskiy }
727*43ec0f41SMaxim Mikityanskiy 
728*43ec0f41SMaxim Mikityanskiy int mlx5e_rx_res_rss_set_hash_fields(struct mlx5e_rx_res *res, enum mlx5e_traffic_types tt,
729*43ec0f41SMaxim Mikityanskiy 				     u8 rx_hash_fields)
730*43ec0f41SMaxim Mikityanskiy {
731*43ec0f41SMaxim Mikityanskiy 	u8 old_rx_hash_fields;
732*43ec0f41SMaxim Mikityanskiy 	int err;
733*43ec0f41SMaxim Mikityanskiy 
734*43ec0f41SMaxim Mikityanskiy 	old_rx_hash_fields = res->rss_params.rx_hash_fields[tt];
735*43ec0f41SMaxim Mikityanskiy 
736*43ec0f41SMaxim Mikityanskiy 	if (old_rx_hash_fields == rx_hash_fields)
737*43ec0f41SMaxim Mikityanskiy 		return 0;
738*43ec0f41SMaxim Mikityanskiy 
739*43ec0f41SMaxim Mikityanskiy 	res->rss_params.rx_hash_fields[tt] = rx_hash_fields;
740*43ec0f41SMaxim Mikityanskiy 
741*43ec0f41SMaxim Mikityanskiy 	err = mlx5e_rx_res_rss_update_tir(res, tt, false);
742*43ec0f41SMaxim Mikityanskiy 	if (err) {
743*43ec0f41SMaxim Mikityanskiy 		res->rss_params.rx_hash_fields[tt] = old_rx_hash_fields;
744*43ec0f41SMaxim Mikityanskiy 		mlx5_core_warn(res->mdev, "Failed to update RSS hash fields of indirect TIR for traffic type %d: err = %d\n",
745*43ec0f41SMaxim Mikityanskiy 			       tt, err);
746*43ec0f41SMaxim Mikityanskiy 		return err;
747*43ec0f41SMaxim Mikityanskiy 	}
748*43ec0f41SMaxim Mikityanskiy 
749*43ec0f41SMaxim Mikityanskiy 	if (!(res->features & MLX5E_RX_RES_FEATURE_INNER_FT))
750*43ec0f41SMaxim Mikityanskiy 		return 0;
751*43ec0f41SMaxim Mikityanskiy 
752*43ec0f41SMaxim Mikityanskiy 	err = mlx5e_rx_res_rss_update_tir(res, tt, true);
753*43ec0f41SMaxim Mikityanskiy 	if (err) {
754*43ec0f41SMaxim Mikityanskiy 		/* Partial update happened. Try to revert - it may fail too, but
755*43ec0f41SMaxim Mikityanskiy 		 * there is nothing more we can do.
756*43ec0f41SMaxim Mikityanskiy 		 */
757*43ec0f41SMaxim Mikityanskiy 		res->rss_params.rx_hash_fields[tt] = old_rx_hash_fields;
758*43ec0f41SMaxim Mikityanskiy 		mlx5_core_warn(res->mdev, "Failed to update RSS hash fields of inner indirect TIR for traffic type %d: err = %d\n",
759*43ec0f41SMaxim Mikityanskiy 			       tt, err);
760*43ec0f41SMaxim Mikityanskiy 		if (mlx5e_rx_res_rss_update_tir(res, tt, false))
761*43ec0f41SMaxim Mikityanskiy 			mlx5_core_warn(res->mdev, "Partial update of RSS hash fields happened: failed to revert indirect TIR for traffic type %d to the old values\n",
762*43ec0f41SMaxim Mikityanskiy 				       tt);
763*43ec0f41SMaxim Mikityanskiy 	}
764*43ec0f41SMaxim Mikityanskiy 
765*43ec0f41SMaxim Mikityanskiy 	return err;
766*43ec0f41SMaxim Mikityanskiy }
767*43ec0f41SMaxim Mikityanskiy 
768*43ec0f41SMaxim Mikityanskiy int mlx5e_rx_res_lro_set_param(struct mlx5e_rx_res *res, struct mlx5e_lro_param *lro_param)
769*43ec0f41SMaxim Mikityanskiy {
770*43ec0f41SMaxim Mikityanskiy 	struct mlx5e_tir_builder *builder;
771*43ec0f41SMaxim Mikityanskiy 	enum mlx5e_traffic_types tt;
772*43ec0f41SMaxim Mikityanskiy 	int err, final_err;
773*43ec0f41SMaxim Mikityanskiy 	unsigned int ix;
774*43ec0f41SMaxim Mikityanskiy 
775*43ec0f41SMaxim Mikityanskiy 	builder = mlx5e_tir_builder_alloc(true);
776*43ec0f41SMaxim Mikityanskiy 	if (!builder)
777*43ec0f41SMaxim Mikityanskiy 		return -ENOMEM;
778*43ec0f41SMaxim Mikityanskiy 
779*43ec0f41SMaxim Mikityanskiy 	mlx5e_tir_builder_build_lro(builder, lro_param);
780*43ec0f41SMaxim Mikityanskiy 
781*43ec0f41SMaxim Mikityanskiy 	final_err = 0;
782*43ec0f41SMaxim Mikityanskiy 
783*43ec0f41SMaxim Mikityanskiy 	for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++) {
784*43ec0f41SMaxim Mikityanskiy 		err = mlx5e_tir_modify(&res->rss[tt].indir_tir, builder);
785*43ec0f41SMaxim Mikityanskiy 		if (err) {
786*43ec0f41SMaxim Mikityanskiy 			mlx5_core_warn(res->mdev, "Failed to update LRO state of indirect TIR %#x for traffic type %d: err = %d\n",
787*43ec0f41SMaxim Mikityanskiy 				       mlx5e_tir_get_tirn(&res->rss[tt].indir_tir), tt, err);
788*43ec0f41SMaxim Mikityanskiy 			if (!final_err)
789*43ec0f41SMaxim Mikityanskiy 				final_err = err;
790*43ec0f41SMaxim Mikityanskiy 		}
791*43ec0f41SMaxim Mikityanskiy 
792*43ec0f41SMaxim Mikityanskiy 		if (!(res->features & MLX5E_RX_RES_FEATURE_INNER_FT))
793*43ec0f41SMaxim Mikityanskiy 			continue;
794*43ec0f41SMaxim Mikityanskiy 
795*43ec0f41SMaxim Mikityanskiy 		err = mlx5e_tir_modify(&res->rss[tt].inner_indir_tir, builder);
796*43ec0f41SMaxim Mikityanskiy 		if (err) {
797*43ec0f41SMaxim Mikityanskiy 			mlx5_core_warn(res->mdev, "Failed to update LRO state of inner indirect TIR %#x for traffic type %d: err = %d\n",
798*43ec0f41SMaxim Mikityanskiy 				       mlx5e_tir_get_tirn(&res->rss[tt].inner_indir_tir), tt, err);
799*43ec0f41SMaxim Mikityanskiy 			if (!final_err)
800*43ec0f41SMaxim Mikityanskiy 				final_err = err;
801*43ec0f41SMaxim Mikityanskiy 		}
802*43ec0f41SMaxim Mikityanskiy 	}
803*43ec0f41SMaxim Mikityanskiy 
804*43ec0f41SMaxim Mikityanskiy 	for (ix = 0; ix < res->max_nch; ix++) {
805*43ec0f41SMaxim Mikityanskiy 		err = mlx5e_tir_modify(&res->channels[ix].direct_tir, builder);
806*43ec0f41SMaxim Mikityanskiy 		if (err) {
807*43ec0f41SMaxim Mikityanskiy 			mlx5_core_warn(res->mdev, "Failed to update LRO state of direct TIR %#x for channel %u: err = %d\n",
808*43ec0f41SMaxim Mikityanskiy 				       mlx5e_tir_get_tirn(&res->channels[ix].direct_tir), ix, err);
809*43ec0f41SMaxim Mikityanskiy 			if (!final_err)
810*43ec0f41SMaxim Mikityanskiy 				final_err = err;
811*43ec0f41SMaxim Mikityanskiy 		}
812*43ec0f41SMaxim Mikityanskiy 	}
813*43ec0f41SMaxim Mikityanskiy 
814*43ec0f41SMaxim Mikityanskiy 	mlx5e_tir_builder_free(builder);
815*43ec0f41SMaxim Mikityanskiy 	return final_err;
816*43ec0f41SMaxim Mikityanskiy }
817*43ec0f41SMaxim Mikityanskiy 
818*43ec0f41SMaxim Mikityanskiy struct mlx5e_rss_params_hash mlx5e_rx_res_get_current_hash(struct mlx5e_rx_res *res)
819*43ec0f41SMaxim Mikityanskiy {
820*43ec0f41SMaxim Mikityanskiy 	return res->rss_params.hash;
821*43ec0f41SMaxim Mikityanskiy }
822