1 /*
2  * Copyright (c) 2016, Mellanox Technologies. All rights reserved.
3  *
4  * This software is available to you under a choice of one of two
5  * licenses.  You may choose to be licensed under the terms of the GNU
6  * General Public License (GPL) Version 2, available from the file
7  * COPYING in the main directory of this source tree, or the
8  * OpenIB.org BSD license below:
9  *
10  *     Redistribution and use in source and binary forms, with or
11  *     without modification, are permitted provided that the following
12  *     conditions are met:
13  *
14  *      - Redistributions of source code must retain the above
15  *        copyright notice, this list of conditions and the following
16  *        disclaimer.
17  *
18  *      - Redistributions in binary form must reproduce the above
19  *        copyright notice, this list of conditions and the following
20  *        disclaimer in the documentation and/or other materials
21  *        provided with the distribution.
22  *
23  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30  * SOFTWARE.
31  */
32 
33 #include <linux/etherdevice.h>
34 #include <linux/idr.h>
35 #include <linux/mlx5/driver.h>
36 #include <linux/mlx5/mlx5_ifc.h>
37 #include <linux/mlx5/vport.h>
38 #include <linux/mlx5/fs.h>
39 #include "mlx5_core.h"
40 #include "eswitch.h"
41 #include "esw/indir_table.h"
42 #include "esw/acl/ofld.h"
43 #include "rdma.h"
44 #include "en.h"
45 #include "fs_core.h"
46 #include "lib/devcom.h"
47 #include "lib/eq.h"
48 #include "lib/fs_chains.h"
49 #include "en_tc.h"
50 #include "en/mapping.h"
51 #include "devlink.h"
52 #include "lag/lag.h"
53 #include "en/tc/post_meter.h"
54 
55 #define mlx5_esw_for_each_rep(esw, i, rep) \
56 	xa_for_each(&((esw)->offloads.vport_reps), i, rep)
57 
58 #define mlx5_esw_for_each_sf_rep(esw, i, rep) \
59 	xa_for_each_marked(&((esw)->offloads.vport_reps), i, rep, MLX5_ESW_VPT_SF)
60 
61 #define mlx5_esw_for_each_vf_rep(esw, index, rep)	\
62 	mlx5_esw_for_each_entry_marked(&((esw)->offloads.vport_reps), index, \
63 				       rep, (esw)->esw_funcs.num_vfs, MLX5_ESW_VPT_VF)
64 
65 /* There are two match-all miss flows, one for unicast dst mac and
66  * one for multicast.
67  */
68 #define MLX5_ESW_MISS_FLOWS (2)
69 #define UPLINK_REP_INDEX 0
70 
71 #define MLX5_ESW_VPORT_TBL_SIZE 128
72 #define MLX5_ESW_VPORT_TBL_NUM_GROUPS  4
73 
74 #define MLX5_ESW_FT_OFFLOADS_DROP_RULE (1)
75 
76 static const struct esw_vport_tbl_namespace mlx5_esw_vport_tbl_mirror_ns = {
77 	.max_fte = MLX5_ESW_VPORT_TBL_SIZE,
78 	.max_num_groups = MLX5_ESW_VPORT_TBL_NUM_GROUPS,
79 	.flags = 0,
80 };
81 
82 static struct mlx5_eswitch_rep *mlx5_eswitch_get_rep(struct mlx5_eswitch *esw,
83 						     u16 vport_num)
84 {
85 	return xa_load(&esw->offloads.vport_reps, vport_num);
86 }
87 
88 static void
89 mlx5_eswitch_set_rule_flow_source(struct mlx5_eswitch *esw,
90 				  struct mlx5_flow_spec *spec,
91 				  struct mlx5_esw_flow_attr *attr)
92 {
93 	if (!MLX5_CAP_ESW_FLOWTABLE(esw->dev, flow_source) || !attr || !attr->in_rep)
94 		return;
95 
96 	if (attr->int_port) {
97 		spec->flow_context.flow_source = mlx5e_tc_int_port_get_flow_source(attr->int_port);
98 
99 		return;
100 	}
101 
102 	spec->flow_context.flow_source = (attr->in_rep->vport == MLX5_VPORT_UPLINK) ?
103 					 MLX5_FLOW_CONTEXT_FLOW_SOURCE_UPLINK :
104 					 MLX5_FLOW_CONTEXT_FLOW_SOURCE_LOCAL_VPORT;
105 }
106 
107 /* Actually only the upper 16 bits of reg c0 need to be cleared, but the lower 16 bits
108  * are not needed as well in the following process. So clear them all for simplicity.
109  */
110 void
111 mlx5_eswitch_clear_rule_source_port(struct mlx5_eswitch *esw, struct mlx5_flow_spec *spec)
112 {
113 	if (mlx5_eswitch_vport_match_metadata_enabled(esw)) {
114 		void *misc2;
115 
116 		misc2 = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters_2);
117 		MLX5_SET(fte_match_set_misc2, misc2, metadata_reg_c_0, 0);
118 
119 		misc2 = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters_2);
120 		MLX5_SET(fte_match_set_misc2, misc2, metadata_reg_c_0, 0);
121 
122 		if (!memchr_inv(misc2, 0, MLX5_ST_SZ_BYTES(fte_match_set_misc2)))
123 			spec->match_criteria_enable &= ~MLX5_MATCH_MISC_PARAMETERS_2;
124 	}
125 }
126 
127 static void
128 mlx5_eswitch_set_rule_source_port(struct mlx5_eswitch *esw,
129 				  struct mlx5_flow_spec *spec,
130 				  struct mlx5_flow_attr *attr,
131 				  struct mlx5_eswitch *src_esw,
132 				  u16 vport)
133 {
134 	struct mlx5_esw_flow_attr *esw_attr = attr->esw_attr;
135 	u32 metadata;
136 	void *misc2;
137 	void *misc;
138 
139 	/* Use metadata matching because vport is not represented by single
140 	 * VHCA in dual-port RoCE mode, and matching on source vport may fail.
141 	 */
142 	if (mlx5_eswitch_vport_match_metadata_enabled(esw)) {
143 		if (mlx5_esw_indir_table_decap_vport(attr))
144 			vport = mlx5_esw_indir_table_decap_vport(attr);
145 
146 		if (!attr->chain && esw_attr && esw_attr->int_port)
147 			metadata =
148 				mlx5e_tc_int_port_get_metadata_for_match(esw_attr->int_port);
149 		else
150 			metadata =
151 				mlx5_eswitch_get_vport_metadata_for_match(src_esw, vport);
152 
153 		misc2 = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters_2);
154 		MLX5_SET(fte_match_set_misc2, misc2, metadata_reg_c_0, metadata);
155 
156 		misc2 = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters_2);
157 		MLX5_SET(fte_match_set_misc2, misc2, metadata_reg_c_0,
158 			 mlx5_eswitch_get_vport_metadata_mask());
159 
160 		spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS_2;
161 	} else {
162 		misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters);
163 		MLX5_SET(fte_match_set_misc, misc, source_port, vport);
164 
165 		if (MLX5_CAP_ESW(esw->dev, merged_eswitch))
166 			MLX5_SET(fte_match_set_misc, misc,
167 				 source_eswitch_owner_vhca_id,
168 				 MLX5_CAP_GEN(src_esw->dev, vhca_id));
169 
170 		misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters);
171 		MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port);
172 		if (MLX5_CAP_ESW(esw->dev, merged_eswitch))
173 			MLX5_SET_TO_ONES(fte_match_set_misc, misc,
174 					 source_eswitch_owner_vhca_id);
175 
176 		spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS;
177 	}
178 }
179 
180 static int
181 esw_setup_decap_indir(struct mlx5_eswitch *esw,
182 		      struct mlx5_flow_attr *attr)
183 {
184 	struct mlx5_flow_table *ft;
185 
186 	if (!(attr->flags & MLX5_ATTR_FLAG_SRC_REWRITE))
187 		return -EOPNOTSUPP;
188 
189 	ft = mlx5_esw_indir_table_get(esw, attr,
190 				      mlx5_esw_indir_table_decap_vport(attr), true);
191 	return PTR_ERR_OR_ZERO(ft);
192 }
193 
194 static void
195 esw_cleanup_decap_indir(struct mlx5_eswitch *esw,
196 			struct mlx5_flow_attr *attr)
197 {
198 	if (mlx5_esw_indir_table_decap_vport(attr))
199 		mlx5_esw_indir_table_put(esw,
200 					 mlx5_esw_indir_table_decap_vport(attr),
201 					 true);
202 }
203 
204 static int
205 esw_setup_mtu_dest(struct mlx5_flow_destination *dest,
206 		   struct mlx5e_meter_attr *meter,
207 		   int i)
208 {
209 	dest[i].type = MLX5_FLOW_DESTINATION_TYPE_RANGE;
210 	dest[i].range.field = MLX5_FLOW_DEST_RANGE_FIELD_PKT_LEN;
211 	dest[i].range.min = 0;
212 	dest[i].range.max = meter->params.mtu;
213 	dest[i].range.hit_ft = mlx5e_post_meter_get_mtu_true_ft(meter->post_meter);
214 	dest[i].range.miss_ft = mlx5e_post_meter_get_mtu_false_ft(meter->post_meter);
215 
216 	return 0;
217 }
218 
219 static int
220 esw_setup_sampler_dest(struct mlx5_flow_destination *dest,
221 		       struct mlx5_flow_act *flow_act,
222 		       u32 sampler_id,
223 		       int i)
224 {
225 	flow_act->flags |= FLOW_ACT_IGNORE_FLOW_LEVEL;
226 	dest[i].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_SAMPLER;
227 	dest[i].sampler_id = sampler_id;
228 
229 	return 0;
230 }
231 
232 static int
233 esw_setup_ft_dest(struct mlx5_flow_destination *dest,
234 		  struct mlx5_flow_act *flow_act,
235 		  struct mlx5_eswitch *esw,
236 		  struct mlx5_flow_attr *attr,
237 		  int i)
238 {
239 	flow_act->flags |= FLOW_ACT_IGNORE_FLOW_LEVEL;
240 	dest[i].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
241 	dest[i].ft = attr->dest_ft;
242 
243 	if (mlx5_esw_indir_table_decap_vport(attr))
244 		return esw_setup_decap_indir(esw, attr);
245 	return 0;
246 }
247 
248 static void
249 esw_setup_accept_dest(struct mlx5_flow_destination *dest, struct mlx5_flow_act *flow_act,
250 		      struct mlx5_fs_chains *chains, int i)
251 {
252 	if (mlx5_chains_ignore_flow_level_supported(chains))
253 		flow_act->flags |= FLOW_ACT_IGNORE_FLOW_LEVEL;
254 	dest[i].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
255 	dest[i].ft = mlx5_chains_get_tc_end_ft(chains);
256 }
257 
258 static void
259 esw_setup_slow_path_dest(struct mlx5_flow_destination *dest, struct mlx5_flow_act *flow_act,
260 			 struct mlx5_eswitch *esw, int i)
261 {
262 	if (MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, ignore_flow_level))
263 		flow_act->flags |= FLOW_ACT_IGNORE_FLOW_LEVEL;
264 	dest[i].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
265 	dest[i].ft = mlx5_eswitch_get_slow_fdb(esw);
266 }
267 
268 static int
269 esw_setup_chain_dest(struct mlx5_flow_destination *dest,
270 		     struct mlx5_flow_act *flow_act,
271 		     struct mlx5_fs_chains *chains,
272 		     u32 chain, u32 prio, u32 level,
273 		     int i)
274 {
275 	struct mlx5_flow_table *ft;
276 
277 	flow_act->flags |= FLOW_ACT_IGNORE_FLOW_LEVEL;
278 	ft = mlx5_chains_get_table(chains, chain, prio, level);
279 	if (IS_ERR(ft))
280 		return PTR_ERR(ft);
281 
282 	dest[i].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
283 	dest[i].ft = ft;
284 	return  0;
285 }
286 
287 static void esw_put_dest_tables_loop(struct mlx5_eswitch *esw, struct mlx5_flow_attr *attr,
288 				     int from, int to)
289 {
290 	struct mlx5_esw_flow_attr *esw_attr = attr->esw_attr;
291 	struct mlx5_fs_chains *chains = esw_chains(esw);
292 	int i;
293 
294 	for (i = from; i < to; i++)
295 		if (esw_attr->dests[i].flags & MLX5_ESW_DEST_CHAIN_WITH_SRC_PORT_CHANGE)
296 			mlx5_chains_put_table(chains, 0, 1, 0);
297 		else if (mlx5_esw_indir_table_needed(esw, attr, esw_attr->dests[i].rep->vport,
298 						     esw_attr->dests[i].mdev))
299 			mlx5_esw_indir_table_put(esw, esw_attr->dests[i].rep->vport,
300 						 false);
301 }
302 
303 static bool
304 esw_is_chain_src_port_rewrite(struct mlx5_eswitch *esw, struct mlx5_esw_flow_attr *esw_attr)
305 {
306 	int i;
307 
308 	for (i = esw_attr->split_count; i < esw_attr->out_count; i++)
309 		if (esw_attr->dests[i].flags & MLX5_ESW_DEST_CHAIN_WITH_SRC_PORT_CHANGE)
310 			return true;
311 	return false;
312 }
313 
314 static int
315 esw_setup_chain_src_port_rewrite(struct mlx5_flow_destination *dest,
316 				 struct mlx5_flow_act *flow_act,
317 				 struct mlx5_eswitch *esw,
318 				 struct mlx5_fs_chains *chains,
319 				 struct mlx5_flow_attr *attr,
320 				 int *i)
321 {
322 	struct mlx5_esw_flow_attr *esw_attr = attr->esw_attr;
323 	int err;
324 
325 	if (!(attr->flags & MLX5_ATTR_FLAG_SRC_REWRITE))
326 		return -EOPNOTSUPP;
327 
328 	/* flow steering cannot handle more than one dest with the same ft
329 	 * in a single flow
330 	 */
331 	if (esw_attr->out_count - esw_attr->split_count > 1)
332 		return -EOPNOTSUPP;
333 
334 	err = esw_setup_chain_dest(dest, flow_act, chains, attr->dest_chain, 1, 0, *i);
335 	if (err)
336 		return err;
337 
338 	if (esw_attr->dests[esw_attr->split_count].pkt_reformat) {
339 		flow_act->action |= MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT;
340 		flow_act->pkt_reformat = esw_attr->dests[esw_attr->split_count].pkt_reformat;
341 	}
342 	(*i)++;
343 
344 	return 0;
345 }
346 
347 static void esw_cleanup_chain_src_port_rewrite(struct mlx5_eswitch *esw,
348 					       struct mlx5_flow_attr *attr)
349 {
350 	struct mlx5_esw_flow_attr *esw_attr = attr->esw_attr;
351 
352 	esw_put_dest_tables_loop(esw, attr, esw_attr->split_count, esw_attr->out_count);
353 }
354 
355 static bool
356 esw_is_indir_table(struct mlx5_eswitch *esw, struct mlx5_flow_attr *attr)
357 {
358 	struct mlx5_esw_flow_attr *esw_attr = attr->esw_attr;
359 	bool result = false;
360 	int i;
361 
362 	/* Indirect table is supported only for flows with in_port uplink
363 	 * and the destination is vport on the same eswitch as the uplink,
364 	 * return false in case at least one of destinations doesn't meet
365 	 * this criteria.
366 	 */
367 	for (i = esw_attr->split_count; i < esw_attr->out_count; i++) {
368 		if (esw_attr->dests[i].rep &&
369 		    mlx5_esw_indir_table_needed(esw, attr, esw_attr->dests[i].rep->vport,
370 						esw_attr->dests[i].mdev)) {
371 			result = true;
372 		} else {
373 			result = false;
374 			break;
375 		}
376 	}
377 	return result;
378 }
379 
380 static int
381 esw_setup_indir_table(struct mlx5_flow_destination *dest,
382 		      struct mlx5_flow_act *flow_act,
383 		      struct mlx5_eswitch *esw,
384 		      struct mlx5_flow_attr *attr,
385 		      bool ignore_flow_lvl,
386 		      int *i)
387 {
388 	struct mlx5_esw_flow_attr *esw_attr = attr->esw_attr;
389 	int j, err;
390 
391 	if (!(attr->flags & MLX5_ATTR_FLAG_SRC_REWRITE))
392 		return -EOPNOTSUPP;
393 
394 	for (j = esw_attr->split_count; j < esw_attr->out_count; j++, (*i)++) {
395 		if (ignore_flow_lvl)
396 			flow_act->flags |= FLOW_ACT_IGNORE_FLOW_LEVEL;
397 		dest[*i].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
398 
399 		dest[*i].ft = mlx5_esw_indir_table_get(esw, attr,
400 						       esw_attr->dests[j].rep->vport, false);
401 		if (IS_ERR(dest[*i].ft)) {
402 			err = PTR_ERR(dest[*i].ft);
403 			goto err_indir_tbl_get;
404 		}
405 	}
406 
407 	if (mlx5_esw_indir_table_decap_vport(attr)) {
408 		err = esw_setup_decap_indir(esw, attr);
409 		if (err)
410 			goto err_indir_tbl_get;
411 	}
412 
413 	return 0;
414 
415 err_indir_tbl_get:
416 	esw_put_dest_tables_loop(esw, attr, esw_attr->split_count, j);
417 	return err;
418 }
419 
420 static void esw_cleanup_indir_table(struct mlx5_eswitch *esw, struct mlx5_flow_attr *attr)
421 {
422 	struct mlx5_esw_flow_attr *esw_attr = attr->esw_attr;
423 
424 	esw_put_dest_tables_loop(esw, attr, esw_attr->split_count, esw_attr->out_count);
425 	esw_cleanup_decap_indir(esw, attr);
426 }
427 
428 static void
429 esw_cleanup_chain_dest(struct mlx5_fs_chains *chains, u32 chain, u32 prio, u32 level)
430 {
431 	mlx5_chains_put_table(chains, chain, prio, level);
432 }
433 
434 static void
435 esw_setup_vport_dest(struct mlx5_flow_destination *dest, struct mlx5_flow_act *flow_act,
436 		     struct mlx5_eswitch *esw, struct mlx5_esw_flow_attr *esw_attr,
437 		     int attr_idx, int dest_idx, bool pkt_reformat)
438 {
439 	dest[dest_idx].type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
440 	dest[dest_idx].vport.num = esw_attr->dests[attr_idx].rep->vport;
441 	if (MLX5_CAP_ESW(esw->dev, merged_eswitch)) {
442 		dest[dest_idx].vport.vhca_id =
443 			MLX5_CAP_GEN(esw_attr->dests[attr_idx].mdev, vhca_id);
444 		dest[dest_idx].vport.flags |= MLX5_FLOW_DEST_VPORT_VHCA_ID;
445 		if (dest[dest_idx].vport.num == MLX5_VPORT_UPLINK &&
446 		    mlx5_lag_is_mpesw(esw->dev))
447 			dest[dest_idx].type = MLX5_FLOW_DESTINATION_TYPE_UPLINK;
448 	}
449 	if (esw_attr->dests[attr_idx].flags & MLX5_ESW_DEST_ENCAP_VALID) {
450 		if (pkt_reformat) {
451 			flow_act->action |= MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT;
452 			flow_act->pkt_reformat = esw_attr->dests[attr_idx].pkt_reformat;
453 		}
454 		dest[dest_idx].vport.flags |= MLX5_FLOW_DEST_VPORT_REFORMAT_ID;
455 		dest[dest_idx].vport.pkt_reformat = esw_attr->dests[attr_idx].pkt_reformat;
456 	}
457 }
458 
459 static int
460 esw_setup_vport_dests(struct mlx5_flow_destination *dest, struct mlx5_flow_act *flow_act,
461 		      struct mlx5_eswitch *esw, struct mlx5_esw_flow_attr *esw_attr,
462 		      int i)
463 {
464 	int j;
465 
466 	for (j = esw_attr->split_count; j < esw_attr->out_count; j++, i++)
467 		esw_setup_vport_dest(dest, flow_act, esw, esw_attr, j, i, true);
468 	return i;
469 }
470 
471 static bool
472 esw_src_port_rewrite_supported(struct mlx5_eswitch *esw)
473 {
474 	return MLX5_CAP_GEN(esw->dev, reg_c_preserve) &&
475 	       mlx5_eswitch_vport_match_metadata_enabled(esw) &&
476 	       MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, ignore_flow_level);
477 }
478 
479 static int
480 esw_setup_dests(struct mlx5_flow_destination *dest,
481 		struct mlx5_flow_act *flow_act,
482 		struct mlx5_eswitch *esw,
483 		struct mlx5_flow_attr *attr,
484 		struct mlx5_flow_spec *spec,
485 		int *i)
486 {
487 	struct mlx5_esw_flow_attr *esw_attr = attr->esw_attr;
488 	struct mlx5_fs_chains *chains = esw_chains(esw);
489 	int err = 0;
490 
491 	if (!mlx5_eswitch_termtbl_required(esw, attr, flow_act, spec) &&
492 	    esw_src_port_rewrite_supported(esw))
493 		attr->flags |= MLX5_ATTR_FLAG_SRC_REWRITE;
494 
495 	if (attr->flags & MLX5_ATTR_FLAG_SLOW_PATH) {
496 		esw_setup_slow_path_dest(dest, flow_act, esw, *i);
497 		(*i)++;
498 		goto out;
499 	}
500 
501 	if (attr->flags & MLX5_ATTR_FLAG_SAMPLE) {
502 		esw_setup_sampler_dest(dest, flow_act, attr->sample_attr.sampler_id, *i);
503 		(*i)++;
504 	} else if (attr->flags & MLX5_ATTR_FLAG_ACCEPT) {
505 		esw_setup_accept_dest(dest, flow_act, chains, *i);
506 		(*i)++;
507 	} else if (attr->flags & MLX5_ATTR_FLAG_MTU) {
508 		err = esw_setup_mtu_dest(dest, &attr->meter_attr, *i);
509 		(*i)++;
510 	} else if (esw_is_indir_table(esw, attr)) {
511 		err = esw_setup_indir_table(dest, flow_act, esw, attr, true, i);
512 	} else if (esw_is_chain_src_port_rewrite(esw, esw_attr)) {
513 		err = esw_setup_chain_src_port_rewrite(dest, flow_act, esw, chains, attr, i);
514 	} else {
515 		*i = esw_setup_vport_dests(dest, flow_act, esw, esw_attr, *i);
516 
517 		if (attr->dest_ft) {
518 			err = esw_setup_ft_dest(dest, flow_act, esw, attr, *i);
519 			(*i)++;
520 		} else if (attr->dest_chain) {
521 			err = esw_setup_chain_dest(dest, flow_act, chains, attr->dest_chain,
522 						   1, 0, *i);
523 			(*i)++;
524 		}
525 	}
526 
527 out:
528 	return err;
529 }
530 
531 static void
532 esw_cleanup_dests(struct mlx5_eswitch *esw,
533 		  struct mlx5_flow_attr *attr)
534 {
535 	struct mlx5_esw_flow_attr *esw_attr = attr->esw_attr;
536 	struct mlx5_fs_chains *chains = esw_chains(esw);
537 
538 	if (attr->dest_ft) {
539 		esw_cleanup_decap_indir(esw, attr);
540 	} else if (!mlx5e_tc_attr_flags_skip(attr->flags)) {
541 		if (attr->dest_chain)
542 			esw_cleanup_chain_dest(chains, attr->dest_chain, 1, 0);
543 		else if (esw_is_indir_table(esw, attr))
544 			esw_cleanup_indir_table(esw, attr);
545 		else if (esw_is_chain_src_port_rewrite(esw, esw_attr))
546 			esw_cleanup_chain_src_port_rewrite(esw, attr);
547 	}
548 }
549 
550 static void
551 esw_setup_meter(struct mlx5_flow_attr *attr, struct mlx5_flow_act *flow_act)
552 {
553 	struct mlx5e_flow_meter_handle *meter;
554 
555 	meter = attr->meter_attr.meter;
556 	flow_act->exe_aso.type = attr->exe_aso_type;
557 	flow_act->exe_aso.object_id = meter->obj_id;
558 	flow_act->exe_aso.flow_meter.meter_idx = meter->idx;
559 	flow_act->exe_aso.flow_meter.init_color = MLX5_FLOW_METER_COLOR_GREEN;
560 	/* use metadata reg 5 for packet color */
561 	flow_act->exe_aso.return_reg_id = 5;
562 }
563 
564 struct mlx5_flow_handle *
565 mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw,
566 				struct mlx5_flow_spec *spec,
567 				struct mlx5_flow_attr *attr)
568 {
569 	struct mlx5_flow_act flow_act = { .flags = FLOW_ACT_NO_APPEND, };
570 	struct mlx5_esw_flow_attr *esw_attr = attr->esw_attr;
571 	struct mlx5_fs_chains *chains = esw_chains(esw);
572 	bool split = !!(esw_attr->split_count);
573 	struct mlx5_vport_tbl_attr fwd_attr;
574 	struct mlx5_flow_destination *dest;
575 	struct mlx5_flow_handle *rule;
576 	struct mlx5_flow_table *fdb;
577 	int i = 0;
578 
579 	if (esw->mode != MLX5_ESWITCH_OFFLOADS)
580 		return ERR_PTR(-EOPNOTSUPP);
581 
582 	if (!mlx5_eswitch_vlan_actions_supported(esw->dev, 1))
583 		return ERR_PTR(-EOPNOTSUPP);
584 
585 	dest = kcalloc(MLX5_MAX_FLOW_FWD_VPORTS + 1, sizeof(*dest), GFP_KERNEL);
586 	if (!dest)
587 		return ERR_PTR(-ENOMEM);
588 
589 	flow_act.action = attr->action;
590 
591 	if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH) {
592 		flow_act.vlan[0].ethtype = ntohs(esw_attr->vlan_proto[0]);
593 		flow_act.vlan[0].vid = esw_attr->vlan_vid[0];
594 		flow_act.vlan[0].prio = esw_attr->vlan_prio[0];
595 		if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH_2) {
596 			flow_act.vlan[1].ethtype = ntohs(esw_attr->vlan_proto[1]);
597 			flow_act.vlan[1].vid = esw_attr->vlan_vid[1];
598 			flow_act.vlan[1].prio = esw_attr->vlan_prio[1];
599 		}
600 	}
601 
602 	mlx5_eswitch_set_rule_flow_source(esw, spec, esw_attr);
603 
604 	if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) {
605 		int err;
606 
607 		err = esw_setup_dests(dest, &flow_act, esw, attr, spec, &i);
608 		if (err) {
609 			rule = ERR_PTR(err);
610 			goto err_create_goto_table;
611 		}
612 	}
613 
614 	if (esw_attr->decap_pkt_reformat)
615 		flow_act.pkt_reformat = esw_attr->decap_pkt_reformat;
616 
617 	if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_COUNT) {
618 		dest[i].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
619 		dest[i].counter_id = mlx5_fc_id(attr->counter);
620 		i++;
621 	}
622 
623 	if (attr->outer_match_level != MLX5_MATCH_NONE)
624 		spec->match_criteria_enable |= MLX5_MATCH_OUTER_HEADERS;
625 	if (attr->inner_match_level != MLX5_MATCH_NONE)
626 		spec->match_criteria_enable |= MLX5_MATCH_INNER_HEADERS;
627 
628 	if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
629 		flow_act.modify_hdr = attr->modify_hdr;
630 
631 	if ((flow_act.action & MLX5_FLOW_CONTEXT_ACTION_EXECUTE_ASO) &&
632 	    attr->exe_aso_type == MLX5_EXE_ASO_FLOW_METER)
633 		esw_setup_meter(attr, &flow_act);
634 
635 	if (split) {
636 		fwd_attr.chain = attr->chain;
637 		fwd_attr.prio = attr->prio;
638 		fwd_attr.vport = esw_attr->in_rep->vport;
639 		fwd_attr.vport_ns = &mlx5_esw_vport_tbl_mirror_ns;
640 
641 		fdb = mlx5_esw_vporttbl_get(esw, &fwd_attr);
642 	} else {
643 		if (attr->chain || attr->prio)
644 			fdb = mlx5_chains_get_table(chains, attr->chain,
645 						    attr->prio, 0);
646 		else
647 			fdb = attr->ft;
648 
649 		if (!(attr->flags & MLX5_ATTR_FLAG_NO_IN_PORT))
650 			mlx5_eswitch_set_rule_source_port(esw, spec, attr,
651 							  esw_attr->in_mdev->priv.eswitch,
652 							  esw_attr->in_rep->vport);
653 	}
654 	if (IS_ERR(fdb)) {
655 		rule = ERR_CAST(fdb);
656 		goto err_esw_get;
657 	}
658 
659 	if (!i) {
660 		kfree(dest);
661 		dest = NULL;
662 	}
663 
664 	if (mlx5_eswitch_termtbl_required(esw, attr, &flow_act, spec))
665 		rule = mlx5_eswitch_add_termtbl_rule(esw, fdb, spec, esw_attr,
666 						     &flow_act, dest, i);
667 	else
668 		rule = mlx5_add_flow_rules(fdb, spec, &flow_act, dest, i);
669 	if (IS_ERR(rule))
670 		goto err_add_rule;
671 	else
672 		atomic64_inc(&esw->offloads.num_flows);
673 
674 	kfree(dest);
675 	return rule;
676 
677 err_add_rule:
678 	if (split)
679 		mlx5_esw_vporttbl_put(esw, &fwd_attr);
680 	else if (attr->chain || attr->prio)
681 		mlx5_chains_put_table(chains, attr->chain, attr->prio, 0);
682 err_esw_get:
683 	esw_cleanup_dests(esw, attr);
684 err_create_goto_table:
685 	kfree(dest);
686 	return rule;
687 }
688 
689 struct mlx5_flow_handle *
690 mlx5_eswitch_add_fwd_rule(struct mlx5_eswitch *esw,
691 			  struct mlx5_flow_spec *spec,
692 			  struct mlx5_flow_attr *attr)
693 {
694 	struct mlx5_flow_act flow_act = { .flags = FLOW_ACT_NO_APPEND, };
695 	struct mlx5_esw_flow_attr *esw_attr = attr->esw_attr;
696 	struct mlx5_fs_chains *chains = esw_chains(esw);
697 	struct mlx5_vport_tbl_attr fwd_attr;
698 	struct mlx5_flow_destination *dest;
699 	struct mlx5_flow_table *fast_fdb;
700 	struct mlx5_flow_table *fwd_fdb;
701 	struct mlx5_flow_handle *rule;
702 	int i, err = 0;
703 
704 	dest = kcalloc(MLX5_MAX_FLOW_FWD_VPORTS + 1, sizeof(*dest), GFP_KERNEL);
705 	if (!dest)
706 		return ERR_PTR(-ENOMEM);
707 
708 	fast_fdb = mlx5_chains_get_table(chains, attr->chain, attr->prio, 0);
709 	if (IS_ERR(fast_fdb)) {
710 		rule = ERR_CAST(fast_fdb);
711 		goto err_get_fast;
712 	}
713 
714 	fwd_attr.chain = attr->chain;
715 	fwd_attr.prio = attr->prio;
716 	fwd_attr.vport = esw_attr->in_rep->vport;
717 	fwd_attr.vport_ns = &mlx5_esw_vport_tbl_mirror_ns;
718 	fwd_fdb = mlx5_esw_vporttbl_get(esw, &fwd_attr);
719 	if (IS_ERR(fwd_fdb)) {
720 		rule = ERR_CAST(fwd_fdb);
721 		goto err_get_fwd;
722 	}
723 
724 	flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
725 	for (i = 0; i < esw_attr->split_count; i++) {
726 		if (esw_is_indir_table(esw, attr))
727 			err = esw_setup_indir_table(dest, &flow_act, esw, attr, false, &i);
728 		else if (esw_is_chain_src_port_rewrite(esw, esw_attr))
729 			err = esw_setup_chain_src_port_rewrite(dest, &flow_act, esw, chains, attr,
730 							       &i);
731 		else
732 			esw_setup_vport_dest(dest, &flow_act, esw, esw_attr, i, i, false);
733 
734 		if (err) {
735 			rule = ERR_PTR(err);
736 			goto err_chain_src_rewrite;
737 		}
738 	}
739 	dest[i].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
740 	dest[i].ft = fwd_fdb;
741 	i++;
742 
743 	mlx5_eswitch_set_rule_source_port(esw, spec, attr,
744 					  esw_attr->in_mdev->priv.eswitch,
745 					  esw_attr->in_rep->vport);
746 
747 	if (attr->outer_match_level != MLX5_MATCH_NONE)
748 		spec->match_criteria_enable |= MLX5_MATCH_OUTER_HEADERS;
749 
750 	flow_act.flags |= FLOW_ACT_IGNORE_FLOW_LEVEL;
751 	rule = mlx5_add_flow_rules(fast_fdb, spec, &flow_act, dest, i);
752 
753 	if (IS_ERR(rule)) {
754 		i = esw_attr->split_count;
755 		goto err_chain_src_rewrite;
756 	}
757 
758 	atomic64_inc(&esw->offloads.num_flows);
759 
760 	kfree(dest);
761 	return rule;
762 err_chain_src_rewrite:
763 	esw_put_dest_tables_loop(esw, attr, 0, i);
764 	mlx5_esw_vporttbl_put(esw, &fwd_attr);
765 err_get_fwd:
766 	mlx5_chains_put_table(chains, attr->chain, attr->prio, 0);
767 err_get_fast:
768 	kfree(dest);
769 	return rule;
770 }
771 
772 static void
773 __mlx5_eswitch_del_rule(struct mlx5_eswitch *esw,
774 			struct mlx5_flow_handle *rule,
775 			struct mlx5_flow_attr *attr,
776 			bool fwd_rule)
777 {
778 	struct mlx5_esw_flow_attr *esw_attr = attr->esw_attr;
779 	struct mlx5_fs_chains *chains = esw_chains(esw);
780 	bool split = (esw_attr->split_count > 0);
781 	struct mlx5_vport_tbl_attr fwd_attr;
782 	int i;
783 
784 	mlx5_del_flow_rules(rule);
785 
786 	if (!mlx5e_tc_attr_flags_skip(attr->flags)) {
787 		/* unref the term table */
788 		for (i = 0; i < MLX5_MAX_FLOW_FWD_VPORTS; i++) {
789 			if (esw_attr->dests[i].termtbl)
790 				mlx5_eswitch_termtbl_put(esw, esw_attr->dests[i].termtbl);
791 		}
792 	}
793 
794 	atomic64_dec(&esw->offloads.num_flows);
795 
796 	if (fwd_rule || split) {
797 		fwd_attr.chain = attr->chain;
798 		fwd_attr.prio = attr->prio;
799 		fwd_attr.vport = esw_attr->in_rep->vport;
800 		fwd_attr.vport_ns = &mlx5_esw_vport_tbl_mirror_ns;
801 	}
802 
803 	if (fwd_rule)  {
804 		mlx5_esw_vporttbl_put(esw, &fwd_attr);
805 		mlx5_chains_put_table(chains, attr->chain, attr->prio, 0);
806 		esw_put_dest_tables_loop(esw, attr, 0, esw_attr->split_count);
807 	} else {
808 		if (split)
809 			mlx5_esw_vporttbl_put(esw, &fwd_attr);
810 		else if (attr->chain || attr->prio)
811 			mlx5_chains_put_table(chains, attr->chain, attr->prio, 0);
812 		esw_cleanup_dests(esw, attr);
813 	}
814 }
815 
816 void
817 mlx5_eswitch_del_offloaded_rule(struct mlx5_eswitch *esw,
818 				struct mlx5_flow_handle *rule,
819 				struct mlx5_flow_attr *attr)
820 {
821 	__mlx5_eswitch_del_rule(esw, rule, attr, false);
822 }
823 
824 void
825 mlx5_eswitch_del_fwd_rule(struct mlx5_eswitch *esw,
826 			  struct mlx5_flow_handle *rule,
827 			  struct mlx5_flow_attr *attr)
828 {
829 	__mlx5_eswitch_del_rule(esw, rule, attr, true);
830 }
831 
832 struct mlx5_flow_handle *
833 mlx5_eswitch_add_send_to_vport_rule(struct mlx5_eswitch *on_esw,
834 				    struct mlx5_eswitch *from_esw,
835 				    struct mlx5_eswitch_rep *rep,
836 				    u32 sqn)
837 {
838 	struct mlx5_flow_act flow_act = {0};
839 	struct mlx5_flow_destination dest = {};
840 	struct mlx5_flow_handle *flow_rule;
841 	struct mlx5_flow_spec *spec;
842 	void *misc;
843 
844 	spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
845 	if (!spec) {
846 		flow_rule = ERR_PTR(-ENOMEM);
847 		goto out;
848 	}
849 
850 	misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters);
851 	MLX5_SET(fte_match_set_misc, misc, source_sqn, sqn);
852 	/* source vport is the esw manager */
853 	MLX5_SET(fte_match_set_misc, misc, source_port, from_esw->manager_vport);
854 	if (MLX5_CAP_ESW(on_esw->dev, merged_eswitch))
855 		MLX5_SET(fte_match_set_misc, misc, source_eswitch_owner_vhca_id,
856 			 MLX5_CAP_GEN(from_esw->dev, vhca_id));
857 
858 	misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters);
859 	MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_sqn);
860 	MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port);
861 	if (MLX5_CAP_ESW(on_esw->dev, merged_eswitch))
862 		MLX5_SET_TO_ONES(fte_match_set_misc, misc,
863 				 source_eswitch_owner_vhca_id);
864 
865 	spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS;
866 	dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
867 	dest.vport.num = rep->vport;
868 	dest.vport.vhca_id = MLX5_CAP_GEN(rep->esw->dev, vhca_id);
869 	dest.vport.flags |= MLX5_FLOW_DEST_VPORT_VHCA_ID;
870 	flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
871 
872 	if (MLX5_CAP_ESW_FLOWTABLE(on_esw->dev, flow_source) &&
873 	    rep->vport == MLX5_VPORT_UPLINK)
874 		spec->flow_context.flow_source = MLX5_FLOW_CONTEXT_FLOW_SOURCE_LOCAL_VPORT;
875 
876 	flow_rule = mlx5_add_flow_rules(mlx5_eswitch_get_slow_fdb(on_esw),
877 					spec, &flow_act, &dest, 1);
878 	if (IS_ERR(flow_rule))
879 		esw_warn(on_esw->dev, "FDB: Failed to add send to vport rule err %ld\n",
880 			 PTR_ERR(flow_rule));
881 out:
882 	kvfree(spec);
883 	return flow_rule;
884 }
885 EXPORT_SYMBOL(mlx5_eswitch_add_send_to_vport_rule);
886 
887 void mlx5_eswitch_del_send_to_vport_rule(struct mlx5_flow_handle *rule)
888 {
889 	mlx5_del_flow_rules(rule);
890 }
891 
892 void mlx5_eswitch_del_send_to_vport_meta_rule(struct mlx5_flow_handle *rule)
893 {
894 	if (rule)
895 		mlx5_del_flow_rules(rule);
896 }
897 
898 struct mlx5_flow_handle *
899 mlx5_eswitch_add_send_to_vport_meta_rule(struct mlx5_eswitch *esw, u16 vport_num)
900 {
901 	struct mlx5_flow_destination dest = {};
902 	struct mlx5_flow_act flow_act = {0};
903 	struct mlx5_flow_handle *flow_rule;
904 	struct mlx5_flow_spec *spec;
905 
906 	spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
907 	if (!spec)
908 		return ERR_PTR(-ENOMEM);
909 
910 	MLX5_SET(fte_match_param, spec->match_criteria,
911 		 misc_parameters_2.metadata_reg_c_0, mlx5_eswitch_get_vport_metadata_mask());
912 	MLX5_SET(fte_match_param, spec->match_criteria,
913 		 misc_parameters_2.metadata_reg_c_1, ESW_TUN_MASK);
914 	MLX5_SET(fte_match_param, spec->match_value, misc_parameters_2.metadata_reg_c_1,
915 		 ESW_TUN_SLOW_TABLE_GOTO_VPORT_MARK);
916 
917 	spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS_2;
918 	dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
919 	flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
920 
921 	MLX5_SET(fte_match_param, spec->match_value, misc_parameters_2.metadata_reg_c_0,
922 		 mlx5_eswitch_get_vport_metadata_for_match(esw, vport_num));
923 	dest.vport.num = vport_num;
924 
925 	flow_rule = mlx5_add_flow_rules(mlx5_eswitch_get_slow_fdb(esw),
926 					spec, &flow_act, &dest, 1);
927 	if (IS_ERR(flow_rule))
928 		esw_warn(esw->dev, "FDB: Failed to add send to vport meta rule vport %d, err %ld\n",
929 			 vport_num, PTR_ERR(flow_rule));
930 
931 	kvfree(spec);
932 	return flow_rule;
933 }
934 
935 static bool mlx5_eswitch_reg_c1_loopback_supported(struct mlx5_eswitch *esw)
936 {
937 	return MLX5_CAP_ESW_FLOWTABLE(esw->dev, fdb_to_vport_reg_c_id) &
938 	       MLX5_FDB_TO_VPORT_REG_C_1;
939 }
940 
941 static int esw_set_passing_vport_metadata(struct mlx5_eswitch *esw, bool enable)
942 {
943 	u32 out[MLX5_ST_SZ_DW(query_esw_vport_context_out)] = {};
944 	u32 min[MLX5_ST_SZ_DW(modify_esw_vport_context_in)] = {};
945 	u32 in[MLX5_ST_SZ_DW(query_esw_vport_context_in)] = {};
946 	u8 curr, wanted;
947 	int err;
948 
949 	if (!mlx5_eswitch_reg_c1_loopback_supported(esw) &&
950 	    !mlx5_eswitch_vport_match_metadata_enabled(esw))
951 		return 0;
952 
953 	MLX5_SET(query_esw_vport_context_in, in, opcode,
954 		 MLX5_CMD_OP_QUERY_ESW_VPORT_CONTEXT);
955 	err = mlx5_cmd_exec_inout(esw->dev, query_esw_vport_context, in, out);
956 	if (err)
957 		return err;
958 
959 	curr = MLX5_GET(query_esw_vport_context_out, out,
960 			esw_vport_context.fdb_to_vport_reg_c_id);
961 	wanted = MLX5_FDB_TO_VPORT_REG_C_0;
962 	if (mlx5_eswitch_reg_c1_loopback_supported(esw))
963 		wanted |= MLX5_FDB_TO_VPORT_REG_C_1;
964 
965 	if (enable)
966 		curr |= wanted;
967 	else
968 		curr &= ~wanted;
969 
970 	MLX5_SET(modify_esw_vport_context_in, min,
971 		 esw_vport_context.fdb_to_vport_reg_c_id, curr);
972 	MLX5_SET(modify_esw_vport_context_in, min,
973 		 field_select.fdb_to_vport_reg_c_id, 1);
974 
975 	err = mlx5_eswitch_modify_esw_vport_context(esw->dev, 0, false, min);
976 	if (!err) {
977 		if (enable && (curr & MLX5_FDB_TO_VPORT_REG_C_1))
978 			esw->flags |= MLX5_ESWITCH_REG_C1_LOOPBACK_ENABLED;
979 		else
980 			esw->flags &= ~MLX5_ESWITCH_REG_C1_LOOPBACK_ENABLED;
981 	}
982 
983 	return err;
984 }
985 
986 static void peer_miss_rules_setup(struct mlx5_eswitch *esw,
987 				  struct mlx5_core_dev *peer_dev,
988 				  struct mlx5_flow_spec *spec,
989 				  struct mlx5_flow_destination *dest)
990 {
991 	void *misc;
992 
993 	if (mlx5_eswitch_vport_match_metadata_enabled(esw)) {
994 		misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
995 				    misc_parameters_2);
996 		MLX5_SET(fte_match_set_misc2, misc, metadata_reg_c_0,
997 			 mlx5_eswitch_get_vport_metadata_mask());
998 
999 		spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS_2;
1000 	} else {
1001 		misc = MLX5_ADDR_OF(fte_match_param, spec->match_value,
1002 				    misc_parameters);
1003 
1004 		MLX5_SET(fte_match_set_misc, misc, source_eswitch_owner_vhca_id,
1005 			 MLX5_CAP_GEN(peer_dev, vhca_id));
1006 
1007 		spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS;
1008 
1009 		misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
1010 				    misc_parameters);
1011 		MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port);
1012 		MLX5_SET_TO_ONES(fte_match_set_misc, misc,
1013 				 source_eswitch_owner_vhca_id);
1014 	}
1015 
1016 	dest->type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
1017 	dest->vport.num = peer_dev->priv.eswitch->manager_vport;
1018 	dest->vport.vhca_id = MLX5_CAP_GEN(peer_dev, vhca_id);
1019 	dest->vport.flags |= MLX5_FLOW_DEST_VPORT_VHCA_ID;
1020 }
1021 
1022 static void esw_set_peer_miss_rule_source_port(struct mlx5_eswitch *esw,
1023 					       struct mlx5_eswitch *peer_esw,
1024 					       struct mlx5_flow_spec *spec,
1025 					       u16 vport)
1026 {
1027 	void *misc;
1028 
1029 	if (mlx5_eswitch_vport_match_metadata_enabled(esw)) {
1030 		misc = MLX5_ADDR_OF(fte_match_param, spec->match_value,
1031 				    misc_parameters_2);
1032 		MLX5_SET(fte_match_set_misc2, misc, metadata_reg_c_0,
1033 			 mlx5_eswitch_get_vport_metadata_for_match(peer_esw,
1034 								   vport));
1035 	} else {
1036 		misc = MLX5_ADDR_OF(fte_match_param, spec->match_value,
1037 				    misc_parameters);
1038 		MLX5_SET(fte_match_set_misc, misc, source_port, vport);
1039 	}
1040 }
1041 
1042 static int esw_add_fdb_peer_miss_rules(struct mlx5_eswitch *esw,
1043 				       struct mlx5_core_dev *peer_dev)
1044 {
1045 	struct mlx5_flow_destination dest = {};
1046 	struct mlx5_flow_act flow_act = {0};
1047 	struct mlx5_flow_handle **flows;
1048 	/* total vports is the same for both e-switches */
1049 	int nvports = esw->total_vports;
1050 	struct mlx5_flow_handle *flow;
1051 	struct mlx5_flow_spec *spec;
1052 	struct mlx5_vport *vport;
1053 	unsigned long i;
1054 	void *misc;
1055 	int err;
1056 
1057 	spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
1058 	if (!spec)
1059 		return -ENOMEM;
1060 
1061 	peer_miss_rules_setup(esw, peer_dev, spec, &dest);
1062 
1063 	flows = kvcalloc(nvports, sizeof(*flows), GFP_KERNEL);
1064 	if (!flows) {
1065 		err = -ENOMEM;
1066 		goto alloc_flows_err;
1067 	}
1068 
1069 	flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
1070 	misc = MLX5_ADDR_OF(fte_match_param, spec->match_value,
1071 			    misc_parameters);
1072 
1073 	if (mlx5_core_is_ecpf_esw_manager(esw->dev)) {
1074 		vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_PF);
1075 		esw_set_peer_miss_rule_source_port(esw, peer_dev->priv.eswitch,
1076 						   spec, MLX5_VPORT_PF);
1077 
1078 		flow = mlx5_add_flow_rules(mlx5_eswitch_get_slow_fdb(esw),
1079 					   spec, &flow_act, &dest, 1);
1080 		if (IS_ERR(flow)) {
1081 			err = PTR_ERR(flow);
1082 			goto add_pf_flow_err;
1083 		}
1084 		flows[vport->index] = flow;
1085 	}
1086 
1087 	if (mlx5_ecpf_vport_exists(esw->dev)) {
1088 		vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_ECPF);
1089 		MLX5_SET(fte_match_set_misc, misc, source_port, MLX5_VPORT_ECPF);
1090 		flow = mlx5_add_flow_rules(mlx5_eswitch_get_slow_fdb(esw),
1091 					   spec, &flow_act, &dest, 1);
1092 		if (IS_ERR(flow)) {
1093 			err = PTR_ERR(flow);
1094 			goto add_ecpf_flow_err;
1095 		}
1096 		flows[vport->index] = flow;
1097 	}
1098 
1099 	mlx5_esw_for_each_vf_vport(esw, i, vport, mlx5_core_max_vfs(esw->dev)) {
1100 		esw_set_peer_miss_rule_source_port(esw,
1101 						   peer_dev->priv.eswitch,
1102 						   spec, vport->vport);
1103 
1104 		flow = mlx5_add_flow_rules(mlx5_eswitch_get_slow_fdb(esw),
1105 					   spec, &flow_act, &dest, 1);
1106 		if (IS_ERR(flow)) {
1107 			err = PTR_ERR(flow);
1108 			goto add_vf_flow_err;
1109 		}
1110 		flows[vport->index] = flow;
1111 	}
1112 
1113 	esw->fdb_table.offloads.peer_miss_rules = flows;
1114 
1115 	kvfree(spec);
1116 	return 0;
1117 
1118 add_vf_flow_err:
1119 	mlx5_esw_for_each_vf_vport(esw, i, vport, mlx5_core_max_vfs(esw->dev)) {
1120 		if (!flows[vport->index])
1121 			continue;
1122 		mlx5_del_flow_rules(flows[vport->index]);
1123 	}
1124 	if (mlx5_ecpf_vport_exists(esw->dev)) {
1125 		vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_ECPF);
1126 		mlx5_del_flow_rules(flows[vport->index]);
1127 	}
1128 add_ecpf_flow_err:
1129 	if (mlx5_core_is_ecpf_esw_manager(esw->dev)) {
1130 		vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_PF);
1131 		mlx5_del_flow_rules(flows[vport->index]);
1132 	}
1133 add_pf_flow_err:
1134 	esw_warn(esw->dev, "FDB: Failed to add peer miss flow rule err %d\n", err);
1135 	kvfree(flows);
1136 alloc_flows_err:
1137 	kvfree(spec);
1138 	return err;
1139 }
1140 
1141 static void esw_del_fdb_peer_miss_rules(struct mlx5_eswitch *esw)
1142 {
1143 	struct mlx5_flow_handle **flows;
1144 	struct mlx5_vport *vport;
1145 	unsigned long i;
1146 
1147 	flows = esw->fdb_table.offloads.peer_miss_rules;
1148 
1149 	mlx5_esw_for_each_vf_vport(esw, i, vport, mlx5_core_max_vfs(esw->dev))
1150 		mlx5_del_flow_rules(flows[vport->index]);
1151 
1152 	if (mlx5_ecpf_vport_exists(esw->dev)) {
1153 		vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_ECPF);
1154 		mlx5_del_flow_rules(flows[vport->index]);
1155 	}
1156 
1157 	if (mlx5_core_is_ecpf_esw_manager(esw->dev)) {
1158 		vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_PF);
1159 		mlx5_del_flow_rules(flows[vport->index]);
1160 	}
1161 	kvfree(flows);
1162 }
1163 
1164 static int esw_add_fdb_miss_rule(struct mlx5_eswitch *esw)
1165 {
1166 	struct mlx5_flow_act flow_act = {0};
1167 	struct mlx5_flow_destination dest = {};
1168 	struct mlx5_flow_handle *flow_rule = NULL;
1169 	struct mlx5_flow_spec *spec;
1170 	void *headers_c;
1171 	void *headers_v;
1172 	int err = 0;
1173 	u8 *dmac_c;
1174 	u8 *dmac_v;
1175 
1176 	spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
1177 	if (!spec) {
1178 		err = -ENOMEM;
1179 		goto out;
1180 	}
1181 
1182 	spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
1183 	headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
1184 				 outer_headers);
1185 	dmac_c = MLX5_ADDR_OF(fte_match_param, headers_c,
1186 			      outer_headers.dmac_47_16);
1187 	dmac_c[0] = 0x01;
1188 
1189 	dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
1190 	dest.vport.num = esw->manager_vport;
1191 	flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
1192 
1193 	flow_rule = mlx5_add_flow_rules(mlx5_eswitch_get_slow_fdb(esw),
1194 					spec, &flow_act, &dest, 1);
1195 	if (IS_ERR(flow_rule)) {
1196 		err = PTR_ERR(flow_rule);
1197 		esw_warn(esw->dev,  "FDB: Failed to add unicast miss flow rule err %d\n", err);
1198 		goto out;
1199 	}
1200 
1201 	esw->fdb_table.offloads.miss_rule_uni = flow_rule;
1202 
1203 	headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value,
1204 				 outer_headers);
1205 	dmac_v = MLX5_ADDR_OF(fte_match_param, headers_v,
1206 			      outer_headers.dmac_47_16);
1207 	dmac_v[0] = 0x01;
1208 	flow_rule = mlx5_add_flow_rules(mlx5_eswitch_get_slow_fdb(esw),
1209 					spec, &flow_act, &dest, 1);
1210 	if (IS_ERR(flow_rule)) {
1211 		err = PTR_ERR(flow_rule);
1212 		esw_warn(esw->dev, "FDB: Failed to add multicast miss flow rule err %d\n", err);
1213 		mlx5_del_flow_rules(esw->fdb_table.offloads.miss_rule_uni);
1214 		goto out;
1215 	}
1216 
1217 	esw->fdb_table.offloads.miss_rule_multi = flow_rule;
1218 
1219 out:
1220 	kvfree(spec);
1221 	return err;
1222 }
1223 
1224 struct mlx5_flow_handle *
1225 esw_add_restore_rule(struct mlx5_eswitch *esw, u32 tag)
1226 {
1227 	struct mlx5_flow_act flow_act = { .flags = FLOW_ACT_NO_APPEND, };
1228 	struct mlx5_flow_table *ft = esw->offloads.ft_offloads_restore;
1229 	struct mlx5_flow_context *flow_context;
1230 	struct mlx5_flow_handle *flow_rule;
1231 	struct mlx5_flow_destination dest;
1232 	struct mlx5_flow_spec *spec;
1233 	void *misc;
1234 
1235 	if (!mlx5_eswitch_reg_c1_loopback_supported(esw))
1236 		return ERR_PTR(-EOPNOTSUPP);
1237 
1238 	spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
1239 	if (!spec)
1240 		return ERR_PTR(-ENOMEM);
1241 
1242 	misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
1243 			    misc_parameters_2);
1244 	MLX5_SET(fte_match_set_misc2, misc, metadata_reg_c_0,
1245 		 ESW_REG_C0_USER_DATA_METADATA_MASK);
1246 	misc = MLX5_ADDR_OF(fte_match_param, spec->match_value,
1247 			    misc_parameters_2);
1248 	MLX5_SET(fte_match_set_misc2, misc, metadata_reg_c_0, tag);
1249 	spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS_2;
1250 	flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
1251 			  MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
1252 	flow_act.modify_hdr = esw->offloads.restore_copy_hdr_id;
1253 
1254 	flow_context = &spec->flow_context;
1255 	flow_context->flags |= FLOW_CONTEXT_HAS_TAG;
1256 	flow_context->flow_tag = tag;
1257 	dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
1258 	dest.ft = esw->offloads.ft_offloads;
1259 
1260 	flow_rule = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
1261 	kvfree(spec);
1262 
1263 	if (IS_ERR(flow_rule))
1264 		esw_warn(esw->dev,
1265 			 "Failed to create restore rule for tag: %d, err(%d)\n",
1266 			 tag, (int)PTR_ERR(flow_rule));
1267 
1268 	return flow_rule;
1269 }
1270 
1271 #define MAX_PF_SQ 256
1272 #define MAX_SQ_NVPORTS 32
1273 
1274 static void esw_set_flow_group_source_port(struct mlx5_eswitch *esw,
1275 					   u32 *flow_group_in)
1276 {
1277 	void *match_criteria = MLX5_ADDR_OF(create_flow_group_in,
1278 					    flow_group_in,
1279 					    match_criteria);
1280 
1281 	if (mlx5_eswitch_vport_match_metadata_enabled(esw)) {
1282 		MLX5_SET(create_flow_group_in, flow_group_in,
1283 			 match_criteria_enable,
1284 			 MLX5_MATCH_MISC_PARAMETERS_2);
1285 
1286 		MLX5_SET(fte_match_param, match_criteria,
1287 			 misc_parameters_2.metadata_reg_c_0,
1288 			 mlx5_eswitch_get_vport_metadata_mask());
1289 	} else {
1290 		MLX5_SET(create_flow_group_in, flow_group_in,
1291 			 match_criteria_enable,
1292 			 MLX5_MATCH_MISC_PARAMETERS);
1293 
1294 		MLX5_SET_TO_ONES(fte_match_param, match_criteria,
1295 				 misc_parameters.source_port);
1296 	}
1297 }
1298 
1299 #if IS_ENABLED(CONFIG_MLX5_CLS_ACT)
1300 static void esw_vport_tbl_put(struct mlx5_eswitch *esw)
1301 {
1302 	struct mlx5_vport_tbl_attr attr;
1303 	struct mlx5_vport *vport;
1304 	unsigned long i;
1305 
1306 	attr.chain = 0;
1307 	attr.prio = 1;
1308 	mlx5_esw_for_each_vport(esw, i, vport) {
1309 		attr.vport = vport->vport;
1310 		attr.vport_ns = &mlx5_esw_vport_tbl_mirror_ns;
1311 		mlx5_esw_vporttbl_put(esw, &attr);
1312 	}
1313 }
1314 
1315 static int esw_vport_tbl_get(struct mlx5_eswitch *esw)
1316 {
1317 	struct mlx5_vport_tbl_attr attr;
1318 	struct mlx5_flow_table *fdb;
1319 	struct mlx5_vport *vport;
1320 	unsigned long i;
1321 
1322 	attr.chain = 0;
1323 	attr.prio = 1;
1324 	mlx5_esw_for_each_vport(esw, i, vport) {
1325 		attr.vport = vport->vport;
1326 		attr.vport_ns = &mlx5_esw_vport_tbl_mirror_ns;
1327 		fdb = mlx5_esw_vporttbl_get(esw, &attr);
1328 		if (IS_ERR(fdb))
1329 			goto out;
1330 	}
1331 	return 0;
1332 
1333 out:
1334 	esw_vport_tbl_put(esw);
1335 	return PTR_ERR(fdb);
1336 }
1337 
1338 #define fdb_modify_header_fwd_to_table_supported(esw) \
1339 	(MLX5_CAP_ESW_FLOWTABLE((esw)->dev, fdb_modify_header_fwd_to_table))
1340 static void esw_init_chains_offload_flags(struct mlx5_eswitch *esw, u32 *flags)
1341 {
1342 	struct mlx5_core_dev *dev = esw->dev;
1343 
1344 	if (MLX5_CAP_ESW_FLOWTABLE_FDB(dev, ignore_flow_level))
1345 		*flags |= MLX5_CHAINS_IGNORE_FLOW_LEVEL_SUPPORTED;
1346 
1347 	if (!MLX5_CAP_ESW_FLOWTABLE(dev, multi_fdb_encap) &&
1348 	    esw->offloads.encap != DEVLINK_ESWITCH_ENCAP_MODE_NONE) {
1349 		*flags &= ~MLX5_CHAINS_AND_PRIOS_SUPPORTED;
1350 		esw_warn(dev, "Tc chains and priorities offload aren't supported, update firmware if needed\n");
1351 	} else if (!mlx5_eswitch_reg_c1_loopback_enabled(esw)) {
1352 		*flags &= ~MLX5_CHAINS_AND_PRIOS_SUPPORTED;
1353 		esw_warn(dev, "Tc chains and priorities offload aren't supported\n");
1354 	} else if (!fdb_modify_header_fwd_to_table_supported(esw)) {
1355 		/* Disabled when ttl workaround is needed, e.g
1356 		 * when ESWITCH_IPV4_TTL_MODIFY_ENABLE = true in mlxconfig
1357 		 */
1358 		esw_warn(dev,
1359 			 "Tc chains and priorities offload aren't supported, check firmware version, or mlxconfig settings\n");
1360 		*flags &= ~MLX5_CHAINS_AND_PRIOS_SUPPORTED;
1361 	} else {
1362 		*flags |= MLX5_CHAINS_AND_PRIOS_SUPPORTED;
1363 		esw_info(dev, "Supported tc chains and prios offload\n");
1364 	}
1365 
1366 	if (esw->offloads.encap != DEVLINK_ESWITCH_ENCAP_MODE_NONE)
1367 		*flags |= MLX5_CHAINS_FT_TUNNEL_SUPPORTED;
1368 }
1369 
1370 static int
1371 esw_chains_create(struct mlx5_eswitch *esw, struct mlx5_flow_table *miss_fdb)
1372 {
1373 	struct mlx5_core_dev *dev = esw->dev;
1374 	struct mlx5_flow_table *nf_ft, *ft;
1375 	struct mlx5_chains_attr attr = {};
1376 	struct mlx5_fs_chains *chains;
1377 	u32 fdb_max;
1378 	int err;
1379 
1380 	fdb_max = 1 << MLX5_CAP_ESW_FLOWTABLE_FDB(dev, log_max_ft_size);
1381 
1382 	esw_init_chains_offload_flags(esw, &attr.flags);
1383 	attr.ns = MLX5_FLOW_NAMESPACE_FDB;
1384 	attr.max_ft_sz = fdb_max;
1385 	attr.max_grp_num = esw->params.large_group_num;
1386 	attr.default_ft = miss_fdb;
1387 	attr.mapping = esw->offloads.reg_c0_obj_pool;
1388 
1389 	chains = mlx5_chains_create(dev, &attr);
1390 	if (IS_ERR(chains)) {
1391 		err = PTR_ERR(chains);
1392 		esw_warn(dev, "Failed to create fdb chains err(%d)\n", err);
1393 		return err;
1394 	}
1395 
1396 	esw->fdb_table.offloads.esw_chains_priv = chains;
1397 
1398 	/* Create tc_end_ft which is the always created ft chain */
1399 	nf_ft = mlx5_chains_get_table(chains, mlx5_chains_get_nf_ft_chain(chains),
1400 				      1, 0);
1401 	if (IS_ERR(nf_ft)) {
1402 		err = PTR_ERR(nf_ft);
1403 		goto nf_ft_err;
1404 	}
1405 
1406 	/* Always open the root for fast path */
1407 	ft = mlx5_chains_get_table(chains, 0, 1, 0);
1408 	if (IS_ERR(ft)) {
1409 		err = PTR_ERR(ft);
1410 		goto level_0_err;
1411 	}
1412 
1413 	/* Open level 1 for split fdb rules now if prios isn't supported  */
1414 	if (!mlx5_chains_prios_supported(chains)) {
1415 		err = esw_vport_tbl_get(esw);
1416 		if (err)
1417 			goto level_1_err;
1418 	}
1419 
1420 	mlx5_chains_set_end_ft(chains, nf_ft);
1421 
1422 	return 0;
1423 
1424 level_1_err:
1425 	mlx5_chains_put_table(chains, 0, 1, 0);
1426 level_0_err:
1427 	mlx5_chains_put_table(chains, mlx5_chains_get_nf_ft_chain(chains), 1, 0);
1428 nf_ft_err:
1429 	mlx5_chains_destroy(chains);
1430 	esw->fdb_table.offloads.esw_chains_priv = NULL;
1431 
1432 	return err;
1433 }
1434 
1435 static void
1436 esw_chains_destroy(struct mlx5_eswitch *esw, struct mlx5_fs_chains *chains)
1437 {
1438 	if (!mlx5_chains_prios_supported(chains))
1439 		esw_vport_tbl_put(esw);
1440 	mlx5_chains_put_table(chains, 0, 1, 0);
1441 	mlx5_chains_put_table(chains, mlx5_chains_get_nf_ft_chain(chains), 1, 0);
1442 	mlx5_chains_destroy(chains);
1443 }
1444 
1445 #else /* CONFIG_MLX5_CLS_ACT */
1446 
1447 static int
1448 esw_chains_create(struct mlx5_eswitch *esw, struct mlx5_flow_table *miss_fdb)
1449 { return 0; }
1450 
1451 static void
1452 esw_chains_destroy(struct mlx5_eswitch *esw, struct mlx5_fs_chains *chains)
1453 {}
1454 
1455 #endif
1456 
1457 static int
1458 esw_create_send_to_vport_group(struct mlx5_eswitch *esw,
1459 			       struct mlx5_flow_table *fdb,
1460 			       u32 *flow_group_in,
1461 			       int *ix)
1462 {
1463 	int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
1464 	struct mlx5_flow_group *g;
1465 	void *match_criteria;
1466 	int count, err = 0;
1467 
1468 	memset(flow_group_in, 0, inlen);
1469 
1470 	MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
1471 		 MLX5_MATCH_MISC_PARAMETERS);
1472 
1473 	match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in, match_criteria);
1474 
1475 	MLX5_SET_TO_ONES(fte_match_param, match_criteria, misc_parameters.source_sqn);
1476 	MLX5_SET_TO_ONES(fte_match_param, match_criteria, misc_parameters.source_port);
1477 	if (MLX5_CAP_ESW(esw->dev, merged_eswitch)) {
1478 		MLX5_SET_TO_ONES(fte_match_param, match_criteria,
1479 				 misc_parameters.source_eswitch_owner_vhca_id);
1480 		MLX5_SET(create_flow_group_in, flow_group_in,
1481 			 source_eswitch_owner_vhca_id_valid, 1);
1482 	}
1483 
1484 	/* See comment at table_size calculation */
1485 	count = MLX5_MAX_PORTS * (esw->total_vports * MAX_SQ_NVPORTS + MAX_PF_SQ);
1486 	MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 0);
1487 	MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, *ix + count - 1);
1488 	*ix += count;
1489 
1490 	g = mlx5_create_flow_group(fdb, flow_group_in);
1491 	if (IS_ERR(g)) {
1492 		err = PTR_ERR(g);
1493 		esw_warn(esw->dev, "Failed to create send-to-vport flow group err(%d)\n", err);
1494 		goto out;
1495 	}
1496 	esw->fdb_table.offloads.send_to_vport_grp = g;
1497 
1498 out:
1499 	return err;
1500 }
1501 
1502 static int
1503 esw_create_meta_send_to_vport_group(struct mlx5_eswitch *esw,
1504 				    struct mlx5_flow_table *fdb,
1505 				    u32 *flow_group_in,
1506 				    int *ix)
1507 {
1508 	int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
1509 	struct mlx5_flow_group *g;
1510 	void *match_criteria;
1511 	int err = 0;
1512 
1513 	if (!esw_src_port_rewrite_supported(esw))
1514 		return 0;
1515 
1516 	memset(flow_group_in, 0, inlen);
1517 
1518 	MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
1519 		 MLX5_MATCH_MISC_PARAMETERS_2);
1520 
1521 	match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in, match_criteria);
1522 
1523 	MLX5_SET(fte_match_param, match_criteria,
1524 		 misc_parameters_2.metadata_reg_c_0,
1525 		 mlx5_eswitch_get_vport_metadata_mask());
1526 	MLX5_SET(fte_match_param, match_criteria,
1527 		 misc_parameters_2.metadata_reg_c_1, ESW_TUN_MASK);
1528 
1529 	MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, *ix);
1530 	MLX5_SET(create_flow_group_in, flow_group_in,
1531 		 end_flow_index, *ix + esw->total_vports - 1);
1532 	*ix += esw->total_vports;
1533 
1534 	g = mlx5_create_flow_group(fdb, flow_group_in);
1535 	if (IS_ERR(g)) {
1536 		err = PTR_ERR(g);
1537 		esw_warn(esw->dev,
1538 			 "Failed to create send-to-vport meta flow group err(%d)\n", err);
1539 		goto send_vport_meta_err;
1540 	}
1541 	esw->fdb_table.offloads.send_to_vport_meta_grp = g;
1542 
1543 	return 0;
1544 
1545 send_vport_meta_err:
1546 	return err;
1547 }
1548 
1549 static int
1550 esw_create_peer_esw_miss_group(struct mlx5_eswitch *esw,
1551 			       struct mlx5_flow_table *fdb,
1552 			       u32 *flow_group_in,
1553 			       int *ix)
1554 {
1555 	int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
1556 	struct mlx5_flow_group *g;
1557 	void *match_criteria;
1558 	int err = 0;
1559 
1560 	if (!MLX5_CAP_ESW(esw->dev, merged_eswitch))
1561 		return 0;
1562 
1563 	memset(flow_group_in, 0, inlen);
1564 
1565 	esw_set_flow_group_source_port(esw, flow_group_in);
1566 
1567 	if (!mlx5_eswitch_vport_match_metadata_enabled(esw)) {
1568 		match_criteria = MLX5_ADDR_OF(create_flow_group_in,
1569 					      flow_group_in,
1570 					      match_criteria);
1571 
1572 		MLX5_SET_TO_ONES(fte_match_param, match_criteria,
1573 				 misc_parameters.source_eswitch_owner_vhca_id);
1574 
1575 		MLX5_SET(create_flow_group_in, flow_group_in,
1576 			 source_eswitch_owner_vhca_id_valid, 1);
1577 	}
1578 
1579 	MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, *ix);
1580 	MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index,
1581 		 *ix + esw->total_vports - 1);
1582 	*ix += esw->total_vports;
1583 
1584 	g = mlx5_create_flow_group(fdb, flow_group_in);
1585 	if (IS_ERR(g)) {
1586 		err = PTR_ERR(g);
1587 		esw_warn(esw->dev, "Failed to create peer miss flow group err(%d)\n", err);
1588 		goto out;
1589 	}
1590 	esw->fdb_table.offloads.peer_miss_grp = g;
1591 
1592 out:
1593 	return err;
1594 }
1595 
1596 static int
1597 esw_create_miss_group(struct mlx5_eswitch *esw,
1598 		      struct mlx5_flow_table *fdb,
1599 		      u32 *flow_group_in,
1600 		      int *ix)
1601 {
1602 	int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
1603 	struct mlx5_flow_group *g;
1604 	void *match_criteria;
1605 	int err = 0;
1606 	u8 *dmac;
1607 
1608 	memset(flow_group_in, 0, inlen);
1609 
1610 	MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
1611 		 MLX5_MATCH_OUTER_HEADERS);
1612 	match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in,
1613 				      match_criteria);
1614 	dmac = MLX5_ADDR_OF(fte_match_param, match_criteria,
1615 			    outer_headers.dmac_47_16);
1616 	dmac[0] = 0x01;
1617 
1618 	MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, *ix);
1619 	MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index,
1620 		 *ix + MLX5_ESW_MISS_FLOWS);
1621 
1622 	g = mlx5_create_flow_group(fdb, flow_group_in);
1623 	if (IS_ERR(g)) {
1624 		err = PTR_ERR(g);
1625 		esw_warn(esw->dev, "Failed to create miss flow group err(%d)\n", err);
1626 		goto miss_err;
1627 	}
1628 	esw->fdb_table.offloads.miss_grp = g;
1629 
1630 	err = esw_add_fdb_miss_rule(esw);
1631 	if (err)
1632 		goto miss_rule_err;
1633 
1634 	return 0;
1635 
1636 miss_rule_err:
1637 	mlx5_destroy_flow_group(esw->fdb_table.offloads.miss_grp);
1638 miss_err:
1639 	return err;
1640 }
1641 
1642 static int esw_create_offloads_fdb_tables(struct mlx5_eswitch *esw)
1643 {
1644 	int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
1645 	struct mlx5_flow_table_attr ft_attr = {};
1646 	struct mlx5_core_dev *dev = esw->dev;
1647 	struct mlx5_flow_namespace *root_ns;
1648 	struct mlx5_flow_table *fdb = NULL;
1649 	int table_size, ix = 0, err = 0;
1650 	u32 flags = 0, *flow_group_in;
1651 
1652 	esw_debug(esw->dev, "Create offloads FDB Tables\n");
1653 
1654 	flow_group_in = kvzalloc(inlen, GFP_KERNEL);
1655 	if (!flow_group_in)
1656 		return -ENOMEM;
1657 
1658 	root_ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_FDB);
1659 	if (!root_ns) {
1660 		esw_warn(dev, "Failed to get FDB flow namespace\n");
1661 		err = -EOPNOTSUPP;
1662 		goto ns_err;
1663 	}
1664 	esw->fdb_table.offloads.ns = root_ns;
1665 	err = mlx5_flow_namespace_set_mode(root_ns,
1666 					   esw->dev->priv.steering->mode);
1667 	if (err) {
1668 		esw_warn(dev, "Failed to set FDB namespace steering mode\n");
1669 		goto ns_err;
1670 	}
1671 
1672 	/* To be strictly correct:
1673 	 *	MLX5_MAX_PORTS * (esw->total_vports * MAX_SQ_NVPORTS + MAX_PF_SQ)
1674 	 * should be:
1675 	 *	esw->total_vports * MAX_SQ_NVPORTS + MAX_PF_SQ +
1676 	 *	peer_esw->total_vports * MAX_SQ_NVPORTS + MAX_PF_SQ
1677 	 * but as the peer device might not be in switchdev mode it's not
1678 	 * possible. We use the fact that by default FW sets max vfs and max sfs
1679 	 * to the same value on both devices. If it needs to be changed in the future note
1680 	 * the peer miss group should also be created based on the number of
1681 	 * total vports of the peer (currently is also uses esw->total_vports).
1682 	 */
1683 	table_size = MLX5_MAX_PORTS * (esw->total_vports * MAX_SQ_NVPORTS + MAX_PF_SQ) +
1684 		     esw->total_vports * 2 + MLX5_ESW_MISS_FLOWS;
1685 
1686 	/* create the slow path fdb with encap set, so further table instances
1687 	 * can be created at run time while VFs are probed if the FW allows that.
1688 	 */
1689 	if (esw->offloads.encap != DEVLINK_ESWITCH_ENCAP_MODE_NONE)
1690 		flags |= (MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT |
1691 			  MLX5_FLOW_TABLE_TUNNEL_EN_DECAP);
1692 
1693 	ft_attr.flags = flags;
1694 	ft_attr.max_fte = table_size;
1695 	ft_attr.prio = FDB_SLOW_PATH;
1696 
1697 	fdb = mlx5_create_flow_table(root_ns, &ft_attr);
1698 	if (IS_ERR(fdb)) {
1699 		err = PTR_ERR(fdb);
1700 		esw_warn(dev, "Failed to create slow path FDB Table err %d\n", err);
1701 		goto slow_fdb_err;
1702 	}
1703 	esw->fdb_table.offloads.slow_fdb = fdb;
1704 
1705 	/* Create empty TC-miss managed table. This allows plugging in following
1706 	 * priorities without directly exposing their level 0 table to
1707 	 * eswitch_offloads and passing it as miss_fdb to following call to
1708 	 * esw_chains_create().
1709 	 */
1710 	memset(&ft_attr, 0, sizeof(ft_attr));
1711 	ft_attr.prio = FDB_TC_MISS;
1712 	esw->fdb_table.offloads.tc_miss_table = mlx5_create_flow_table(root_ns, &ft_attr);
1713 	if (IS_ERR(esw->fdb_table.offloads.tc_miss_table)) {
1714 		err = PTR_ERR(esw->fdb_table.offloads.tc_miss_table);
1715 		esw_warn(dev, "Failed to create TC miss FDB Table err %d\n", err);
1716 		goto tc_miss_table_err;
1717 	}
1718 
1719 	err = esw_chains_create(esw, esw->fdb_table.offloads.tc_miss_table);
1720 	if (err) {
1721 		esw_warn(dev, "Failed to open fdb chains err(%d)\n", err);
1722 		goto fdb_chains_err;
1723 	}
1724 
1725 	err = esw_create_send_to_vport_group(esw, fdb, flow_group_in, &ix);
1726 	if (err)
1727 		goto send_vport_err;
1728 
1729 	err = esw_create_meta_send_to_vport_group(esw, fdb, flow_group_in, &ix);
1730 	if (err)
1731 		goto send_vport_meta_err;
1732 
1733 	err = esw_create_peer_esw_miss_group(esw, fdb, flow_group_in, &ix);
1734 	if (err)
1735 		goto peer_miss_err;
1736 
1737 	err = esw_create_miss_group(esw, fdb, flow_group_in, &ix);
1738 	if (err)
1739 		goto miss_err;
1740 
1741 	kvfree(flow_group_in);
1742 	return 0;
1743 
1744 miss_err:
1745 	if (MLX5_CAP_ESW(esw->dev, merged_eswitch))
1746 		mlx5_destroy_flow_group(esw->fdb_table.offloads.peer_miss_grp);
1747 peer_miss_err:
1748 	if (esw->fdb_table.offloads.send_to_vport_meta_grp)
1749 		mlx5_destroy_flow_group(esw->fdb_table.offloads.send_to_vport_meta_grp);
1750 send_vport_meta_err:
1751 	mlx5_destroy_flow_group(esw->fdb_table.offloads.send_to_vport_grp);
1752 send_vport_err:
1753 	esw_chains_destroy(esw, esw_chains(esw));
1754 fdb_chains_err:
1755 	mlx5_destroy_flow_table(esw->fdb_table.offloads.tc_miss_table);
1756 tc_miss_table_err:
1757 	mlx5_destroy_flow_table(mlx5_eswitch_get_slow_fdb(esw));
1758 slow_fdb_err:
1759 	/* Holds true only as long as DMFS is the default */
1760 	mlx5_flow_namespace_set_mode(root_ns, MLX5_FLOW_STEERING_MODE_DMFS);
1761 ns_err:
1762 	kvfree(flow_group_in);
1763 	return err;
1764 }
1765 
1766 static void esw_destroy_offloads_fdb_tables(struct mlx5_eswitch *esw)
1767 {
1768 	if (!mlx5_eswitch_get_slow_fdb(esw))
1769 		return;
1770 
1771 	esw_debug(esw->dev, "Destroy offloads FDB Tables\n");
1772 	mlx5_del_flow_rules(esw->fdb_table.offloads.miss_rule_multi);
1773 	mlx5_del_flow_rules(esw->fdb_table.offloads.miss_rule_uni);
1774 	mlx5_destroy_flow_group(esw->fdb_table.offloads.send_to_vport_grp);
1775 	if (esw->fdb_table.offloads.send_to_vport_meta_grp)
1776 		mlx5_destroy_flow_group(esw->fdb_table.offloads.send_to_vport_meta_grp);
1777 	if (MLX5_CAP_ESW(esw->dev, merged_eswitch))
1778 		mlx5_destroy_flow_group(esw->fdb_table.offloads.peer_miss_grp);
1779 	mlx5_destroy_flow_group(esw->fdb_table.offloads.miss_grp);
1780 
1781 	esw_chains_destroy(esw, esw_chains(esw));
1782 
1783 	mlx5_destroy_flow_table(esw->fdb_table.offloads.tc_miss_table);
1784 	mlx5_destroy_flow_table(mlx5_eswitch_get_slow_fdb(esw));
1785 	/* Holds true only as long as DMFS is the default */
1786 	mlx5_flow_namespace_set_mode(esw->fdb_table.offloads.ns,
1787 				     MLX5_FLOW_STEERING_MODE_DMFS);
1788 	atomic64_set(&esw->user_count, 0);
1789 }
1790 
1791 static int esw_get_nr_ft_offloads_steering_src_ports(struct mlx5_eswitch *esw)
1792 {
1793 	int nvports;
1794 
1795 	nvports = esw->total_vports + MLX5_ESW_MISS_FLOWS;
1796 	if (mlx5e_tc_int_port_supported(esw))
1797 		nvports += MLX5E_TC_MAX_INT_PORT_NUM;
1798 
1799 	return nvports;
1800 }
1801 
1802 static int esw_create_offloads_table(struct mlx5_eswitch *esw)
1803 {
1804 	struct mlx5_flow_table_attr ft_attr = {};
1805 	struct mlx5_core_dev *dev = esw->dev;
1806 	struct mlx5_flow_table *ft_offloads;
1807 	struct mlx5_flow_namespace *ns;
1808 	int err = 0;
1809 
1810 	ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_OFFLOADS);
1811 	if (!ns) {
1812 		esw_warn(esw->dev, "Failed to get offloads flow namespace\n");
1813 		return -EOPNOTSUPP;
1814 	}
1815 
1816 	ft_attr.max_fte = esw_get_nr_ft_offloads_steering_src_ports(esw) +
1817 			  MLX5_ESW_FT_OFFLOADS_DROP_RULE;
1818 	ft_attr.prio = 1;
1819 
1820 	ft_offloads = mlx5_create_flow_table(ns, &ft_attr);
1821 	if (IS_ERR(ft_offloads)) {
1822 		err = PTR_ERR(ft_offloads);
1823 		esw_warn(esw->dev, "Failed to create offloads table, err %d\n", err);
1824 		return err;
1825 	}
1826 
1827 	esw->offloads.ft_offloads = ft_offloads;
1828 	return 0;
1829 }
1830 
1831 static void esw_destroy_offloads_table(struct mlx5_eswitch *esw)
1832 {
1833 	struct mlx5_esw_offload *offloads = &esw->offloads;
1834 
1835 	mlx5_destroy_flow_table(offloads->ft_offloads);
1836 }
1837 
1838 static int esw_create_vport_rx_group(struct mlx5_eswitch *esw)
1839 {
1840 	int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
1841 	struct mlx5_flow_group *g;
1842 	u32 *flow_group_in;
1843 	int nvports;
1844 	int err = 0;
1845 
1846 	nvports = esw_get_nr_ft_offloads_steering_src_ports(esw);
1847 	flow_group_in = kvzalloc(inlen, GFP_KERNEL);
1848 	if (!flow_group_in)
1849 		return -ENOMEM;
1850 
1851 	/* create vport rx group */
1852 	esw_set_flow_group_source_port(esw, flow_group_in);
1853 
1854 	MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 0);
1855 	MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, nvports - 1);
1856 
1857 	g = mlx5_create_flow_group(esw->offloads.ft_offloads, flow_group_in);
1858 
1859 	if (IS_ERR(g)) {
1860 		err = PTR_ERR(g);
1861 		mlx5_core_warn(esw->dev, "Failed to create vport rx group err %d\n", err);
1862 		goto out;
1863 	}
1864 
1865 	esw->offloads.vport_rx_group = g;
1866 out:
1867 	kvfree(flow_group_in);
1868 	return err;
1869 }
1870 
1871 static void esw_destroy_vport_rx_group(struct mlx5_eswitch *esw)
1872 {
1873 	mlx5_destroy_flow_group(esw->offloads.vport_rx_group);
1874 }
1875 
1876 static int esw_create_vport_rx_drop_rule_index(struct mlx5_eswitch *esw)
1877 {
1878 	/* ft_offloads table is enlarged by MLX5_ESW_FT_OFFLOADS_DROP_RULE (1)
1879 	 * for the drop rule, which is placed at the end of the table.
1880 	 * So return the total of vport and int_port as rule index.
1881 	 */
1882 	return esw_get_nr_ft_offloads_steering_src_ports(esw);
1883 }
1884 
1885 static int esw_create_vport_rx_drop_group(struct mlx5_eswitch *esw)
1886 {
1887 	int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
1888 	struct mlx5_flow_group *g;
1889 	u32 *flow_group_in;
1890 	int flow_index;
1891 	int err = 0;
1892 
1893 	flow_index = esw_create_vport_rx_drop_rule_index(esw);
1894 
1895 	flow_group_in = kvzalloc(inlen, GFP_KERNEL);
1896 	if (!flow_group_in)
1897 		return -ENOMEM;
1898 
1899 	MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, flow_index);
1900 	MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, flow_index);
1901 
1902 	g = mlx5_create_flow_group(esw->offloads.ft_offloads, flow_group_in);
1903 
1904 	if (IS_ERR(g)) {
1905 		err = PTR_ERR(g);
1906 		mlx5_core_warn(esw->dev, "Failed to create vport rx drop group err %d\n", err);
1907 		goto out;
1908 	}
1909 
1910 	esw->offloads.vport_rx_drop_group = g;
1911 out:
1912 	kvfree(flow_group_in);
1913 	return err;
1914 }
1915 
1916 static void esw_destroy_vport_rx_drop_group(struct mlx5_eswitch *esw)
1917 {
1918 	if (esw->offloads.vport_rx_drop_group)
1919 		mlx5_destroy_flow_group(esw->offloads.vport_rx_drop_group);
1920 }
1921 
1922 struct mlx5_flow_handle *
1923 mlx5_eswitch_create_vport_rx_rule(struct mlx5_eswitch *esw, u16 vport,
1924 				  struct mlx5_flow_destination *dest)
1925 {
1926 	struct mlx5_flow_act flow_act = {0};
1927 	struct mlx5_flow_handle *flow_rule;
1928 	struct mlx5_flow_spec *spec;
1929 	void *misc;
1930 
1931 	spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
1932 	if (!spec) {
1933 		flow_rule = ERR_PTR(-ENOMEM);
1934 		goto out;
1935 	}
1936 
1937 	if (mlx5_eswitch_vport_match_metadata_enabled(esw)) {
1938 		misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters_2);
1939 		MLX5_SET(fte_match_set_misc2, misc, metadata_reg_c_0,
1940 			 mlx5_eswitch_get_vport_metadata_for_match(esw, vport));
1941 
1942 		misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters_2);
1943 		MLX5_SET(fte_match_set_misc2, misc, metadata_reg_c_0,
1944 			 mlx5_eswitch_get_vport_metadata_mask());
1945 
1946 		spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS_2;
1947 	} else {
1948 		misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters);
1949 		MLX5_SET(fte_match_set_misc, misc, source_port, vport);
1950 
1951 		misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters);
1952 		MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port);
1953 
1954 		spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS;
1955 	}
1956 
1957 	flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
1958 	flow_rule = mlx5_add_flow_rules(esw->offloads.ft_offloads, spec,
1959 					&flow_act, dest, 1);
1960 	if (IS_ERR(flow_rule)) {
1961 		esw_warn(esw->dev, "fs offloads: Failed to add vport rx rule err %ld\n", PTR_ERR(flow_rule));
1962 		goto out;
1963 	}
1964 
1965 out:
1966 	kvfree(spec);
1967 	return flow_rule;
1968 }
1969 
1970 static int esw_create_vport_rx_drop_rule(struct mlx5_eswitch *esw)
1971 {
1972 	struct mlx5_flow_act flow_act = {};
1973 	struct mlx5_flow_handle *flow_rule;
1974 
1975 	flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP;
1976 	flow_rule = mlx5_add_flow_rules(esw->offloads.ft_offloads, NULL,
1977 					&flow_act, NULL, 0);
1978 	if (IS_ERR(flow_rule)) {
1979 		esw_warn(esw->dev,
1980 			 "fs offloads: Failed to add vport rx drop rule err %ld\n",
1981 			 PTR_ERR(flow_rule));
1982 		return PTR_ERR(flow_rule);
1983 	}
1984 
1985 	esw->offloads.vport_rx_drop_rule = flow_rule;
1986 
1987 	return 0;
1988 }
1989 
1990 static void esw_destroy_vport_rx_drop_rule(struct mlx5_eswitch *esw)
1991 {
1992 	if (esw->offloads.vport_rx_drop_rule)
1993 		mlx5_del_flow_rules(esw->offloads.vport_rx_drop_rule);
1994 }
1995 
1996 static int mlx5_eswitch_inline_mode_get(struct mlx5_eswitch *esw, u8 *mode)
1997 {
1998 	u8 prev_mlx5_mode, mlx5_mode = MLX5_INLINE_MODE_L2;
1999 	struct mlx5_core_dev *dev = esw->dev;
2000 	struct mlx5_vport *vport;
2001 	unsigned long i;
2002 
2003 	if (!MLX5_CAP_GEN(dev, vport_group_manager))
2004 		return -EOPNOTSUPP;
2005 
2006 	if (!mlx5_esw_is_fdb_created(esw))
2007 		return -EOPNOTSUPP;
2008 
2009 	switch (MLX5_CAP_ETH(dev, wqe_inline_mode)) {
2010 	case MLX5_CAP_INLINE_MODE_NOT_REQUIRED:
2011 		mlx5_mode = MLX5_INLINE_MODE_NONE;
2012 		goto out;
2013 	case MLX5_CAP_INLINE_MODE_L2:
2014 		mlx5_mode = MLX5_INLINE_MODE_L2;
2015 		goto out;
2016 	case MLX5_CAP_INLINE_MODE_VPORT_CONTEXT:
2017 		goto query_vports;
2018 	}
2019 
2020 query_vports:
2021 	mlx5_query_nic_vport_min_inline(dev, esw->first_host_vport, &prev_mlx5_mode);
2022 	mlx5_esw_for_each_host_func_vport(esw, i, vport, esw->esw_funcs.num_vfs) {
2023 		mlx5_query_nic_vport_min_inline(dev, vport->vport, &mlx5_mode);
2024 		if (prev_mlx5_mode != mlx5_mode)
2025 			return -EINVAL;
2026 		prev_mlx5_mode = mlx5_mode;
2027 	}
2028 
2029 out:
2030 	*mode = mlx5_mode;
2031 	return 0;
2032 }
2033 
2034 static void esw_destroy_restore_table(struct mlx5_eswitch *esw)
2035 {
2036 	struct mlx5_esw_offload *offloads = &esw->offloads;
2037 
2038 	if (!mlx5_eswitch_reg_c1_loopback_supported(esw))
2039 		return;
2040 
2041 	mlx5_modify_header_dealloc(esw->dev, offloads->restore_copy_hdr_id);
2042 	mlx5_destroy_flow_group(offloads->restore_group);
2043 	mlx5_destroy_flow_table(offloads->ft_offloads_restore);
2044 }
2045 
2046 static int esw_create_restore_table(struct mlx5_eswitch *esw)
2047 {
2048 	u8 modact[MLX5_UN_SZ_BYTES(set_add_copy_action_in_auto)] = {};
2049 	int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
2050 	struct mlx5_flow_table_attr ft_attr = {};
2051 	struct mlx5_core_dev *dev = esw->dev;
2052 	struct mlx5_flow_namespace *ns;
2053 	struct mlx5_modify_hdr *mod_hdr;
2054 	void *match_criteria, *misc;
2055 	struct mlx5_flow_table *ft;
2056 	struct mlx5_flow_group *g;
2057 	u32 *flow_group_in;
2058 	int err = 0;
2059 
2060 	if (!mlx5_eswitch_reg_c1_loopback_supported(esw))
2061 		return 0;
2062 
2063 	ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_OFFLOADS);
2064 	if (!ns) {
2065 		esw_warn(esw->dev, "Failed to get offloads flow namespace\n");
2066 		return -EOPNOTSUPP;
2067 	}
2068 
2069 	flow_group_in = kvzalloc(inlen, GFP_KERNEL);
2070 	if (!flow_group_in) {
2071 		err = -ENOMEM;
2072 		goto out_free;
2073 	}
2074 
2075 	ft_attr.max_fte = 1 << ESW_REG_C0_USER_DATA_METADATA_BITS;
2076 	ft = mlx5_create_flow_table(ns, &ft_attr);
2077 	if (IS_ERR(ft)) {
2078 		err = PTR_ERR(ft);
2079 		esw_warn(esw->dev, "Failed to create restore table, err %d\n",
2080 			 err);
2081 		goto out_free;
2082 	}
2083 
2084 	match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in,
2085 				      match_criteria);
2086 	misc = MLX5_ADDR_OF(fte_match_param, match_criteria,
2087 			    misc_parameters_2);
2088 
2089 	MLX5_SET(fte_match_set_misc2, misc, metadata_reg_c_0,
2090 		 ESW_REG_C0_USER_DATA_METADATA_MASK);
2091 	MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 0);
2092 	MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index,
2093 		 ft_attr.max_fte - 1);
2094 	MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
2095 		 MLX5_MATCH_MISC_PARAMETERS_2);
2096 	g = mlx5_create_flow_group(ft, flow_group_in);
2097 	if (IS_ERR(g)) {
2098 		err = PTR_ERR(g);
2099 		esw_warn(dev, "Failed to create restore flow group, err: %d\n",
2100 			 err);
2101 		goto err_group;
2102 	}
2103 
2104 	MLX5_SET(copy_action_in, modact, action_type, MLX5_ACTION_TYPE_COPY);
2105 	MLX5_SET(copy_action_in, modact, src_field,
2106 		 MLX5_ACTION_IN_FIELD_METADATA_REG_C_1);
2107 	MLX5_SET(copy_action_in, modact, dst_field,
2108 		 MLX5_ACTION_IN_FIELD_METADATA_REG_B);
2109 	mod_hdr = mlx5_modify_header_alloc(esw->dev,
2110 					   MLX5_FLOW_NAMESPACE_KERNEL, 1,
2111 					   modact);
2112 	if (IS_ERR(mod_hdr)) {
2113 		err = PTR_ERR(mod_hdr);
2114 		esw_warn(dev, "Failed to create restore mod header, err: %d\n",
2115 			 err);
2116 		goto err_mod_hdr;
2117 	}
2118 
2119 	esw->offloads.ft_offloads_restore = ft;
2120 	esw->offloads.restore_group = g;
2121 	esw->offloads.restore_copy_hdr_id = mod_hdr;
2122 
2123 	kvfree(flow_group_in);
2124 
2125 	return 0;
2126 
2127 err_mod_hdr:
2128 	mlx5_destroy_flow_group(g);
2129 err_group:
2130 	mlx5_destroy_flow_table(ft);
2131 out_free:
2132 	kvfree(flow_group_in);
2133 
2134 	return err;
2135 }
2136 
2137 static int esw_offloads_start(struct mlx5_eswitch *esw,
2138 			      struct netlink_ext_ack *extack)
2139 {
2140 	int err;
2141 
2142 	esw->mode = MLX5_ESWITCH_OFFLOADS;
2143 	err = mlx5_eswitch_enable_locked(esw, esw->dev->priv.sriov.num_vfs);
2144 	if (err) {
2145 		NL_SET_ERR_MSG_MOD(extack,
2146 				   "Failed setting eswitch to offloads");
2147 		esw->mode = MLX5_ESWITCH_LEGACY;
2148 		mlx5_rescan_drivers(esw->dev);
2149 	}
2150 	if (esw->offloads.inline_mode == MLX5_INLINE_MODE_NONE) {
2151 		if (mlx5_eswitch_inline_mode_get(esw,
2152 						 &esw->offloads.inline_mode)) {
2153 			esw->offloads.inline_mode = MLX5_INLINE_MODE_L2;
2154 			NL_SET_ERR_MSG_MOD(extack,
2155 					   "Inline mode is different between vports");
2156 		}
2157 	}
2158 	return err;
2159 }
2160 
2161 static void mlx5_esw_offloads_rep_mark_set(struct mlx5_eswitch *esw,
2162 					   struct mlx5_eswitch_rep *rep,
2163 					   xa_mark_t mark)
2164 {
2165 	bool mark_set;
2166 
2167 	/* Copy the mark from vport to its rep */
2168 	mark_set = xa_get_mark(&esw->vports, rep->vport, mark);
2169 	if (mark_set)
2170 		xa_set_mark(&esw->offloads.vport_reps, rep->vport, mark);
2171 }
2172 
2173 static int mlx5_esw_offloads_rep_init(struct mlx5_eswitch *esw, const struct mlx5_vport *vport)
2174 {
2175 	struct mlx5_eswitch_rep *rep;
2176 	int rep_type;
2177 	int err;
2178 
2179 	rep = kzalloc(sizeof(*rep), GFP_KERNEL);
2180 	if (!rep)
2181 		return -ENOMEM;
2182 
2183 	rep->vport = vport->vport;
2184 	rep->vport_index = vport->index;
2185 	for (rep_type = 0; rep_type < NUM_REP_TYPES; rep_type++)
2186 		atomic_set(&rep->rep_data[rep_type].state, REP_UNREGISTERED);
2187 
2188 	err = xa_insert(&esw->offloads.vport_reps, rep->vport, rep, GFP_KERNEL);
2189 	if (err)
2190 		goto insert_err;
2191 
2192 	mlx5_esw_offloads_rep_mark_set(esw, rep, MLX5_ESW_VPT_HOST_FN);
2193 	mlx5_esw_offloads_rep_mark_set(esw, rep, MLX5_ESW_VPT_VF);
2194 	mlx5_esw_offloads_rep_mark_set(esw, rep, MLX5_ESW_VPT_SF);
2195 	return 0;
2196 
2197 insert_err:
2198 	kfree(rep);
2199 	return err;
2200 }
2201 
2202 static void mlx5_esw_offloads_rep_cleanup(struct mlx5_eswitch *esw,
2203 					  struct mlx5_eswitch_rep *rep)
2204 {
2205 	xa_erase(&esw->offloads.vport_reps, rep->vport);
2206 	kfree(rep);
2207 }
2208 
2209 static void esw_offloads_cleanup_reps(struct mlx5_eswitch *esw)
2210 {
2211 	struct mlx5_eswitch_rep *rep;
2212 	unsigned long i;
2213 
2214 	mlx5_esw_for_each_rep(esw, i, rep)
2215 		mlx5_esw_offloads_rep_cleanup(esw, rep);
2216 	xa_destroy(&esw->offloads.vport_reps);
2217 }
2218 
2219 static int esw_offloads_init_reps(struct mlx5_eswitch *esw)
2220 {
2221 	struct mlx5_vport *vport;
2222 	unsigned long i;
2223 	int err;
2224 
2225 	xa_init(&esw->offloads.vport_reps);
2226 
2227 	mlx5_esw_for_each_vport(esw, i, vport) {
2228 		err = mlx5_esw_offloads_rep_init(esw, vport);
2229 		if (err)
2230 			goto err;
2231 	}
2232 	return 0;
2233 
2234 err:
2235 	esw_offloads_cleanup_reps(esw);
2236 	return err;
2237 }
2238 
2239 static int esw_port_metadata_set(struct devlink *devlink, u32 id,
2240 				 struct devlink_param_gset_ctx *ctx)
2241 {
2242 	struct mlx5_core_dev *dev = devlink_priv(devlink);
2243 	struct mlx5_eswitch *esw = dev->priv.eswitch;
2244 	int err = 0;
2245 
2246 	down_write(&esw->mode_lock);
2247 	if (mlx5_esw_is_fdb_created(esw)) {
2248 		err = -EBUSY;
2249 		goto done;
2250 	}
2251 	if (!mlx5_esw_vport_match_metadata_supported(esw)) {
2252 		err = -EOPNOTSUPP;
2253 		goto done;
2254 	}
2255 	if (ctx->val.vbool)
2256 		esw->flags |= MLX5_ESWITCH_VPORT_MATCH_METADATA;
2257 	else
2258 		esw->flags &= ~MLX5_ESWITCH_VPORT_MATCH_METADATA;
2259 done:
2260 	up_write(&esw->mode_lock);
2261 	return err;
2262 }
2263 
2264 static int esw_port_metadata_get(struct devlink *devlink, u32 id,
2265 				 struct devlink_param_gset_ctx *ctx)
2266 {
2267 	struct mlx5_core_dev *dev = devlink_priv(devlink);
2268 
2269 	ctx->val.vbool = mlx5_eswitch_vport_match_metadata_enabled(dev->priv.eswitch);
2270 	return 0;
2271 }
2272 
2273 static int esw_port_metadata_validate(struct devlink *devlink, u32 id,
2274 				      union devlink_param_value val,
2275 				      struct netlink_ext_ack *extack)
2276 {
2277 	struct mlx5_core_dev *dev = devlink_priv(devlink);
2278 	u8 esw_mode;
2279 
2280 	esw_mode = mlx5_eswitch_mode(dev);
2281 	if (esw_mode == MLX5_ESWITCH_OFFLOADS) {
2282 		NL_SET_ERR_MSG_MOD(extack,
2283 				   "E-Switch must either disabled or non switchdev mode");
2284 		return -EBUSY;
2285 	}
2286 	return 0;
2287 }
2288 
2289 static const struct devlink_param esw_devlink_params[] = {
2290 	DEVLINK_PARAM_DRIVER(MLX5_DEVLINK_PARAM_ID_ESW_PORT_METADATA,
2291 			     "esw_port_metadata", DEVLINK_PARAM_TYPE_BOOL,
2292 			     BIT(DEVLINK_PARAM_CMODE_RUNTIME),
2293 			     esw_port_metadata_get,
2294 			     esw_port_metadata_set,
2295 			     esw_port_metadata_validate),
2296 };
2297 
2298 int esw_offloads_init(struct mlx5_eswitch *esw)
2299 {
2300 	int err;
2301 
2302 	err = esw_offloads_init_reps(esw);
2303 	if (err)
2304 		return err;
2305 
2306 	err = devl_params_register(priv_to_devlink(esw->dev),
2307 				   esw_devlink_params,
2308 				   ARRAY_SIZE(esw_devlink_params));
2309 	if (err)
2310 		goto err_params;
2311 
2312 	return 0;
2313 
2314 err_params:
2315 	esw_offloads_cleanup_reps(esw);
2316 	return err;
2317 }
2318 
2319 void esw_offloads_cleanup(struct mlx5_eswitch *esw)
2320 {
2321 	devl_params_unregister(priv_to_devlink(esw->dev),
2322 			       esw_devlink_params,
2323 			       ARRAY_SIZE(esw_devlink_params));
2324 	esw_offloads_cleanup_reps(esw);
2325 }
2326 
2327 static void __esw_offloads_unload_rep(struct mlx5_eswitch *esw,
2328 				      struct mlx5_eswitch_rep *rep, u8 rep_type)
2329 {
2330 	if (atomic_cmpxchg(&rep->rep_data[rep_type].state,
2331 			   REP_LOADED, REP_REGISTERED) == REP_LOADED)
2332 		esw->offloads.rep_ops[rep_type]->unload(rep);
2333 }
2334 
2335 static void __unload_reps_sf_vport(struct mlx5_eswitch *esw, u8 rep_type)
2336 {
2337 	struct mlx5_eswitch_rep *rep;
2338 	unsigned long i;
2339 
2340 	mlx5_esw_for_each_sf_rep(esw, i, rep)
2341 		__esw_offloads_unload_rep(esw, rep, rep_type);
2342 }
2343 
2344 static void __unload_reps_all_vport(struct mlx5_eswitch *esw, u8 rep_type)
2345 {
2346 	struct mlx5_eswitch_rep *rep;
2347 	unsigned long i;
2348 
2349 	__unload_reps_sf_vport(esw, rep_type);
2350 
2351 	mlx5_esw_for_each_vf_rep(esw, i, rep)
2352 		__esw_offloads_unload_rep(esw, rep, rep_type);
2353 
2354 	if (mlx5_ecpf_vport_exists(esw->dev)) {
2355 		rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_ECPF);
2356 		__esw_offloads_unload_rep(esw, rep, rep_type);
2357 	}
2358 
2359 	if (mlx5_core_is_ecpf_esw_manager(esw->dev)) {
2360 		rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_PF);
2361 		__esw_offloads_unload_rep(esw, rep, rep_type);
2362 	}
2363 
2364 	rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_UPLINK);
2365 	__esw_offloads_unload_rep(esw, rep, rep_type);
2366 }
2367 
2368 int mlx5_esw_offloads_rep_load(struct mlx5_eswitch *esw, u16 vport_num)
2369 {
2370 	struct mlx5_eswitch_rep *rep;
2371 	int rep_type;
2372 	int err;
2373 
2374 	rep = mlx5_eswitch_get_rep(esw, vport_num);
2375 	for (rep_type = 0; rep_type < NUM_REP_TYPES; rep_type++)
2376 		if (atomic_cmpxchg(&rep->rep_data[rep_type].state,
2377 				   REP_REGISTERED, REP_LOADED) == REP_REGISTERED) {
2378 			err = esw->offloads.rep_ops[rep_type]->load(esw->dev, rep);
2379 			if (err)
2380 				goto err_reps;
2381 		}
2382 
2383 	return 0;
2384 
2385 err_reps:
2386 	atomic_set(&rep->rep_data[rep_type].state, REP_REGISTERED);
2387 	for (--rep_type; rep_type >= 0; rep_type--)
2388 		__esw_offloads_unload_rep(esw, rep, rep_type);
2389 	return err;
2390 }
2391 
2392 void mlx5_esw_offloads_rep_unload(struct mlx5_eswitch *esw, u16 vport_num)
2393 {
2394 	struct mlx5_eswitch_rep *rep;
2395 	int rep_type;
2396 
2397 	rep = mlx5_eswitch_get_rep(esw, vport_num);
2398 	for (rep_type = NUM_REP_TYPES - 1; rep_type >= 0; rep_type--)
2399 		__esw_offloads_unload_rep(esw, rep, rep_type);
2400 }
2401 
2402 int esw_offloads_load_rep(struct mlx5_eswitch *esw, u16 vport_num)
2403 {
2404 	int err;
2405 
2406 	if (esw->mode != MLX5_ESWITCH_OFFLOADS)
2407 		return 0;
2408 
2409 	if (vport_num != MLX5_VPORT_UPLINK) {
2410 		err = mlx5_esw_offloads_devlink_port_register(esw, vport_num);
2411 		if (err)
2412 			return err;
2413 	}
2414 
2415 	err = mlx5_esw_offloads_rep_load(esw, vport_num);
2416 	if (err)
2417 		goto load_err;
2418 	return err;
2419 
2420 load_err:
2421 	if (vport_num != MLX5_VPORT_UPLINK)
2422 		mlx5_esw_offloads_devlink_port_unregister(esw, vport_num);
2423 	return err;
2424 }
2425 
2426 void esw_offloads_unload_rep(struct mlx5_eswitch *esw, u16 vport_num)
2427 {
2428 	if (esw->mode != MLX5_ESWITCH_OFFLOADS)
2429 		return;
2430 
2431 	mlx5_esw_offloads_rep_unload(esw, vport_num);
2432 
2433 	if (vport_num != MLX5_VPORT_UPLINK)
2434 		mlx5_esw_offloads_devlink_port_unregister(esw, vport_num);
2435 }
2436 
2437 static int esw_set_slave_root_fdb(struct mlx5_core_dev *master,
2438 				  struct mlx5_core_dev *slave)
2439 {
2440 	u32 in[MLX5_ST_SZ_DW(set_flow_table_root_in)]   = {};
2441 	u32 out[MLX5_ST_SZ_DW(set_flow_table_root_out)] = {};
2442 	struct mlx5_flow_root_namespace *root;
2443 	struct mlx5_flow_namespace *ns;
2444 	int err;
2445 
2446 	MLX5_SET(set_flow_table_root_in, in, opcode,
2447 		 MLX5_CMD_OP_SET_FLOW_TABLE_ROOT);
2448 	MLX5_SET(set_flow_table_root_in, in, table_type,
2449 		 FS_FT_FDB);
2450 
2451 	if (master) {
2452 		ns = mlx5_get_flow_namespace(master,
2453 					     MLX5_FLOW_NAMESPACE_FDB);
2454 		root = find_root(&ns->node);
2455 		mutex_lock(&root->chain_lock);
2456 		MLX5_SET(set_flow_table_root_in, in,
2457 			 table_eswitch_owner_vhca_id_valid, 1);
2458 		MLX5_SET(set_flow_table_root_in, in,
2459 			 table_eswitch_owner_vhca_id,
2460 			 MLX5_CAP_GEN(master, vhca_id));
2461 		MLX5_SET(set_flow_table_root_in, in, table_id,
2462 			 root->root_ft->id);
2463 	} else {
2464 		ns = mlx5_get_flow_namespace(slave,
2465 					     MLX5_FLOW_NAMESPACE_FDB);
2466 		root = find_root(&ns->node);
2467 		mutex_lock(&root->chain_lock);
2468 		MLX5_SET(set_flow_table_root_in, in, table_id,
2469 			 root->root_ft->id);
2470 	}
2471 
2472 	err = mlx5_cmd_exec(slave, in, sizeof(in), out, sizeof(out));
2473 	mutex_unlock(&root->chain_lock);
2474 
2475 	return err;
2476 }
2477 
2478 static int __esw_set_master_egress_rule(struct mlx5_core_dev *master,
2479 					struct mlx5_core_dev *slave,
2480 					struct mlx5_vport *vport,
2481 					struct mlx5_flow_table *acl)
2482 {
2483 	struct mlx5_flow_handle *flow_rule = NULL;
2484 	struct mlx5_flow_destination dest = {};
2485 	struct mlx5_flow_act flow_act = {};
2486 	struct mlx5_flow_spec *spec;
2487 	int err = 0;
2488 	void *misc;
2489 
2490 	spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
2491 	if (!spec)
2492 		return -ENOMEM;
2493 
2494 	spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS;
2495 	misc = MLX5_ADDR_OF(fte_match_param, spec->match_value,
2496 			    misc_parameters);
2497 	MLX5_SET(fte_match_set_misc, misc, source_port, MLX5_VPORT_UPLINK);
2498 	MLX5_SET(fte_match_set_misc, misc, source_eswitch_owner_vhca_id,
2499 		 MLX5_CAP_GEN(slave, vhca_id));
2500 
2501 	misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters);
2502 	MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port);
2503 	MLX5_SET_TO_ONES(fte_match_set_misc, misc,
2504 			 source_eswitch_owner_vhca_id);
2505 
2506 	flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
2507 	dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
2508 	dest.vport.num = slave->priv.eswitch->manager_vport;
2509 	dest.vport.vhca_id = MLX5_CAP_GEN(slave, vhca_id);
2510 	dest.vport.flags |= MLX5_FLOW_DEST_VPORT_VHCA_ID;
2511 
2512 	flow_rule = mlx5_add_flow_rules(acl, spec, &flow_act,
2513 					&dest, 1);
2514 	if (IS_ERR(flow_rule))
2515 		err = PTR_ERR(flow_rule);
2516 	else
2517 		vport->egress.offloads.bounce_rule = flow_rule;
2518 
2519 	kvfree(spec);
2520 	return err;
2521 }
2522 
2523 static int esw_set_master_egress_rule(struct mlx5_core_dev *master,
2524 				      struct mlx5_core_dev *slave)
2525 {
2526 	int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
2527 	struct mlx5_eswitch *esw = master->priv.eswitch;
2528 	struct mlx5_flow_table_attr ft_attr = {
2529 		.max_fte = 1, .prio = 0, .level = 0,
2530 		.flags = MLX5_FLOW_TABLE_OTHER_VPORT,
2531 	};
2532 	struct mlx5_flow_namespace *egress_ns;
2533 	struct mlx5_flow_table *acl;
2534 	struct mlx5_flow_group *g;
2535 	struct mlx5_vport *vport;
2536 	void *match_criteria;
2537 	u32 *flow_group_in;
2538 	int err;
2539 
2540 	vport = mlx5_eswitch_get_vport(esw, esw->manager_vport);
2541 	if (IS_ERR(vport))
2542 		return PTR_ERR(vport);
2543 
2544 	egress_ns = mlx5_get_flow_vport_acl_namespace(master,
2545 						      MLX5_FLOW_NAMESPACE_ESW_EGRESS,
2546 						      vport->index);
2547 	if (!egress_ns)
2548 		return -EINVAL;
2549 
2550 	if (vport->egress.acl)
2551 		return -EINVAL;
2552 
2553 	flow_group_in = kvzalloc(inlen, GFP_KERNEL);
2554 	if (!flow_group_in)
2555 		return -ENOMEM;
2556 
2557 	acl = mlx5_create_vport_flow_table(egress_ns, &ft_attr, vport->vport);
2558 	if (IS_ERR(acl)) {
2559 		err = PTR_ERR(acl);
2560 		goto out;
2561 	}
2562 
2563 	match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in,
2564 				      match_criteria);
2565 	MLX5_SET_TO_ONES(fte_match_param, match_criteria,
2566 			 misc_parameters.source_port);
2567 	MLX5_SET_TO_ONES(fte_match_param, match_criteria,
2568 			 misc_parameters.source_eswitch_owner_vhca_id);
2569 	MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
2570 		 MLX5_MATCH_MISC_PARAMETERS);
2571 
2572 	MLX5_SET(create_flow_group_in, flow_group_in,
2573 		 source_eswitch_owner_vhca_id_valid, 1);
2574 	MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 0);
2575 	MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 0);
2576 
2577 	g = mlx5_create_flow_group(acl, flow_group_in);
2578 	if (IS_ERR(g)) {
2579 		err = PTR_ERR(g);
2580 		goto err_group;
2581 	}
2582 
2583 	err = __esw_set_master_egress_rule(master, slave, vport, acl);
2584 	if (err)
2585 		goto err_rule;
2586 
2587 	vport->egress.acl = acl;
2588 	vport->egress.offloads.bounce_grp = g;
2589 
2590 	kvfree(flow_group_in);
2591 
2592 	return 0;
2593 
2594 err_rule:
2595 	mlx5_destroy_flow_group(g);
2596 err_group:
2597 	mlx5_destroy_flow_table(acl);
2598 out:
2599 	kvfree(flow_group_in);
2600 	return err;
2601 }
2602 
2603 static void esw_unset_master_egress_rule(struct mlx5_core_dev *dev)
2604 {
2605 	struct mlx5_vport *vport;
2606 
2607 	vport = mlx5_eswitch_get_vport(dev->priv.eswitch,
2608 				       dev->priv.eswitch->manager_vport);
2609 
2610 	esw_acl_egress_ofld_cleanup(vport);
2611 }
2612 
2613 int mlx5_eswitch_offloads_config_single_fdb(struct mlx5_eswitch *master_esw,
2614 					    struct mlx5_eswitch *slave_esw)
2615 {
2616 	int err;
2617 
2618 	err = esw_set_slave_root_fdb(master_esw->dev,
2619 				     slave_esw->dev);
2620 	if (err)
2621 		return err;
2622 
2623 	err = esw_set_master_egress_rule(master_esw->dev,
2624 					 slave_esw->dev);
2625 	if (err)
2626 		goto err_acl;
2627 
2628 	return err;
2629 
2630 err_acl:
2631 	esw_set_slave_root_fdb(NULL, slave_esw->dev);
2632 
2633 	return err;
2634 }
2635 
2636 void mlx5_eswitch_offloads_destroy_single_fdb(struct mlx5_eswitch *master_esw,
2637 					      struct mlx5_eswitch *slave_esw)
2638 {
2639 	esw_unset_master_egress_rule(master_esw->dev);
2640 	esw_set_slave_root_fdb(NULL, slave_esw->dev);
2641 }
2642 
2643 #define ESW_OFFLOADS_DEVCOM_PAIR	(0)
2644 #define ESW_OFFLOADS_DEVCOM_UNPAIR	(1)
2645 
2646 static void mlx5_esw_offloads_rep_event_unpair(struct mlx5_eswitch *esw)
2647 {
2648 	const struct mlx5_eswitch_rep_ops *ops;
2649 	struct mlx5_eswitch_rep *rep;
2650 	unsigned long i;
2651 	u8 rep_type;
2652 
2653 	mlx5_esw_for_each_rep(esw, i, rep) {
2654 		rep_type = NUM_REP_TYPES;
2655 		while (rep_type--) {
2656 			ops = esw->offloads.rep_ops[rep_type];
2657 			if (atomic_read(&rep->rep_data[rep_type].state) == REP_LOADED &&
2658 			    ops->event)
2659 				ops->event(esw, rep, MLX5_SWITCHDEV_EVENT_UNPAIR, NULL);
2660 		}
2661 	}
2662 }
2663 
2664 static void mlx5_esw_offloads_unpair(struct mlx5_eswitch *esw)
2665 {
2666 #if IS_ENABLED(CONFIG_MLX5_CLS_ACT)
2667 	mlx5e_tc_clean_fdb_peer_flows(esw);
2668 #endif
2669 	mlx5_esw_offloads_rep_event_unpair(esw);
2670 	esw_del_fdb_peer_miss_rules(esw);
2671 }
2672 
2673 static int mlx5_esw_offloads_pair(struct mlx5_eswitch *esw,
2674 				  struct mlx5_eswitch *peer_esw)
2675 {
2676 	const struct mlx5_eswitch_rep_ops *ops;
2677 	struct mlx5_eswitch_rep *rep;
2678 	unsigned long i;
2679 	u8 rep_type;
2680 	int err;
2681 
2682 	err = esw_add_fdb_peer_miss_rules(esw, peer_esw->dev);
2683 	if (err)
2684 		return err;
2685 
2686 	mlx5_esw_for_each_rep(esw, i, rep) {
2687 		for (rep_type = 0; rep_type < NUM_REP_TYPES; rep_type++) {
2688 			ops = esw->offloads.rep_ops[rep_type];
2689 			if (atomic_read(&rep->rep_data[rep_type].state) == REP_LOADED &&
2690 			    ops->event) {
2691 				err = ops->event(esw, rep, MLX5_SWITCHDEV_EVENT_PAIR, peer_esw);
2692 				if (err)
2693 					goto err_out;
2694 			}
2695 		}
2696 	}
2697 
2698 	return 0;
2699 
2700 err_out:
2701 	mlx5_esw_offloads_unpair(esw);
2702 	return err;
2703 }
2704 
2705 static int mlx5_esw_offloads_set_ns_peer(struct mlx5_eswitch *esw,
2706 					 struct mlx5_eswitch *peer_esw,
2707 					 bool pair)
2708 {
2709 	struct mlx5_flow_root_namespace *peer_ns;
2710 	struct mlx5_flow_root_namespace *ns;
2711 	int err;
2712 
2713 	peer_ns = peer_esw->dev->priv.steering->fdb_root_ns;
2714 	ns = esw->dev->priv.steering->fdb_root_ns;
2715 
2716 	if (pair) {
2717 		err = mlx5_flow_namespace_set_peer(ns, peer_ns);
2718 		if (err)
2719 			return err;
2720 
2721 		err = mlx5_flow_namespace_set_peer(peer_ns, ns);
2722 		if (err) {
2723 			mlx5_flow_namespace_set_peer(ns, NULL);
2724 			return err;
2725 		}
2726 	} else {
2727 		mlx5_flow_namespace_set_peer(ns, NULL);
2728 		mlx5_flow_namespace_set_peer(peer_ns, NULL);
2729 	}
2730 
2731 	return 0;
2732 }
2733 
2734 static int mlx5_esw_offloads_devcom_event(int event,
2735 					  void *my_data,
2736 					  void *event_data)
2737 {
2738 	struct mlx5_eswitch *esw = my_data;
2739 	struct mlx5_devcom *devcom = esw->dev->priv.devcom;
2740 	struct mlx5_eswitch *peer_esw = event_data;
2741 	int err;
2742 
2743 	switch (event) {
2744 	case ESW_OFFLOADS_DEVCOM_PAIR:
2745 		if (mlx5_eswitch_vport_match_metadata_enabled(esw) !=
2746 		    mlx5_eswitch_vport_match_metadata_enabled(peer_esw))
2747 			break;
2748 
2749 		err = mlx5_esw_offloads_set_ns_peer(esw, peer_esw, true);
2750 		if (err)
2751 			goto err_out;
2752 		err = mlx5_esw_offloads_pair(esw, peer_esw);
2753 		if (err)
2754 			goto err_peer;
2755 
2756 		err = mlx5_esw_offloads_pair(peer_esw, esw);
2757 		if (err)
2758 			goto err_pair;
2759 
2760 		mlx5_devcom_set_paired(devcom, MLX5_DEVCOM_ESW_OFFLOADS, true);
2761 		break;
2762 
2763 	case ESW_OFFLOADS_DEVCOM_UNPAIR:
2764 		if (!mlx5_devcom_is_paired(devcom, MLX5_DEVCOM_ESW_OFFLOADS))
2765 			break;
2766 
2767 		mlx5_devcom_set_paired(devcom, MLX5_DEVCOM_ESW_OFFLOADS, false);
2768 		mlx5_esw_offloads_unpair(peer_esw);
2769 		mlx5_esw_offloads_unpair(esw);
2770 		mlx5_esw_offloads_set_ns_peer(esw, peer_esw, false);
2771 		break;
2772 	}
2773 
2774 	return 0;
2775 
2776 err_pair:
2777 	mlx5_esw_offloads_unpair(esw);
2778 err_peer:
2779 	mlx5_esw_offloads_set_ns_peer(esw, peer_esw, false);
2780 err_out:
2781 	mlx5_core_err(esw->dev, "esw offloads devcom event failure, event %u err %d",
2782 		      event, err);
2783 	return err;
2784 }
2785 
2786 static void esw_offloads_devcom_init(struct mlx5_eswitch *esw)
2787 {
2788 	struct mlx5_devcom *devcom = esw->dev->priv.devcom;
2789 
2790 	INIT_LIST_HEAD(&esw->offloads.peer_flows);
2791 	mutex_init(&esw->offloads.peer_mutex);
2792 
2793 	if (!MLX5_CAP_ESW(esw->dev, merged_eswitch))
2794 		return;
2795 
2796 	if (!mlx5_is_lag_supported(esw->dev))
2797 		return;
2798 
2799 	mlx5_devcom_register_component(devcom,
2800 				       MLX5_DEVCOM_ESW_OFFLOADS,
2801 				       mlx5_esw_offloads_devcom_event,
2802 				       esw);
2803 
2804 	mlx5_devcom_send_event(devcom,
2805 			       MLX5_DEVCOM_ESW_OFFLOADS,
2806 			       ESW_OFFLOADS_DEVCOM_PAIR, esw);
2807 }
2808 
2809 static void esw_offloads_devcom_cleanup(struct mlx5_eswitch *esw)
2810 {
2811 	struct mlx5_devcom *devcom = esw->dev->priv.devcom;
2812 
2813 	if (!MLX5_CAP_ESW(esw->dev, merged_eswitch))
2814 		return;
2815 
2816 	if (!mlx5_is_lag_supported(esw->dev))
2817 		return;
2818 
2819 	mlx5_devcom_send_event(devcom, MLX5_DEVCOM_ESW_OFFLOADS,
2820 			       ESW_OFFLOADS_DEVCOM_UNPAIR, esw);
2821 
2822 	mlx5_devcom_unregister_component(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
2823 }
2824 
2825 bool mlx5_esw_vport_match_metadata_supported(const struct mlx5_eswitch *esw)
2826 {
2827 	if (!MLX5_CAP_ESW(esw->dev, esw_uplink_ingress_acl))
2828 		return false;
2829 
2830 	if (!(MLX5_CAP_ESW_FLOWTABLE(esw->dev, fdb_to_vport_reg_c_id) &
2831 	      MLX5_FDB_TO_VPORT_REG_C_0))
2832 		return false;
2833 
2834 	if (!MLX5_CAP_ESW_FLOWTABLE(esw->dev, flow_source))
2835 		return false;
2836 
2837 	return true;
2838 }
2839 
2840 #define MLX5_ESW_METADATA_RSVD_UPLINK 1
2841 
2842 /* Share the same metadata for uplink's. This is fine because:
2843  * (a) In shared FDB mode (LAG) both uplink's are treated the
2844  *     same and tagged with the same metadata.
2845  * (b) In non shared FDB mode, packets from physical port0
2846  *     cannot hit eswitch of PF1 and vice versa.
2847  */
2848 static u32 mlx5_esw_match_metadata_reserved(struct mlx5_eswitch *esw)
2849 {
2850 	return MLX5_ESW_METADATA_RSVD_UPLINK;
2851 }
2852 
2853 u32 mlx5_esw_match_metadata_alloc(struct mlx5_eswitch *esw)
2854 {
2855 	u32 vport_end_ida = (1 << ESW_VPORT_BITS) - 1;
2856 	/* Reserve 0xf for internal port offload */
2857 	u32 max_pf_num = (1 << ESW_PFNUM_BITS) - 2;
2858 	u32 pf_num;
2859 	int id;
2860 
2861 	/* Only 4 bits of pf_num */
2862 	pf_num = mlx5_get_dev_index(esw->dev);
2863 	if (pf_num > max_pf_num)
2864 		return 0;
2865 
2866 	/* Metadata is 4 bits of PFNUM and 12 bits of unique id */
2867 	/* Use only non-zero vport_id (2-4095) for all PF's */
2868 	id = ida_alloc_range(&esw->offloads.vport_metadata_ida,
2869 			     MLX5_ESW_METADATA_RSVD_UPLINK + 1,
2870 			     vport_end_ida, GFP_KERNEL);
2871 	if (id < 0)
2872 		return 0;
2873 	id = (pf_num << ESW_VPORT_BITS) | id;
2874 	return id;
2875 }
2876 
2877 void mlx5_esw_match_metadata_free(struct mlx5_eswitch *esw, u32 metadata)
2878 {
2879 	u32 vport_bit_mask = (1 << ESW_VPORT_BITS) - 1;
2880 
2881 	/* Metadata contains only 12 bits of actual ida id */
2882 	ida_free(&esw->offloads.vport_metadata_ida, metadata & vport_bit_mask);
2883 }
2884 
2885 static int esw_offloads_vport_metadata_setup(struct mlx5_eswitch *esw,
2886 					     struct mlx5_vport *vport)
2887 {
2888 	if (vport->vport == MLX5_VPORT_UPLINK)
2889 		vport->default_metadata = mlx5_esw_match_metadata_reserved(esw);
2890 	else
2891 		vport->default_metadata = mlx5_esw_match_metadata_alloc(esw);
2892 
2893 	vport->metadata = vport->default_metadata;
2894 	return vport->metadata ? 0 : -ENOSPC;
2895 }
2896 
2897 static void esw_offloads_vport_metadata_cleanup(struct mlx5_eswitch *esw,
2898 						struct mlx5_vport *vport)
2899 {
2900 	if (!vport->default_metadata)
2901 		return;
2902 
2903 	if (vport->vport == MLX5_VPORT_UPLINK)
2904 		return;
2905 
2906 	WARN_ON(vport->metadata != vport->default_metadata);
2907 	mlx5_esw_match_metadata_free(esw, vport->default_metadata);
2908 }
2909 
2910 static void esw_offloads_metadata_uninit(struct mlx5_eswitch *esw)
2911 {
2912 	struct mlx5_vport *vport;
2913 	unsigned long i;
2914 
2915 	if (!mlx5_eswitch_vport_match_metadata_enabled(esw))
2916 		return;
2917 
2918 	mlx5_esw_for_each_vport(esw, i, vport)
2919 		esw_offloads_vport_metadata_cleanup(esw, vport);
2920 }
2921 
2922 static int esw_offloads_metadata_init(struct mlx5_eswitch *esw)
2923 {
2924 	struct mlx5_vport *vport;
2925 	unsigned long i;
2926 	int err;
2927 
2928 	if (!mlx5_eswitch_vport_match_metadata_enabled(esw))
2929 		return 0;
2930 
2931 	mlx5_esw_for_each_vport(esw, i, vport) {
2932 		err = esw_offloads_vport_metadata_setup(esw, vport);
2933 		if (err)
2934 			goto metadata_err;
2935 	}
2936 
2937 	return 0;
2938 
2939 metadata_err:
2940 	esw_offloads_metadata_uninit(esw);
2941 	return err;
2942 }
2943 
2944 int mlx5_esw_offloads_vport_metadata_set(struct mlx5_eswitch *esw, bool enable)
2945 {
2946 	int err = 0;
2947 
2948 	down_write(&esw->mode_lock);
2949 	if (mlx5_esw_is_fdb_created(esw)) {
2950 		err = -EBUSY;
2951 		goto done;
2952 	}
2953 	if (!mlx5_esw_vport_match_metadata_supported(esw)) {
2954 		err = -EOPNOTSUPP;
2955 		goto done;
2956 	}
2957 	if (enable)
2958 		esw->flags |= MLX5_ESWITCH_VPORT_MATCH_METADATA;
2959 	else
2960 		esw->flags &= ~MLX5_ESWITCH_VPORT_MATCH_METADATA;
2961 done:
2962 	up_write(&esw->mode_lock);
2963 	return err;
2964 }
2965 
2966 int
2967 esw_vport_create_offloads_acl_tables(struct mlx5_eswitch *esw,
2968 				     struct mlx5_vport *vport)
2969 {
2970 	int err;
2971 
2972 	err = esw_acl_ingress_ofld_setup(esw, vport);
2973 	if (err)
2974 		return err;
2975 
2976 	err = esw_acl_egress_ofld_setup(esw, vport);
2977 	if (err)
2978 		goto egress_err;
2979 
2980 	return 0;
2981 
2982 egress_err:
2983 	esw_acl_ingress_ofld_cleanup(esw, vport);
2984 	return err;
2985 }
2986 
2987 void
2988 esw_vport_destroy_offloads_acl_tables(struct mlx5_eswitch *esw,
2989 				      struct mlx5_vport *vport)
2990 {
2991 	esw_acl_egress_ofld_cleanup(vport);
2992 	esw_acl_ingress_ofld_cleanup(esw, vport);
2993 }
2994 
2995 static int esw_create_uplink_offloads_acl_tables(struct mlx5_eswitch *esw)
2996 {
2997 	struct mlx5_vport *vport;
2998 
2999 	vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_UPLINK);
3000 	if (IS_ERR(vport))
3001 		return PTR_ERR(vport);
3002 
3003 	return esw_vport_create_offloads_acl_tables(esw, vport);
3004 }
3005 
3006 static void esw_destroy_uplink_offloads_acl_tables(struct mlx5_eswitch *esw)
3007 {
3008 	struct mlx5_vport *vport;
3009 
3010 	vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_UPLINK);
3011 	if (IS_ERR(vport))
3012 		return;
3013 
3014 	esw_vport_destroy_offloads_acl_tables(esw, vport);
3015 }
3016 
3017 int mlx5_eswitch_reload_reps(struct mlx5_eswitch *esw)
3018 {
3019 	struct mlx5_eswitch_rep *rep;
3020 	unsigned long i;
3021 	int ret;
3022 
3023 	if (!esw || esw->mode != MLX5_ESWITCH_OFFLOADS)
3024 		return 0;
3025 
3026 	rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_UPLINK);
3027 	if (atomic_read(&rep->rep_data[REP_ETH].state) != REP_LOADED)
3028 		return 0;
3029 
3030 	ret = mlx5_esw_offloads_rep_load(esw, MLX5_VPORT_UPLINK);
3031 	if (ret)
3032 		return ret;
3033 
3034 	mlx5_esw_for_each_rep(esw, i, rep) {
3035 		if (atomic_read(&rep->rep_data[REP_ETH].state) == REP_LOADED)
3036 			mlx5_esw_offloads_rep_load(esw, rep->vport);
3037 	}
3038 
3039 	return 0;
3040 }
3041 
3042 static int esw_offloads_steering_init(struct mlx5_eswitch *esw)
3043 {
3044 	struct mlx5_esw_indir_table *indir;
3045 	int err;
3046 
3047 	memset(&esw->fdb_table.offloads, 0, sizeof(struct offloads_fdb));
3048 	mutex_init(&esw->fdb_table.offloads.vports.lock);
3049 	hash_init(esw->fdb_table.offloads.vports.table);
3050 	atomic64_set(&esw->user_count, 0);
3051 
3052 	indir = mlx5_esw_indir_table_init();
3053 	if (IS_ERR(indir)) {
3054 		err = PTR_ERR(indir);
3055 		goto create_indir_err;
3056 	}
3057 	esw->fdb_table.offloads.indir = indir;
3058 
3059 	err = esw_create_uplink_offloads_acl_tables(esw);
3060 	if (err)
3061 		goto create_acl_err;
3062 
3063 	err = esw_create_offloads_table(esw);
3064 	if (err)
3065 		goto create_offloads_err;
3066 
3067 	err = esw_create_restore_table(esw);
3068 	if (err)
3069 		goto create_restore_err;
3070 
3071 	err = esw_create_offloads_fdb_tables(esw);
3072 	if (err)
3073 		goto create_fdb_err;
3074 
3075 	err = esw_create_vport_rx_group(esw);
3076 	if (err)
3077 		goto create_fg_err;
3078 
3079 	err = esw_create_vport_rx_drop_group(esw);
3080 	if (err)
3081 		goto create_rx_drop_fg_err;
3082 
3083 	err = esw_create_vport_rx_drop_rule(esw);
3084 	if (err)
3085 		goto create_rx_drop_rule_err;
3086 
3087 	return 0;
3088 
3089 create_rx_drop_rule_err:
3090 	esw_destroy_vport_rx_drop_group(esw);
3091 create_rx_drop_fg_err:
3092 	esw_destroy_vport_rx_group(esw);
3093 create_fg_err:
3094 	esw_destroy_offloads_fdb_tables(esw);
3095 create_fdb_err:
3096 	esw_destroy_restore_table(esw);
3097 create_restore_err:
3098 	esw_destroy_offloads_table(esw);
3099 create_offloads_err:
3100 	esw_destroy_uplink_offloads_acl_tables(esw);
3101 create_acl_err:
3102 	mlx5_esw_indir_table_destroy(esw->fdb_table.offloads.indir);
3103 create_indir_err:
3104 	mutex_destroy(&esw->fdb_table.offloads.vports.lock);
3105 	return err;
3106 }
3107 
3108 static void esw_offloads_steering_cleanup(struct mlx5_eswitch *esw)
3109 {
3110 	esw_destroy_vport_rx_drop_rule(esw);
3111 	esw_destroy_vport_rx_drop_group(esw);
3112 	esw_destroy_vport_rx_group(esw);
3113 	esw_destroy_offloads_fdb_tables(esw);
3114 	esw_destroy_restore_table(esw);
3115 	esw_destroy_offloads_table(esw);
3116 	esw_destroy_uplink_offloads_acl_tables(esw);
3117 	mlx5_esw_indir_table_destroy(esw->fdb_table.offloads.indir);
3118 	mutex_destroy(&esw->fdb_table.offloads.vports.lock);
3119 }
3120 
3121 static void
3122 esw_vfs_changed_event_handler(struct mlx5_eswitch *esw, const u32 *out)
3123 {
3124 	struct devlink *devlink;
3125 	bool host_pf_disabled;
3126 	u16 new_num_vfs;
3127 
3128 	new_num_vfs = MLX5_GET(query_esw_functions_out, out,
3129 			       host_params_context.host_num_of_vfs);
3130 	host_pf_disabled = MLX5_GET(query_esw_functions_out, out,
3131 				    host_params_context.host_pf_disabled);
3132 
3133 	if (new_num_vfs == esw->esw_funcs.num_vfs || host_pf_disabled)
3134 		return;
3135 
3136 	devlink = priv_to_devlink(esw->dev);
3137 	devl_lock(devlink);
3138 	/* Number of VFs can only change from "0 to x" or "x to 0". */
3139 	if (esw->esw_funcs.num_vfs > 0) {
3140 		mlx5_eswitch_unload_vf_vports(esw, esw->esw_funcs.num_vfs);
3141 	} else {
3142 		int err;
3143 
3144 		err = mlx5_eswitch_load_vf_vports(esw, new_num_vfs,
3145 						  MLX5_VPORT_UC_ADDR_CHANGE);
3146 		if (err) {
3147 			devl_unlock(devlink);
3148 			return;
3149 		}
3150 	}
3151 	esw->esw_funcs.num_vfs = new_num_vfs;
3152 	devl_unlock(devlink);
3153 }
3154 
3155 static void esw_functions_changed_event_handler(struct work_struct *work)
3156 {
3157 	struct mlx5_host_work *host_work;
3158 	struct mlx5_eswitch *esw;
3159 	const u32 *out;
3160 
3161 	host_work = container_of(work, struct mlx5_host_work, work);
3162 	esw = host_work->esw;
3163 
3164 	out = mlx5_esw_query_functions(esw->dev);
3165 	if (IS_ERR(out))
3166 		goto out;
3167 
3168 	esw_vfs_changed_event_handler(esw, out);
3169 	kvfree(out);
3170 out:
3171 	kfree(host_work);
3172 }
3173 
3174 int mlx5_esw_funcs_changed_handler(struct notifier_block *nb, unsigned long type, void *data)
3175 {
3176 	struct mlx5_esw_functions *esw_funcs;
3177 	struct mlx5_host_work *host_work;
3178 	struct mlx5_eswitch *esw;
3179 
3180 	host_work = kzalloc(sizeof(*host_work), GFP_ATOMIC);
3181 	if (!host_work)
3182 		return NOTIFY_DONE;
3183 
3184 	esw_funcs = mlx5_nb_cof(nb, struct mlx5_esw_functions, nb);
3185 	esw = container_of(esw_funcs, struct mlx5_eswitch, esw_funcs);
3186 
3187 	host_work->esw = esw;
3188 
3189 	INIT_WORK(&host_work->work, esw_functions_changed_event_handler);
3190 	queue_work(esw->work_queue, &host_work->work);
3191 
3192 	return NOTIFY_OK;
3193 }
3194 
3195 static int mlx5_esw_host_number_init(struct mlx5_eswitch *esw)
3196 {
3197 	const u32 *query_host_out;
3198 
3199 	if (!mlx5_core_is_ecpf_esw_manager(esw->dev))
3200 		return 0;
3201 
3202 	query_host_out = mlx5_esw_query_functions(esw->dev);
3203 	if (IS_ERR(query_host_out))
3204 		return PTR_ERR(query_host_out);
3205 
3206 	/* Mark non local controller with non zero controller number. */
3207 	esw->offloads.host_number = MLX5_GET(query_esw_functions_out, query_host_out,
3208 					     host_params_context.host_number);
3209 	kvfree(query_host_out);
3210 	return 0;
3211 }
3212 
3213 bool mlx5_esw_offloads_controller_valid(const struct mlx5_eswitch *esw, u32 controller)
3214 {
3215 	/* Local controller is always valid */
3216 	if (controller == 0)
3217 		return true;
3218 
3219 	if (!mlx5_core_is_ecpf_esw_manager(esw->dev))
3220 		return false;
3221 
3222 	/* External host number starts with zero in device */
3223 	return (controller == esw->offloads.host_number + 1);
3224 }
3225 
3226 int esw_offloads_enable(struct mlx5_eswitch *esw)
3227 {
3228 	struct mapping_ctx *reg_c0_obj_pool;
3229 	struct mlx5_vport *vport;
3230 	unsigned long i;
3231 	u64 mapping_id;
3232 	int err;
3233 
3234 	mutex_init(&esw->offloads.termtbl_mutex);
3235 	mlx5_rdma_enable_roce(esw->dev);
3236 
3237 	err = mlx5_esw_host_number_init(esw);
3238 	if (err)
3239 		goto err_metadata;
3240 
3241 	err = esw_offloads_metadata_init(esw);
3242 	if (err)
3243 		goto err_metadata;
3244 
3245 	err = esw_set_passing_vport_metadata(esw, true);
3246 	if (err)
3247 		goto err_vport_metadata;
3248 
3249 	mapping_id = mlx5_query_nic_system_image_guid(esw->dev);
3250 
3251 	reg_c0_obj_pool = mapping_create_for_id(mapping_id, MAPPING_TYPE_CHAIN,
3252 						sizeof(struct mlx5_mapped_obj),
3253 						ESW_REG_C0_USER_DATA_METADATA_MASK,
3254 						true);
3255 
3256 	if (IS_ERR(reg_c0_obj_pool)) {
3257 		err = PTR_ERR(reg_c0_obj_pool);
3258 		goto err_pool;
3259 	}
3260 	esw->offloads.reg_c0_obj_pool = reg_c0_obj_pool;
3261 
3262 	err = esw_offloads_steering_init(esw);
3263 	if (err)
3264 		goto err_steering_init;
3265 
3266 	/* Representor will control the vport link state */
3267 	mlx5_esw_for_each_vf_vport(esw, i, vport, esw->esw_funcs.num_vfs)
3268 		vport->info.link_state = MLX5_VPORT_ADMIN_STATE_DOWN;
3269 
3270 	/* Uplink vport rep must load first. */
3271 	err = esw_offloads_load_rep(esw, MLX5_VPORT_UPLINK);
3272 	if (err)
3273 		goto err_uplink;
3274 
3275 	err = mlx5_eswitch_enable_pf_vf_vports(esw, MLX5_VPORT_UC_ADDR_CHANGE);
3276 	if (err)
3277 		goto err_vports;
3278 
3279 	esw_offloads_devcom_init(esw);
3280 
3281 	return 0;
3282 
3283 err_vports:
3284 	esw_offloads_unload_rep(esw, MLX5_VPORT_UPLINK);
3285 err_uplink:
3286 	esw_offloads_steering_cleanup(esw);
3287 err_steering_init:
3288 	mapping_destroy(reg_c0_obj_pool);
3289 err_pool:
3290 	esw_set_passing_vport_metadata(esw, false);
3291 err_vport_metadata:
3292 	esw_offloads_metadata_uninit(esw);
3293 err_metadata:
3294 	mlx5_rdma_disable_roce(esw->dev);
3295 	mutex_destroy(&esw->offloads.termtbl_mutex);
3296 	return err;
3297 }
3298 
3299 static int esw_offloads_stop(struct mlx5_eswitch *esw,
3300 			     struct netlink_ext_ack *extack)
3301 {
3302 	int err;
3303 
3304 	esw->mode = MLX5_ESWITCH_LEGACY;
3305 
3306 	/* If changing from switchdev to legacy mode without sriov enabled,
3307 	 * no need to create legacy fdb.
3308 	 */
3309 	if (!mlx5_sriov_is_enabled(esw->dev))
3310 		return 0;
3311 
3312 	err = mlx5_eswitch_enable_locked(esw, MLX5_ESWITCH_IGNORE_NUM_VFS);
3313 	if (err)
3314 		NL_SET_ERR_MSG_MOD(extack, "Failed setting eswitch to legacy");
3315 
3316 	return err;
3317 }
3318 
3319 void esw_offloads_disable(struct mlx5_eswitch *esw)
3320 {
3321 	esw_offloads_devcom_cleanup(esw);
3322 	mlx5_eswitch_disable_pf_vf_vports(esw);
3323 	esw_offloads_unload_rep(esw, MLX5_VPORT_UPLINK);
3324 	esw_set_passing_vport_metadata(esw, false);
3325 	esw_offloads_steering_cleanup(esw);
3326 	mapping_destroy(esw->offloads.reg_c0_obj_pool);
3327 	esw_offloads_metadata_uninit(esw);
3328 	mlx5_rdma_disable_roce(esw->dev);
3329 	mutex_destroy(&esw->offloads.termtbl_mutex);
3330 }
3331 
3332 static int esw_mode_from_devlink(u16 mode, u16 *mlx5_mode)
3333 {
3334 	switch (mode) {
3335 	case DEVLINK_ESWITCH_MODE_LEGACY:
3336 		*mlx5_mode = MLX5_ESWITCH_LEGACY;
3337 		break;
3338 	case DEVLINK_ESWITCH_MODE_SWITCHDEV:
3339 		*mlx5_mode = MLX5_ESWITCH_OFFLOADS;
3340 		break;
3341 	default:
3342 		return -EINVAL;
3343 	}
3344 
3345 	return 0;
3346 }
3347 
3348 static int esw_mode_to_devlink(u16 mlx5_mode, u16 *mode)
3349 {
3350 	switch (mlx5_mode) {
3351 	case MLX5_ESWITCH_LEGACY:
3352 		*mode = DEVLINK_ESWITCH_MODE_LEGACY;
3353 		break;
3354 	case MLX5_ESWITCH_OFFLOADS:
3355 		*mode = DEVLINK_ESWITCH_MODE_SWITCHDEV;
3356 		break;
3357 	default:
3358 		return -EINVAL;
3359 	}
3360 
3361 	return 0;
3362 }
3363 
3364 static int esw_inline_mode_from_devlink(u8 mode, u8 *mlx5_mode)
3365 {
3366 	switch (mode) {
3367 	case DEVLINK_ESWITCH_INLINE_MODE_NONE:
3368 		*mlx5_mode = MLX5_INLINE_MODE_NONE;
3369 		break;
3370 	case DEVLINK_ESWITCH_INLINE_MODE_LINK:
3371 		*mlx5_mode = MLX5_INLINE_MODE_L2;
3372 		break;
3373 	case DEVLINK_ESWITCH_INLINE_MODE_NETWORK:
3374 		*mlx5_mode = MLX5_INLINE_MODE_IP;
3375 		break;
3376 	case DEVLINK_ESWITCH_INLINE_MODE_TRANSPORT:
3377 		*mlx5_mode = MLX5_INLINE_MODE_TCP_UDP;
3378 		break;
3379 	default:
3380 		return -EINVAL;
3381 	}
3382 
3383 	return 0;
3384 }
3385 
3386 static int esw_inline_mode_to_devlink(u8 mlx5_mode, u8 *mode)
3387 {
3388 	switch (mlx5_mode) {
3389 	case MLX5_INLINE_MODE_NONE:
3390 		*mode = DEVLINK_ESWITCH_INLINE_MODE_NONE;
3391 		break;
3392 	case MLX5_INLINE_MODE_L2:
3393 		*mode = DEVLINK_ESWITCH_INLINE_MODE_LINK;
3394 		break;
3395 	case MLX5_INLINE_MODE_IP:
3396 		*mode = DEVLINK_ESWITCH_INLINE_MODE_NETWORK;
3397 		break;
3398 	case MLX5_INLINE_MODE_TCP_UDP:
3399 		*mode = DEVLINK_ESWITCH_INLINE_MODE_TRANSPORT;
3400 		break;
3401 	default:
3402 		return -EINVAL;
3403 	}
3404 
3405 	return 0;
3406 }
3407 
3408 int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode,
3409 				  struct netlink_ext_ack *extack)
3410 {
3411 	u16 cur_mlx5_mode, mlx5_mode = 0;
3412 	struct mlx5_eswitch *esw;
3413 	int err = 0;
3414 
3415 	esw = mlx5_devlink_eswitch_get(devlink);
3416 	if (IS_ERR(esw))
3417 		return PTR_ERR(esw);
3418 
3419 	if (esw_mode_from_devlink(mode, &mlx5_mode))
3420 		return -EINVAL;
3421 
3422 	mlx5_lag_disable_change(esw->dev);
3423 	err = mlx5_esw_try_lock(esw);
3424 	if (err < 0) {
3425 		NL_SET_ERR_MSG_MOD(extack, "Can't change mode, E-Switch is busy");
3426 		goto enable_lag;
3427 	}
3428 	cur_mlx5_mode = err;
3429 	err = 0;
3430 
3431 	if (cur_mlx5_mode == mlx5_mode)
3432 		goto unlock;
3433 
3434 	mlx5_eswitch_disable_locked(esw);
3435 	if (mode == DEVLINK_ESWITCH_MODE_SWITCHDEV) {
3436 		if (mlx5_devlink_trap_get_num_active(esw->dev)) {
3437 			NL_SET_ERR_MSG_MOD(extack,
3438 					   "Can't change mode while devlink traps are active");
3439 			err = -EOPNOTSUPP;
3440 			goto unlock;
3441 		}
3442 		err = esw_offloads_start(esw, extack);
3443 	} else if (mode == DEVLINK_ESWITCH_MODE_LEGACY) {
3444 		err = esw_offloads_stop(esw, extack);
3445 		mlx5_rescan_drivers(esw->dev);
3446 	} else {
3447 		err = -EINVAL;
3448 	}
3449 
3450 unlock:
3451 	mlx5_esw_unlock(esw);
3452 enable_lag:
3453 	mlx5_lag_enable_change(esw->dev);
3454 	return err;
3455 }
3456 
3457 int mlx5_devlink_eswitch_mode_get(struct devlink *devlink, u16 *mode)
3458 {
3459 	struct mlx5_eswitch *esw;
3460 	int err;
3461 
3462 	esw = mlx5_devlink_eswitch_get(devlink);
3463 	if (IS_ERR(esw))
3464 		return PTR_ERR(esw);
3465 
3466 	down_read(&esw->mode_lock);
3467 	err = esw_mode_to_devlink(esw->mode, mode);
3468 	up_read(&esw->mode_lock);
3469 	return err;
3470 }
3471 
3472 static int mlx5_esw_vports_inline_set(struct mlx5_eswitch *esw, u8 mlx5_mode,
3473 				      struct netlink_ext_ack *extack)
3474 {
3475 	struct mlx5_core_dev *dev = esw->dev;
3476 	struct mlx5_vport *vport;
3477 	u16 err_vport_num = 0;
3478 	unsigned long i;
3479 	int err = 0;
3480 
3481 	mlx5_esw_for_each_host_func_vport(esw, i, vport, esw->esw_funcs.num_vfs) {
3482 		err = mlx5_modify_nic_vport_min_inline(dev, vport->vport, mlx5_mode);
3483 		if (err) {
3484 			err_vport_num = vport->vport;
3485 			NL_SET_ERR_MSG_MOD(extack,
3486 					   "Failed to set min inline on vport");
3487 			goto revert_inline_mode;
3488 		}
3489 	}
3490 	return 0;
3491 
3492 revert_inline_mode:
3493 	mlx5_esw_for_each_host_func_vport(esw, i, vport, esw->esw_funcs.num_vfs) {
3494 		if (vport->vport == err_vport_num)
3495 			break;
3496 		mlx5_modify_nic_vport_min_inline(dev,
3497 						 vport->vport,
3498 						 esw->offloads.inline_mode);
3499 	}
3500 	return err;
3501 }
3502 
3503 int mlx5_devlink_eswitch_inline_mode_set(struct devlink *devlink, u8 mode,
3504 					 struct netlink_ext_ack *extack)
3505 {
3506 	struct mlx5_core_dev *dev = devlink_priv(devlink);
3507 	struct mlx5_eswitch *esw;
3508 	u8 mlx5_mode;
3509 	int err;
3510 
3511 	esw = mlx5_devlink_eswitch_get(devlink);
3512 	if (IS_ERR(esw))
3513 		return PTR_ERR(esw);
3514 
3515 	down_write(&esw->mode_lock);
3516 
3517 	switch (MLX5_CAP_ETH(dev, wqe_inline_mode)) {
3518 	case MLX5_CAP_INLINE_MODE_NOT_REQUIRED:
3519 		if (mode == DEVLINK_ESWITCH_INLINE_MODE_NONE) {
3520 			err = 0;
3521 			goto out;
3522 		}
3523 
3524 		fallthrough;
3525 	case MLX5_CAP_INLINE_MODE_L2:
3526 		NL_SET_ERR_MSG_MOD(extack, "Inline mode can't be set");
3527 		err = -EOPNOTSUPP;
3528 		goto out;
3529 	case MLX5_CAP_INLINE_MODE_VPORT_CONTEXT:
3530 		break;
3531 	}
3532 
3533 	if (atomic64_read(&esw->offloads.num_flows) > 0) {
3534 		NL_SET_ERR_MSG_MOD(extack,
3535 				   "Can't set inline mode when flows are configured");
3536 		err = -EOPNOTSUPP;
3537 		goto out;
3538 	}
3539 
3540 	err = esw_inline_mode_from_devlink(mode, &mlx5_mode);
3541 	if (err)
3542 		goto out;
3543 
3544 	err = mlx5_esw_vports_inline_set(esw, mlx5_mode, extack);
3545 	if (err)
3546 		goto out;
3547 
3548 	esw->offloads.inline_mode = mlx5_mode;
3549 	up_write(&esw->mode_lock);
3550 	return 0;
3551 
3552 out:
3553 	up_write(&esw->mode_lock);
3554 	return err;
3555 }
3556 
3557 int mlx5_devlink_eswitch_inline_mode_get(struct devlink *devlink, u8 *mode)
3558 {
3559 	struct mlx5_eswitch *esw;
3560 	int err;
3561 
3562 	esw = mlx5_devlink_eswitch_get(devlink);
3563 	if (IS_ERR(esw))
3564 		return PTR_ERR(esw);
3565 
3566 	down_read(&esw->mode_lock);
3567 	err = esw_inline_mode_to_devlink(esw->offloads.inline_mode, mode);
3568 	up_read(&esw->mode_lock);
3569 	return err;
3570 }
3571 
3572 int mlx5_devlink_eswitch_encap_mode_set(struct devlink *devlink,
3573 					enum devlink_eswitch_encap_mode encap,
3574 					struct netlink_ext_ack *extack)
3575 {
3576 	struct mlx5_core_dev *dev = devlink_priv(devlink);
3577 	struct mlx5_eswitch *esw;
3578 	int err = 0;
3579 
3580 	esw = mlx5_devlink_eswitch_get(devlink);
3581 	if (IS_ERR(esw))
3582 		return PTR_ERR(esw);
3583 
3584 	down_write(&esw->mode_lock);
3585 
3586 	if (encap != DEVLINK_ESWITCH_ENCAP_MODE_NONE &&
3587 	    (!MLX5_CAP_ESW_FLOWTABLE_FDB(dev, reformat) ||
3588 	     !MLX5_CAP_ESW_FLOWTABLE_FDB(dev, decap))) {
3589 		err = -EOPNOTSUPP;
3590 		goto unlock;
3591 	}
3592 
3593 	if (encap && encap != DEVLINK_ESWITCH_ENCAP_MODE_BASIC) {
3594 		err = -EOPNOTSUPP;
3595 		goto unlock;
3596 	}
3597 
3598 	if (esw->mode == MLX5_ESWITCH_LEGACY) {
3599 		esw->offloads.encap = encap;
3600 		goto unlock;
3601 	}
3602 
3603 	if (esw->offloads.encap == encap)
3604 		goto unlock;
3605 
3606 	if (atomic64_read(&esw->offloads.num_flows) > 0) {
3607 		NL_SET_ERR_MSG_MOD(extack,
3608 				   "Can't set encapsulation when flows are configured");
3609 		err = -EOPNOTSUPP;
3610 		goto unlock;
3611 	}
3612 
3613 	esw_destroy_offloads_fdb_tables(esw);
3614 
3615 	esw->offloads.encap = encap;
3616 
3617 	err = esw_create_offloads_fdb_tables(esw);
3618 
3619 	if (err) {
3620 		NL_SET_ERR_MSG_MOD(extack,
3621 				   "Failed re-creating fast FDB table");
3622 		esw->offloads.encap = !encap;
3623 		(void)esw_create_offloads_fdb_tables(esw);
3624 	}
3625 
3626 unlock:
3627 	up_write(&esw->mode_lock);
3628 	return err;
3629 }
3630 
3631 int mlx5_devlink_eswitch_encap_mode_get(struct devlink *devlink,
3632 					enum devlink_eswitch_encap_mode *encap)
3633 {
3634 	struct mlx5_eswitch *esw;
3635 
3636 	esw = mlx5_devlink_eswitch_get(devlink);
3637 	if (IS_ERR(esw))
3638 		return PTR_ERR(esw);
3639 
3640 	down_read(&esw->mode_lock);
3641 	*encap = esw->offloads.encap;
3642 	up_read(&esw->mode_lock);
3643 	return 0;
3644 }
3645 
3646 static bool
3647 mlx5_eswitch_vport_has_rep(const struct mlx5_eswitch *esw, u16 vport_num)
3648 {
3649 	/* Currently, only ECPF based device has representor for host PF. */
3650 	if (vport_num == MLX5_VPORT_PF &&
3651 	    !mlx5_core_is_ecpf_esw_manager(esw->dev))
3652 		return false;
3653 
3654 	if (vport_num == MLX5_VPORT_ECPF &&
3655 	    !mlx5_ecpf_vport_exists(esw->dev))
3656 		return false;
3657 
3658 	return true;
3659 }
3660 
3661 void mlx5_eswitch_register_vport_reps(struct mlx5_eswitch *esw,
3662 				      const struct mlx5_eswitch_rep_ops *ops,
3663 				      u8 rep_type)
3664 {
3665 	struct mlx5_eswitch_rep_data *rep_data;
3666 	struct mlx5_eswitch_rep *rep;
3667 	unsigned long i;
3668 
3669 	esw->offloads.rep_ops[rep_type] = ops;
3670 	mlx5_esw_for_each_rep(esw, i, rep) {
3671 		if (likely(mlx5_eswitch_vport_has_rep(esw, rep->vport))) {
3672 			rep->esw = esw;
3673 			rep_data = &rep->rep_data[rep_type];
3674 			atomic_set(&rep_data->state, REP_REGISTERED);
3675 		}
3676 	}
3677 }
3678 EXPORT_SYMBOL(mlx5_eswitch_register_vport_reps);
3679 
3680 void mlx5_eswitch_unregister_vport_reps(struct mlx5_eswitch *esw, u8 rep_type)
3681 {
3682 	struct mlx5_eswitch_rep *rep;
3683 	unsigned long i;
3684 
3685 	if (esw->mode == MLX5_ESWITCH_OFFLOADS)
3686 		__unload_reps_all_vport(esw, rep_type);
3687 
3688 	mlx5_esw_for_each_rep(esw, i, rep)
3689 		atomic_set(&rep->rep_data[rep_type].state, REP_UNREGISTERED);
3690 }
3691 EXPORT_SYMBOL(mlx5_eswitch_unregister_vport_reps);
3692 
3693 void *mlx5_eswitch_get_uplink_priv(struct mlx5_eswitch *esw, u8 rep_type)
3694 {
3695 	struct mlx5_eswitch_rep *rep;
3696 
3697 	rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_UPLINK);
3698 	return rep->rep_data[rep_type].priv;
3699 }
3700 
3701 void *mlx5_eswitch_get_proto_dev(struct mlx5_eswitch *esw,
3702 				 u16 vport,
3703 				 u8 rep_type)
3704 {
3705 	struct mlx5_eswitch_rep *rep;
3706 
3707 	rep = mlx5_eswitch_get_rep(esw, vport);
3708 
3709 	if (atomic_read(&rep->rep_data[rep_type].state) == REP_LOADED &&
3710 	    esw->offloads.rep_ops[rep_type]->get_proto_dev)
3711 		return esw->offloads.rep_ops[rep_type]->get_proto_dev(rep);
3712 	return NULL;
3713 }
3714 EXPORT_SYMBOL(mlx5_eswitch_get_proto_dev);
3715 
3716 void *mlx5_eswitch_uplink_get_proto_dev(struct mlx5_eswitch *esw, u8 rep_type)
3717 {
3718 	return mlx5_eswitch_get_proto_dev(esw, MLX5_VPORT_UPLINK, rep_type);
3719 }
3720 EXPORT_SYMBOL(mlx5_eswitch_uplink_get_proto_dev);
3721 
3722 struct mlx5_eswitch_rep *mlx5_eswitch_vport_rep(struct mlx5_eswitch *esw,
3723 						u16 vport)
3724 {
3725 	return mlx5_eswitch_get_rep(esw, vport);
3726 }
3727 EXPORT_SYMBOL(mlx5_eswitch_vport_rep);
3728 
3729 bool mlx5_eswitch_reg_c1_loopback_enabled(const struct mlx5_eswitch *esw)
3730 {
3731 	return !!(esw->flags & MLX5_ESWITCH_REG_C1_LOOPBACK_ENABLED);
3732 }
3733 EXPORT_SYMBOL(mlx5_eswitch_reg_c1_loopback_enabled);
3734 
3735 bool mlx5_eswitch_vport_match_metadata_enabled(const struct mlx5_eswitch *esw)
3736 {
3737 	return !!(esw->flags & MLX5_ESWITCH_VPORT_MATCH_METADATA);
3738 }
3739 EXPORT_SYMBOL(mlx5_eswitch_vport_match_metadata_enabled);
3740 
3741 u32 mlx5_eswitch_get_vport_metadata_for_match(struct mlx5_eswitch *esw,
3742 					      u16 vport_num)
3743 {
3744 	struct mlx5_vport *vport = mlx5_eswitch_get_vport(esw, vport_num);
3745 
3746 	if (WARN_ON_ONCE(IS_ERR(vport)))
3747 		return 0;
3748 
3749 	return vport->metadata << (32 - ESW_SOURCE_PORT_METADATA_BITS);
3750 }
3751 EXPORT_SYMBOL(mlx5_eswitch_get_vport_metadata_for_match);
3752 
3753 int mlx5_esw_offloads_sf_vport_enable(struct mlx5_eswitch *esw, struct devlink_port *dl_port,
3754 				      u16 vport_num, u32 controller, u32 sfnum)
3755 {
3756 	int err;
3757 
3758 	err = mlx5_esw_vport_enable(esw, vport_num, MLX5_VPORT_UC_ADDR_CHANGE);
3759 	if (err)
3760 		return err;
3761 
3762 	err = mlx5_esw_devlink_sf_port_register(esw, dl_port, vport_num, controller, sfnum);
3763 	if (err)
3764 		goto devlink_err;
3765 
3766 	mlx5_esw_vport_debugfs_create(esw, vport_num, true, sfnum);
3767 	err = mlx5_esw_offloads_rep_load(esw, vport_num);
3768 	if (err)
3769 		goto rep_err;
3770 	return 0;
3771 
3772 rep_err:
3773 	mlx5_esw_vport_debugfs_destroy(esw, vport_num);
3774 	mlx5_esw_devlink_sf_port_unregister(esw, vport_num);
3775 devlink_err:
3776 	mlx5_esw_vport_disable(esw, vport_num);
3777 	return err;
3778 }
3779 
3780 void mlx5_esw_offloads_sf_vport_disable(struct mlx5_eswitch *esw, u16 vport_num)
3781 {
3782 	mlx5_esw_offloads_rep_unload(esw, vport_num);
3783 	mlx5_esw_vport_debugfs_destroy(esw, vport_num);
3784 	mlx5_esw_devlink_sf_port_unregister(esw, vport_num);
3785 	mlx5_esw_vport_disable(esw, vport_num);
3786 }
3787 
3788 static int mlx5_esw_query_vport_vhca_id(struct mlx5_eswitch *esw, u16 vport_num, u16 *vhca_id)
3789 {
3790 	int query_out_sz = MLX5_ST_SZ_BYTES(query_hca_cap_out);
3791 	void *query_ctx;
3792 	void *hca_caps;
3793 	int err;
3794 
3795 	*vhca_id = 0;
3796 	if (mlx5_esw_is_manager_vport(esw, vport_num) ||
3797 	    !MLX5_CAP_GEN(esw->dev, vhca_resource_manager))
3798 		return -EPERM;
3799 
3800 	query_ctx = kzalloc(query_out_sz, GFP_KERNEL);
3801 	if (!query_ctx)
3802 		return -ENOMEM;
3803 
3804 	err = mlx5_vport_get_other_func_general_cap(esw->dev, vport_num, query_ctx);
3805 	if (err)
3806 		goto out_free;
3807 
3808 	hca_caps = MLX5_ADDR_OF(query_hca_cap_out, query_ctx, capability);
3809 	*vhca_id = MLX5_GET(cmd_hca_cap, hca_caps, vhca_id);
3810 
3811 out_free:
3812 	kfree(query_ctx);
3813 	return err;
3814 }
3815 
3816 int mlx5_esw_vport_vhca_id_set(struct mlx5_eswitch *esw, u16 vport_num)
3817 {
3818 	u16 *old_entry, *vhca_map_entry, vhca_id;
3819 	int err;
3820 
3821 	err = mlx5_esw_query_vport_vhca_id(esw, vport_num, &vhca_id);
3822 	if (err) {
3823 		esw_warn(esw->dev, "Getting vhca_id for vport failed (vport=%u,err=%d)\n",
3824 			 vport_num, err);
3825 		return err;
3826 	}
3827 
3828 	vhca_map_entry = kmalloc(sizeof(*vhca_map_entry), GFP_KERNEL);
3829 	if (!vhca_map_entry)
3830 		return -ENOMEM;
3831 
3832 	*vhca_map_entry = vport_num;
3833 	old_entry = xa_store(&esw->offloads.vhca_map, vhca_id, vhca_map_entry, GFP_KERNEL);
3834 	if (xa_is_err(old_entry)) {
3835 		kfree(vhca_map_entry);
3836 		return xa_err(old_entry);
3837 	}
3838 	kfree(old_entry);
3839 	return 0;
3840 }
3841 
3842 void mlx5_esw_vport_vhca_id_clear(struct mlx5_eswitch *esw, u16 vport_num)
3843 {
3844 	u16 *vhca_map_entry, vhca_id;
3845 	int err;
3846 
3847 	err = mlx5_esw_query_vport_vhca_id(esw, vport_num, &vhca_id);
3848 	if (err)
3849 		esw_warn(esw->dev, "Getting vhca_id for vport failed (vport=%hu,err=%d)\n",
3850 			 vport_num, err);
3851 
3852 	vhca_map_entry = xa_erase(&esw->offloads.vhca_map, vhca_id);
3853 	kfree(vhca_map_entry);
3854 }
3855 
3856 int mlx5_eswitch_vhca_id_to_vport(struct mlx5_eswitch *esw, u16 vhca_id, u16 *vport_num)
3857 {
3858 	u16 *res = xa_load(&esw->offloads.vhca_map, vhca_id);
3859 
3860 	if (!res)
3861 		return -ENOENT;
3862 
3863 	*vport_num = *res;
3864 	return 0;
3865 }
3866 
3867 u32 mlx5_eswitch_get_vport_metadata_for_set(struct mlx5_eswitch *esw,
3868 					    u16 vport_num)
3869 {
3870 	struct mlx5_vport *vport = mlx5_eswitch_get_vport(esw, vport_num);
3871 
3872 	if (WARN_ON_ONCE(IS_ERR(vport)))
3873 		return 0;
3874 
3875 	return vport->metadata;
3876 }
3877 EXPORT_SYMBOL(mlx5_eswitch_get_vport_metadata_for_set);
3878 
3879 static bool
3880 is_port_function_supported(struct mlx5_eswitch *esw, u16 vport_num)
3881 {
3882 	return vport_num == MLX5_VPORT_PF ||
3883 	       mlx5_eswitch_is_vf_vport(esw, vport_num) ||
3884 	       mlx5_esw_is_sf_vport(esw, vport_num);
3885 }
3886 
3887 int mlx5_devlink_port_function_hw_addr_get(struct devlink_port *port,
3888 					   u8 *hw_addr, int *hw_addr_len,
3889 					   struct netlink_ext_ack *extack)
3890 {
3891 	struct mlx5_eswitch *esw;
3892 	struct mlx5_vport *vport;
3893 	u16 vport_num;
3894 
3895 	esw = mlx5_devlink_eswitch_get(port->devlink);
3896 	if (IS_ERR(esw))
3897 		return PTR_ERR(esw);
3898 
3899 	vport_num = mlx5_esw_devlink_port_index_to_vport_num(port->index);
3900 	if (!is_port_function_supported(esw, vport_num))
3901 		return -EOPNOTSUPP;
3902 
3903 	vport = mlx5_eswitch_get_vport(esw, vport_num);
3904 	if (IS_ERR(vport)) {
3905 		NL_SET_ERR_MSG_MOD(extack, "Invalid port");
3906 		return PTR_ERR(vport);
3907 	}
3908 
3909 	mutex_lock(&esw->state_lock);
3910 	ether_addr_copy(hw_addr, vport->info.mac);
3911 	*hw_addr_len = ETH_ALEN;
3912 	mutex_unlock(&esw->state_lock);
3913 	return 0;
3914 }
3915 
3916 int mlx5_devlink_port_function_hw_addr_set(struct devlink_port *port,
3917 					   const u8 *hw_addr, int hw_addr_len,
3918 					   struct netlink_ext_ack *extack)
3919 {
3920 	struct mlx5_eswitch *esw;
3921 	u16 vport_num;
3922 
3923 	esw = mlx5_devlink_eswitch_get(port->devlink);
3924 	if (IS_ERR(esw)) {
3925 		NL_SET_ERR_MSG_MOD(extack, "Eswitch doesn't support set hw_addr");
3926 		return PTR_ERR(esw);
3927 	}
3928 
3929 	vport_num = mlx5_esw_devlink_port_index_to_vport_num(port->index);
3930 	if (!is_port_function_supported(esw, vport_num)) {
3931 		NL_SET_ERR_MSG_MOD(extack, "Port doesn't support set hw_addr");
3932 		return -EINVAL;
3933 	}
3934 
3935 	return mlx5_eswitch_set_vport_mac(esw, vport_num, hw_addr);
3936 }
3937 
3938 static struct mlx5_vport *
3939 mlx5_devlink_port_fn_get_vport(struct devlink_port *port, struct mlx5_eswitch *esw)
3940 {
3941 	u16 vport_num;
3942 
3943 	if (!MLX5_CAP_GEN(esw->dev, vhca_resource_manager))
3944 		return ERR_PTR(-EOPNOTSUPP);
3945 
3946 	vport_num = mlx5_esw_devlink_port_index_to_vport_num(port->index);
3947 	if (!is_port_function_supported(esw, vport_num))
3948 		return ERR_PTR(-EOPNOTSUPP);
3949 
3950 	return mlx5_eswitch_get_vport(esw, vport_num);
3951 }
3952 
3953 int mlx5_devlink_port_fn_migratable_get(struct devlink_port *port, bool *is_enabled,
3954 					struct netlink_ext_ack *extack)
3955 {
3956 	struct mlx5_eswitch *esw;
3957 	struct mlx5_vport *vport;
3958 	int err = -EOPNOTSUPP;
3959 
3960 	esw = mlx5_devlink_eswitch_get(port->devlink);
3961 	if (IS_ERR(esw))
3962 		return PTR_ERR(esw);
3963 
3964 	if (!MLX5_CAP_GEN(esw->dev, migration)) {
3965 		NL_SET_ERR_MSG_MOD(extack, "Device doesn't support migration");
3966 		return err;
3967 	}
3968 
3969 	vport = mlx5_devlink_port_fn_get_vport(port, esw);
3970 	if (IS_ERR(vport)) {
3971 		NL_SET_ERR_MSG_MOD(extack, "Invalid port");
3972 		return PTR_ERR(vport);
3973 	}
3974 
3975 	mutex_lock(&esw->state_lock);
3976 	if (vport->enabled) {
3977 		*is_enabled = vport->info.mig_enabled;
3978 		err = 0;
3979 	}
3980 	mutex_unlock(&esw->state_lock);
3981 	return err;
3982 }
3983 
3984 int mlx5_devlink_port_fn_migratable_set(struct devlink_port *port, bool enable,
3985 					struct netlink_ext_ack *extack)
3986 {
3987 	int query_out_sz = MLX5_ST_SZ_BYTES(query_hca_cap_out);
3988 	struct mlx5_eswitch *esw;
3989 	struct mlx5_vport *vport;
3990 	void *query_ctx;
3991 	void *hca_caps;
3992 	int err = -EOPNOTSUPP;
3993 
3994 	esw = mlx5_devlink_eswitch_get(port->devlink);
3995 	if (IS_ERR(esw))
3996 		return PTR_ERR(esw);
3997 
3998 	if (!MLX5_CAP_GEN(esw->dev, migration)) {
3999 		NL_SET_ERR_MSG_MOD(extack, "Device doesn't support migration");
4000 		return err;
4001 	}
4002 
4003 	vport = mlx5_devlink_port_fn_get_vport(port, esw);
4004 	if (IS_ERR(vport)) {
4005 		NL_SET_ERR_MSG_MOD(extack, "Invalid port");
4006 		return PTR_ERR(vport);
4007 	}
4008 
4009 	mutex_lock(&esw->state_lock);
4010 	if (!vport->enabled) {
4011 		NL_SET_ERR_MSG_MOD(extack, "Eswitch vport is disabled");
4012 		goto out;
4013 	}
4014 
4015 	if (vport->info.mig_enabled == enable) {
4016 		err = 0;
4017 		goto out;
4018 	}
4019 
4020 	query_ctx = kzalloc(query_out_sz, GFP_KERNEL);
4021 	if (!query_ctx) {
4022 		err = -ENOMEM;
4023 		goto out;
4024 	}
4025 
4026 	err = mlx5_vport_get_other_func_cap(esw->dev, vport->vport, query_ctx,
4027 					    MLX5_CAP_GENERAL_2);
4028 	if (err) {
4029 		NL_SET_ERR_MSG_MOD(extack, "Failed getting HCA caps");
4030 		goto out_free;
4031 	}
4032 
4033 	hca_caps = MLX5_ADDR_OF(query_hca_cap_out, query_ctx, capability);
4034 	MLX5_SET(cmd_hca_cap_2, hca_caps, migratable, 1);
4035 
4036 	err = mlx5_vport_set_other_func_cap(esw->dev, hca_caps, vport->vport,
4037 					    MLX5_SET_HCA_CAP_OP_MOD_GENERAL_DEVICE2);
4038 	if (err) {
4039 		NL_SET_ERR_MSG_MOD(extack, "Failed setting HCA migratable cap");
4040 		goto out_free;
4041 	}
4042 
4043 	vport->info.mig_enabled = enable;
4044 
4045 out_free:
4046 	kfree(query_ctx);
4047 out:
4048 	mutex_unlock(&esw->state_lock);
4049 	return err;
4050 }
4051 
4052 int mlx5_devlink_port_fn_roce_get(struct devlink_port *port, bool *is_enabled,
4053 				  struct netlink_ext_ack *extack)
4054 {
4055 	struct mlx5_eswitch *esw;
4056 	struct mlx5_vport *vport;
4057 	int err = -EOPNOTSUPP;
4058 
4059 	esw = mlx5_devlink_eswitch_get(port->devlink);
4060 	if (IS_ERR(esw))
4061 		return PTR_ERR(esw);
4062 
4063 	vport = mlx5_devlink_port_fn_get_vport(port, esw);
4064 	if (IS_ERR(vport)) {
4065 		NL_SET_ERR_MSG_MOD(extack, "Invalid port");
4066 		return PTR_ERR(vport);
4067 	}
4068 
4069 	mutex_lock(&esw->state_lock);
4070 	if (vport->enabled) {
4071 		*is_enabled = vport->info.roce_enabled;
4072 		err = 0;
4073 	}
4074 	mutex_unlock(&esw->state_lock);
4075 	return err;
4076 }
4077 
4078 int mlx5_devlink_port_fn_roce_set(struct devlink_port *port, bool enable,
4079 				  struct netlink_ext_ack *extack)
4080 {
4081 	int query_out_sz = MLX5_ST_SZ_BYTES(query_hca_cap_out);
4082 	struct mlx5_eswitch *esw;
4083 	struct mlx5_vport *vport;
4084 	int err = -EOPNOTSUPP;
4085 	void *query_ctx;
4086 	void *hca_caps;
4087 	u16 vport_num;
4088 
4089 	esw = mlx5_devlink_eswitch_get(port->devlink);
4090 	if (IS_ERR(esw))
4091 		return PTR_ERR(esw);
4092 
4093 	vport = mlx5_devlink_port_fn_get_vport(port, esw);
4094 	if (IS_ERR(vport)) {
4095 		NL_SET_ERR_MSG_MOD(extack, "Invalid port");
4096 		return PTR_ERR(vport);
4097 	}
4098 	vport_num = vport->vport;
4099 
4100 	mutex_lock(&esw->state_lock);
4101 	if (!vport->enabled) {
4102 		NL_SET_ERR_MSG_MOD(extack, "Eswitch vport is disabled");
4103 		goto out;
4104 	}
4105 
4106 	if (vport->info.roce_enabled == enable) {
4107 		err = 0;
4108 		goto out;
4109 	}
4110 
4111 	query_ctx = kzalloc(query_out_sz, GFP_KERNEL);
4112 	if (!query_ctx) {
4113 		err = -ENOMEM;
4114 		goto out;
4115 	}
4116 
4117 	err = mlx5_vport_get_other_func_cap(esw->dev, vport_num, query_ctx,
4118 					    MLX5_CAP_GENERAL);
4119 	if (err) {
4120 		NL_SET_ERR_MSG_MOD(extack, "Failed getting HCA caps");
4121 		goto out_free;
4122 	}
4123 
4124 	hca_caps = MLX5_ADDR_OF(query_hca_cap_out, query_ctx, capability);
4125 	MLX5_SET(cmd_hca_cap, hca_caps, roce, enable);
4126 
4127 	err = mlx5_vport_set_other_func_cap(esw->dev, hca_caps, vport_num,
4128 					    MLX5_SET_HCA_CAP_OP_MOD_GENERAL_DEVICE);
4129 	if (err) {
4130 		NL_SET_ERR_MSG_MOD(extack, "Failed setting HCA roce cap");
4131 		goto out_free;
4132 	}
4133 
4134 	vport->info.roce_enabled = enable;
4135 
4136 out_free:
4137 	kfree(query_ctx);
4138 out:
4139 	mutex_unlock(&esw->state_lock);
4140 	return err;
4141 }
4142