• 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_apply_vport_rx_mode(esw, vport, false, false);
1343 	esw_vport_cleanup(esw, vport);
1344 	esw->enabled_vports--;
1345 
1346 done:
1347 	mutex_unlock(&esw->state_lock);
1348 }
1349 
eswitch_vport_event(struct notifier_block * nb,unsigned long type,void * data)1350 static int eswitch_vport_event(struct notifier_block *nb,
1351 			       unsigned long type, void *data)
1352 {
1353 	struct mlx5_eswitch *esw = mlx5_nb_cof(nb, struct mlx5_eswitch, nb);
1354 	struct mlx5_eqe *eqe = data;
1355 	struct mlx5_vport *vport;
1356 	u16 vport_num;
1357 
1358 	vport_num = be16_to_cpu(eqe->data.vport_change.vport_num);
1359 	vport = mlx5_eswitch_get_vport(esw, vport_num);
1360 	if (!IS_ERR(vport))
1361 		queue_work(esw->work_queue, &vport->vport_change_handler);
1362 	return NOTIFY_OK;
1363 }
1364 
1365 /**
1366  * mlx5_esw_query_functions - Returns raw output about functions state
1367  * @dev:	Pointer to device to query
1368  *
1369  * mlx5_esw_query_functions() allocates and returns functions changed
1370  * raw output memory pointer from device on success. Otherwise returns ERR_PTR.
1371  * Caller must free the memory using kvfree() when valid pointer is returned.
1372  */
mlx5_esw_query_functions(struct mlx5_core_dev * dev)1373 const u32 *mlx5_esw_query_functions(struct mlx5_core_dev *dev)
1374 {
1375 	int outlen = MLX5_ST_SZ_BYTES(query_esw_functions_out);
1376 	u32 in[MLX5_ST_SZ_DW(query_esw_functions_in)] = {};
1377 	u32 *out;
1378 	int err;
1379 
1380 	out = kvzalloc(outlen, GFP_KERNEL);
1381 	if (!out)
1382 		return ERR_PTR(-ENOMEM);
1383 
1384 	MLX5_SET(query_esw_functions_in, in, opcode,
1385 		 MLX5_CMD_OP_QUERY_ESW_FUNCTIONS);
1386 
1387 	err = mlx5_cmd_exec_inout(dev, query_esw_functions, in, out);
1388 	if (!err)
1389 		return out;
1390 
1391 	kvfree(out);
1392 	return ERR_PTR(err);
1393 }
1394 
mlx5_eswitch_event_handlers_register(struct mlx5_eswitch * esw)1395 static void mlx5_eswitch_event_handlers_register(struct mlx5_eswitch *esw)
1396 {
1397 	MLX5_NB_INIT(&esw->nb, eswitch_vport_event, NIC_VPORT_CHANGE);
1398 	mlx5_eq_notifier_register(esw->dev, &esw->nb);
1399 
1400 	if (esw->mode == MLX5_ESWITCH_OFFLOADS && mlx5_eswitch_is_funcs_handler(esw->dev)) {
1401 		MLX5_NB_INIT(&esw->esw_funcs.nb, mlx5_esw_funcs_changed_handler,
1402 			     ESW_FUNCTIONS_CHANGED);
1403 		mlx5_eq_notifier_register(esw->dev, &esw->esw_funcs.nb);
1404 	}
1405 }
1406 
mlx5_eswitch_event_handlers_unregister(struct mlx5_eswitch * esw)1407 static void mlx5_eswitch_event_handlers_unregister(struct mlx5_eswitch *esw)
1408 {
1409 	if (esw->mode == MLX5_ESWITCH_OFFLOADS && mlx5_eswitch_is_funcs_handler(esw->dev))
1410 		mlx5_eq_notifier_unregister(esw->dev, &esw->esw_funcs.nb);
1411 
1412 	mlx5_eq_notifier_unregister(esw->dev, &esw->nb);
1413 
1414 	flush_workqueue(esw->work_queue);
1415 }
1416 
mlx5_eswitch_clear_vf_vports_info(struct mlx5_eswitch * esw)1417 static void mlx5_eswitch_clear_vf_vports_info(struct mlx5_eswitch *esw)
1418 {
1419 	struct mlx5_vport *vport;
1420 	int i;
1421 
1422 	mlx5_esw_for_each_vf_vport(esw, i, vport, esw->esw_funcs.num_vfs) {
1423 		memset(&vport->qos, 0, sizeof(vport->qos));
1424 		memset(&vport->info, 0, sizeof(vport->info));
1425 		vport->info.link_state = MLX5_VPORT_ADMIN_STATE_AUTO;
1426 	}
1427 }
1428 
1429 /* Public E-Switch API */
1430 #define ESW_ALLOWED(esw) ((esw) && MLX5_ESWITCH_MANAGER((esw)->dev))
1431 
mlx5_eswitch_load_vport(struct mlx5_eswitch * esw,u16 vport_num,enum mlx5_eswitch_vport_event enabled_events)1432 int mlx5_eswitch_load_vport(struct mlx5_eswitch *esw, u16 vport_num,
1433 			    enum mlx5_eswitch_vport_event enabled_events)
1434 {
1435 	int err;
1436 
1437 	err = esw_enable_vport(esw, vport_num, enabled_events);
1438 	if (err)
1439 		return err;
1440 
1441 	err = esw_offloads_load_rep(esw, vport_num);
1442 	if (err)
1443 		goto err_rep;
1444 
1445 	return err;
1446 
1447 err_rep:
1448 	esw_disable_vport(esw, vport_num);
1449 	return err;
1450 }
1451 
mlx5_eswitch_unload_vport(struct mlx5_eswitch * esw,u16 vport_num)1452 void mlx5_eswitch_unload_vport(struct mlx5_eswitch *esw, u16 vport_num)
1453 {
1454 	esw_offloads_unload_rep(esw, vport_num);
1455 	esw_disable_vport(esw, vport_num);
1456 }
1457 
mlx5_eswitch_unload_vf_vports(struct mlx5_eswitch * esw,u16 num_vfs)1458 void mlx5_eswitch_unload_vf_vports(struct mlx5_eswitch *esw, u16 num_vfs)
1459 {
1460 	int i;
1461 
1462 	mlx5_esw_for_each_vf_vport_num_reverse(esw, i, num_vfs)
1463 		mlx5_eswitch_unload_vport(esw, i);
1464 }
1465 
mlx5_eswitch_load_vf_vports(struct mlx5_eswitch * esw,u16 num_vfs,enum mlx5_eswitch_vport_event enabled_events)1466 int mlx5_eswitch_load_vf_vports(struct mlx5_eswitch *esw, u16 num_vfs,
1467 				enum mlx5_eswitch_vport_event enabled_events)
1468 {
1469 	int err;
1470 	int i;
1471 
1472 	mlx5_esw_for_each_vf_vport_num(esw, i, num_vfs) {
1473 		err = mlx5_eswitch_load_vport(esw, i, enabled_events);
1474 		if (err)
1475 			goto vf_err;
1476 	}
1477 
1478 	return 0;
1479 
1480 vf_err:
1481 	mlx5_eswitch_unload_vf_vports(esw, i - 1);
1482 	return err;
1483 }
1484 
1485 /* mlx5_eswitch_enable_pf_vf_vports() enables vports of PF, ECPF and VFs
1486  * whichever are present on the eswitch.
1487  */
1488 int
mlx5_eswitch_enable_pf_vf_vports(struct mlx5_eswitch * esw,enum mlx5_eswitch_vport_event enabled_events)1489 mlx5_eswitch_enable_pf_vf_vports(struct mlx5_eswitch *esw,
1490 				 enum mlx5_eswitch_vport_event enabled_events)
1491 {
1492 	int ret;
1493 
1494 	/* Enable PF vport */
1495 	ret = mlx5_eswitch_load_vport(esw, MLX5_VPORT_PF, enabled_events);
1496 	if (ret)
1497 		return ret;
1498 
1499 	/* Enable ECPF vport */
1500 	if (mlx5_ecpf_vport_exists(esw->dev)) {
1501 		ret = mlx5_eswitch_load_vport(esw, MLX5_VPORT_ECPF, enabled_events);
1502 		if (ret)
1503 			goto ecpf_err;
1504 	}
1505 
1506 	/* Enable VF vports */
1507 	ret = mlx5_eswitch_load_vf_vports(esw, esw->esw_funcs.num_vfs,
1508 					  enabled_events);
1509 	if (ret)
1510 		goto vf_err;
1511 	return 0;
1512 
1513 vf_err:
1514 	if (mlx5_ecpf_vport_exists(esw->dev))
1515 		mlx5_eswitch_unload_vport(esw, MLX5_VPORT_ECPF);
1516 
1517 ecpf_err:
1518 	mlx5_eswitch_unload_vport(esw, MLX5_VPORT_PF);
1519 	return ret;
1520 }
1521 
1522 /* mlx5_eswitch_disable_pf_vf_vports() disables vports of PF, ECPF and VFs
1523  * whichever are previously enabled on the eswitch.
1524  */
mlx5_eswitch_disable_pf_vf_vports(struct mlx5_eswitch * esw)1525 void mlx5_eswitch_disable_pf_vf_vports(struct mlx5_eswitch *esw)
1526 {
1527 	mlx5_eswitch_unload_vf_vports(esw, esw->esw_funcs.num_vfs);
1528 
1529 	if (mlx5_ecpf_vport_exists(esw->dev))
1530 		mlx5_eswitch_unload_vport(esw, MLX5_VPORT_ECPF);
1531 
1532 	mlx5_eswitch_unload_vport(esw, MLX5_VPORT_PF);
1533 }
1534 
mlx5_eswitch_get_devlink_param(struct mlx5_eswitch * esw)1535 static void mlx5_eswitch_get_devlink_param(struct mlx5_eswitch *esw)
1536 {
1537 	struct devlink *devlink = priv_to_devlink(esw->dev);
1538 	union devlink_param_value val;
1539 	int err;
1540 
1541 	err = devlink_param_driverinit_value_get(devlink,
1542 						 MLX5_DEVLINK_PARAM_ID_ESW_LARGE_GROUP_NUM,
1543 						 &val);
1544 	if (!err) {
1545 		esw->params.large_group_num = val.vu32;
1546 	} else {
1547 		esw_warn(esw->dev,
1548 			 "Devlink can't get param fdb_large_groups, uses default (%d).\n",
1549 			 ESW_OFFLOADS_DEFAULT_NUM_GROUPS);
1550 		esw->params.large_group_num = ESW_OFFLOADS_DEFAULT_NUM_GROUPS;
1551 	}
1552 }
1553 
1554 static void
mlx5_eswitch_update_num_of_vfs(struct mlx5_eswitch * esw,int num_vfs)1555 mlx5_eswitch_update_num_of_vfs(struct mlx5_eswitch *esw, int num_vfs)
1556 {
1557 	const u32 *out;
1558 
1559 	WARN_ON_ONCE(esw->mode != MLX5_ESWITCH_NONE);
1560 
1561 	if (num_vfs < 0)
1562 		return;
1563 
1564 	if (!mlx5_core_is_ecpf_esw_manager(esw->dev)) {
1565 		esw->esw_funcs.num_vfs = num_vfs;
1566 		return;
1567 	}
1568 
1569 	out = mlx5_esw_query_functions(esw->dev);
1570 	if (IS_ERR(out))
1571 		return;
1572 
1573 	esw->esw_funcs.num_vfs = MLX5_GET(query_esw_functions_out, out,
1574 					  host_params_context.host_num_of_vfs);
1575 	kvfree(out);
1576 }
1577 
1578 /**
1579  * mlx5_eswitch_enable_locked - Enable eswitch
1580  * @esw:	Pointer to eswitch
1581  * @mode:	Eswitch mode to enable
1582  * @num_vfs:	Enable eswitch for given number of VFs. This is optional.
1583  *		Valid value are 0, > 0 and MLX5_ESWITCH_IGNORE_NUM_VFS.
1584  *		Caller should pass num_vfs > 0 when enabling eswitch for
1585  *		vf vports. Caller should pass num_vfs = 0, when eswitch
1586  *		is enabled without sriov VFs or when caller
1587  *		is unaware of the sriov state of the host PF on ECPF based
1588  *		eswitch. Caller should pass < 0 when num_vfs should be
1589  *		completely ignored. This is typically the case when eswitch
1590  *		is enabled without sriov regardless of PF/ECPF system.
1591  * mlx5_eswitch_enable_locked() Enables eswitch in either legacy or offloads
1592  * mode. If num_vfs >=0 is provided, it setup VF related eswitch vports.
1593  * It returns 0 on success or error code on failure.
1594  */
mlx5_eswitch_enable_locked(struct mlx5_eswitch * esw,int mode,int num_vfs)1595 int mlx5_eswitch_enable_locked(struct mlx5_eswitch *esw, int mode, int num_vfs)
1596 {
1597 	int err;
1598 
1599 	lockdep_assert_held(&esw->mode_lock);
1600 
1601 	if (!MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, ft_support)) {
1602 		esw_warn(esw->dev, "FDB is not supported, aborting ...\n");
1603 		return -EOPNOTSUPP;
1604 	}
1605 
1606 	if (!MLX5_CAP_ESW_INGRESS_ACL(esw->dev, ft_support))
1607 		esw_warn(esw->dev, "ingress ACL is not supported by FW\n");
1608 
1609 	if (!MLX5_CAP_ESW_EGRESS_ACL(esw->dev, ft_support))
1610 		esw_warn(esw->dev, "engress ACL is not supported by FW\n");
1611 
1612 	mlx5_eswitch_get_devlink_param(esw);
1613 
1614 	mlx5_eswitch_update_num_of_vfs(esw, num_vfs);
1615 
1616 	esw_create_tsar(esw);
1617 
1618 	esw->mode = mode;
1619 
1620 	mlx5_lag_update(esw->dev);
1621 
1622 	if (mode == MLX5_ESWITCH_LEGACY) {
1623 		err = esw_legacy_enable(esw);
1624 	} else {
1625 		mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_ETH);
1626 		mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_IB);
1627 		err = esw_offloads_enable(esw);
1628 	}
1629 
1630 	if (err)
1631 		goto abort;
1632 
1633 	mlx5_eswitch_event_handlers_register(esw);
1634 
1635 	esw_info(esw->dev, "Enable: mode(%s), nvfs(%d), active vports(%d)\n",
1636 		 mode == MLX5_ESWITCH_LEGACY ? "LEGACY" : "OFFLOADS",
1637 		 esw->esw_funcs.num_vfs, esw->enabled_vports);
1638 
1639 	return 0;
1640 
1641 abort:
1642 	esw->mode = MLX5_ESWITCH_NONE;
1643 
1644 	if (mode == MLX5_ESWITCH_OFFLOADS) {
1645 		mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_IB);
1646 		mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_ETH);
1647 	}
1648 	esw_destroy_tsar(esw);
1649 	return err;
1650 }
1651 
1652 /**
1653  * mlx5_eswitch_enable - Enable eswitch
1654  * @esw:	Pointer to eswitch
1655  * @num_vfs:	Enable eswitch swich for given number of VFs.
1656  *		Caller must pass num_vfs > 0 when enabling eswitch for
1657  *		vf vports.
1658  * mlx5_eswitch_enable() returns 0 on success or error code on failure.
1659  */
mlx5_eswitch_enable(struct mlx5_eswitch * esw,int num_vfs)1660 int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int num_vfs)
1661 {
1662 	int ret;
1663 
1664 	if (!ESW_ALLOWED(esw))
1665 		return 0;
1666 
1667 	down_write(&esw->mode_lock);
1668 	if (esw->mode == MLX5_ESWITCH_NONE) {
1669 		ret = mlx5_eswitch_enable_locked(esw, MLX5_ESWITCH_LEGACY, num_vfs);
1670 	} else {
1671 		enum mlx5_eswitch_vport_event vport_events;
1672 
1673 		vport_events = (esw->mode == MLX5_ESWITCH_LEGACY) ?
1674 					MLX5_LEGACY_SRIOV_VPORT_EVENTS : MLX5_VPORT_UC_ADDR_CHANGE;
1675 		ret = mlx5_eswitch_load_vf_vports(esw, num_vfs, vport_events);
1676 		if (!ret)
1677 			esw->esw_funcs.num_vfs = num_vfs;
1678 	}
1679 	up_write(&esw->mode_lock);
1680 	return ret;
1681 }
1682 
mlx5_eswitch_disable_locked(struct mlx5_eswitch * esw,bool clear_vf)1683 void mlx5_eswitch_disable_locked(struct mlx5_eswitch *esw, bool clear_vf)
1684 {
1685 	int old_mode;
1686 
1687 	lockdep_assert_held_write(&esw->mode_lock);
1688 
1689 	if (esw->mode == MLX5_ESWITCH_NONE)
1690 		return;
1691 
1692 	esw_info(esw->dev, "Disable: mode(%s), nvfs(%d), active vports(%d)\n",
1693 		 esw->mode == MLX5_ESWITCH_LEGACY ? "LEGACY" : "OFFLOADS",
1694 		 esw->esw_funcs.num_vfs, esw->enabled_vports);
1695 
1696 	mlx5_eswitch_event_handlers_unregister(esw);
1697 
1698 	if (esw->mode == MLX5_ESWITCH_LEGACY)
1699 		esw_legacy_disable(esw);
1700 	else if (esw->mode == MLX5_ESWITCH_OFFLOADS)
1701 		esw_offloads_disable(esw);
1702 
1703 	old_mode = esw->mode;
1704 	esw->mode = MLX5_ESWITCH_NONE;
1705 
1706 	mlx5_lag_update(esw->dev);
1707 
1708 	if (old_mode == MLX5_ESWITCH_OFFLOADS) {
1709 		mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_IB);
1710 		mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_ETH);
1711 	}
1712 	esw_destroy_tsar(esw);
1713 
1714 	if (clear_vf)
1715 		mlx5_eswitch_clear_vf_vports_info(esw);
1716 }
1717 
mlx5_eswitch_disable(struct mlx5_eswitch * esw,bool clear_vf)1718 void mlx5_eswitch_disable(struct mlx5_eswitch *esw, bool clear_vf)
1719 {
1720 	if (!ESW_ALLOWED(esw))
1721 		return;
1722 
1723 	down_write(&esw->mode_lock);
1724 	mlx5_eswitch_disable_locked(esw, clear_vf);
1725 	esw->esw_funcs.num_vfs = 0;
1726 	up_write(&esw->mode_lock);
1727 }
1728 
mlx5_eswitch_init(struct mlx5_core_dev * dev)1729 int mlx5_eswitch_init(struct mlx5_core_dev *dev)
1730 {
1731 	struct mlx5_eswitch *esw;
1732 	struct mlx5_vport *vport;
1733 	int total_vports;
1734 	int err, i;
1735 
1736 	if (!MLX5_VPORT_MANAGER(dev))
1737 		return 0;
1738 
1739 	total_vports = mlx5_eswitch_get_total_vports(dev);
1740 
1741 	esw_info(dev,
1742 		 "Total vports %d, per vport: max uc(%d) max mc(%d)\n",
1743 		 total_vports,
1744 		 MLX5_MAX_UC_PER_VPORT(dev),
1745 		 MLX5_MAX_MC_PER_VPORT(dev));
1746 
1747 	esw = kzalloc(sizeof(*esw), GFP_KERNEL);
1748 	if (!esw)
1749 		return -ENOMEM;
1750 
1751 	esw->dev = dev;
1752 	esw->manager_vport = mlx5_eswitch_manager_vport(dev);
1753 	esw->first_host_vport = mlx5_eswitch_first_host_vport_num(dev);
1754 
1755 	esw->work_queue = create_singlethread_workqueue("mlx5_esw_wq");
1756 	if (!esw->work_queue) {
1757 		err = -ENOMEM;
1758 		goto abort;
1759 	}
1760 
1761 	esw->vports = kcalloc(total_vports, sizeof(struct mlx5_vport),
1762 			      GFP_KERNEL);
1763 	if (!esw->vports) {
1764 		err = -ENOMEM;
1765 		goto abort;
1766 	}
1767 
1768 	esw->total_vports = total_vports;
1769 
1770 	err = esw_offloads_init_reps(esw);
1771 	if (err)
1772 		goto abort;
1773 
1774 	mutex_init(&esw->offloads.encap_tbl_lock);
1775 	hash_init(esw->offloads.encap_tbl);
1776 	mutex_init(&esw->offloads.decap_tbl_lock);
1777 	hash_init(esw->offloads.decap_tbl);
1778 	mlx5e_mod_hdr_tbl_init(&esw->offloads.mod_hdr);
1779 	atomic64_set(&esw->offloads.num_flows, 0);
1780 	ida_init(&esw->offloads.vport_metadata_ida);
1781 	mutex_init(&esw->state_lock);
1782 	init_rwsem(&esw->mode_lock);
1783 
1784 	mlx5_esw_for_all_vports(esw, i, vport) {
1785 		vport->vport = mlx5_eswitch_index_to_vport_num(esw, i);
1786 		vport->info.link_state = MLX5_VPORT_ADMIN_STATE_AUTO;
1787 		vport->dev = dev;
1788 		INIT_WORK(&vport->vport_change_handler,
1789 			  esw_vport_change_handler);
1790 	}
1791 
1792 	esw->enabled_vports = 0;
1793 	esw->mode = MLX5_ESWITCH_NONE;
1794 	esw->offloads.inline_mode = MLX5_INLINE_MODE_NONE;
1795 
1796 	dev->priv.eswitch = esw;
1797 	return 0;
1798 abort:
1799 	if (esw->work_queue)
1800 		destroy_workqueue(esw->work_queue);
1801 	esw_offloads_cleanup_reps(esw);
1802 	kfree(esw->vports);
1803 	kfree(esw);
1804 	return err;
1805 }
1806 
mlx5_eswitch_cleanup(struct mlx5_eswitch * esw)1807 void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw)
1808 {
1809 	if (!esw || !MLX5_VPORT_MANAGER(esw->dev))
1810 		return;
1811 
1812 	esw_info(esw->dev, "cleanup\n");
1813 
1814 	esw->dev->priv.eswitch = NULL;
1815 	destroy_workqueue(esw->work_queue);
1816 	esw_offloads_cleanup_reps(esw);
1817 	mutex_destroy(&esw->state_lock);
1818 	ida_destroy(&esw->offloads.vport_metadata_ida);
1819 	mlx5e_mod_hdr_tbl_destroy(&esw->offloads.mod_hdr);
1820 	mutex_destroy(&esw->offloads.encap_tbl_lock);
1821 	mutex_destroy(&esw->offloads.decap_tbl_lock);
1822 	kfree(esw->vports);
1823 	kfree(esw);
1824 }
1825 
1826 /* Vport Administration */
1827 static int
mlx5_esw_set_vport_mac_locked(struct mlx5_eswitch * esw,struct mlx5_vport * evport,const u8 * mac)1828 mlx5_esw_set_vport_mac_locked(struct mlx5_eswitch *esw,
1829 			      struct mlx5_vport *evport, const u8 *mac)
1830 {
1831 	u16 vport_num = evport->vport;
1832 	u64 node_guid;
1833 	int err = 0;
1834 
1835 	if (is_multicast_ether_addr(mac))
1836 		return -EINVAL;
1837 
1838 	if (evport->info.spoofchk && !is_valid_ether_addr(mac))
1839 		mlx5_core_warn(esw->dev,
1840 			       "Set invalid MAC while spoofchk is on, vport(%d)\n",
1841 			       vport_num);
1842 
1843 	err = mlx5_modify_nic_vport_mac_address(esw->dev, vport_num, mac);
1844 	if (err) {
1845 		mlx5_core_warn(esw->dev,
1846 			       "Failed to mlx5_modify_nic_vport_mac vport(%d) err=(%d)\n",
1847 			       vport_num, err);
1848 		return err;
1849 	}
1850 
1851 	node_guid_gen_from_mac(&node_guid, mac);
1852 	err = mlx5_modify_nic_vport_node_guid(esw->dev, vport_num, node_guid);
1853 	if (err)
1854 		mlx5_core_warn(esw->dev,
1855 			       "Failed to set vport %d node guid, err = %d. RDMA_CM will not function properly for this VF.\n",
1856 			       vport_num, err);
1857 
1858 	ether_addr_copy(evport->info.mac, mac);
1859 	evport->info.node_guid = node_guid;
1860 	if (evport->enabled && esw->mode == MLX5_ESWITCH_LEGACY)
1861 		err = esw_acl_ingress_lgcy_setup(esw, evport);
1862 
1863 	return err;
1864 }
1865 
mlx5_eswitch_set_vport_mac(struct mlx5_eswitch * esw,u16 vport,const u8 * mac)1866 int mlx5_eswitch_set_vport_mac(struct mlx5_eswitch *esw,
1867 			       u16 vport, const u8 *mac)
1868 {
1869 	struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
1870 	int err = 0;
1871 
1872 	if (IS_ERR(evport))
1873 		return PTR_ERR(evport);
1874 
1875 	mutex_lock(&esw->state_lock);
1876 	err = mlx5_esw_set_vport_mac_locked(esw, evport, mac);
1877 	mutex_unlock(&esw->state_lock);
1878 	return err;
1879 }
1880 
1881 static bool
is_port_function_supported(const struct mlx5_eswitch * esw,u16 vport_num)1882 is_port_function_supported(const struct mlx5_eswitch *esw, u16 vport_num)
1883 {
1884 	return vport_num == MLX5_VPORT_PF ||
1885 	       mlx5_eswitch_is_vf_vport(esw, vport_num);
1886 }
1887 
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)1888 int mlx5_devlink_port_function_hw_addr_get(struct devlink *devlink,
1889 					   struct devlink_port *port,
1890 					   u8 *hw_addr, int *hw_addr_len,
1891 					   struct netlink_ext_ack *extack)
1892 {
1893 	struct mlx5_eswitch *esw;
1894 	struct mlx5_vport *vport;
1895 	int err = -EOPNOTSUPP;
1896 	u16 vport_num;
1897 
1898 	esw = mlx5_devlink_eswitch_get(devlink);
1899 	if (IS_ERR(esw))
1900 		return PTR_ERR(esw);
1901 
1902 	vport_num = mlx5_esw_devlink_port_index_to_vport_num(port->index);
1903 	if (!is_port_function_supported(esw, vport_num))
1904 		return -EOPNOTSUPP;
1905 
1906 	vport = mlx5_eswitch_get_vport(esw, vport_num);
1907 	if (IS_ERR(vport)) {
1908 		NL_SET_ERR_MSG_MOD(extack, "Invalid port");
1909 		return PTR_ERR(vport);
1910 	}
1911 
1912 	mutex_lock(&esw->state_lock);
1913 	if (vport->enabled) {
1914 		ether_addr_copy(hw_addr, vport->info.mac);
1915 		*hw_addr_len = ETH_ALEN;
1916 		err = 0;
1917 	}
1918 	mutex_unlock(&esw->state_lock);
1919 	return err;
1920 }
1921 
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)1922 int mlx5_devlink_port_function_hw_addr_set(struct devlink *devlink,
1923 					   struct devlink_port *port,
1924 					   const u8 *hw_addr, int hw_addr_len,
1925 					   struct netlink_ext_ack *extack)
1926 {
1927 	struct mlx5_eswitch *esw;
1928 	struct mlx5_vport *vport;
1929 	int err = -EOPNOTSUPP;
1930 	u16 vport_num;
1931 
1932 	esw = mlx5_devlink_eswitch_get(devlink);
1933 	if (IS_ERR(esw)) {
1934 		NL_SET_ERR_MSG_MOD(extack, "Eswitch doesn't support set hw_addr");
1935 		return PTR_ERR(esw);
1936 	}
1937 
1938 	vport_num = mlx5_esw_devlink_port_index_to_vport_num(port->index);
1939 	if (!is_port_function_supported(esw, vport_num)) {
1940 		NL_SET_ERR_MSG_MOD(extack, "Port doesn't support set hw_addr");
1941 		return -EINVAL;
1942 	}
1943 	vport = mlx5_eswitch_get_vport(esw, vport_num);
1944 	if (IS_ERR(vport)) {
1945 		NL_SET_ERR_MSG_MOD(extack, "Invalid port");
1946 		return PTR_ERR(vport);
1947 	}
1948 
1949 	mutex_lock(&esw->state_lock);
1950 	if (vport->enabled)
1951 		err = mlx5_esw_set_vport_mac_locked(esw, vport, hw_addr);
1952 	else
1953 		NL_SET_ERR_MSG_MOD(extack, "Eswitch vport is disabled");
1954 	mutex_unlock(&esw->state_lock);
1955 	return err;
1956 }
1957 
mlx5_eswitch_set_vport_state(struct mlx5_eswitch * esw,u16 vport,int link_state)1958 int mlx5_eswitch_set_vport_state(struct mlx5_eswitch *esw,
1959 				 u16 vport, int link_state)
1960 {
1961 	struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
1962 	int opmod = MLX5_VPORT_STATE_OP_MOD_ESW_VPORT;
1963 	int other_vport = 1;
1964 	int err = 0;
1965 
1966 	if (!ESW_ALLOWED(esw))
1967 		return -EPERM;
1968 	if (IS_ERR(evport))
1969 		return PTR_ERR(evport);
1970 
1971 	if (vport == MLX5_VPORT_UPLINK) {
1972 		opmod = MLX5_VPORT_STATE_OP_MOD_UPLINK;
1973 		other_vport = 0;
1974 		vport = 0;
1975 	}
1976 	mutex_lock(&esw->state_lock);
1977 
1978 	err = mlx5_modify_vport_admin_state(esw->dev, opmod, vport, other_vport, link_state);
1979 	if (err) {
1980 		mlx5_core_warn(esw->dev, "Failed to set vport %d link state, opmod = %d, err = %d",
1981 			       vport, opmod, err);
1982 		goto unlock;
1983 	}
1984 
1985 	evport->info.link_state = link_state;
1986 
1987 unlock:
1988 	mutex_unlock(&esw->state_lock);
1989 	return err;
1990 }
1991 
mlx5_eswitch_get_vport_config(struct mlx5_eswitch * esw,u16 vport,struct ifla_vf_info * ivi)1992 int mlx5_eswitch_get_vport_config(struct mlx5_eswitch *esw,
1993 				  u16 vport, struct ifla_vf_info *ivi)
1994 {
1995 	struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
1996 
1997 	if (IS_ERR(evport))
1998 		return PTR_ERR(evport);
1999 
2000 	memset(ivi, 0, sizeof(*ivi));
2001 	ivi->vf = vport - 1;
2002 
2003 	mutex_lock(&esw->state_lock);
2004 	ether_addr_copy(ivi->mac, evport->info.mac);
2005 	ivi->linkstate = evport->info.link_state;
2006 	ivi->vlan = evport->info.vlan;
2007 	ivi->qos = evport->info.qos;
2008 	ivi->spoofchk = evport->info.spoofchk;
2009 	ivi->trusted = evport->info.trusted;
2010 	ivi->min_tx_rate = evport->info.min_rate;
2011 	ivi->max_tx_rate = evport->info.max_rate;
2012 	mutex_unlock(&esw->state_lock);
2013 
2014 	return 0;
2015 }
2016 
__mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch * esw,u16 vport,u16 vlan,u8 qos,u8 set_flags)2017 int __mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw,
2018 				  u16 vport, u16 vlan, u8 qos, u8 set_flags)
2019 {
2020 	struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
2021 	int err = 0;
2022 
2023 	if (IS_ERR(evport))
2024 		return PTR_ERR(evport);
2025 	if (vlan > 4095 || qos > 7)
2026 		return -EINVAL;
2027 
2028 	err = modify_esw_vport_cvlan(esw->dev, vport, vlan, qos, set_flags);
2029 	if (err)
2030 		return err;
2031 
2032 	evport->info.vlan = vlan;
2033 	evport->info.qos = qos;
2034 	if (evport->enabled && esw->mode == MLX5_ESWITCH_LEGACY) {
2035 		err = esw_acl_ingress_lgcy_setup(esw, evport);
2036 		if (err)
2037 			return err;
2038 		err = esw_acl_egress_lgcy_setup(esw, evport);
2039 	}
2040 
2041 	return err;
2042 }
2043 
mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch * esw,u16 vport,u16 vlan,u8 qos)2044 int mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw,
2045 				u16 vport, u16 vlan, u8 qos)
2046 {
2047 	u8 set_flags = 0;
2048 	int err;
2049 
2050 	if (!ESW_ALLOWED(esw))
2051 		return -EPERM;
2052 
2053 	if (vlan || qos)
2054 		set_flags = SET_VLAN_STRIP | SET_VLAN_INSERT;
2055 
2056 	mutex_lock(&esw->state_lock);
2057 	err = __mlx5_eswitch_set_vport_vlan(esw, vport, vlan, qos, set_flags);
2058 	mutex_unlock(&esw->state_lock);
2059 
2060 	return err;
2061 }
2062 
mlx5_eswitch_set_vport_spoofchk(struct mlx5_eswitch * esw,u16 vport,bool spoofchk)2063 int mlx5_eswitch_set_vport_spoofchk(struct mlx5_eswitch *esw,
2064 				    u16 vport, bool spoofchk)
2065 {
2066 	struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
2067 	bool pschk;
2068 	int err = 0;
2069 
2070 	if (!ESW_ALLOWED(esw))
2071 		return -EPERM;
2072 	if (IS_ERR(evport))
2073 		return PTR_ERR(evport);
2074 
2075 	mutex_lock(&esw->state_lock);
2076 	pschk = evport->info.spoofchk;
2077 	evport->info.spoofchk = spoofchk;
2078 	if (pschk && !is_valid_ether_addr(evport->info.mac))
2079 		mlx5_core_warn(esw->dev,
2080 			       "Spoofchk in set while MAC is invalid, vport(%d)\n",
2081 			       evport->vport);
2082 	if (evport->enabled && esw->mode == MLX5_ESWITCH_LEGACY)
2083 		err = esw_acl_ingress_lgcy_setup(esw, evport);
2084 	if (err)
2085 		evport->info.spoofchk = pschk;
2086 	mutex_unlock(&esw->state_lock);
2087 
2088 	return err;
2089 }
2090 
esw_cleanup_vepa_rules(struct mlx5_eswitch * esw)2091 static void esw_cleanup_vepa_rules(struct mlx5_eswitch *esw)
2092 {
2093 	if (esw->fdb_table.legacy.vepa_uplink_rule)
2094 		mlx5_del_flow_rules(esw->fdb_table.legacy.vepa_uplink_rule);
2095 
2096 	if (esw->fdb_table.legacy.vepa_star_rule)
2097 		mlx5_del_flow_rules(esw->fdb_table.legacy.vepa_star_rule);
2098 
2099 	esw->fdb_table.legacy.vepa_uplink_rule = NULL;
2100 	esw->fdb_table.legacy.vepa_star_rule = NULL;
2101 }
2102 
_mlx5_eswitch_set_vepa_locked(struct mlx5_eswitch * esw,u8 setting)2103 static int _mlx5_eswitch_set_vepa_locked(struct mlx5_eswitch *esw,
2104 					 u8 setting)
2105 {
2106 	struct mlx5_flow_destination dest = {};
2107 	struct mlx5_flow_act flow_act = {};
2108 	struct mlx5_flow_handle *flow_rule;
2109 	struct mlx5_flow_spec *spec;
2110 	int err = 0;
2111 	void *misc;
2112 
2113 	if (!setting) {
2114 		esw_cleanup_vepa_rules(esw);
2115 		return 0;
2116 	}
2117 
2118 	if (esw->fdb_table.legacy.vepa_uplink_rule)
2119 		return 0;
2120 
2121 	spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
2122 	if (!spec)
2123 		return -ENOMEM;
2124 
2125 	/* Uplink rule forward uplink traffic to FDB */
2126 	misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters);
2127 	MLX5_SET(fte_match_set_misc, misc, source_port, MLX5_VPORT_UPLINK);
2128 
2129 	misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters);
2130 	MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port);
2131 
2132 	spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS;
2133 	dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
2134 	dest.ft = esw->fdb_table.legacy.fdb;
2135 	flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
2136 	flow_rule = mlx5_add_flow_rules(esw->fdb_table.legacy.vepa_fdb, spec,
2137 					&flow_act, &dest, 1);
2138 	if (IS_ERR(flow_rule)) {
2139 		err = PTR_ERR(flow_rule);
2140 		goto out;
2141 	} else {
2142 		esw->fdb_table.legacy.vepa_uplink_rule = flow_rule;
2143 	}
2144 
2145 	/* Star rule to forward all traffic to uplink vport */
2146 	memset(&dest, 0, sizeof(dest));
2147 	dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
2148 	dest.vport.num = MLX5_VPORT_UPLINK;
2149 	flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
2150 	flow_rule = mlx5_add_flow_rules(esw->fdb_table.legacy.vepa_fdb, NULL,
2151 					&flow_act, &dest, 1);
2152 	if (IS_ERR(flow_rule)) {
2153 		err = PTR_ERR(flow_rule);
2154 		goto out;
2155 	} else {
2156 		esw->fdb_table.legacy.vepa_star_rule = flow_rule;
2157 	}
2158 
2159 out:
2160 	kvfree(spec);
2161 	if (err)
2162 		esw_cleanup_vepa_rules(esw);
2163 	return err;
2164 }
2165 
mlx5_eswitch_set_vepa(struct mlx5_eswitch * esw,u8 setting)2166 int mlx5_eswitch_set_vepa(struct mlx5_eswitch *esw, u8 setting)
2167 {
2168 	int err = 0;
2169 
2170 	if (!esw)
2171 		return -EOPNOTSUPP;
2172 
2173 	if (!ESW_ALLOWED(esw))
2174 		return -EPERM;
2175 
2176 	mutex_lock(&esw->state_lock);
2177 	if (esw->mode != MLX5_ESWITCH_LEGACY) {
2178 		err = -EOPNOTSUPP;
2179 		goto out;
2180 	}
2181 
2182 	err = _mlx5_eswitch_set_vepa_locked(esw, setting);
2183 
2184 out:
2185 	mutex_unlock(&esw->state_lock);
2186 	return err;
2187 }
2188 
mlx5_eswitch_get_vepa(struct mlx5_eswitch * esw,u8 * setting)2189 int mlx5_eswitch_get_vepa(struct mlx5_eswitch *esw, u8 *setting)
2190 {
2191 	if (!esw)
2192 		return -EOPNOTSUPP;
2193 
2194 	if (!ESW_ALLOWED(esw))
2195 		return -EPERM;
2196 
2197 	if (esw->mode != MLX5_ESWITCH_LEGACY)
2198 		return -EOPNOTSUPP;
2199 
2200 	*setting = esw->fdb_table.legacy.vepa_uplink_rule ? 1 : 0;
2201 	return 0;
2202 }
2203 
mlx5_eswitch_set_vport_trust(struct mlx5_eswitch * esw,u16 vport,bool setting)2204 int mlx5_eswitch_set_vport_trust(struct mlx5_eswitch *esw,
2205 				 u16 vport, bool setting)
2206 {
2207 	struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
2208 
2209 	if (!ESW_ALLOWED(esw))
2210 		return -EPERM;
2211 	if (IS_ERR(evport))
2212 		return PTR_ERR(evport);
2213 
2214 	mutex_lock(&esw->state_lock);
2215 	evport->info.trusted = setting;
2216 	if (evport->enabled)
2217 		esw_vport_change_handle_locked(evport);
2218 	mutex_unlock(&esw->state_lock);
2219 
2220 	return 0;
2221 }
2222 
calculate_vports_min_rate_divider(struct mlx5_eswitch * esw)2223 static u32 calculate_vports_min_rate_divider(struct mlx5_eswitch *esw)
2224 {
2225 	u32 fw_max_bw_share = MLX5_CAP_QOS(esw->dev, max_tsar_bw_share);
2226 	struct mlx5_vport *evport;
2227 	u32 max_guarantee = 0;
2228 	int i;
2229 
2230 	mlx5_esw_for_all_vports(esw, i, evport) {
2231 		if (!evport->enabled || evport->info.min_rate < max_guarantee)
2232 			continue;
2233 		max_guarantee = evport->info.min_rate;
2234 	}
2235 
2236 	if (max_guarantee)
2237 		return max_t(u32, max_guarantee / fw_max_bw_share, 1);
2238 	return 0;
2239 }
2240 
normalize_vports_min_rate(struct mlx5_eswitch * esw)2241 static int normalize_vports_min_rate(struct mlx5_eswitch *esw)
2242 {
2243 	u32 fw_max_bw_share = MLX5_CAP_QOS(esw->dev, max_tsar_bw_share);
2244 	u32 divider = calculate_vports_min_rate_divider(esw);
2245 	struct mlx5_vport *evport;
2246 	u32 vport_max_rate;
2247 	u32 vport_min_rate;
2248 	u32 bw_share;
2249 	int err;
2250 	int i;
2251 
2252 	mlx5_esw_for_all_vports(esw, i, evport) {
2253 		if (!evport->enabled)
2254 			continue;
2255 		vport_min_rate = evport->info.min_rate;
2256 		vport_max_rate = evport->info.max_rate;
2257 		bw_share = 0;
2258 
2259 		if (divider)
2260 			bw_share = MLX5_RATE_TO_BW_SHARE(vport_min_rate,
2261 							 divider,
2262 							 fw_max_bw_share);
2263 
2264 		if (bw_share == evport->qos.bw_share)
2265 			continue;
2266 
2267 		err = esw_vport_qos_config(esw, evport, vport_max_rate,
2268 					   bw_share);
2269 		if (!err)
2270 			evport->qos.bw_share = bw_share;
2271 		else
2272 			return err;
2273 	}
2274 
2275 	return 0;
2276 }
2277 
mlx5_eswitch_set_vport_rate(struct mlx5_eswitch * esw,u16 vport,u32 max_rate,u32 min_rate)2278 int mlx5_eswitch_set_vport_rate(struct mlx5_eswitch *esw, u16 vport,
2279 				u32 max_rate, u32 min_rate)
2280 {
2281 	struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
2282 	u32 fw_max_bw_share;
2283 	u32 previous_min_rate;
2284 	bool min_rate_supported;
2285 	bool max_rate_supported;
2286 	int err = 0;
2287 
2288 	if (!ESW_ALLOWED(esw))
2289 		return -EPERM;
2290 	if (IS_ERR(evport))
2291 		return PTR_ERR(evport);
2292 
2293 	fw_max_bw_share = MLX5_CAP_QOS(esw->dev, max_tsar_bw_share);
2294 	min_rate_supported = MLX5_CAP_QOS(esw->dev, esw_bw_share) &&
2295 				fw_max_bw_share >= MLX5_MIN_BW_SHARE;
2296 	max_rate_supported = MLX5_CAP_QOS(esw->dev, esw_rate_limit);
2297 
2298 	if ((min_rate && !min_rate_supported) || (max_rate && !max_rate_supported))
2299 		return -EOPNOTSUPP;
2300 
2301 	mutex_lock(&esw->state_lock);
2302 
2303 	if (min_rate == evport->info.min_rate)
2304 		goto set_max_rate;
2305 
2306 	previous_min_rate = evport->info.min_rate;
2307 	evport->info.min_rate = min_rate;
2308 	err = normalize_vports_min_rate(esw);
2309 	if (err) {
2310 		evport->info.min_rate = previous_min_rate;
2311 		goto unlock;
2312 	}
2313 
2314 set_max_rate:
2315 	if (max_rate == evport->info.max_rate)
2316 		goto unlock;
2317 
2318 	err = esw_vport_qos_config(esw, evport, max_rate, evport->qos.bw_share);
2319 	if (!err)
2320 		evport->info.max_rate = max_rate;
2321 
2322 unlock:
2323 	mutex_unlock(&esw->state_lock);
2324 	return err;
2325 }
2326 
mlx5_eswitch_query_vport_drop_stats(struct mlx5_core_dev * dev,struct mlx5_vport * vport,struct mlx5_vport_drop_stats * stats)2327 static int mlx5_eswitch_query_vport_drop_stats(struct mlx5_core_dev *dev,
2328 					       struct mlx5_vport *vport,
2329 					       struct mlx5_vport_drop_stats *stats)
2330 {
2331 	struct mlx5_eswitch *esw = dev->priv.eswitch;
2332 	u64 rx_discard_vport_down, tx_discard_vport_down;
2333 	u64 bytes = 0;
2334 	int err = 0;
2335 
2336 	if (esw->mode != MLX5_ESWITCH_LEGACY)
2337 		return 0;
2338 
2339 	mutex_lock(&esw->state_lock);
2340 	if (!vport->enabled)
2341 		goto unlock;
2342 
2343 	if (!IS_ERR_OR_NULL(vport->egress.legacy.drop_counter))
2344 		mlx5_fc_query(dev, vport->egress.legacy.drop_counter,
2345 			      &stats->rx_dropped, &bytes);
2346 
2347 	if (vport->ingress.legacy.drop_counter)
2348 		mlx5_fc_query(dev, vport->ingress.legacy.drop_counter,
2349 			      &stats->tx_dropped, &bytes);
2350 
2351 	if (!MLX5_CAP_GEN(dev, receive_discard_vport_down) &&
2352 	    !MLX5_CAP_GEN(dev, transmit_discard_vport_down))
2353 		goto unlock;
2354 
2355 	err = mlx5_query_vport_down_stats(dev, vport->vport, 1,
2356 					  &rx_discard_vport_down,
2357 					  &tx_discard_vport_down);
2358 	if (err)
2359 		goto unlock;
2360 
2361 	if (MLX5_CAP_GEN(dev, receive_discard_vport_down))
2362 		stats->rx_dropped += rx_discard_vport_down;
2363 	if (MLX5_CAP_GEN(dev, transmit_discard_vport_down))
2364 		stats->tx_dropped += tx_discard_vport_down;
2365 
2366 unlock:
2367 	mutex_unlock(&esw->state_lock);
2368 	return err;
2369 }
2370 
mlx5_eswitch_get_vport_stats(struct mlx5_eswitch * esw,u16 vport_num,struct ifla_vf_stats * vf_stats)2371 int mlx5_eswitch_get_vport_stats(struct mlx5_eswitch *esw,
2372 				 u16 vport_num,
2373 				 struct ifla_vf_stats *vf_stats)
2374 {
2375 	struct mlx5_vport *vport = mlx5_eswitch_get_vport(esw, vport_num);
2376 	int outlen = MLX5_ST_SZ_BYTES(query_vport_counter_out);
2377 	u32 in[MLX5_ST_SZ_DW(query_vport_counter_in)] = {};
2378 	struct mlx5_vport_drop_stats stats = {};
2379 	int err = 0;
2380 	u32 *out;
2381 
2382 	if (IS_ERR(vport))
2383 		return PTR_ERR(vport);
2384 
2385 	out = kvzalloc(outlen, GFP_KERNEL);
2386 	if (!out)
2387 		return -ENOMEM;
2388 
2389 	MLX5_SET(query_vport_counter_in, in, opcode,
2390 		 MLX5_CMD_OP_QUERY_VPORT_COUNTER);
2391 	MLX5_SET(query_vport_counter_in, in, op_mod, 0);
2392 	MLX5_SET(query_vport_counter_in, in, vport_number, vport->vport);
2393 	MLX5_SET(query_vport_counter_in, in, other_vport, 1);
2394 
2395 	err = mlx5_cmd_exec_inout(esw->dev, query_vport_counter, in, out);
2396 	if (err)
2397 		goto free_out;
2398 
2399 	#define MLX5_GET_CTR(p, x) \
2400 		MLX5_GET64(query_vport_counter_out, p, x)
2401 
2402 	memset(vf_stats, 0, sizeof(*vf_stats));
2403 	vf_stats->rx_packets =
2404 		MLX5_GET_CTR(out, received_eth_unicast.packets) +
2405 		MLX5_GET_CTR(out, received_ib_unicast.packets) +
2406 		MLX5_GET_CTR(out, received_eth_multicast.packets) +
2407 		MLX5_GET_CTR(out, received_ib_multicast.packets) +
2408 		MLX5_GET_CTR(out, received_eth_broadcast.packets);
2409 
2410 	vf_stats->rx_bytes =
2411 		MLX5_GET_CTR(out, received_eth_unicast.octets) +
2412 		MLX5_GET_CTR(out, received_ib_unicast.octets) +
2413 		MLX5_GET_CTR(out, received_eth_multicast.octets) +
2414 		MLX5_GET_CTR(out, received_ib_multicast.octets) +
2415 		MLX5_GET_CTR(out, received_eth_broadcast.octets);
2416 
2417 	vf_stats->tx_packets =
2418 		MLX5_GET_CTR(out, transmitted_eth_unicast.packets) +
2419 		MLX5_GET_CTR(out, transmitted_ib_unicast.packets) +
2420 		MLX5_GET_CTR(out, transmitted_eth_multicast.packets) +
2421 		MLX5_GET_CTR(out, transmitted_ib_multicast.packets) +
2422 		MLX5_GET_CTR(out, transmitted_eth_broadcast.packets);
2423 
2424 	vf_stats->tx_bytes =
2425 		MLX5_GET_CTR(out, transmitted_eth_unicast.octets) +
2426 		MLX5_GET_CTR(out, transmitted_ib_unicast.octets) +
2427 		MLX5_GET_CTR(out, transmitted_eth_multicast.octets) +
2428 		MLX5_GET_CTR(out, transmitted_ib_multicast.octets) +
2429 		MLX5_GET_CTR(out, transmitted_eth_broadcast.octets);
2430 
2431 	vf_stats->multicast =
2432 		MLX5_GET_CTR(out, received_eth_multicast.packets) +
2433 		MLX5_GET_CTR(out, received_ib_multicast.packets);
2434 
2435 	vf_stats->broadcast =
2436 		MLX5_GET_CTR(out, received_eth_broadcast.packets);
2437 
2438 	err = mlx5_eswitch_query_vport_drop_stats(esw->dev, vport, &stats);
2439 	if (err)
2440 		goto free_out;
2441 	vf_stats->rx_dropped = stats.rx_dropped;
2442 	vf_stats->tx_dropped = stats.tx_dropped;
2443 
2444 free_out:
2445 	kvfree(out);
2446 	return err;
2447 }
2448 
mlx5_eswitch_mode(struct mlx5_eswitch * esw)2449 u8 mlx5_eswitch_mode(struct mlx5_eswitch *esw)
2450 {
2451 	return ESW_ALLOWED(esw) ? esw->mode : MLX5_ESWITCH_NONE;
2452 }
2453 EXPORT_SYMBOL_GPL(mlx5_eswitch_mode);
2454 
2455 enum devlink_eswitch_encap_mode
mlx5_eswitch_get_encap_mode(const struct mlx5_core_dev * dev)2456 mlx5_eswitch_get_encap_mode(const struct mlx5_core_dev *dev)
2457 {
2458 	struct mlx5_eswitch *esw;
2459 
2460 	esw = dev->priv.eswitch;
2461 	return ESW_ALLOWED(esw) ? esw->offloads.encap :
2462 		DEVLINK_ESWITCH_ENCAP_MODE_NONE;
2463 }
2464 EXPORT_SYMBOL(mlx5_eswitch_get_encap_mode);
2465 
mlx5_esw_lag_prereq(struct mlx5_core_dev * dev0,struct mlx5_core_dev * dev1)2466 bool mlx5_esw_lag_prereq(struct mlx5_core_dev *dev0, struct mlx5_core_dev *dev1)
2467 {
2468 	if ((dev0->priv.eswitch->mode == MLX5_ESWITCH_NONE &&
2469 	     dev1->priv.eswitch->mode == MLX5_ESWITCH_NONE) ||
2470 	    (dev0->priv.eswitch->mode == MLX5_ESWITCH_OFFLOADS &&
2471 	     dev1->priv.eswitch->mode == MLX5_ESWITCH_OFFLOADS))
2472 		return true;
2473 
2474 	return false;
2475 }
2476 
mlx5_esw_multipath_prereq(struct mlx5_core_dev * dev0,struct mlx5_core_dev * dev1)2477 bool mlx5_esw_multipath_prereq(struct mlx5_core_dev *dev0,
2478 			       struct mlx5_core_dev *dev1)
2479 {
2480 	return (dev0->priv.eswitch->mode == MLX5_ESWITCH_OFFLOADS &&
2481 		dev1->priv.eswitch->mode == MLX5_ESWITCH_OFFLOADS);
2482 }
2483 
2484 
2485