• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2015, 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/mlx5/driver.h>
35 #include <linux/mlx5/mlx5_ifc.h>
36 #include <linux/mlx5/vport.h>
37 #include <linux/mlx5/fs.h>
38 #include <linux/mlx5/mpfs.h>
39 #include "esw/acl/lgcy.h"
40 #include "mlx5_core.h"
41 #include "lib/eq.h"
42 #include "eswitch.h"
43 #include "fs_core.h"
44 #include "devlink.h"
45 #include "ecpf.h"
46 #include "en/mod_hdr.h"
47 
48 enum {
49 	MLX5_ACTION_NONE = 0,
50 	MLX5_ACTION_ADD  = 1,
51 	MLX5_ACTION_DEL  = 2,
52 };
53 
54 /* Vport UC/MC hash node */
55 struct vport_addr {
56 	struct l2addr_node     node;
57 	u8                     action;
58 	u16                    vport;
59 	struct mlx5_flow_handle *flow_rule;
60 	bool mpfs; /* UC MAC was added to MPFs */
61 	/* A flag indicating that mac was added due to mc promiscuous vport */
62 	bool mc_promisc;
63 };
64 
65 static void esw_destroy_legacy_fdb_table(struct mlx5_eswitch *esw);
66 static void esw_cleanup_vepa_rules(struct mlx5_eswitch *esw);
67 
mlx5_eswitch_check(const struct mlx5_core_dev * dev)68 static int mlx5_eswitch_check(const struct mlx5_core_dev *dev)
69 {
70 	if (MLX5_CAP_GEN(dev, port_type) != MLX5_CAP_PORT_TYPE_ETH)
71 		return -EOPNOTSUPP;
72 
73 	if (!MLX5_ESWITCH_MANAGER(dev))
74 		return -EOPNOTSUPP;
75 
76 	return 0;
77 }
78 
mlx5_devlink_eswitch_get(struct devlink * devlink)79 struct mlx5_eswitch *mlx5_devlink_eswitch_get(struct devlink *devlink)
80 {
81 	struct mlx5_core_dev *dev = devlink_priv(devlink);
82 	int err;
83 
84 	err = mlx5_eswitch_check(dev);
85 	if (err)
86 		return ERR_PTR(err);
87 
88 	return dev->priv.eswitch;
89 }
90 
91 struct mlx5_vport *__must_check
mlx5_eswitch_get_vport(struct mlx5_eswitch * esw,u16 vport_num)92 mlx5_eswitch_get_vport(struct mlx5_eswitch *esw, u16 vport_num)
93 {
94 	u16 idx;
95 
96 	if (!esw || !MLX5_CAP_GEN(esw->dev, vport_group_manager))
97 		return ERR_PTR(-EPERM);
98 
99 	idx = mlx5_eswitch_vport_num_to_index(esw, vport_num);
100 
101 	if (idx > esw->total_vports - 1) {
102 		esw_debug(esw->dev, "vport out of range: num(0x%x), idx(0x%x)\n",
103 			  vport_num, idx);
104 		return ERR_PTR(-EINVAL);
105 	}
106 
107 	return &esw->vports[idx];
108 }
109 
arm_vport_context_events_cmd(struct mlx5_core_dev * dev,u16 vport,u32 events_mask)110 static int arm_vport_context_events_cmd(struct mlx5_core_dev *dev, u16 vport,
111 					u32 events_mask)
112 {
113 	u32 in[MLX5_ST_SZ_DW(modify_nic_vport_context_in)] = {};
114 	void *nic_vport_ctx;
115 
116 	MLX5_SET(modify_nic_vport_context_in, in,
117 		 opcode, MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT);
118 	MLX5_SET(modify_nic_vport_context_in, in, field_select.change_event, 1);
119 	MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport);
120 	MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1);
121 	nic_vport_ctx = MLX5_ADDR_OF(modify_nic_vport_context_in,
122 				     in, nic_vport_context);
123 
124 	MLX5_SET(nic_vport_context, nic_vport_ctx, arm_change_event, 1);
125 
126 	if (events_mask & MLX5_VPORT_UC_ADDR_CHANGE)
127 		MLX5_SET(nic_vport_context, nic_vport_ctx,
128 			 event_on_uc_address_change, 1);
129 	if (events_mask & MLX5_VPORT_MC_ADDR_CHANGE)
130 		MLX5_SET(nic_vport_context, nic_vport_ctx,
131 			 event_on_mc_address_change, 1);
132 	if (events_mask & MLX5_VPORT_PROMISC_CHANGE)
133 		MLX5_SET(nic_vport_context, nic_vport_ctx,
134 			 event_on_promisc_change, 1);
135 
136 	return mlx5_cmd_exec_in(dev, modify_nic_vport_context, in);
137 }
138 
139 /* E-Switch vport context HW commands */
mlx5_eswitch_modify_esw_vport_context(struct mlx5_core_dev * dev,u16 vport,bool other_vport,void * in)140 int mlx5_eswitch_modify_esw_vport_context(struct mlx5_core_dev *dev, u16 vport,
141 					  bool other_vport, void *in)
142 {
143 	MLX5_SET(modify_esw_vport_context_in, in, opcode,
144 		 MLX5_CMD_OP_MODIFY_ESW_VPORT_CONTEXT);
145 	MLX5_SET(modify_esw_vport_context_in, in, vport_number, vport);
146 	MLX5_SET(modify_esw_vport_context_in, in, other_vport, other_vport);
147 	return mlx5_cmd_exec_in(dev, modify_esw_vport_context, in);
148 }
149 
modify_esw_vport_cvlan(struct mlx5_core_dev * dev,u16 vport,u16 vlan,u8 qos,u8 set_flags)150 static int modify_esw_vport_cvlan(struct mlx5_core_dev *dev, u16 vport,
151 				  u16 vlan, u8 qos, u8 set_flags)
152 {
153 	u32 in[MLX5_ST_SZ_DW(modify_esw_vport_context_in)] = {};
154 
155 	if (!MLX5_CAP_ESW(dev, vport_cvlan_strip) ||
156 	    !MLX5_CAP_ESW(dev, vport_cvlan_insert_if_not_exist))
157 		return -EOPNOTSUPP;
158 
159 	esw_debug(dev, "Set Vport[%d] VLAN %d qos %d set=%x\n",
160 		  vport, vlan, qos, set_flags);
161 
162 	if (set_flags & SET_VLAN_STRIP)
163 		MLX5_SET(modify_esw_vport_context_in, in,
164 			 esw_vport_context.vport_cvlan_strip, 1);
165 
166 	if (set_flags & SET_VLAN_INSERT) {
167 		/* insert only if no vlan in packet */
168 		MLX5_SET(modify_esw_vport_context_in, in,
169 			 esw_vport_context.vport_cvlan_insert, 1);
170 
171 		MLX5_SET(modify_esw_vport_context_in, in,
172 			 esw_vport_context.cvlan_pcp, qos);
173 		MLX5_SET(modify_esw_vport_context_in, in,
174 			 esw_vport_context.cvlan_id, vlan);
175 	}
176 
177 	MLX5_SET(modify_esw_vport_context_in, in,
178 		 field_select.vport_cvlan_strip, 1);
179 	MLX5_SET(modify_esw_vport_context_in, in,
180 		 field_select.vport_cvlan_insert, 1);
181 
182 	return mlx5_eswitch_modify_esw_vport_context(dev, vport, true, in);
183 }
184 
185 /* E-Switch FDB */
186 static struct mlx5_flow_handle *
__esw_fdb_set_vport_rule(struct mlx5_eswitch * esw,u16 vport,bool rx_rule,u8 mac_c[ETH_ALEN],u8 mac_v[ETH_ALEN])187 __esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u16 vport, bool rx_rule,
188 			 u8 mac_c[ETH_ALEN], u8 mac_v[ETH_ALEN])
189 {
190 	int match_header = (is_zero_ether_addr(mac_c) ? 0 :
191 			    MLX5_MATCH_OUTER_HEADERS);
192 	struct mlx5_flow_handle *flow_rule = NULL;
193 	struct mlx5_flow_act flow_act = {0};
194 	struct mlx5_flow_destination dest = {};
195 	struct mlx5_flow_spec *spec;
196 	void *mv_misc = NULL;
197 	void *mc_misc = NULL;
198 	u8 *dmac_v = NULL;
199 	u8 *dmac_c = NULL;
200 
201 	if (rx_rule)
202 		match_header |= MLX5_MATCH_MISC_PARAMETERS;
203 
204 	spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
205 	if (!spec)
206 		return NULL;
207 
208 	dmac_v = MLX5_ADDR_OF(fte_match_param, spec->match_value,
209 			      outer_headers.dmac_47_16);
210 	dmac_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
211 			      outer_headers.dmac_47_16);
212 
213 	if (match_header & MLX5_MATCH_OUTER_HEADERS) {
214 		ether_addr_copy(dmac_v, mac_v);
215 		ether_addr_copy(dmac_c, mac_c);
216 	}
217 
218 	if (match_header & MLX5_MATCH_MISC_PARAMETERS) {
219 		mv_misc  = MLX5_ADDR_OF(fte_match_param, spec->match_value,
220 					misc_parameters);
221 		mc_misc  = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
222 					misc_parameters);
223 		MLX5_SET(fte_match_set_misc, mv_misc, source_port, MLX5_VPORT_UPLINK);
224 		MLX5_SET_TO_ONES(fte_match_set_misc, mc_misc, source_port);
225 	}
226 
227 	dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
228 	dest.vport.num = vport;
229 
230 	esw_debug(esw->dev,
231 		  "\tFDB add rule dmac_v(%pM) dmac_c(%pM) -> vport(%d)\n",
232 		  dmac_v, dmac_c, vport);
233 	spec->match_criteria_enable = match_header;
234 	flow_act.action =  MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
235 	flow_rule =
236 		mlx5_add_flow_rules(esw->fdb_table.legacy.fdb, spec,
237 				    &flow_act, &dest, 1);
238 	if (IS_ERR(flow_rule)) {
239 		esw_warn(esw->dev,
240 			 "FDB: Failed to add flow rule: dmac_v(%pM) dmac_c(%pM) -> vport(%d), err(%ld)\n",
241 			 dmac_v, dmac_c, vport, PTR_ERR(flow_rule));
242 		flow_rule = NULL;
243 	}
244 
245 	kvfree(spec);
246 	return flow_rule;
247 }
248 
249 static struct mlx5_flow_handle *
esw_fdb_set_vport_rule(struct mlx5_eswitch * esw,u8 mac[ETH_ALEN],u16 vport)250 esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u8 mac[ETH_ALEN], u16 vport)
251 {
252 	u8 mac_c[ETH_ALEN];
253 
254 	eth_broadcast_addr(mac_c);
255 	return __esw_fdb_set_vport_rule(esw, vport, false, mac_c, mac);
256 }
257 
258 static struct mlx5_flow_handle *
esw_fdb_set_vport_allmulti_rule(struct mlx5_eswitch * esw,u16 vport)259 esw_fdb_set_vport_allmulti_rule(struct mlx5_eswitch *esw, u16 vport)
260 {
261 	u8 mac_c[ETH_ALEN];
262 	u8 mac_v[ETH_ALEN];
263 
264 	eth_zero_addr(mac_c);
265 	eth_zero_addr(mac_v);
266 	mac_c[0] = 0x01;
267 	mac_v[0] = 0x01;
268 	return __esw_fdb_set_vport_rule(esw, vport, false, mac_c, mac_v);
269 }
270 
271 static struct mlx5_flow_handle *
esw_fdb_set_vport_promisc_rule(struct mlx5_eswitch * esw,u16 vport)272 esw_fdb_set_vport_promisc_rule(struct mlx5_eswitch *esw, u16 vport)
273 {
274 	u8 mac_c[ETH_ALEN];
275 	u8 mac_v[ETH_ALEN];
276 
277 	eth_zero_addr(mac_c);
278 	eth_zero_addr(mac_v);
279 	return __esw_fdb_set_vport_rule(esw, vport, true, mac_c, mac_v);
280 }
281 
282 enum {
283 	LEGACY_VEPA_PRIO = 0,
284 	LEGACY_FDB_PRIO,
285 };
286 
esw_create_legacy_vepa_table(struct mlx5_eswitch * esw)287 static int esw_create_legacy_vepa_table(struct mlx5_eswitch *esw)
288 {
289 	struct mlx5_flow_table_attr ft_attr = {};
290 	struct mlx5_core_dev *dev = esw->dev;
291 	struct mlx5_flow_namespace *root_ns;
292 	struct mlx5_flow_table *fdb;
293 	int err;
294 
295 	root_ns = mlx5_get_fdb_sub_ns(dev, 0);
296 	if (!root_ns) {
297 		esw_warn(dev, "Failed to get FDB flow namespace\n");
298 		return -EOPNOTSUPP;
299 	}
300 
301 	/* num FTE 2, num FG 2 */
302 	ft_attr.prio = LEGACY_VEPA_PRIO;
303 	ft_attr.max_fte = 2;
304 	ft_attr.autogroup.max_num_groups = 2;
305 	fdb = mlx5_create_auto_grouped_flow_table(root_ns, &ft_attr);
306 	if (IS_ERR(fdb)) {
307 		err = PTR_ERR(fdb);
308 		esw_warn(dev, "Failed to create VEPA FDB err %d\n", err);
309 		return err;
310 	}
311 	esw->fdb_table.legacy.vepa_fdb = fdb;
312 
313 	return 0;
314 }
315 
esw_create_legacy_fdb_table(struct mlx5_eswitch * esw)316 static int esw_create_legacy_fdb_table(struct mlx5_eswitch *esw)
317 {
318 	int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
319 	struct mlx5_flow_table_attr ft_attr = {};
320 	struct mlx5_core_dev *dev = esw->dev;
321 	struct mlx5_flow_namespace *root_ns;
322 	struct mlx5_flow_table *fdb;
323 	struct mlx5_flow_group *g;
324 	void *match_criteria;
325 	int table_size;
326 	u32 *flow_group_in;
327 	u8 *dmac;
328 	int err = 0;
329 
330 	esw_debug(dev, "Create FDB log_max_size(%d)\n",
331 		  MLX5_CAP_ESW_FLOWTABLE_FDB(dev, log_max_ft_size));
332 
333 	root_ns = mlx5_get_fdb_sub_ns(dev, 0);
334 	if (!root_ns) {
335 		esw_warn(dev, "Failed to get FDB flow namespace\n");
336 		return -EOPNOTSUPP;
337 	}
338 
339 	flow_group_in = kvzalloc(inlen, GFP_KERNEL);
340 	if (!flow_group_in)
341 		return -ENOMEM;
342 
343 	table_size = BIT(MLX5_CAP_ESW_FLOWTABLE_FDB(dev, log_max_ft_size));
344 	ft_attr.max_fte = table_size;
345 	ft_attr.prio = LEGACY_FDB_PRIO;
346 	fdb = mlx5_create_flow_table(root_ns, &ft_attr);
347 	if (IS_ERR(fdb)) {
348 		err = PTR_ERR(fdb);
349 		esw_warn(dev, "Failed to create FDB Table err %d\n", err);
350 		goto out;
351 	}
352 	esw->fdb_table.legacy.fdb = fdb;
353 
354 	/* Addresses group : Full match unicast/multicast addresses */
355 	MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
356 		 MLX5_MATCH_OUTER_HEADERS);
357 	match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in, match_criteria);
358 	dmac = MLX5_ADDR_OF(fte_match_param, match_criteria, outer_headers.dmac_47_16);
359 	MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 0);
360 	/* Preserve 2 entries for allmulti and promisc rules*/
361 	MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, table_size - 3);
362 	eth_broadcast_addr(dmac);
363 	g = mlx5_create_flow_group(fdb, flow_group_in);
364 	if (IS_ERR(g)) {
365 		err = PTR_ERR(g);
366 		esw_warn(dev, "Failed to create flow group err(%d)\n", err);
367 		goto out;
368 	}
369 	esw->fdb_table.legacy.addr_grp = g;
370 
371 	/* Allmulti group : One rule that forwards any mcast traffic */
372 	MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
373 		 MLX5_MATCH_OUTER_HEADERS);
374 	MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, table_size - 2);
375 	MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, table_size - 2);
376 	eth_zero_addr(dmac);
377 	dmac[0] = 0x01;
378 	g = mlx5_create_flow_group(fdb, flow_group_in);
379 	if (IS_ERR(g)) {
380 		err = PTR_ERR(g);
381 		esw_warn(dev, "Failed to create allmulti flow group err(%d)\n", err);
382 		goto out;
383 	}
384 	esw->fdb_table.legacy.allmulti_grp = g;
385 
386 	/* Promiscuous group :
387 	 * One rule that forward all unmatched traffic from previous groups
388 	 */
389 	eth_zero_addr(dmac);
390 	MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
391 		 MLX5_MATCH_MISC_PARAMETERS);
392 	MLX5_SET_TO_ONES(fte_match_param, match_criteria, misc_parameters.source_port);
393 	MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, table_size - 1);
394 	MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, table_size - 1);
395 	g = mlx5_create_flow_group(fdb, flow_group_in);
396 	if (IS_ERR(g)) {
397 		err = PTR_ERR(g);
398 		esw_warn(dev, "Failed to create promisc flow group err(%d)\n", err);
399 		goto out;
400 	}
401 	esw->fdb_table.legacy.promisc_grp = g;
402 
403 out:
404 	if (err)
405 		esw_destroy_legacy_fdb_table(esw);
406 
407 	kvfree(flow_group_in);
408 	return err;
409 }
410 
esw_destroy_legacy_vepa_table(struct mlx5_eswitch * esw)411 static void esw_destroy_legacy_vepa_table(struct mlx5_eswitch *esw)
412 {
413 	esw_debug(esw->dev, "Destroy VEPA Table\n");
414 	if (!esw->fdb_table.legacy.vepa_fdb)
415 		return;
416 
417 	mlx5_destroy_flow_table(esw->fdb_table.legacy.vepa_fdb);
418 	esw->fdb_table.legacy.vepa_fdb = NULL;
419 }
420 
esw_destroy_legacy_fdb_table(struct mlx5_eswitch * esw)421 static void esw_destroy_legacy_fdb_table(struct mlx5_eswitch *esw)
422 {
423 	esw_debug(esw->dev, "Destroy FDB Table\n");
424 	if (!esw->fdb_table.legacy.fdb)
425 		return;
426 
427 	if (esw->fdb_table.legacy.promisc_grp)
428 		mlx5_destroy_flow_group(esw->fdb_table.legacy.promisc_grp);
429 	if (esw->fdb_table.legacy.allmulti_grp)
430 		mlx5_destroy_flow_group(esw->fdb_table.legacy.allmulti_grp);
431 	if (esw->fdb_table.legacy.addr_grp)
432 		mlx5_destroy_flow_group(esw->fdb_table.legacy.addr_grp);
433 	mlx5_destroy_flow_table(esw->fdb_table.legacy.fdb);
434 
435 	esw->fdb_table.legacy.fdb = NULL;
436 	esw->fdb_table.legacy.addr_grp = NULL;
437 	esw->fdb_table.legacy.allmulti_grp = NULL;
438 	esw->fdb_table.legacy.promisc_grp = NULL;
439 }
440 
esw_create_legacy_table(struct mlx5_eswitch * esw)441 static int esw_create_legacy_table(struct mlx5_eswitch *esw)
442 {
443 	int err;
444 
445 	memset(&esw->fdb_table.legacy, 0, sizeof(struct legacy_fdb));
446 
447 	err = esw_create_legacy_vepa_table(esw);
448 	if (err)
449 		return err;
450 
451 	err = esw_create_legacy_fdb_table(esw);
452 	if (err)
453 		esw_destroy_legacy_vepa_table(esw);
454 
455 	return err;
456 }
457 
esw_destroy_legacy_table(struct mlx5_eswitch * esw)458 static void esw_destroy_legacy_table(struct mlx5_eswitch *esw)
459 {
460 	esw_cleanup_vepa_rules(esw);
461 	esw_destroy_legacy_fdb_table(esw);
462 	esw_destroy_legacy_vepa_table(esw);
463 }
464 
465 #define MLX5_LEGACY_SRIOV_VPORT_EVENTS (MLX5_VPORT_UC_ADDR_CHANGE | \
466 					MLX5_VPORT_MC_ADDR_CHANGE | \
467 					MLX5_VPORT_PROMISC_CHANGE)
468 
esw_legacy_enable(struct mlx5_eswitch * esw)469 static int esw_legacy_enable(struct mlx5_eswitch *esw)
470 {
471 	struct mlx5_vport *vport;
472 	int ret, i;
473 
474 	ret = esw_create_legacy_table(esw);
475 	if (ret)
476 		return ret;
477 
478 	mlx5_esw_for_each_vf_vport(esw, i, vport, esw->esw_funcs.num_vfs)
479 		vport->info.link_state = MLX5_VPORT_ADMIN_STATE_AUTO;
480 
481 	ret = mlx5_eswitch_enable_pf_vf_vports(esw, MLX5_LEGACY_SRIOV_VPORT_EVENTS);
482 	if (ret)
483 		esw_destroy_legacy_table(esw);
484 	return ret;
485 }
486 
esw_legacy_disable(struct mlx5_eswitch * esw)487 static void esw_legacy_disable(struct mlx5_eswitch *esw)
488 {
489 	struct esw_mc_addr *mc_promisc;
490 
491 	mlx5_eswitch_disable_pf_vf_vports(esw);
492 
493 	mc_promisc = &esw->mc_promisc;
494 	if (mc_promisc->uplink_rule)
495 		mlx5_del_flow_rules(mc_promisc->uplink_rule);
496 
497 	esw_destroy_legacy_table(esw);
498 }
499 
500 /* E-Switch vport UC/MC lists management */
501 typedef int (*vport_addr_action)(struct mlx5_eswitch *esw,
502 				 struct vport_addr *vaddr);
503 
esw_add_uc_addr(struct mlx5_eswitch * esw,struct vport_addr * vaddr)504 static int esw_add_uc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr)
505 {
506 	u8 *mac = vaddr->node.addr;
507 	u16 vport = vaddr->vport;
508 	int err;
509 
510 	/* Skip mlx5_mpfs_add_mac for eswitch_managers,
511 	 * it is already done by its netdev in mlx5e_execute_l2_action
512 	 */
513 	if (mlx5_esw_is_manager_vport(esw, vport))
514 		goto fdb_add;
515 
516 	err = mlx5_mpfs_add_mac(esw->dev, mac);
517 	if (err) {
518 		esw_warn(esw->dev,
519 			 "Failed to add L2 table mac(%pM) for vport(0x%x), err(%d)\n",
520 			 mac, vport, err);
521 		return err;
522 	}
523 	vaddr->mpfs = true;
524 
525 fdb_add:
526 	/* SRIOV is enabled: Forward UC MAC to vport */
527 	if (esw->fdb_table.legacy.fdb && esw->mode == MLX5_ESWITCH_LEGACY)
528 		vaddr->flow_rule = esw_fdb_set_vport_rule(esw, mac, vport);
529 
530 	esw_debug(esw->dev, "\tADDED UC MAC: vport[%d] %pM fr(%p)\n",
531 		  vport, mac, vaddr->flow_rule);
532 
533 	return 0;
534 }
535 
esw_del_uc_addr(struct mlx5_eswitch * esw,struct vport_addr * vaddr)536 static int esw_del_uc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr)
537 {
538 	u8 *mac = vaddr->node.addr;
539 	u16 vport = vaddr->vport;
540 	int err = 0;
541 
542 	/* Skip mlx5_mpfs_del_mac for eswitch managers,
543 	 * it is already done by its netdev in mlx5e_execute_l2_action
544 	 */
545 	if (!vaddr->mpfs || mlx5_esw_is_manager_vport(esw, vport))
546 		goto fdb_del;
547 
548 	err = mlx5_mpfs_del_mac(esw->dev, mac);
549 	if (err)
550 		esw_warn(esw->dev,
551 			 "Failed to del L2 table mac(%pM) for vport(%d), err(%d)\n",
552 			 mac, vport, err);
553 	vaddr->mpfs = false;
554 
555 fdb_del:
556 	if (vaddr->flow_rule)
557 		mlx5_del_flow_rules(vaddr->flow_rule);
558 	vaddr->flow_rule = NULL;
559 
560 	return 0;
561 }
562 
update_allmulti_vports(struct mlx5_eswitch * esw,struct vport_addr * vaddr,struct esw_mc_addr * esw_mc)563 static void update_allmulti_vports(struct mlx5_eswitch *esw,
564 				   struct vport_addr *vaddr,
565 				   struct esw_mc_addr *esw_mc)
566 {
567 	u8 *mac = vaddr->node.addr;
568 	struct mlx5_vport *vport;
569 	u16 i, vport_num;
570 
571 	mlx5_esw_for_all_vports(esw, i, vport) {
572 		struct hlist_head *vport_hash = vport->mc_list;
573 		struct vport_addr *iter_vaddr =
574 					l2addr_hash_find(vport_hash,
575 							 mac,
576 							 struct vport_addr);
577 		vport_num = vport->vport;
578 		if (IS_ERR_OR_NULL(vport->allmulti_rule) ||
579 		    vaddr->vport == vport_num)
580 			continue;
581 		switch (vaddr->action) {
582 		case MLX5_ACTION_ADD:
583 			if (iter_vaddr)
584 				continue;
585 			iter_vaddr = l2addr_hash_add(vport_hash, mac,
586 						     struct vport_addr,
587 						     GFP_KERNEL);
588 			if (!iter_vaddr) {
589 				esw_warn(esw->dev,
590 					 "ALL-MULTI: Failed to add MAC(%pM) to vport[%d] DB\n",
591 					 mac, vport_num);
592 				continue;
593 			}
594 			iter_vaddr->vport = vport_num;
595 			iter_vaddr->flow_rule =
596 					esw_fdb_set_vport_rule(esw,
597 							       mac,
598 							       vport_num);
599 			iter_vaddr->mc_promisc = true;
600 			break;
601 		case MLX5_ACTION_DEL:
602 			if (!iter_vaddr)
603 				continue;
604 			mlx5_del_flow_rules(iter_vaddr->flow_rule);
605 			l2addr_hash_del(iter_vaddr);
606 			break;
607 		}
608 	}
609 }
610 
esw_add_mc_addr(struct mlx5_eswitch * esw,struct vport_addr * vaddr)611 static int esw_add_mc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr)
612 {
613 	struct hlist_head *hash = esw->mc_table;
614 	struct esw_mc_addr *esw_mc;
615 	u8 *mac = vaddr->node.addr;
616 	u16 vport = vaddr->vport;
617 
618 	if (!esw->fdb_table.legacy.fdb)
619 		return 0;
620 
621 	esw_mc = l2addr_hash_find(hash, mac, struct esw_mc_addr);
622 	if (esw_mc)
623 		goto add;
624 
625 	esw_mc = l2addr_hash_add(hash, mac, struct esw_mc_addr, GFP_KERNEL);
626 	if (!esw_mc)
627 		return -ENOMEM;
628 
629 	esw_mc->uplink_rule = /* Forward MC MAC to Uplink */
630 		esw_fdb_set_vport_rule(esw, mac, MLX5_VPORT_UPLINK);
631 
632 	/* Add this multicast mac to all the mc promiscuous vports */
633 	update_allmulti_vports(esw, vaddr, esw_mc);
634 
635 add:
636 	/* If the multicast mac is added as a result of mc promiscuous vport,
637 	 * don't increment the multicast ref count
638 	 */
639 	if (!vaddr->mc_promisc)
640 		esw_mc->refcnt++;
641 
642 	/* Forward MC MAC to vport */
643 	vaddr->flow_rule = esw_fdb_set_vport_rule(esw, mac, vport);
644 	esw_debug(esw->dev,
645 		  "\tADDED MC MAC: vport[%d] %pM fr(%p) refcnt(%d) uplinkfr(%p)\n",
646 		  vport, mac, vaddr->flow_rule,
647 		  esw_mc->refcnt, esw_mc->uplink_rule);
648 	return 0;
649 }
650 
esw_del_mc_addr(struct mlx5_eswitch * esw,struct vport_addr * vaddr)651 static int esw_del_mc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr)
652 {
653 	struct hlist_head *hash = esw->mc_table;
654 	struct esw_mc_addr *esw_mc;
655 	u8 *mac = vaddr->node.addr;
656 	u16 vport = vaddr->vport;
657 
658 	if (!esw->fdb_table.legacy.fdb)
659 		return 0;
660 
661 	esw_mc = l2addr_hash_find(hash, mac, struct esw_mc_addr);
662 	if (!esw_mc) {
663 		esw_warn(esw->dev,
664 			 "Failed to find eswitch MC addr for MAC(%pM) vport(%d)",
665 			 mac, vport);
666 		return -EINVAL;
667 	}
668 	esw_debug(esw->dev,
669 		  "\tDELETE MC MAC: vport[%d] %pM fr(%p) refcnt(%d) uplinkfr(%p)\n",
670 		  vport, mac, vaddr->flow_rule, esw_mc->refcnt,
671 		  esw_mc->uplink_rule);
672 
673 	if (vaddr->flow_rule)
674 		mlx5_del_flow_rules(vaddr->flow_rule);
675 	vaddr->flow_rule = NULL;
676 
677 	/* If the multicast mac is added as a result of mc promiscuous vport,
678 	 * don't decrement the multicast ref count.
679 	 */
680 	if (vaddr->mc_promisc || (--esw_mc->refcnt > 0))
681 		return 0;
682 
683 	/* Remove this multicast mac from all the mc promiscuous vports */
684 	update_allmulti_vports(esw, vaddr, esw_mc);
685 
686 	if (esw_mc->uplink_rule)
687 		mlx5_del_flow_rules(esw_mc->uplink_rule);
688 
689 	l2addr_hash_del(esw_mc);
690 	return 0;
691 }
692 
693 /* Apply vport UC/MC list to HW l2 table and FDB table */
esw_apply_vport_addr_list(struct mlx5_eswitch * esw,struct mlx5_vport * vport,int list_type)694 static void esw_apply_vport_addr_list(struct mlx5_eswitch *esw,
695 				      struct mlx5_vport *vport, int list_type)
696 {
697 	bool is_uc = list_type == MLX5_NVPRT_LIST_TYPE_UC;
698 	vport_addr_action vport_addr_add;
699 	vport_addr_action vport_addr_del;
700 	struct vport_addr *addr;
701 	struct l2addr_node *node;
702 	struct hlist_head *hash;
703 	struct hlist_node *tmp;
704 	int hi;
705 
706 	vport_addr_add = is_uc ? esw_add_uc_addr :
707 				 esw_add_mc_addr;
708 	vport_addr_del = is_uc ? esw_del_uc_addr :
709 				 esw_del_mc_addr;
710 
711 	hash = is_uc ? vport->uc_list : vport->mc_list;
712 	for_each_l2hash_node(node, tmp, hash, hi) {
713 		addr = container_of(node, struct vport_addr, node);
714 		switch (addr->action) {
715 		case MLX5_ACTION_ADD:
716 			vport_addr_add(esw, addr);
717 			addr->action = MLX5_ACTION_NONE;
718 			break;
719 		case MLX5_ACTION_DEL:
720 			vport_addr_del(esw, addr);
721 			l2addr_hash_del(addr);
722 			break;
723 		}
724 	}
725 }
726 
727 /* Sync vport UC/MC list from vport context */
esw_update_vport_addr_list(struct mlx5_eswitch * esw,struct mlx5_vport * vport,int list_type)728 static void esw_update_vport_addr_list(struct mlx5_eswitch *esw,
729 				       struct mlx5_vport *vport, int list_type)
730 {
731 	bool is_uc = list_type == MLX5_NVPRT_LIST_TYPE_UC;
732 	u8 (*mac_list)[ETH_ALEN];
733 	struct l2addr_node *node;
734 	struct vport_addr *addr;
735 	struct hlist_head *hash;
736 	struct hlist_node *tmp;
737 	int size;
738 	int err;
739 	int hi;
740 	int i;
741 
742 	size = is_uc ? MLX5_MAX_UC_PER_VPORT(esw->dev) :
743 		       MLX5_MAX_MC_PER_VPORT(esw->dev);
744 
745 	mac_list = kcalloc(size, ETH_ALEN, GFP_KERNEL);
746 	if (!mac_list)
747 		return;
748 
749 	hash = is_uc ? vport->uc_list : vport->mc_list;
750 
751 	for_each_l2hash_node(node, tmp, hash, hi) {
752 		addr = container_of(node, struct vport_addr, node);
753 		addr->action = MLX5_ACTION_DEL;
754 	}
755 
756 	if (!vport->enabled)
757 		goto out;
758 
759 	err = mlx5_query_nic_vport_mac_list(esw->dev, vport->vport, list_type,
760 					    mac_list, &size);
761 	if (err)
762 		goto out;
763 	esw_debug(esw->dev, "vport[%d] context update %s list size (%d)\n",
764 		  vport->vport, is_uc ? "UC" : "MC", size);
765 
766 	for (i = 0; i < size; i++) {
767 		if (is_uc && !is_valid_ether_addr(mac_list[i]))
768 			continue;
769 
770 		if (!is_uc && !is_multicast_ether_addr(mac_list[i]))
771 			continue;
772 
773 		addr = l2addr_hash_find(hash, mac_list[i], struct vport_addr);
774 		if (addr) {
775 			addr->action = MLX5_ACTION_NONE;
776 			/* If this mac was previously added because of allmulti
777 			 * promiscuous rx mode, its now converted to be original
778 			 * vport mac.
779 			 */
780 			if (addr->mc_promisc) {
781 				struct esw_mc_addr *esw_mc =
782 					l2addr_hash_find(esw->mc_table,
783 							 mac_list[i],
784 							 struct esw_mc_addr);
785 				if (!esw_mc) {
786 					esw_warn(esw->dev,
787 						 "Failed to MAC(%pM) in mcast DB\n",
788 						 mac_list[i]);
789 					continue;
790 				}
791 				esw_mc->refcnt++;
792 				addr->mc_promisc = false;
793 			}
794 			continue;
795 		}
796 
797 		addr = l2addr_hash_add(hash, mac_list[i], struct vport_addr,
798 				       GFP_KERNEL);
799 		if (!addr) {
800 			esw_warn(esw->dev,
801 				 "Failed to add MAC(%pM) to vport[%d] DB\n",
802 				 mac_list[i], vport->vport);
803 			continue;
804 		}
805 		addr->vport = vport->vport;
806 		addr->action = MLX5_ACTION_ADD;
807 	}
808 out:
809 	kfree(mac_list);
810 }
811 
812 /* Sync vport UC/MC list from vport context
813  * Must be called after esw_update_vport_addr_list
814  */
esw_update_vport_mc_promisc(struct mlx5_eswitch * esw,struct mlx5_vport * vport)815 static void esw_update_vport_mc_promisc(struct mlx5_eswitch *esw,
816 					struct mlx5_vport *vport)
817 {
818 	struct l2addr_node *node;
819 	struct vport_addr *addr;
820 	struct hlist_head *hash;
821 	struct hlist_node *tmp;
822 	int hi;
823 
824 	hash = vport->mc_list;
825 
826 	for_each_l2hash_node(node, tmp, esw->mc_table, hi) {
827 		u8 *mac = node->addr;
828 
829 		addr = l2addr_hash_find(hash, mac, struct vport_addr);
830 		if (addr) {
831 			if (addr->action == MLX5_ACTION_DEL)
832 				addr->action = MLX5_ACTION_NONE;
833 			continue;
834 		}
835 		addr = l2addr_hash_add(hash, mac, struct vport_addr,
836 				       GFP_KERNEL);
837 		if (!addr) {
838 			esw_warn(esw->dev,
839 				 "Failed to add allmulti MAC(%pM) to vport[%d] DB\n",
840 				 mac, vport->vport);
841 			continue;
842 		}
843 		addr->vport = vport->vport;
844 		addr->action = MLX5_ACTION_ADD;
845 		addr->mc_promisc = true;
846 	}
847 }
848 
849 /* Apply vport rx mode to HW FDB table */
esw_apply_vport_rx_mode(struct mlx5_eswitch * esw,struct mlx5_vport * vport,bool promisc,bool mc_promisc)850 static void esw_apply_vport_rx_mode(struct mlx5_eswitch *esw,
851 				    struct mlx5_vport *vport,
852 				    bool promisc, bool mc_promisc)
853 {
854 	struct esw_mc_addr *allmulti_addr = &esw->mc_promisc;
855 
856 	if (IS_ERR_OR_NULL(vport->allmulti_rule) != mc_promisc)
857 		goto promisc;
858 
859 	if (mc_promisc) {
860 		vport->allmulti_rule =
861 			esw_fdb_set_vport_allmulti_rule(esw, vport->vport);
862 		if (!allmulti_addr->uplink_rule)
863 			allmulti_addr->uplink_rule =
864 				esw_fdb_set_vport_allmulti_rule(esw,
865 								MLX5_VPORT_UPLINK);
866 		allmulti_addr->refcnt++;
867 	} else if (vport->allmulti_rule) {
868 		mlx5_del_flow_rules(vport->allmulti_rule);
869 		vport->allmulti_rule = NULL;
870 
871 		if (--allmulti_addr->refcnt > 0)
872 			goto promisc;
873 
874 		if (allmulti_addr->uplink_rule)
875 			mlx5_del_flow_rules(allmulti_addr->uplink_rule);
876 		allmulti_addr->uplink_rule = NULL;
877 	}
878 
879 promisc:
880 	if (IS_ERR_OR_NULL(vport->promisc_rule) != promisc)
881 		return;
882 
883 	if (promisc) {
884 		vport->promisc_rule =
885 			esw_fdb_set_vport_promisc_rule(esw, vport->vport);
886 	} else if (vport->promisc_rule) {
887 		mlx5_del_flow_rules(vport->promisc_rule);
888 		vport->promisc_rule = NULL;
889 	}
890 }
891 
892 /* Sync vport rx mode from vport context */
esw_update_vport_rx_mode(struct mlx5_eswitch * esw,struct mlx5_vport * vport)893 static void esw_update_vport_rx_mode(struct mlx5_eswitch *esw,
894 				     struct mlx5_vport *vport)
895 {
896 	int promisc_all = 0;
897 	int promisc_uc = 0;
898 	int promisc_mc = 0;
899 	int err;
900 
901 	err = mlx5_query_nic_vport_promisc(esw->dev,
902 					   vport->vport,
903 					   &promisc_uc,
904 					   &promisc_mc,
905 					   &promisc_all);
906 	if (err)
907 		return;
908 	esw_debug(esw->dev, "vport[%d] context update rx mode promisc_all=%d, all_multi=%d\n",
909 		  vport->vport, promisc_all, promisc_mc);
910 
911 	if (!vport->info.trusted || !vport->enabled) {
912 		promisc_uc = 0;
913 		promisc_mc = 0;
914 		promisc_all = 0;
915 	}
916 
917 	esw_apply_vport_rx_mode(esw, vport, promisc_all,
918 				(promisc_all || promisc_mc));
919 }
920 
esw_vport_change_handle_locked(struct mlx5_vport * vport)921 static void esw_vport_change_handle_locked(struct mlx5_vport *vport)
922 {
923 	struct mlx5_core_dev *dev = vport->dev;
924 	struct mlx5_eswitch *esw = dev->priv.eswitch;
925 	u8 mac[ETH_ALEN];
926 
927 	mlx5_query_nic_vport_mac_address(dev, vport->vport, true, mac);
928 	esw_debug(dev, "vport[%d] Context Changed: perm mac: %pM\n",
929 		  vport->vport, mac);
930 
931 	if (vport->enabled_events & MLX5_VPORT_UC_ADDR_CHANGE) {
932 		esw_update_vport_addr_list(esw, vport, MLX5_NVPRT_LIST_TYPE_UC);
933 		esw_apply_vport_addr_list(esw, vport, MLX5_NVPRT_LIST_TYPE_UC);
934 	}
935 
936 	if (vport->enabled_events & MLX5_VPORT_MC_ADDR_CHANGE)
937 		esw_update_vport_addr_list(esw, vport, MLX5_NVPRT_LIST_TYPE_MC);
938 
939 	if (vport->enabled_events & MLX5_VPORT_PROMISC_CHANGE) {
940 		esw_update_vport_rx_mode(esw, vport);
941 		if (!IS_ERR_OR_NULL(vport->allmulti_rule))
942 			esw_update_vport_mc_promisc(esw, vport);
943 	}
944 
945 	if (vport->enabled_events & (MLX5_VPORT_PROMISC_CHANGE | MLX5_VPORT_MC_ADDR_CHANGE))
946 		esw_apply_vport_addr_list(esw, vport, MLX5_NVPRT_LIST_TYPE_MC);
947 
948 	esw_debug(esw->dev, "vport[%d] Context Changed: Done\n", vport->vport);
949 	if (vport->enabled)
950 		arm_vport_context_events_cmd(dev, vport->vport,
951 					     vport->enabled_events);
952 }
953 
esw_vport_change_handler(struct work_struct * work)954 static void esw_vport_change_handler(struct work_struct *work)
955 {
956 	struct mlx5_vport *vport =
957 		container_of(work, struct mlx5_vport, vport_change_handler);
958 	struct mlx5_eswitch *esw = vport->dev->priv.eswitch;
959 
960 	mutex_lock(&esw->state_lock);
961 	esw_vport_change_handle_locked(vport);
962 	mutex_unlock(&esw->state_lock);
963 }
964 
element_type_supported(struct mlx5_eswitch * esw,int type)965 static bool element_type_supported(struct mlx5_eswitch *esw, int type)
966 {
967 	const struct mlx5_core_dev *dev = esw->dev;
968 
969 	switch (type) {
970 	case SCHEDULING_CONTEXT_ELEMENT_TYPE_TSAR:
971 		return MLX5_CAP_QOS(dev, esw_element_type) &
972 		       ELEMENT_TYPE_CAP_MASK_TASR;
973 	case SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT:
974 		return MLX5_CAP_QOS(dev, esw_element_type) &
975 		       ELEMENT_TYPE_CAP_MASK_VPORT;
976 	case SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT_TC:
977 		return MLX5_CAP_QOS(dev, esw_element_type) &
978 		       ELEMENT_TYPE_CAP_MASK_VPORT_TC;
979 	case SCHEDULING_CONTEXT_ELEMENT_TYPE_PARA_VPORT_TC:
980 		return MLX5_CAP_QOS(dev, esw_element_type) &
981 		       ELEMENT_TYPE_CAP_MASK_PARA_VPORT_TC;
982 	}
983 	return false;
984 }
985 
986 /* Vport QoS management */
esw_create_tsar(struct mlx5_eswitch * esw)987 static void esw_create_tsar(struct mlx5_eswitch *esw)
988 {
989 	u32 tsar_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {0};
990 	struct mlx5_core_dev *dev = esw->dev;
991 	__be32 *attr;
992 	int err;
993 
994 	if (!MLX5_CAP_GEN(dev, qos) || !MLX5_CAP_QOS(dev, esw_scheduling))
995 		return;
996 
997 	if (!element_type_supported(esw, SCHEDULING_CONTEXT_ELEMENT_TYPE_TSAR))
998 		return;
999 
1000 	if (esw->qos.enabled)
1001 		return;
1002 
1003 	MLX5_SET(scheduling_context, tsar_ctx, element_type,
1004 		 SCHEDULING_CONTEXT_ELEMENT_TYPE_TSAR);
1005 
1006 	attr = MLX5_ADDR_OF(scheduling_context, tsar_ctx, element_attributes);
1007 	*attr = cpu_to_be32(TSAR_ELEMENT_TSAR_TYPE_DWRR << 16);
1008 
1009 	err = mlx5_create_scheduling_element_cmd(dev,
1010 						 SCHEDULING_HIERARCHY_E_SWITCH,
1011 						 tsar_ctx,
1012 						 &esw->qos.root_tsar_id);
1013 	if (err) {
1014 		esw_warn(esw->dev, "E-Switch create TSAR failed (%d)\n", err);
1015 		return;
1016 	}
1017 
1018 	esw->qos.enabled = true;
1019 }
1020 
esw_destroy_tsar(struct mlx5_eswitch * esw)1021 static void esw_destroy_tsar(struct mlx5_eswitch *esw)
1022 {
1023 	int err;
1024 
1025 	if (!esw->qos.enabled)
1026 		return;
1027 
1028 	err = mlx5_destroy_scheduling_element_cmd(esw->dev,
1029 						  SCHEDULING_HIERARCHY_E_SWITCH,
1030 						  esw->qos.root_tsar_id);
1031 	if (err)
1032 		esw_warn(esw->dev, "E-Switch destroy TSAR failed (%d)\n", err);
1033 
1034 	esw->qos.enabled = false;
1035 }
1036 
esw_vport_enable_qos(struct mlx5_eswitch * esw,struct mlx5_vport * vport,u32 initial_max_rate,u32 initial_bw_share)1037 static int esw_vport_enable_qos(struct mlx5_eswitch *esw,
1038 				struct mlx5_vport *vport,
1039 				u32 initial_max_rate, u32 initial_bw_share)
1040 {
1041 	u32 sched_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {0};
1042 	struct mlx5_core_dev *dev = esw->dev;
1043 	void *vport_elem;
1044 	int err = 0;
1045 
1046 	if (!esw->qos.enabled || !MLX5_CAP_GEN(dev, qos) ||
1047 	    !MLX5_CAP_QOS(dev, esw_scheduling))
1048 		return 0;
1049 
1050 	if (vport->qos.enabled)
1051 		return -EEXIST;
1052 
1053 	MLX5_SET(scheduling_context, sched_ctx, element_type,
1054 		 SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT);
1055 	vport_elem = MLX5_ADDR_OF(scheduling_context, sched_ctx,
1056 				  element_attributes);
1057 	MLX5_SET(vport_element, vport_elem, vport_number, vport->vport);
1058 	MLX5_SET(scheduling_context, sched_ctx, parent_element_id,
1059 		 esw->qos.root_tsar_id);
1060 	MLX5_SET(scheduling_context, sched_ctx, max_average_bw,
1061 		 initial_max_rate);
1062 	MLX5_SET(scheduling_context, sched_ctx, bw_share, initial_bw_share);
1063 
1064 	err = mlx5_create_scheduling_element_cmd(dev,
1065 						 SCHEDULING_HIERARCHY_E_SWITCH,
1066 						 sched_ctx,
1067 						 &vport->qos.esw_tsar_ix);
1068 	if (err) {
1069 		esw_warn(esw->dev, "E-Switch create TSAR vport element failed (vport=%d,err=%d)\n",
1070 			 vport->vport, err);
1071 		return err;
1072 	}
1073 
1074 	vport->qos.enabled = true;
1075 	return 0;
1076 }
1077 
esw_vport_disable_qos(struct mlx5_eswitch * esw,struct mlx5_vport * vport)1078 static void esw_vport_disable_qos(struct mlx5_eswitch *esw,
1079 				  struct mlx5_vport *vport)
1080 {
1081 	int err;
1082 
1083 	if (!vport->qos.enabled)
1084 		return;
1085 
1086 	err = mlx5_destroy_scheduling_element_cmd(esw->dev,
1087 						  SCHEDULING_HIERARCHY_E_SWITCH,
1088 						  vport->qos.esw_tsar_ix);
1089 	if (err)
1090 		esw_warn(esw->dev, "E-Switch destroy TSAR vport element failed (vport=%d,err=%d)\n",
1091 			 vport->vport, err);
1092 
1093 	vport->qos.enabled = false;
1094 }
1095 
esw_vport_qos_config(struct mlx5_eswitch * esw,struct mlx5_vport * vport,u32 max_rate,u32 bw_share)1096 static int esw_vport_qos_config(struct mlx5_eswitch *esw,
1097 				struct mlx5_vport *vport,
1098 				u32 max_rate, u32 bw_share)
1099 {
1100 	u32 sched_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {0};
1101 	struct mlx5_core_dev *dev = esw->dev;
1102 	void *vport_elem;
1103 	u32 bitmask = 0;
1104 	int err = 0;
1105 
1106 	if (!MLX5_CAP_GEN(dev, qos) || !MLX5_CAP_QOS(dev, esw_scheduling))
1107 		return -EOPNOTSUPP;
1108 
1109 	if (!vport->qos.enabled)
1110 		return -EIO;
1111 
1112 	MLX5_SET(scheduling_context, sched_ctx, element_type,
1113 		 SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT);
1114 	vport_elem = MLX5_ADDR_OF(scheduling_context, sched_ctx,
1115 				  element_attributes);
1116 	MLX5_SET(vport_element, vport_elem, vport_number, vport->vport);
1117 	MLX5_SET(scheduling_context, sched_ctx, parent_element_id,
1118 		 esw->qos.root_tsar_id);
1119 	MLX5_SET(scheduling_context, sched_ctx, max_average_bw,
1120 		 max_rate);
1121 	MLX5_SET(scheduling_context, sched_ctx, bw_share, bw_share);
1122 	bitmask |= MODIFY_SCHEDULING_ELEMENT_IN_MODIFY_BITMASK_MAX_AVERAGE_BW;
1123 	bitmask |= MODIFY_SCHEDULING_ELEMENT_IN_MODIFY_BITMASK_BW_SHARE;
1124 
1125 	err = mlx5_modify_scheduling_element_cmd(dev,
1126 						 SCHEDULING_HIERARCHY_E_SWITCH,
1127 						 sched_ctx,
1128 						 vport->qos.esw_tsar_ix,
1129 						 bitmask);
1130 	if (err) {
1131 		esw_warn(esw->dev, "E-Switch modify TSAR vport element failed (vport=%d,err=%d)\n",
1132 			 vport->vport, err);
1133 		return err;
1134 	}
1135 
1136 	return 0;
1137 }
1138 
mlx5_esw_modify_vport_rate(struct mlx5_eswitch * esw,u16 vport_num,u32 rate_mbps)1139 int mlx5_esw_modify_vport_rate(struct mlx5_eswitch *esw, u16 vport_num,
1140 			       u32 rate_mbps)
1141 {
1142 	u32 ctx[MLX5_ST_SZ_DW(scheduling_context)] = {};
1143 	struct mlx5_vport *vport;
1144 
1145 	vport = mlx5_eswitch_get_vport(esw, vport_num);
1146 
1147 	if (!vport->qos.enabled)
1148 		return -EOPNOTSUPP;
1149 
1150 	MLX5_SET(scheduling_context, ctx, max_average_bw, rate_mbps);
1151 
1152 	return mlx5_modify_scheduling_element_cmd(esw->dev,
1153 						  SCHEDULING_HIERARCHY_E_SWITCH,
1154 						  ctx,
1155 						  vport->qos.esw_tsar_ix,
1156 						  MODIFY_SCHEDULING_ELEMENT_IN_MODIFY_BITMASK_MAX_AVERAGE_BW);
1157 }
1158 
node_guid_gen_from_mac(u64 * node_guid,const u8 * mac)1159 static void node_guid_gen_from_mac(u64 *node_guid, const u8 *mac)
1160 {
1161 	((u8 *)node_guid)[7] = mac[0];
1162 	((u8 *)node_guid)[6] = mac[1];
1163 	((u8 *)node_guid)[5] = mac[2];
1164 	((u8 *)node_guid)[4] = 0xff;
1165 	((u8 *)node_guid)[3] = 0xfe;
1166 	((u8 *)node_guid)[2] = mac[3];
1167 	((u8 *)node_guid)[1] = mac[4];
1168 	((u8 *)node_guid)[0] = mac[5];
1169 }
1170 
esw_vport_create_legacy_acl_tables(struct mlx5_eswitch * esw,struct mlx5_vport * vport)1171 static int esw_vport_create_legacy_acl_tables(struct mlx5_eswitch *esw,
1172 					      struct mlx5_vport *vport)
1173 {
1174 	int ret;
1175 
1176 	/* Only non manager vports need ACL in legacy mode */
1177 	if (mlx5_esw_is_manager_vport(esw, vport->vport))
1178 		return 0;
1179 
1180 	ret = esw_acl_ingress_lgcy_setup(esw, vport);
1181 	if (ret)
1182 		goto ingress_err;
1183 
1184 	ret = esw_acl_egress_lgcy_setup(esw, vport);
1185 	if (ret)
1186 		goto egress_err;
1187 
1188 	return 0;
1189 
1190 egress_err:
1191 	esw_acl_ingress_lgcy_cleanup(esw, vport);
1192 ingress_err:
1193 	return ret;
1194 }
1195 
esw_vport_setup_acl(struct mlx5_eswitch * esw,struct mlx5_vport * vport)1196 static int esw_vport_setup_acl(struct mlx5_eswitch *esw,
1197 			       struct mlx5_vport *vport)
1198 {
1199 	if (esw->mode == MLX5_ESWITCH_LEGACY)
1200 		return esw_vport_create_legacy_acl_tables(esw, vport);
1201 	else
1202 		return esw_vport_create_offloads_acl_tables(esw, vport);
1203 }
1204 
esw_vport_destroy_legacy_acl_tables(struct mlx5_eswitch * esw,struct mlx5_vport * vport)1205 static void esw_vport_destroy_legacy_acl_tables(struct mlx5_eswitch *esw,
1206 						struct mlx5_vport *vport)
1207 
1208 {
1209 	if (mlx5_esw_is_manager_vport(esw, vport->vport))
1210 		return;
1211 
1212 	esw_acl_egress_lgcy_cleanup(esw, vport);
1213 	esw_acl_ingress_lgcy_cleanup(esw, vport);
1214 }
1215 
esw_vport_cleanup_acl(struct mlx5_eswitch * esw,struct mlx5_vport * vport)1216 static void esw_vport_cleanup_acl(struct mlx5_eswitch *esw,
1217 				  struct mlx5_vport *vport)
1218 {
1219 	if (esw->mode == MLX5_ESWITCH_LEGACY)
1220 		esw_vport_destroy_legacy_acl_tables(esw, vport);
1221 	else
1222 		esw_vport_destroy_offloads_acl_tables(esw, vport);
1223 }
1224 
esw_vport_setup(struct mlx5_eswitch * esw,struct mlx5_vport * vport)1225 static int esw_vport_setup(struct mlx5_eswitch *esw, struct mlx5_vport *vport)
1226 {
1227 	u16 vport_num = vport->vport;
1228 	int flags;
1229 	int err;
1230 
1231 	err = esw_vport_setup_acl(esw, vport);
1232 	if (err)
1233 		return err;
1234 
1235 	/* Attach vport to the eswitch rate limiter */
1236 	esw_vport_enable_qos(esw, vport, vport->info.max_rate, vport->qos.bw_share);
1237 
1238 	if (mlx5_esw_is_manager_vport(esw, vport_num))
1239 		return 0;
1240 
1241 	mlx5_modify_vport_admin_state(esw->dev,
1242 				      MLX5_VPORT_STATE_OP_MOD_ESW_VPORT,
1243 				      vport_num, 1,
1244 				      vport->info.link_state);
1245 
1246 	/* Host PF has its own mac/guid. */
1247 	if (vport_num) {
1248 		mlx5_modify_nic_vport_mac_address(esw->dev, vport_num,
1249 						  vport->info.mac);
1250 		mlx5_modify_nic_vport_node_guid(esw->dev, vport_num,
1251 						vport->info.node_guid);
1252 	}
1253 
1254 	flags = (vport->info.vlan || vport->info.qos) ?
1255 		SET_VLAN_STRIP | SET_VLAN_INSERT : 0;
1256 	modify_esw_vport_cvlan(esw->dev, vport_num, vport->info.vlan,
1257 			       vport->info.qos, flags);
1258 
1259 	return 0;
1260 }
1261 
1262 /* Don't cleanup vport->info, it's needed to restore vport configuration */
esw_vport_cleanup(struct mlx5_eswitch * esw,struct mlx5_vport * vport)1263 static void esw_vport_cleanup(struct mlx5_eswitch *esw, struct mlx5_vport *vport)
1264 {
1265 	u16 vport_num = vport->vport;
1266 
1267 	if (!mlx5_esw_is_manager_vport(esw, vport_num))
1268 		mlx5_modify_vport_admin_state(esw->dev,
1269 					      MLX5_VPORT_STATE_OP_MOD_ESW_VPORT,
1270 					      vport_num, 1,
1271 					      MLX5_VPORT_ADMIN_STATE_DOWN);
1272 
1273 	esw_vport_disable_qos(esw, vport);
1274 	esw_vport_cleanup_acl(esw, vport);
1275 }
1276 
esw_enable_vport(struct mlx5_eswitch * esw,u16 vport_num,enum mlx5_eswitch_vport_event enabled_events)1277 static int esw_enable_vport(struct mlx5_eswitch *esw, u16 vport_num,
1278 			    enum mlx5_eswitch_vport_event enabled_events)
1279 {
1280 	struct mlx5_vport *vport;
1281 	int ret;
1282 
1283 	vport = mlx5_eswitch_get_vport(esw, vport_num);
1284 
1285 	mutex_lock(&esw->state_lock);
1286 	WARN_ON(vport->enabled);
1287 
1288 	esw_debug(esw->dev, "Enabling VPORT(%d)\n", vport_num);
1289 
1290 	ret = esw_vport_setup(esw, vport);
1291 	if (ret)
1292 		goto done;
1293 
1294 	/* Sync with current vport context */
1295 	vport->enabled_events = enabled_events;
1296 	vport->enabled = true;
1297 
1298 	/* Esw manager is trusted by default. Host PF (vport 0) is trusted as well
1299 	 * in smartNIC as it's a vport group manager.
1300 	 */
1301 	if (mlx5_esw_is_manager_vport(esw, vport_num) ||
1302 	    (!vport_num && mlx5_core_is_ecpf(esw->dev)))
1303 		vport->info.trusted = true;
1304 
1305 	/* External controller host PF has factory programmed MAC.
1306 	 * Read it from the device.
1307 	 */
1308 	if (mlx5_core_is_ecpf(esw->dev) && vport_num == MLX5_VPORT_PF)
1309 		mlx5_query_nic_vport_mac_address(esw->dev, vport_num, true, vport->info.mac);
1310 
1311 	esw_vport_change_handle_locked(vport);
1312 
1313 	esw->enabled_vports++;
1314 	esw_debug(esw->dev, "Enabled VPORT(%d)\n", vport_num);
1315 done:
1316 	mutex_unlock(&esw->state_lock);
1317 	return ret;
1318 }
1319 
esw_disable_vport(struct mlx5_eswitch * esw,u16 vport_num)1320 static void esw_disable_vport(struct mlx5_eswitch *esw, u16 vport_num)
1321 {
1322 	struct mlx5_vport *vport;
1323 
1324 	vport = mlx5_eswitch_get_vport(esw, vport_num);
1325 
1326 	mutex_lock(&esw->state_lock);
1327 	if (!vport->enabled)
1328 		goto done;
1329 
1330 	esw_debug(esw->dev, "Disabling vport(%d)\n", vport_num);
1331 	/* Mark this vport as disabled to discard new events */
1332 	vport->enabled = false;
1333 
1334 	/* Disable events from this vport */
1335 	arm_vport_context_events_cmd(esw->dev, vport->vport, 0);
1336 	/* We don't assume VFs will cleanup after themselves.
1337 	 * Calling vport change handler while vport is disabled will cleanup
1338 	 * the vport resources.
1339 	 */
1340 	esw_vport_change_handle_locked(vport);
1341 	vport->enabled_events = 0;
1342 	esw_vport_cleanup(esw, vport);
1343 	esw->enabled_vports--;
1344 
1345 done:
1346 	mutex_unlock(&esw->state_lock);
1347 }
1348 
eswitch_vport_event(struct notifier_block * nb,unsigned long type,void * data)1349 static int eswitch_vport_event(struct notifier_block *nb,
1350 			       unsigned long type, void *data)
1351 {
1352 	struct mlx5_eswitch *esw = mlx5_nb_cof(nb, struct mlx5_eswitch, nb);
1353 	struct mlx5_eqe *eqe = data;
1354 	struct mlx5_vport *vport;
1355 	u16 vport_num;
1356 
1357 	vport_num = be16_to_cpu(eqe->data.vport_change.vport_num);
1358 	vport = mlx5_eswitch_get_vport(esw, vport_num);
1359 	if (!IS_ERR(vport))
1360 		queue_work(esw->work_queue, &vport->vport_change_handler);
1361 	return NOTIFY_OK;
1362 }
1363 
1364 /**
1365  * mlx5_esw_query_functions - Returns raw output about functions state
1366  * @dev:	Pointer to device to query
1367  *
1368  * mlx5_esw_query_functions() allocates and returns functions changed
1369  * raw output memory pointer from device on success. Otherwise returns ERR_PTR.
1370  * Caller must free the memory using kvfree() when valid pointer is returned.
1371  */
mlx5_esw_query_functions(struct mlx5_core_dev * dev)1372 const u32 *mlx5_esw_query_functions(struct mlx5_core_dev *dev)
1373 {
1374 	int outlen = MLX5_ST_SZ_BYTES(query_esw_functions_out);
1375 	u32 in[MLX5_ST_SZ_DW(query_esw_functions_in)] = {};
1376 	u32 *out;
1377 	int err;
1378 
1379 	out = kvzalloc(outlen, GFP_KERNEL);
1380 	if (!out)
1381 		return ERR_PTR(-ENOMEM);
1382 
1383 	MLX5_SET(query_esw_functions_in, in, opcode,
1384 		 MLX5_CMD_OP_QUERY_ESW_FUNCTIONS);
1385 
1386 	err = mlx5_cmd_exec_inout(dev, query_esw_functions, in, out);
1387 	if (!err)
1388 		return out;
1389 
1390 	kvfree(out);
1391 	return ERR_PTR(err);
1392 }
1393 
mlx5_eswitch_event_handlers_register(struct mlx5_eswitch * esw)1394 static void mlx5_eswitch_event_handlers_register(struct mlx5_eswitch *esw)
1395 {
1396 	MLX5_NB_INIT(&esw->nb, eswitch_vport_event, NIC_VPORT_CHANGE);
1397 	mlx5_eq_notifier_register(esw->dev, &esw->nb);
1398 
1399 	if (esw->mode == MLX5_ESWITCH_OFFLOADS && mlx5_eswitch_is_funcs_handler(esw->dev)) {
1400 		MLX5_NB_INIT(&esw->esw_funcs.nb, mlx5_esw_funcs_changed_handler,
1401 			     ESW_FUNCTIONS_CHANGED);
1402 		mlx5_eq_notifier_register(esw->dev, &esw->esw_funcs.nb);
1403 	}
1404 }
1405 
mlx5_eswitch_event_handlers_unregister(struct mlx5_eswitch * esw)1406 static void mlx5_eswitch_event_handlers_unregister(struct mlx5_eswitch *esw)
1407 {
1408 	if (esw->mode == MLX5_ESWITCH_OFFLOADS && mlx5_eswitch_is_funcs_handler(esw->dev))
1409 		mlx5_eq_notifier_unregister(esw->dev, &esw->esw_funcs.nb);
1410 
1411 	mlx5_eq_notifier_unregister(esw->dev, &esw->nb);
1412 
1413 	flush_workqueue(esw->work_queue);
1414 }
1415 
mlx5_eswitch_clear_vf_vports_info(struct mlx5_eswitch * esw)1416 static void mlx5_eswitch_clear_vf_vports_info(struct mlx5_eswitch *esw)
1417 {
1418 	struct mlx5_vport *vport;
1419 	int i;
1420 
1421 	mlx5_esw_for_each_vf_vport(esw, i, vport, esw->esw_funcs.num_vfs) {
1422 		memset(&vport->qos, 0, sizeof(vport->qos));
1423 		memset(&vport->info, 0, sizeof(vport->info));
1424 		vport->info.link_state = MLX5_VPORT_ADMIN_STATE_AUTO;
1425 	}
1426 }
1427 
1428 /* Public E-Switch API */
1429 #define ESW_ALLOWED(esw) ((esw) && MLX5_ESWITCH_MANAGER((esw)->dev))
1430 
mlx5_eswitch_load_vport(struct mlx5_eswitch * esw,u16 vport_num,enum mlx5_eswitch_vport_event enabled_events)1431 int mlx5_eswitch_load_vport(struct mlx5_eswitch *esw, u16 vport_num,
1432 			    enum mlx5_eswitch_vport_event enabled_events)
1433 {
1434 	int err;
1435 
1436 	err = esw_enable_vport(esw, vport_num, enabled_events);
1437 	if (err)
1438 		return err;
1439 
1440 	err = esw_offloads_load_rep(esw, vport_num);
1441 	if (err)
1442 		goto err_rep;
1443 
1444 	return err;
1445 
1446 err_rep:
1447 	esw_disable_vport(esw, vport_num);
1448 	return err;
1449 }
1450 
mlx5_eswitch_unload_vport(struct mlx5_eswitch * esw,u16 vport_num)1451 void mlx5_eswitch_unload_vport(struct mlx5_eswitch *esw, u16 vport_num)
1452 {
1453 	esw_offloads_unload_rep(esw, vport_num);
1454 	esw_disable_vport(esw, vport_num);
1455 }
1456 
mlx5_eswitch_unload_vf_vports(struct mlx5_eswitch * esw,u16 num_vfs)1457 void mlx5_eswitch_unload_vf_vports(struct mlx5_eswitch *esw, u16 num_vfs)
1458 {
1459 	int i;
1460 
1461 	mlx5_esw_for_each_vf_vport_num_reverse(esw, i, num_vfs)
1462 		mlx5_eswitch_unload_vport(esw, i);
1463 }
1464 
mlx5_eswitch_load_vf_vports(struct mlx5_eswitch * esw,u16 num_vfs,enum mlx5_eswitch_vport_event enabled_events)1465 int mlx5_eswitch_load_vf_vports(struct mlx5_eswitch *esw, u16 num_vfs,
1466 				enum mlx5_eswitch_vport_event enabled_events)
1467 {
1468 	int err;
1469 	int i;
1470 
1471 	mlx5_esw_for_each_vf_vport_num(esw, i, num_vfs) {
1472 		err = mlx5_eswitch_load_vport(esw, i, enabled_events);
1473 		if (err)
1474 			goto vf_err;
1475 	}
1476 
1477 	return 0;
1478 
1479 vf_err:
1480 	mlx5_eswitch_unload_vf_vports(esw, i - 1);
1481 	return err;
1482 }
1483 
1484 /* mlx5_eswitch_enable_pf_vf_vports() enables vports of PF, ECPF and VFs
1485  * whichever are present on the eswitch.
1486  */
1487 int
mlx5_eswitch_enable_pf_vf_vports(struct mlx5_eswitch * esw,enum mlx5_eswitch_vport_event enabled_events)1488 mlx5_eswitch_enable_pf_vf_vports(struct mlx5_eswitch *esw,
1489 				 enum mlx5_eswitch_vport_event enabled_events)
1490 {
1491 	int ret;
1492 
1493 	/* Enable PF vport */
1494 	ret = mlx5_eswitch_load_vport(esw, MLX5_VPORT_PF, enabled_events);
1495 	if (ret)
1496 		return ret;
1497 
1498 	/* Enable ECPF vport */
1499 	if (mlx5_ecpf_vport_exists(esw->dev)) {
1500 		ret = mlx5_eswitch_load_vport(esw, MLX5_VPORT_ECPF, enabled_events);
1501 		if (ret)
1502 			goto ecpf_err;
1503 	}
1504 
1505 	/* Enable VF vports */
1506 	ret = mlx5_eswitch_load_vf_vports(esw, esw->esw_funcs.num_vfs,
1507 					  enabled_events);
1508 	if (ret)
1509 		goto vf_err;
1510 	return 0;
1511 
1512 vf_err:
1513 	if (mlx5_ecpf_vport_exists(esw->dev))
1514 		mlx5_eswitch_unload_vport(esw, MLX5_VPORT_ECPF);
1515 
1516 ecpf_err:
1517 	mlx5_eswitch_unload_vport(esw, MLX5_VPORT_PF);
1518 	return ret;
1519 }
1520 
1521 /* mlx5_eswitch_disable_pf_vf_vports() disables vports of PF, ECPF and VFs
1522  * whichever are previously enabled on the eswitch.
1523  */
mlx5_eswitch_disable_pf_vf_vports(struct mlx5_eswitch * esw)1524 void mlx5_eswitch_disable_pf_vf_vports(struct mlx5_eswitch *esw)
1525 {
1526 	mlx5_eswitch_unload_vf_vports(esw, esw->esw_funcs.num_vfs);
1527 
1528 	if (mlx5_ecpf_vport_exists(esw->dev))
1529 		mlx5_eswitch_unload_vport(esw, MLX5_VPORT_ECPF);
1530 
1531 	mlx5_eswitch_unload_vport(esw, MLX5_VPORT_PF);
1532 }
1533 
mlx5_eswitch_get_devlink_param(struct mlx5_eswitch * esw)1534 static void mlx5_eswitch_get_devlink_param(struct mlx5_eswitch *esw)
1535 {
1536 	struct devlink *devlink = priv_to_devlink(esw->dev);
1537 	union devlink_param_value val;
1538 	int err;
1539 
1540 	err = devlink_param_driverinit_value_get(devlink,
1541 						 MLX5_DEVLINK_PARAM_ID_ESW_LARGE_GROUP_NUM,
1542 						 &val);
1543 	if (!err) {
1544 		esw->params.large_group_num = val.vu32;
1545 	} else {
1546 		esw_warn(esw->dev,
1547 			 "Devlink can't get param fdb_large_groups, uses default (%d).\n",
1548 			 ESW_OFFLOADS_DEFAULT_NUM_GROUPS);
1549 		esw->params.large_group_num = ESW_OFFLOADS_DEFAULT_NUM_GROUPS;
1550 	}
1551 }
1552 
1553 static void
mlx5_eswitch_update_num_of_vfs(struct mlx5_eswitch * esw,int num_vfs)1554 mlx5_eswitch_update_num_of_vfs(struct mlx5_eswitch *esw, int num_vfs)
1555 {
1556 	const u32 *out;
1557 
1558 	WARN_ON_ONCE(esw->mode != MLX5_ESWITCH_NONE);
1559 
1560 	if (num_vfs < 0)
1561 		return;
1562 
1563 	if (!mlx5_core_is_ecpf_esw_manager(esw->dev)) {
1564 		esw->esw_funcs.num_vfs = num_vfs;
1565 		return;
1566 	}
1567 
1568 	out = mlx5_esw_query_functions(esw->dev);
1569 	if (IS_ERR(out))
1570 		return;
1571 
1572 	esw->esw_funcs.num_vfs = MLX5_GET(query_esw_functions_out, out,
1573 					  host_params_context.host_num_of_vfs);
1574 	kvfree(out);
1575 }
1576 
1577 /**
1578  * mlx5_eswitch_enable_locked - Enable eswitch
1579  * @esw:	Pointer to eswitch
1580  * @mode:	Eswitch mode to enable
1581  * @num_vfs:	Enable eswitch for given number of VFs. This is optional.
1582  *		Valid value are 0, > 0 and MLX5_ESWITCH_IGNORE_NUM_VFS.
1583  *		Caller should pass num_vfs > 0 when enabling eswitch for
1584  *		vf vports. Caller should pass num_vfs = 0, when eswitch
1585  *		is enabled without sriov VFs or when caller
1586  *		is unaware of the sriov state of the host PF on ECPF based
1587  *		eswitch. Caller should pass < 0 when num_vfs should be
1588  *		completely ignored. This is typically the case when eswitch
1589  *		is enabled without sriov regardless of PF/ECPF system.
1590  * mlx5_eswitch_enable_locked() Enables eswitch in either legacy or offloads
1591  * mode. If num_vfs >=0 is provided, it setup VF related eswitch vports.
1592  * It returns 0 on success or error code on failure.
1593  */
mlx5_eswitch_enable_locked(struct mlx5_eswitch * esw,int mode,int num_vfs)1594 int mlx5_eswitch_enable_locked(struct mlx5_eswitch *esw, int mode, int num_vfs)
1595 {
1596 	int err;
1597 
1598 	lockdep_assert_held(&esw->mode_lock);
1599 
1600 	if (!MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, ft_support)) {
1601 		esw_warn(esw->dev, "FDB is not supported, aborting ...\n");
1602 		return -EOPNOTSUPP;
1603 	}
1604 
1605 	if (!MLX5_CAP_ESW_INGRESS_ACL(esw->dev, ft_support))
1606 		esw_warn(esw->dev, "ingress ACL is not supported by FW\n");
1607 
1608 	if (!MLX5_CAP_ESW_EGRESS_ACL(esw->dev, ft_support))
1609 		esw_warn(esw->dev, "engress ACL is not supported by FW\n");
1610 
1611 	mlx5_eswitch_get_devlink_param(esw);
1612 
1613 	mlx5_eswitch_update_num_of_vfs(esw, num_vfs);
1614 
1615 	esw_create_tsar(esw);
1616 
1617 	esw->mode = mode;
1618 
1619 	mlx5_lag_update(esw->dev);
1620 
1621 	if (mode == MLX5_ESWITCH_LEGACY) {
1622 		err = esw_legacy_enable(esw);
1623 	} else {
1624 		mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_ETH);
1625 		mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_IB);
1626 		err = esw_offloads_enable(esw);
1627 	}
1628 
1629 	if (err)
1630 		goto abort;
1631 
1632 	mlx5_eswitch_event_handlers_register(esw);
1633 
1634 	esw_info(esw->dev, "Enable: mode(%s), nvfs(%d), active vports(%d)\n",
1635 		 mode == MLX5_ESWITCH_LEGACY ? "LEGACY" : "OFFLOADS",
1636 		 esw->esw_funcs.num_vfs, esw->enabled_vports);
1637 
1638 	return 0;
1639 
1640 abort:
1641 	esw->mode = MLX5_ESWITCH_NONE;
1642 
1643 	if (mode == MLX5_ESWITCH_OFFLOADS) {
1644 		mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_IB);
1645 		mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_ETH);
1646 	}
1647 	esw_destroy_tsar(esw);
1648 	return err;
1649 }
1650 
1651 /**
1652  * mlx5_eswitch_enable - Enable eswitch
1653  * @esw:	Pointer to eswitch
1654  * @num_vfs:	Enable eswitch swich for given number of VFs.
1655  *		Caller must pass num_vfs > 0 when enabling eswitch for
1656  *		vf vports.
1657  * mlx5_eswitch_enable() returns 0 on success or error code on failure.
1658  */
mlx5_eswitch_enable(struct mlx5_eswitch * esw,int num_vfs)1659 int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int num_vfs)
1660 {
1661 	int ret;
1662 
1663 	if (!ESW_ALLOWED(esw))
1664 		return 0;
1665 
1666 	down_write(&esw->mode_lock);
1667 	if (esw->mode == MLX5_ESWITCH_NONE) {
1668 		ret = mlx5_eswitch_enable_locked(esw, MLX5_ESWITCH_LEGACY, num_vfs);
1669 	} else {
1670 		enum mlx5_eswitch_vport_event vport_events;
1671 
1672 		vport_events = (esw->mode == MLX5_ESWITCH_LEGACY) ?
1673 					MLX5_LEGACY_SRIOV_VPORT_EVENTS : MLX5_VPORT_UC_ADDR_CHANGE;
1674 		ret = mlx5_eswitch_load_vf_vports(esw, num_vfs, vport_events);
1675 		if (!ret)
1676 			esw->esw_funcs.num_vfs = num_vfs;
1677 	}
1678 	up_write(&esw->mode_lock);
1679 	return ret;
1680 }
1681 
mlx5_eswitch_disable_locked(struct mlx5_eswitch * esw,bool clear_vf)1682 void mlx5_eswitch_disable_locked(struct mlx5_eswitch *esw, bool clear_vf)
1683 {
1684 	int old_mode;
1685 
1686 	lockdep_assert_held_write(&esw->mode_lock);
1687 
1688 	if (esw->mode == MLX5_ESWITCH_NONE)
1689 		return;
1690 
1691 	esw_info(esw->dev, "Disable: mode(%s), nvfs(%d), active vports(%d)\n",
1692 		 esw->mode == MLX5_ESWITCH_LEGACY ? "LEGACY" : "OFFLOADS",
1693 		 esw->esw_funcs.num_vfs, esw->enabled_vports);
1694 
1695 	mlx5_eswitch_event_handlers_unregister(esw);
1696 
1697 	if (esw->mode == MLX5_ESWITCH_LEGACY)
1698 		esw_legacy_disable(esw);
1699 	else if (esw->mode == MLX5_ESWITCH_OFFLOADS)
1700 		esw_offloads_disable(esw);
1701 
1702 	old_mode = esw->mode;
1703 	esw->mode = MLX5_ESWITCH_NONE;
1704 
1705 	mlx5_lag_update(esw->dev);
1706 
1707 	if (old_mode == MLX5_ESWITCH_OFFLOADS) {
1708 		mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_IB);
1709 		mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_ETH);
1710 	}
1711 	esw_destroy_tsar(esw);
1712 
1713 	if (clear_vf)
1714 		mlx5_eswitch_clear_vf_vports_info(esw);
1715 }
1716 
mlx5_eswitch_disable(struct mlx5_eswitch * esw,bool clear_vf)1717 void mlx5_eswitch_disable(struct mlx5_eswitch *esw, bool clear_vf)
1718 {
1719 	if (!ESW_ALLOWED(esw))
1720 		return;
1721 
1722 	down_write(&esw->mode_lock);
1723 	mlx5_eswitch_disable_locked(esw, clear_vf);
1724 	esw->esw_funcs.num_vfs = 0;
1725 	up_write(&esw->mode_lock);
1726 }
1727 
mlx5_eswitch_init(struct mlx5_core_dev * dev)1728 int mlx5_eswitch_init(struct mlx5_core_dev *dev)
1729 {
1730 	struct mlx5_eswitch *esw;
1731 	struct mlx5_vport *vport;
1732 	int total_vports;
1733 	int err, i;
1734 
1735 	if (!MLX5_VPORT_MANAGER(dev))
1736 		return 0;
1737 
1738 	total_vports = mlx5_eswitch_get_total_vports(dev);
1739 
1740 	esw_info(dev,
1741 		 "Total vports %d, per vport: max uc(%d) max mc(%d)\n",
1742 		 total_vports,
1743 		 MLX5_MAX_UC_PER_VPORT(dev),
1744 		 MLX5_MAX_MC_PER_VPORT(dev));
1745 
1746 	esw = kzalloc(sizeof(*esw), GFP_KERNEL);
1747 	if (!esw)
1748 		return -ENOMEM;
1749 
1750 	esw->dev = dev;
1751 	esw->manager_vport = mlx5_eswitch_manager_vport(dev);
1752 	esw->first_host_vport = mlx5_eswitch_first_host_vport_num(dev);
1753 
1754 	esw->work_queue = create_singlethread_workqueue("mlx5_esw_wq");
1755 	if (!esw->work_queue) {
1756 		err = -ENOMEM;
1757 		goto abort;
1758 	}
1759 
1760 	esw->vports = kcalloc(total_vports, sizeof(struct mlx5_vport),
1761 			      GFP_KERNEL);
1762 	if (!esw->vports) {
1763 		err = -ENOMEM;
1764 		goto abort;
1765 	}
1766 
1767 	esw->total_vports = total_vports;
1768 
1769 	err = esw_offloads_init_reps(esw);
1770 	if (err)
1771 		goto abort;
1772 
1773 	mutex_init(&esw->offloads.encap_tbl_lock);
1774 	hash_init(esw->offloads.encap_tbl);
1775 	mutex_init(&esw->offloads.decap_tbl_lock);
1776 	hash_init(esw->offloads.decap_tbl);
1777 	mlx5e_mod_hdr_tbl_init(&esw->offloads.mod_hdr);
1778 	atomic64_set(&esw->offloads.num_flows, 0);
1779 	ida_init(&esw->offloads.vport_metadata_ida);
1780 	mutex_init(&esw->state_lock);
1781 	init_rwsem(&esw->mode_lock);
1782 
1783 	mlx5_esw_for_all_vports(esw, i, vport) {
1784 		vport->vport = mlx5_eswitch_index_to_vport_num(esw, i);
1785 		vport->info.link_state = MLX5_VPORT_ADMIN_STATE_AUTO;
1786 		vport->dev = dev;
1787 		INIT_WORK(&vport->vport_change_handler,
1788 			  esw_vport_change_handler);
1789 	}
1790 
1791 	esw->enabled_vports = 0;
1792 	esw->mode = MLX5_ESWITCH_NONE;
1793 	esw->offloads.inline_mode = MLX5_INLINE_MODE_NONE;
1794 
1795 	dev->priv.eswitch = esw;
1796 	return 0;
1797 abort:
1798 	if (esw->work_queue)
1799 		destroy_workqueue(esw->work_queue);
1800 	esw_offloads_cleanup_reps(esw);
1801 	kfree(esw->vports);
1802 	kfree(esw);
1803 	return err;
1804 }
1805 
mlx5_eswitch_cleanup(struct mlx5_eswitch * esw)1806 void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw)
1807 {
1808 	if (!esw || !MLX5_VPORT_MANAGER(esw->dev))
1809 		return;
1810 
1811 	esw_info(esw->dev, "cleanup\n");
1812 
1813 	esw->dev->priv.eswitch = NULL;
1814 	destroy_workqueue(esw->work_queue);
1815 	esw_offloads_cleanup_reps(esw);
1816 	mutex_destroy(&esw->state_lock);
1817 	ida_destroy(&esw->offloads.vport_metadata_ida);
1818 	mlx5e_mod_hdr_tbl_destroy(&esw->offloads.mod_hdr);
1819 	mutex_destroy(&esw->offloads.encap_tbl_lock);
1820 	mutex_destroy(&esw->offloads.decap_tbl_lock);
1821 	kfree(esw->vports);
1822 	kfree(esw);
1823 }
1824 
1825 /* Vport Administration */
1826 static int
mlx5_esw_set_vport_mac_locked(struct mlx5_eswitch * esw,struct mlx5_vport * evport,const u8 * mac)1827 mlx5_esw_set_vport_mac_locked(struct mlx5_eswitch *esw,
1828 			      struct mlx5_vport *evport, const u8 *mac)
1829 {
1830 	u16 vport_num = evport->vport;
1831 	u64 node_guid;
1832 	int err = 0;
1833 
1834 	if (is_multicast_ether_addr(mac))
1835 		return -EINVAL;
1836 
1837 	if (evport->info.spoofchk && !is_valid_ether_addr(mac))
1838 		mlx5_core_warn(esw->dev,
1839 			       "Set invalid MAC while spoofchk is on, vport(%d)\n",
1840 			       vport_num);
1841 
1842 	err = mlx5_modify_nic_vport_mac_address(esw->dev, vport_num, mac);
1843 	if (err) {
1844 		mlx5_core_warn(esw->dev,
1845 			       "Failed to mlx5_modify_nic_vport_mac vport(%d) err=(%d)\n",
1846 			       vport_num, err);
1847 		return err;
1848 	}
1849 
1850 	node_guid_gen_from_mac(&node_guid, mac);
1851 	err = mlx5_modify_nic_vport_node_guid(esw->dev, vport_num, node_guid);
1852 	if (err)
1853 		mlx5_core_warn(esw->dev,
1854 			       "Failed to set vport %d node guid, err = %d. RDMA_CM will not function properly for this VF.\n",
1855 			       vport_num, err);
1856 
1857 	ether_addr_copy(evport->info.mac, mac);
1858 	evport->info.node_guid = node_guid;
1859 	if (evport->enabled && esw->mode == MLX5_ESWITCH_LEGACY)
1860 		err = esw_acl_ingress_lgcy_setup(esw, evport);
1861 
1862 	return err;
1863 }
1864 
mlx5_eswitch_set_vport_mac(struct mlx5_eswitch * esw,u16 vport,const u8 * mac)1865 int mlx5_eswitch_set_vport_mac(struct mlx5_eswitch *esw,
1866 			       u16 vport, const u8 *mac)
1867 {
1868 	struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
1869 	int err = 0;
1870 
1871 	if (IS_ERR(evport))
1872 		return PTR_ERR(evport);
1873 
1874 	mutex_lock(&esw->state_lock);
1875 	err = mlx5_esw_set_vport_mac_locked(esw, evport, mac);
1876 	mutex_unlock(&esw->state_lock);
1877 	return err;
1878 }
1879 
1880 static bool
is_port_function_supported(const struct mlx5_eswitch * esw,u16 vport_num)1881 is_port_function_supported(const struct mlx5_eswitch *esw, u16 vport_num)
1882 {
1883 	return vport_num == MLX5_VPORT_PF ||
1884 	       mlx5_eswitch_is_vf_vport(esw, vport_num);
1885 }
1886 
mlx5_devlink_port_function_hw_addr_get(struct devlink * devlink,struct devlink_port * port,u8 * hw_addr,int * hw_addr_len,struct netlink_ext_ack * extack)1887 int mlx5_devlink_port_function_hw_addr_get(struct devlink *devlink,
1888 					   struct devlink_port *port,
1889 					   u8 *hw_addr, int *hw_addr_len,
1890 					   struct netlink_ext_ack *extack)
1891 {
1892 	struct mlx5_eswitch *esw;
1893 	struct mlx5_vport *vport;
1894 	int err = -EOPNOTSUPP;
1895 	u16 vport_num;
1896 
1897 	esw = mlx5_devlink_eswitch_get(devlink);
1898 	if (IS_ERR(esw))
1899 		return PTR_ERR(esw);
1900 
1901 	vport_num = mlx5_esw_devlink_port_index_to_vport_num(port->index);
1902 	if (!is_port_function_supported(esw, vport_num))
1903 		return -EOPNOTSUPP;
1904 
1905 	vport = mlx5_eswitch_get_vport(esw, vport_num);
1906 	if (IS_ERR(vport)) {
1907 		NL_SET_ERR_MSG_MOD(extack, "Invalid port");
1908 		return PTR_ERR(vport);
1909 	}
1910 
1911 	mutex_lock(&esw->state_lock);
1912 	if (vport->enabled) {
1913 		ether_addr_copy(hw_addr, vport->info.mac);
1914 		*hw_addr_len = ETH_ALEN;
1915 		err = 0;
1916 	}
1917 	mutex_unlock(&esw->state_lock);
1918 	return err;
1919 }
1920 
mlx5_devlink_port_function_hw_addr_set(struct devlink * devlink,struct devlink_port * port,const u8 * hw_addr,int hw_addr_len,struct netlink_ext_ack * extack)1921 int mlx5_devlink_port_function_hw_addr_set(struct devlink *devlink,
1922 					   struct devlink_port *port,
1923 					   const u8 *hw_addr, int hw_addr_len,
1924 					   struct netlink_ext_ack *extack)
1925 {
1926 	struct mlx5_eswitch *esw;
1927 	struct mlx5_vport *vport;
1928 	int err = -EOPNOTSUPP;
1929 	u16 vport_num;
1930 
1931 	esw = mlx5_devlink_eswitch_get(devlink);
1932 	if (IS_ERR(esw)) {
1933 		NL_SET_ERR_MSG_MOD(extack, "Eswitch doesn't support set hw_addr");
1934 		return PTR_ERR(esw);
1935 	}
1936 
1937 	vport_num = mlx5_esw_devlink_port_index_to_vport_num(port->index);
1938 	if (!is_port_function_supported(esw, vport_num)) {
1939 		NL_SET_ERR_MSG_MOD(extack, "Port doesn't support set hw_addr");
1940 		return -EINVAL;
1941 	}
1942 	vport = mlx5_eswitch_get_vport(esw, vport_num);
1943 	if (IS_ERR(vport)) {
1944 		NL_SET_ERR_MSG_MOD(extack, "Invalid port");
1945 		return PTR_ERR(vport);
1946 	}
1947 
1948 	mutex_lock(&esw->state_lock);
1949 	if (vport->enabled)
1950 		err = mlx5_esw_set_vport_mac_locked(esw, vport, hw_addr);
1951 	else
1952 		NL_SET_ERR_MSG_MOD(extack, "Eswitch vport is disabled");
1953 	mutex_unlock(&esw->state_lock);
1954 	return err;
1955 }
1956 
mlx5_eswitch_set_vport_state(struct mlx5_eswitch * esw,u16 vport,int link_state)1957 int mlx5_eswitch_set_vport_state(struct mlx5_eswitch *esw,
1958 				 u16 vport, int link_state)
1959 {
1960 	struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
1961 	int opmod = MLX5_VPORT_STATE_OP_MOD_ESW_VPORT;
1962 	int other_vport = 1;
1963 	int err = 0;
1964 
1965 	if (!ESW_ALLOWED(esw))
1966 		return -EPERM;
1967 	if (IS_ERR(evport))
1968 		return PTR_ERR(evport);
1969 
1970 	if (vport == MLX5_VPORT_UPLINK) {
1971 		opmod = MLX5_VPORT_STATE_OP_MOD_UPLINK;
1972 		other_vport = 0;
1973 		vport = 0;
1974 	}
1975 	mutex_lock(&esw->state_lock);
1976 
1977 	err = mlx5_modify_vport_admin_state(esw->dev, opmod, vport, other_vport, link_state);
1978 	if (err) {
1979 		mlx5_core_warn(esw->dev, "Failed to set vport %d link state, opmod = %d, err = %d",
1980 			       vport, opmod, err);
1981 		goto unlock;
1982 	}
1983 
1984 	evport->info.link_state = link_state;
1985 
1986 unlock:
1987 	mutex_unlock(&esw->state_lock);
1988 	return err;
1989 }
1990 
mlx5_eswitch_get_vport_config(struct mlx5_eswitch * esw,u16 vport,struct ifla_vf_info * ivi)1991 int mlx5_eswitch_get_vport_config(struct mlx5_eswitch *esw,
1992 				  u16 vport, struct ifla_vf_info *ivi)
1993 {
1994 	struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
1995 
1996 	if (IS_ERR(evport))
1997 		return PTR_ERR(evport);
1998 
1999 	memset(ivi, 0, sizeof(*ivi));
2000 	ivi->vf = vport - 1;
2001 
2002 	mutex_lock(&esw->state_lock);
2003 	ether_addr_copy(ivi->mac, evport->info.mac);
2004 	ivi->linkstate = evport->info.link_state;
2005 	ivi->vlan = evport->info.vlan;
2006 	ivi->qos = evport->info.qos;
2007 	ivi->spoofchk = evport->info.spoofchk;
2008 	ivi->trusted = evport->info.trusted;
2009 	ivi->min_tx_rate = evport->info.min_rate;
2010 	ivi->max_tx_rate = evport->info.max_rate;
2011 	mutex_unlock(&esw->state_lock);
2012 
2013 	return 0;
2014 }
2015 
__mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch * esw,u16 vport,u16 vlan,u8 qos,u8 set_flags)2016 int __mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw,
2017 				  u16 vport, u16 vlan, u8 qos, u8 set_flags)
2018 {
2019 	struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
2020 	int err = 0;
2021 
2022 	if (IS_ERR(evport))
2023 		return PTR_ERR(evport);
2024 	if (vlan > 4095 || qos > 7)
2025 		return -EINVAL;
2026 
2027 	err = modify_esw_vport_cvlan(esw->dev, vport, vlan, qos, set_flags);
2028 	if (err)
2029 		return err;
2030 
2031 	evport->info.vlan = vlan;
2032 	evport->info.qos = qos;
2033 	if (evport->enabled && esw->mode == MLX5_ESWITCH_LEGACY) {
2034 		err = esw_acl_ingress_lgcy_setup(esw, evport);
2035 		if (err)
2036 			return err;
2037 		err = esw_acl_egress_lgcy_setup(esw, evport);
2038 	}
2039 
2040 	return err;
2041 }
2042 
mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch * esw,u16 vport,u16 vlan,u8 qos)2043 int mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw,
2044 				u16 vport, u16 vlan, u8 qos)
2045 {
2046 	u8 set_flags = 0;
2047 	int err;
2048 
2049 	if (!ESW_ALLOWED(esw))
2050 		return -EPERM;
2051 
2052 	if (vlan || qos)
2053 		set_flags = SET_VLAN_STRIP | SET_VLAN_INSERT;
2054 
2055 	mutex_lock(&esw->state_lock);
2056 	err = __mlx5_eswitch_set_vport_vlan(esw, vport, vlan, qos, set_flags);
2057 	mutex_unlock(&esw->state_lock);
2058 
2059 	return err;
2060 }
2061 
mlx5_eswitch_set_vport_spoofchk(struct mlx5_eswitch * esw,u16 vport,bool spoofchk)2062 int mlx5_eswitch_set_vport_spoofchk(struct mlx5_eswitch *esw,
2063 				    u16 vport, bool spoofchk)
2064 {
2065 	struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
2066 	bool pschk;
2067 	int err = 0;
2068 
2069 	if (!ESW_ALLOWED(esw))
2070 		return -EPERM;
2071 	if (IS_ERR(evport))
2072 		return PTR_ERR(evport);
2073 
2074 	mutex_lock(&esw->state_lock);
2075 	pschk = evport->info.spoofchk;
2076 	evport->info.spoofchk = spoofchk;
2077 	if (pschk && !is_valid_ether_addr(evport->info.mac))
2078 		mlx5_core_warn(esw->dev,
2079 			       "Spoofchk in set while MAC is invalid, vport(%d)\n",
2080 			       evport->vport);
2081 	if (evport->enabled && esw->mode == MLX5_ESWITCH_LEGACY)
2082 		err = esw_acl_ingress_lgcy_setup(esw, evport);
2083 	if (err)
2084 		evport->info.spoofchk = pschk;
2085 	mutex_unlock(&esw->state_lock);
2086 
2087 	return err;
2088 }
2089 
esw_cleanup_vepa_rules(struct mlx5_eswitch * esw)2090 static void esw_cleanup_vepa_rules(struct mlx5_eswitch *esw)
2091 {
2092 	if (esw->fdb_table.legacy.vepa_uplink_rule)
2093 		mlx5_del_flow_rules(esw->fdb_table.legacy.vepa_uplink_rule);
2094 
2095 	if (esw->fdb_table.legacy.vepa_star_rule)
2096 		mlx5_del_flow_rules(esw->fdb_table.legacy.vepa_star_rule);
2097 
2098 	esw->fdb_table.legacy.vepa_uplink_rule = NULL;
2099 	esw->fdb_table.legacy.vepa_star_rule = NULL;
2100 }
2101 
_mlx5_eswitch_set_vepa_locked(struct mlx5_eswitch * esw,u8 setting)2102 static int _mlx5_eswitch_set_vepa_locked(struct mlx5_eswitch *esw,
2103 					 u8 setting)
2104 {
2105 	struct mlx5_flow_destination dest = {};
2106 	struct mlx5_flow_act flow_act = {};
2107 	struct mlx5_flow_handle *flow_rule;
2108 	struct mlx5_flow_spec *spec;
2109 	int err = 0;
2110 	void *misc;
2111 
2112 	if (!setting) {
2113 		esw_cleanup_vepa_rules(esw);
2114 		return 0;
2115 	}
2116 
2117 	if (esw->fdb_table.legacy.vepa_uplink_rule)
2118 		return 0;
2119 
2120 	spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
2121 	if (!spec)
2122 		return -ENOMEM;
2123 
2124 	/* Uplink rule forward uplink traffic to FDB */
2125 	misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters);
2126 	MLX5_SET(fte_match_set_misc, misc, source_port, MLX5_VPORT_UPLINK);
2127 
2128 	misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters);
2129 	MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port);
2130 
2131 	spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS;
2132 	dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
2133 	dest.ft = esw->fdb_table.legacy.fdb;
2134 	flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
2135 	flow_rule = mlx5_add_flow_rules(esw->fdb_table.legacy.vepa_fdb, spec,
2136 					&flow_act, &dest, 1);
2137 	if (IS_ERR(flow_rule)) {
2138 		err = PTR_ERR(flow_rule);
2139 		goto out;
2140 	} else {
2141 		esw->fdb_table.legacy.vepa_uplink_rule = flow_rule;
2142 	}
2143 
2144 	/* Star rule to forward all traffic to uplink vport */
2145 	memset(&dest, 0, sizeof(dest));
2146 	dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
2147 	dest.vport.num = MLX5_VPORT_UPLINK;
2148 	flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
2149 	flow_rule = mlx5_add_flow_rules(esw->fdb_table.legacy.vepa_fdb, NULL,
2150 					&flow_act, &dest, 1);
2151 	if (IS_ERR(flow_rule)) {
2152 		err = PTR_ERR(flow_rule);
2153 		goto out;
2154 	} else {
2155 		esw->fdb_table.legacy.vepa_star_rule = flow_rule;
2156 	}
2157 
2158 out:
2159 	kvfree(spec);
2160 	if (err)
2161 		esw_cleanup_vepa_rules(esw);
2162 	return err;
2163 }
2164 
mlx5_eswitch_set_vepa(struct mlx5_eswitch * esw,u8 setting)2165 int mlx5_eswitch_set_vepa(struct mlx5_eswitch *esw, u8 setting)
2166 {
2167 	int err = 0;
2168 
2169 	if (!esw)
2170 		return -EOPNOTSUPP;
2171 
2172 	if (!ESW_ALLOWED(esw))
2173 		return -EPERM;
2174 
2175 	mutex_lock(&esw->state_lock);
2176 	if (esw->mode != MLX5_ESWITCH_LEGACY) {
2177 		err = -EOPNOTSUPP;
2178 		goto out;
2179 	}
2180 
2181 	err = _mlx5_eswitch_set_vepa_locked(esw, setting);
2182 
2183 out:
2184 	mutex_unlock(&esw->state_lock);
2185 	return err;
2186 }
2187 
mlx5_eswitch_get_vepa(struct mlx5_eswitch * esw,u8 * setting)2188 int mlx5_eswitch_get_vepa(struct mlx5_eswitch *esw, u8 *setting)
2189 {
2190 	if (!esw)
2191 		return -EOPNOTSUPP;
2192 
2193 	if (!ESW_ALLOWED(esw))
2194 		return -EPERM;
2195 
2196 	if (esw->mode != MLX5_ESWITCH_LEGACY)
2197 		return -EOPNOTSUPP;
2198 
2199 	*setting = esw->fdb_table.legacy.vepa_uplink_rule ? 1 : 0;
2200 	return 0;
2201 }
2202 
mlx5_eswitch_set_vport_trust(struct mlx5_eswitch * esw,u16 vport,bool setting)2203 int mlx5_eswitch_set_vport_trust(struct mlx5_eswitch *esw,
2204 				 u16 vport, bool setting)
2205 {
2206 	struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
2207 
2208 	if (!ESW_ALLOWED(esw))
2209 		return -EPERM;
2210 	if (IS_ERR(evport))
2211 		return PTR_ERR(evport);
2212 
2213 	mutex_lock(&esw->state_lock);
2214 	evport->info.trusted = setting;
2215 	if (evport->enabled)
2216 		esw_vport_change_handle_locked(evport);
2217 	mutex_unlock(&esw->state_lock);
2218 
2219 	return 0;
2220 }
2221 
calculate_vports_min_rate_divider(struct mlx5_eswitch * esw)2222 static u32 calculate_vports_min_rate_divider(struct mlx5_eswitch *esw)
2223 {
2224 	u32 fw_max_bw_share = MLX5_CAP_QOS(esw->dev, max_tsar_bw_share);
2225 	struct mlx5_vport *evport;
2226 	u32 max_guarantee = 0;
2227 	int i;
2228 
2229 	mlx5_esw_for_all_vports(esw, i, evport) {
2230 		if (!evport->enabled || evport->info.min_rate < max_guarantee)
2231 			continue;
2232 		max_guarantee = evport->info.min_rate;
2233 	}
2234 
2235 	if (max_guarantee)
2236 		return max_t(u32, max_guarantee / fw_max_bw_share, 1);
2237 	return 0;
2238 }
2239 
normalize_vports_min_rate(struct mlx5_eswitch * esw)2240 static int normalize_vports_min_rate(struct mlx5_eswitch *esw)
2241 {
2242 	u32 fw_max_bw_share = MLX5_CAP_QOS(esw->dev, max_tsar_bw_share);
2243 	u32 divider = calculate_vports_min_rate_divider(esw);
2244 	struct mlx5_vport *evport;
2245 	u32 vport_max_rate;
2246 	u32 vport_min_rate;
2247 	u32 bw_share;
2248 	int err;
2249 	int i;
2250 
2251 	mlx5_esw_for_all_vports(esw, i, evport) {
2252 		if (!evport->enabled)
2253 			continue;
2254 		vport_min_rate = evport->info.min_rate;
2255 		vport_max_rate = evport->info.max_rate;
2256 		bw_share = 0;
2257 
2258 		if (divider)
2259 			bw_share = MLX5_RATE_TO_BW_SHARE(vport_min_rate,
2260 							 divider,
2261 							 fw_max_bw_share);
2262 
2263 		if (bw_share == evport->qos.bw_share)
2264 			continue;
2265 
2266 		err = esw_vport_qos_config(esw, evport, vport_max_rate,
2267 					   bw_share);
2268 		if (!err)
2269 			evport->qos.bw_share = bw_share;
2270 		else
2271 			return err;
2272 	}
2273 
2274 	return 0;
2275 }
2276 
mlx5_eswitch_set_vport_rate(struct mlx5_eswitch * esw,u16 vport,u32 max_rate,u32 min_rate)2277 int mlx5_eswitch_set_vport_rate(struct mlx5_eswitch *esw, u16 vport,
2278 				u32 max_rate, u32 min_rate)
2279 {
2280 	struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
2281 	u32 fw_max_bw_share;
2282 	u32 previous_min_rate;
2283 	bool min_rate_supported;
2284 	bool max_rate_supported;
2285 	int err = 0;
2286 
2287 	if (!ESW_ALLOWED(esw))
2288 		return -EPERM;
2289 	if (IS_ERR(evport))
2290 		return PTR_ERR(evport);
2291 
2292 	fw_max_bw_share = MLX5_CAP_QOS(esw->dev, max_tsar_bw_share);
2293 	min_rate_supported = MLX5_CAP_QOS(esw->dev, esw_bw_share) &&
2294 				fw_max_bw_share >= MLX5_MIN_BW_SHARE;
2295 	max_rate_supported = MLX5_CAP_QOS(esw->dev, esw_rate_limit);
2296 
2297 	if ((min_rate && !min_rate_supported) || (max_rate && !max_rate_supported))
2298 		return -EOPNOTSUPP;
2299 
2300 	mutex_lock(&esw->state_lock);
2301 
2302 	if (min_rate == evport->info.min_rate)
2303 		goto set_max_rate;
2304 
2305 	previous_min_rate = evport->info.min_rate;
2306 	evport->info.min_rate = min_rate;
2307 	err = normalize_vports_min_rate(esw);
2308 	if (err) {
2309 		evport->info.min_rate = previous_min_rate;
2310 		goto unlock;
2311 	}
2312 
2313 set_max_rate:
2314 	if (max_rate == evport->info.max_rate)
2315 		goto unlock;
2316 
2317 	err = esw_vport_qos_config(esw, evport, max_rate, evport->qos.bw_share);
2318 	if (!err)
2319 		evport->info.max_rate = max_rate;
2320 
2321 unlock:
2322 	mutex_unlock(&esw->state_lock);
2323 	return err;
2324 }
2325 
mlx5_eswitch_query_vport_drop_stats(struct mlx5_core_dev * dev,struct mlx5_vport * vport,struct mlx5_vport_drop_stats * stats)2326 static int mlx5_eswitch_query_vport_drop_stats(struct mlx5_core_dev *dev,
2327 					       struct mlx5_vport *vport,
2328 					       struct mlx5_vport_drop_stats *stats)
2329 {
2330 	struct mlx5_eswitch *esw = dev->priv.eswitch;
2331 	u64 rx_discard_vport_down, tx_discard_vport_down;
2332 	u64 bytes = 0;
2333 	int err = 0;
2334 
2335 	if (esw->mode != MLX5_ESWITCH_LEGACY)
2336 		return 0;
2337 
2338 	mutex_lock(&esw->state_lock);
2339 	if (!vport->enabled)
2340 		goto unlock;
2341 
2342 	if (!IS_ERR_OR_NULL(vport->egress.legacy.drop_counter))
2343 		mlx5_fc_query(dev, vport->egress.legacy.drop_counter,
2344 			      &stats->rx_dropped, &bytes);
2345 
2346 	if (vport->ingress.legacy.drop_counter)
2347 		mlx5_fc_query(dev, vport->ingress.legacy.drop_counter,
2348 			      &stats->tx_dropped, &bytes);
2349 
2350 	if (!MLX5_CAP_GEN(dev, receive_discard_vport_down) &&
2351 	    !MLX5_CAP_GEN(dev, transmit_discard_vport_down))
2352 		goto unlock;
2353 
2354 	err = mlx5_query_vport_down_stats(dev, vport->vport, 1,
2355 					  &rx_discard_vport_down,
2356 					  &tx_discard_vport_down);
2357 	if (err)
2358 		goto unlock;
2359 
2360 	if (MLX5_CAP_GEN(dev, receive_discard_vport_down))
2361 		stats->rx_dropped += rx_discard_vport_down;
2362 	if (MLX5_CAP_GEN(dev, transmit_discard_vport_down))
2363 		stats->tx_dropped += tx_discard_vport_down;
2364 
2365 unlock:
2366 	mutex_unlock(&esw->state_lock);
2367 	return err;
2368 }
2369 
mlx5_eswitch_get_vport_stats(struct mlx5_eswitch * esw,u16 vport_num,struct ifla_vf_stats * vf_stats)2370 int mlx5_eswitch_get_vport_stats(struct mlx5_eswitch *esw,
2371 				 u16 vport_num,
2372 				 struct ifla_vf_stats *vf_stats)
2373 {
2374 	struct mlx5_vport *vport = mlx5_eswitch_get_vport(esw, vport_num);
2375 	int outlen = MLX5_ST_SZ_BYTES(query_vport_counter_out);
2376 	u32 in[MLX5_ST_SZ_DW(query_vport_counter_in)] = {};
2377 	struct mlx5_vport_drop_stats stats = {};
2378 	int err = 0;
2379 	u32 *out;
2380 
2381 	if (IS_ERR(vport))
2382 		return PTR_ERR(vport);
2383 
2384 	out = kvzalloc(outlen, GFP_KERNEL);
2385 	if (!out)
2386 		return -ENOMEM;
2387 
2388 	MLX5_SET(query_vport_counter_in, in, opcode,
2389 		 MLX5_CMD_OP_QUERY_VPORT_COUNTER);
2390 	MLX5_SET(query_vport_counter_in, in, op_mod, 0);
2391 	MLX5_SET(query_vport_counter_in, in, vport_number, vport->vport);
2392 	MLX5_SET(query_vport_counter_in, in, other_vport, 1);
2393 
2394 	err = mlx5_cmd_exec_inout(esw->dev, query_vport_counter, in, out);
2395 	if (err)
2396 		goto free_out;
2397 
2398 	#define MLX5_GET_CTR(p, x) \
2399 		MLX5_GET64(query_vport_counter_out, p, x)
2400 
2401 	memset(vf_stats, 0, sizeof(*vf_stats));
2402 	vf_stats->rx_packets =
2403 		MLX5_GET_CTR(out, received_eth_unicast.packets) +
2404 		MLX5_GET_CTR(out, received_ib_unicast.packets) +
2405 		MLX5_GET_CTR(out, received_eth_multicast.packets) +
2406 		MLX5_GET_CTR(out, received_ib_multicast.packets) +
2407 		MLX5_GET_CTR(out, received_eth_broadcast.packets);
2408 
2409 	vf_stats->rx_bytes =
2410 		MLX5_GET_CTR(out, received_eth_unicast.octets) +
2411 		MLX5_GET_CTR(out, received_ib_unicast.octets) +
2412 		MLX5_GET_CTR(out, received_eth_multicast.octets) +
2413 		MLX5_GET_CTR(out, received_ib_multicast.octets) +
2414 		MLX5_GET_CTR(out, received_eth_broadcast.octets);
2415 
2416 	vf_stats->tx_packets =
2417 		MLX5_GET_CTR(out, transmitted_eth_unicast.packets) +
2418 		MLX5_GET_CTR(out, transmitted_ib_unicast.packets) +
2419 		MLX5_GET_CTR(out, transmitted_eth_multicast.packets) +
2420 		MLX5_GET_CTR(out, transmitted_ib_multicast.packets) +
2421 		MLX5_GET_CTR(out, transmitted_eth_broadcast.packets);
2422 
2423 	vf_stats->tx_bytes =
2424 		MLX5_GET_CTR(out, transmitted_eth_unicast.octets) +
2425 		MLX5_GET_CTR(out, transmitted_ib_unicast.octets) +
2426 		MLX5_GET_CTR(out, transmitted_eth_multicast.octets) +
2427 		MLX5_GET_CTR(out, transmitted_ib_multicast.octets) +
2428 		MLX5_GET_CTR(out, transmitted_eth_broadcast.octets);
2429 
2430 	vf_stats->multicast =
2431 		MLX5_GET_CTR(out, received_eth_multicast.packets) +
2432 		MLX5_GET_CTR(out, received_ib_multicast.packets);
2433 
2434 	vf_stats->broadcast =
2435 		MLX5_GET_CTR(out, received_eth_broadcast.packets);
2436 
2437 	err = mlx5_eswitch_query_vport_drop_stats(esw->dev, vport, &stats);
2438 	if (err)
2439 		goto free_out;
2440 	vf_stats->rx_dropped = stats.rx_dropped;
2441 	vf_stats->tx_dropped = stats.tx_dropped;
2442 
2443 free_out:
2444 	kvfree(out);
2445 	return err;
2446 }
2447 
mlx5_eswitch_mode(struct mlx5_eswitch * esw)2448 u8 mlx5_eswitch_mode(struct mlx5_eswitch *esw)
2449 {
2450 	return ESW_ALLOWED(esw) ? esw->mode : MLX5_ESWITCH_NONE;
2451 }
2452 EXPORT_SYMBOL_GPL(mlx5_eswitch_mode);
2453 
2454 enum devlink_eswitch_encap_mode
mlx5_eswitch_get_encap_mode(const struct mlx5_core_dev * dev)2455 mlx5_eswitch_get_encap_mode(const struct mlx5_core_dev *dev)
2456 {
2457 	struct mlx5_eswitch *esw;
2458 
2459 	esw = dev->priv.eswitch;
2460 	return ESW_ALLOWED(esw) ? esw->offloads.encap :
2461 		DEVLINK_ESWITCH_ENCAP_MODE_NONE;
2462 }
2463 EXPORT_SYMBOL(mlx5_eswitch_get_encap_mode);
2464 
mlx5_esw_lag_prereq(struct mlx5_core_dev * dev0,struct mlx5_core_dev * dev1)2465 bool mlx5_esw_lag_prereq(struct mlx5_core_dev *dev0, struct mlx5_core_dev *dev1)
2466 {
2467 	if ((dev0->priv.eswitch->mode == MLX5_ESWITCH_NONE &&
2468 	     dev1->priv.eswitch->mode == MLX5_ESWITCH_NONE) ||
2469 	    (dev0->priv.eswitch->mode == MLX5_ESWITCH_OFFLOADS &&
2470 	     dev1->priv.eswitch->mode == MLX5_ESWITCH_OFFLOADS))
2471 		return true;
2472 
2473 	return false;
2474 }
2475 
mlx5_esw_multipath_prereq(struct mlx5_core_dev * dev0,struct mlx5_core_dev * dev1)2476 bool mlx5_esw_multipath_prereq(struct mlx5_core_dev *dev0,
2477 			       struct mlx5_core_dev *dev1)
2478 {
2479 	return (dev0->priv.eswitch->mode == MLX5_ESWITCH_OFFLOADS &&
2480 		dev1->priv.eswitch->mode == MLX5_ESWITCH_OFFLOADS);
2481 }
2482 
2483 
2484