1b55b3538SParav Pandit // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2b55b3538SParav Pandit /* Copyright (c) 2021 Mellanox Technologies Ltd */
3b55b3538SParav Pandit 
4b55b3538SParav Pandit #include <linux/etherdevice.h>
5b55b3538SParav Pandit #include <linux/mlx5/driver.h>
6b55b3538SParav Pandit #include <linux/mlx5/mlx5_ifc.h>
7b55b3538SParav Pandit #include <linux/mlx5/vport.h>
8b55b3538SParav Pandit #include <linux/mlx5/fs.h>
9b55b3538SParav Pandit #include "esw/acl/lgcy.h"
10b55b3538SParav Pandit #include "esw/legacy.h"
11b55b3538SParav Pandit #include "mlx5_core.h"
12b55b3538SParav Pandit #include "eswitch.h"
13b55b3538SParav Pandit #include "fs_core.h"
140c9d8765SPaul Blakey #include "fs_ft_pool.h"
152d116e3eSDmytro Linkin #include "esw/qos.h"
16b55b3538SParav Pandit 
17b55b3538SParav Pandit enum {
18b55b3538SParav Pandit 	LEGACY_VEPA_PRIO = 0,
19b55b3538SParav Pandit 	LEGACY_FDB_PRIO,
20b55b3538SParav Pandit };
21b55b3538SParav Pandit 
esw_create_legacy_vepa_table(struct mlx5_eswitch * esw)22b55b3538SParav Pandit static int esw_create_legacy_vepa_table(struct mlx5_eswitch *esw)
23b55b3538SParav Pandit {
24b55b3538SParav Pandit 	struct mlx5_flow_table_attr ft_attr = {};
25b55b3538SParav Pandit 	struct mlx5_core_dev *dev = esw->dev;
26b55b3538SParav Pandit 	struct mlx5_flow_namespace *root_ns;
27b55b3538SParav Pandit 	struct mlx5_flow_table *fdb;
28b55b3538SParav Pandit 	int err;
29b55b3538SParav Pandit 
30b55b3538SParav Pandit 	root_ns = mlx5_get_fdb_sub_ns(dev, 0);
31b55b3538SParav Pandit 	if (!root_ns) {
32b55b3538SParav Pandit 		esw_warn(dev, "Failed to get FDB flow namespace\n");
33b55b3538SParav Pandit 		return -EOPNOTSUPP;
34b55b3538SParav Pandit 	}
35b55b3538SParav Pandit 
36b55b3538SParav Pandit 	/* num FTE 2, num FG 2 */
37b55b3538SParav Pandit 	ft_attr.prio = LEGACY_VEPA_PRIO;
38b55b3538SParav Pandit 	ft_attr.max_fte = 2;
39b55b3538SParav Pandit 	ft_attr.autogroup.max_num_groups = 2;
40b55b3538SParav Pandit 	fdb = mlx5_create_auto_grouped_flow_table(root_ns, &ft_attr);
41b55b3538SParav Pandit 	if (IS_ERR(fdb)) {
42b55b3538SParav Pandit 		err = PTR_ERR(fdb);
43b55b3538SParav Pandit 		esw_warn(dev, "Failed to create VEPA FDB err %d\n", err);
44b55b3538SParav Pandit 		return err;
45b55b3538SParav Pandit 	}
46b55b3538SParav Pandit 	esw->fdb_table.legacy.vepa_fdb = fdb;
47b55b3538SParav Pandit 
48b55b3538SParav Pandit 	return 0;
49b55b3538SParav Pandit }
50b55b3538SParav Pandit 
esw_destroy_legacy_fdb_table(struct mlx5_eswitch * esw)51b55b3538SParav Pandit static void esw_destroy_legacy_fdb_table(struct mlx5_eswitch *esw)
52b55b3538SParav Pandit {
53b55b3538SParav Pandit 	esw_debug(esw->dev, "Destroy FDB Table\n");
54b55b3538SParav Pandit 	if (!esw->fdb_table.legacy.fdb)
55b55b3538SParav Pandit 		return;
56b55b3538SParav Pandit 
57b55b3538SParav Pandit 	if (esw->fdb_table.legacy.promisc_grp)
58b55b3538SParav Pandit 		mlx5_destroy_flow_group(esw->fdb_table.legacy.promisc_grp);
59b55b3538SParav Pandit 	if (esw->fdb_table.legacy.allmulti_grp)
60b55b3538SParav Pandit 		mlx5_destroy_flow_group(esw->fdb_table.legacy.allmulti_grp);
61b55b3538SParav Pandit 	if (esw->fdb_table.legacy.addr_grp)
62b55b3538SParav Pandit 		mlx5_destroy_flow_group(esw->fdb_table.legacy.addr_grp);
63b55b3538SParav Pandit 	mlx5_destroy_flow_table(esw->fdb_table.legacy.fdb);
64b55b3538SParav Pandit 
65b55b3538SParav Pandit 	esw->fdb_table.legacy.fdb = NULL;
66b55b3538SParav Pandit 	esw->fdb_table.legacy.addr_grp = NULL;
67b55b3538SParav Pandit 	esw->fdb_table.legacy.allmulti_grp = NULL;
68b55b3538SParav Pandit 	esw->fdb_table.legacy.promisc_grp = NULL;
69b55b3538SParav Pandit 	atomic64_set(&esw->user_count, 0);
70b55b3538SParav Pandit }
71b55b3538SParav Pandit 
esw_create_legacy_fdb_table(struct mlx5_eswitch * esw)72b55b3538SParav Pandit static int esw_create_legacy_fdb_table(struct mlx5_eswitch *esw)
73b55b3538SParav Pandit {
74b55b3538SParav Pandit 	int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
75b55b3538SParav Pandit 	struct mlx5_flow_table_attr ft_attr = {};
76b55b3538SParav Pandit 	struct mlx5_core_dev *dev = esw->dev;
77b55b3538SParav Pandit 	struct mlx5_flow_namespace *root_ns;
78b55b3538SParav Pandit 	struct mlx5_flow_table *fdb;
79b55b3538SParav Pandit 	struct mlx5_flow_group *g;
80b55b3538SParav Pandit 	void *match_criteria;
81b55b3538SParav Pandit 	int table_size;
82b55b3538SParav Pandit 	u32 *flow_group_in;
83b55b3538SParav Pandit 	u8 *dmac;
84b55b3538SParav Pandit 	int err = 0;
85b55b3538SParav Pandit 
86b55b3538SParav Pandit 	esw_debug(dev, "Create FDB log_max_size(%d)\n",
87b55b3538SParav Pandit 		  MLX5_CAP_ESW_FLOWTABLE_FDB(dev, log_max_ft_size));
88b55b3538SParav Pandit 
89b55b3538SParav Pandit 	root_ns = mlx5_get_fdb_sub_ns(dev, 0);
90b55b3538SParav Pandit 	if (!root_ns) {
91b55b3538SParav Pandit 		esw_warn(dev, "Failed to get FDB flow namespace\n");
92b55b3538SParav Pandit 		return -EOPNOTSUPP;
93b55b3538SParav Pandit 	}
94b55b3538SParav Pandit 
95b55b3538SParav Pandit 	flow_group_in = kvzalloc(inlen, GFP_KERNEL);
96b55b3538SParav Pandit 	if (!flow_group_in)
97b55b3538SParav Pandit 		return -ENOMEM;
98b55b3538SParav Pandit 
990c9d8765SPaul Blakey 	ft_attr.max_fte = POOL_NEXT_SIZE;
100b55b3538SParav Pandit 	ft_attr.prio = LEGACY_FDB_PRIO;
101b55b3538SParav Pandit 	fdb = mlx5_create_flow_table(root_ns, &ft_attr);
102b55b3538SParav Pandit 	if (IS_ERR(fdb)) {
103b55b3538SParav Pandit 		err = PTR_ERR(fdb);
104b55b3538SParav Pandit 		esw_warn(dev, "Failed to create FDB Table err %d\n", err);
105b55b3538SParav Pandit 		goto out;
106b55b3538SParav Pandit 	}
107b55b3538SParav Pandit 	esw->fdb_table.legacy.fdb = fdb;
1080c9d8765SPaul Blakey 	table_size = fdb->max_fte;
109b55b3538SParav Pandit 
110b55b3538SParav Pandit 	/* Addresses group : Full match unicast/multicast addresses */
111b55b3538SParav Pandit 	MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
112b55b3538SParav Pandit 		 MLX5_MATCH_OUTER_HEADERS);
113b55b3538SParav Pandit 	match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in, match_criteria);
114b55b3538SParav Pandit 	dmac = MLX5_ADDR_OF(fte_match_param, match_criteria, outer_headers.dmac_47_16);
115b55b3538SParav Pandit 	MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 0);
116b55b3538SParav Pandit 	/* Preserve 2 entries for allmulti and promisc rules*/
117b55b3538SParav Pandit 	MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, table_size - 3);
118b55b3538SParav Pandit 	eth_broadcast_addr(dmac);
119b55b3538SParav Pandit 	g = mlx5_create_flow_group(fdb, flow_group_in);
120b55b3538SParav Pandit 	if (IS_ERR(g)) {
121b55b3538SParav Pandit 		err = PTR_ERR(g);
122b55b3538SParav Pandit 		esw_warn(dev, "Failed to create flow group err(%d)\n", err);
123b55b3538SParav Pandit 		goto out;
124b55b3538SParav Pandit 	}
125b55b3538SParav Pandit 	esw->fdb_table.legacy.addr_grp = g;
126b55b3538SParav Pandit 
127b55b3538SParav Pandit 	/* Allmulti group : One rule that forwards any mcast traffic */
128b55b3538SParav Pandit 	MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
129b55b3538SParav Pandit 		 MLX5_MATCH_OUTER_HEADERS);
130b55b3538SParav Pandit 	MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, table_size - 2);
131b55b3538SParav Pandit 	MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, table_size - 2);
132b55b3538SParav Pandit 	eth_zero_addr(dmac);
133b55b3538SParav Pandit 	dmac[0] = 0x01;
134b55b3538SParav Pandit 	g = mlx5_create_flow_group(fdb, flow_group_in);
135b55b3538SParav Pandit 	if (IS_ERR(g)) {
136b55b3538SParav Pandit 		err = PTR_ERR(g);
137b55b3538SParav Pandit 		esw_warn(dev, "Failed to create allmulti flow group err(%d)\n", err);
138b55b3538SParav Pandit 		goto out;
139b55b3538SParav Pandit 	}
140b55b3538SParav Pandit 	esw->fdb_table.legacy.allmulti_grp = g;
141b55b3538SParav Pandit 
142b55b3538SParav Pandit 	/* Promiscuous group :
143b55b3538SParav Pandit 	 * One rule that forward all unmatched traffic from previous groups
144b55b3538SParav Pandit 	 */
145b55b3538SParav Pandit 	eth_zero_addr(dmac);
146b55b3538SParav Pandit 	MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
147b55b3538SParav Pandit 		 MLX5_MATCH_MISC_PARAMETERS);
148b55b3538SParav Pandit 	MLX5_SET_TO_ONES(fte_match_param, match_criteria, misc_parameters.source_port);
149b55b3538SParav Pandit 	MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, table_size - 1);
150b55b3538SParav Pandit 	MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, table_size - 1);
151b55b3538SParav Pandit 	g = mlx5_create_flow_group(fdb, flow_group_in);
152b55b3538SParav Pandit 	if (IS_ERR(g)) {
153b55b3538SParav Pandit 		err = PTR_ERR(g);
154b55b3538SParav Pandit 		esw_warn(dev, "Failed to create promisc flow group err(%d)\n", err);
155b55b3538SParav Pandit 		goto out;
156b55b3538SParav Pandit 	}
157b55b3538SParav Pandit 	esw->fdb_table.legacy.promisc_grp = g;
158b55b3538SParav Pandit 
159b55b3538SParav Pandit out:
160b55b3538SParav Pandit 	if (err)
161b55b3538SParav Pandit 		esw_destroy_legacy_fdb_table(esw);
162b55b3538SParav Pandit 
163b55b3538SParav Pandit 	kvfree(flow_group_in);
164b55b3538SParav Pandit 	return err;
165b55b3538SParav Pandit }
166b55b3538SParav Pandit 
esw_destroy_legacy_vepa_table(struct mlx5_eswitch * esw)167b55b3538SParav Pandit static void esw_destroy_legacy_vepa_table(struct mlx5_eswitch *esw)
168b55b3538SParav Pandit {
169b55b3538SParav Pandit 	esw_debug(esw->dev, "Destroy VEPA Table\n");
170b55b3538SParav Pandit 	if (!esw->fdb_table.legacy.vepa_fdb)
171b55b3538SParav Pandit 		return;
172b55b3538SParav Pandit 
173b55b3538SParav Pandit 	mlx5_destroy_flow_table(esw->fdb_table.legacy.vepa_fdb);
174b55b3538SParav Pandit 	esw->fdb_table.legacy.vepa_fdb = NULL;
175b55b3538SParav Pandit }
176b55b3538SParav Pandit 
esw_create_legacy_table(struct mlx5_eswitch * esw)177b55b3538SParav Pandit static int esw_create_legacy_table(struct mlx5_eswitch *esw)
178b55b3538SParav Pandit {
179b55b3538SParav Pandit 	int err;
180b55b3538SParav Pandit 
181b55b3538SParav Pandit 	memset(&esw->fdb_table.legacy, 0, sizeof(struct legacy_fdb));
182b55b3538SParav Pandit 	atomic64_set(&esw->user_count, 0);
183b55b3538SParav Pandit 
184b55b3538SParav Pandit 	err = esw_create_legacy_vepa_table(esw);
185b55b3538SParav Pandit 	if (err)
186b55b3538SParav Pandit 		return err;
187b55b3538SParav Pandit 
188b55b3538SParav Pandit 	err = esw_create_legacy_fdb_table(esw);
189b55b3538SParav Pandit 	if (err)
190b55b3538SParav Pandit 		esw_destroy_legacy_vepa_table(esw);
191b55b3538SParav Pandit 
192b55b3538SParav Pandit 	return err;
193b55b3538SParav Pandit }
194b55b3538SParav Pandit 
esw_cleanup_vepa_rules(struct mlx5_eswitch * esw)195b55b3538SParav Pandit static void esw_cleanup_vepa_rules(struct mlx5_eswitch *esw)
196b55b3538SParav Pandit {
197b55b3538SParav Pandit 	if (esw->fdb_table.legacy.vepa_uplink_rule)
198b55b3538SParav Pandit 		mlx5_del_flow_rules(esw->fdb_table.legacy.vepa_uplink_rule);
199b55b3538SParav Pandit 
200b55b3538SParav Pandit 	if (esw->fdb_table.legacy.vepa_star_rule)
201b55b3538SParav Pandit 		mlx5_del_flow_rules(esw->fdb_table.legacy.vepa_star_rule);
202b55b3538SParav Pandit 
203b55b3538SParav Pandit 	esw->fdb_table.legacy.vepa_uplink_rule = NULL;
204b55b3538SParav Pandit 	esw->fdb_table.legacy.vepa_star_rule = NULL;
205b55b3538SParav Pandit }
206b55b3538SParav Pandit 
esw_destroy_legacy_table(struct mlx5_eswitch * esw)207b55b3538SParav Pandit static void esw_destroy_legacy_table(struct mlx5_eswitch *esw)
208b55b3538SParav Pandit {
209b55b3538SParav Pandit 	esw_cleanup_vepa_rules(esw);
210b55b3538SParav Pandit 	esw_destroy_legacy_fdb_table(esw);
211b55b3538SParav Pandit 	esw_destroy_legacy_vepa_table(esw);
212b55b3538SParav Pandit }
213b55b3538SParav Pandit 
214b55b3538SParav Pandit #define MLX5_LEGACY_SRIOV_VPORT_EVENTS (MLX5_VPORT_UC_ADDR_CHANGE | \
215b55b3538SParav Pandit 					MLX5_VPORT_MC_ADDR_CHANGE | \
216b55b3538SParav Pandit 					MLX5_VPORT_PROMISC_CHANGE)
217b55b3538SParav Pandit 
esw_legacy_enable(struct mlx5_eswitch * esw)218b55b3538SParav Pandit int esw_legacy_enable(struct mlx5_eswitch *esw)
219b55b3538SParav Pandit {
220b55b3538SParav Pandit 	struct mlx5_vport *vport;
22147dd7e60SParav Pandit 	unsigned long i;
22247dd7e60SParav Pandit 	int ret;
223b55b3538SParav Pandit 
224b55b3538SParav Pandit 	ret = esw_create_legacy_table(esw);
225b55b3538SParav Pandit 	if (ret)
226b55b3538SParav Pandit 		return ret;
227b55b3538SParav Pandit 
228b55b3538SParav Pandit 	mlx5_esw_for_each_vf_vport(esw, i, vport, esw->esw_funcs.num_vfs)
229b55b3538SParav Pandit 		vport->info.link_state = MLX5_VPORT_ADMIN_STATE_AUTO;
230b55b3538SParav Pandit 
231b55b3538SParav Pandit 	ret = mlx5_eswitch_enable_pf_vf_vports(esw, MLX5_LEGACY_SRIOV_VPORT_EVENTS);
232b55b3538SParav Pandit 	if (ret)
233b55b3538SParav Pandit 		esw_destroy_legacy_table(esw);
234b55b3538SParav Pandit 	return ret;
235b55b3538SParav Pandit }
236b55b3538SParav Pandit 
esw_legacy_disable(struct mlx5_eswitch * esw)237b55b3538SParav Pandit void esw_legacy_disable(struct mlx5_eswitch *esw)
238b55b3538SParav Pandit {
239b55b3538SParav Pandit 	struct esw_mc_addr *mc_promisc;
240b55b3538SParav Pandit 
241b55b3538SParav Pandit 	mlx5_eswitch_disable_pf_vf_vports(esw);
242b55b3538SParav Pandit 
243b55b3538SParav Pandit 	mc_promisc = &esw->mc_promisc;
244b55b3538SParav Pandit 	if (mc_promisc->uplink_rule)
245b55b3538SParav Pandit 		mlx5_del_flow_rules(mc_promisc->uplink_rule);
246b55b3538SParav Pandit 
247b55b3538SParav Pandit 	esw_destroy_legacy_table(esw);
248b55b3538SParav Pandit }
249b55b3538SParav Pandit 
_mlx5_eswitch_set_vepa_locked(struct mlx5_eswitch * esw,u8 setting)250b55b3538SParav Pandit static int _mlx5_eswitch_set_vepa_locked(struct mlx5_eswitch *esw,
251b55b3538SParav Pandit 					 u8 setting)
252b55b3538SParav Pandit {
253b55b3538SParav Pandit 	struct mlx5_flow_destination dest = {};
254b55b3538SParav Pandit 	struct mlx5_flow_act flow_act = {};
255b55b3538SParav Pandit 	struct mlx5_flow_handle *flow_rule;
256b55b3538SParav Pandit 	struct mlx5_flow_spec *spec;
257b55b3538SParav Pandit 	int err = 0;
258b55b3538SParav Pandit 	void *misc;
259b55b3538SParav Pandit 
260b55b3538SParav Pandit 	if (!setting) {
261b55b3538SParav Pandit 		esw_cleanup_vepa_rules(esw);
262b55b3538SParav Pandit 		return 0;
263b55b3538SParav Pandit 	}
264b55b3538SParav Pandit 
265b55b3538SParav Pandit 	if (esw->fdb_table.legacy.vepa_uplink_rule)
266b55b3538SParav Pandit 		return 0;
267b55b3538SParav Pandit 
268b55b3538SParav Pandit 	spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
269b55b3538SParav Pandit 	if (!spec)
270b55b3538SParav Pandit 		return -ENOMEM;
271b55b3538SParav Pandit 
272b55b3538SParav Pandit 	/* Uplink rule forward uplink traffic to FDB */
273b55b3538SParav Pandit 	misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters);
274b55b3538SParav Pandit 	MLX5_SET(fte_match_set_misc, misc, source_port, MLX5_VPORT_UPLINK);
275b55b3538SParav Pandit 
276b55b3538SParav Pandit 	misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters);
277b55b3538SParav Pandit 	MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port);
278b55b3538SParav Pandit 
279b55b3538SParav Pandit 	spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS;
280b55b3538SParav Pandit 	dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
281b55b3538SParav Pandit 	dest.ft = esw->fdb_table.legacy.fdb;
282b55b3538SParav Pandit 	flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
283b55b3538SParav Pandit 	flow_rule = mlx5_add_flow_rules(esw->fdb_table.legacy.vepa_fdb, spec,
284b55b3538SParav Pandit 					&flow_act, &dest, 1);
285b55b3538SParav Pandit 	if (IS_ERR(flow_rule)) {
286b55b3538SParav Pandit 		err = PTR_ERR(flow_rule);
287b55b3538SParav Pandit 		goto out;
288b55b3538SParav Pandit 	}
289*8a955da2SSaeed Mahameed 	esw->fdb_table.legacy.vepa_uplink_rule = flow_rule;
290b55b3538SParav Pandit 
291b55b3538SParav Pandit 	/* Star rule to forward all traffic to uplink vport */
292b55b3538SParav Pandit 	memset(&dest, 0, sizeof(dest));
293b55b3538SParav Pandit 	dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
294b55b3538SParav Pandit 	dest.vport.num = MLX5_VPORT_UPLINK;
295b55b3538SParav Pandit 	flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
296b55b3538SParav Pandit 	flow_rule = mlx5_add_flow_rules(esw->fdb_table.legacy.vepa_fdb, NULL,
297b55b3538SParav Pandit 					&flow_act, &dest, 1);
298b55b3538SParav Pandit 	if (IS_ERR(flow_rule)) {
299b55b3538SParav Pandit 		err = PTR_ERR(flow_rule);
300b55b3538SParav Pandit 		goto out;
301b55b3538SParav Pandit 	}
302*8a955da2SSaeed Mahameed 	esw->fdb_table.legacy.vepa_star_rule = flow_rule;
303b55b3538SParav Pandit 
304b55b3538SParav Pandit out:
305b55b3538SParav Pandit 	kvfree(spec);
306b55b3538SParav Pandit 	if (err)
307b55b3538SParav Pandit 		esw_cleanup_vepa_rules(esw);
308b55b3538SParav Pandit 	return err;
309b55b3538SParav Pandit }
310b55b3538SParav Pandit 
mlx5_eswitch_set_vepa(struct mlx5_eswitch * esw,u8 setting)311b55b3538SParav Pandit int mlx5_eswitch_set_vepa(struct mlx5_eswitch *esw, u8 setting)
312b55b3538SParav Pandit {
313b55b3538SParav Pandit 	int err = 0;
314b55b3538SParav Pandit 
315b55b3538SParav Pandit 	if (!esw)
316b55b3538SParav Pandit 		return -EOPNOTSUPP;
317b55b3538SParav Pandit 
318b55b3538SParav Pandit 	if (!mlx5_esw_allowed(esw))
319b55b3538SParav Pandit 		return -EPERM;
320b55b3538SParav Pandit 
321b55b3538SParav Pandit 	mutex_lock(&esw->state_lock);
322b55b3538SParav Pandit 	if (esw->mode != MLX5_ESWITCH_LEGACY) {
323b55b3538SParav Pandit 		err = -EOPNOTSUPP;
324b55b3538SParav Pandit 		goto out;
325b55b3538SParav Pandit 	}
326b55b3538SParav Pandit 
327b55b3538SParav Pandit 	err = _mlx5_eswitch_set_vepa_locked(esw, setting);
328b55b3538SParav Pandit 
329b55b3538SParav Pandit out:
330b55b3538SParav Pandit 	mutex_unlock(&esw->state_lock);
331b55b3538SParav Pandit 	return err;
332b55b3538SParav Pandit }
333b55b3538SParav Pandit 
mlx5_eswitch_get_vepa(struct mlx5_eswitch * esw,u8 * setting)334b55b3538SParav Pandit int mlx5_eswitch_get_vepa(struct mlx5_eswitch *esw, u8 *setting)
335b55b3538SParav Pandit {
336b55b3538SParav Pandit 	if (!esw)
337b55b3538SParav Pandit 		return -EOPNOTSUPP;
338b55b3538SParav Pandit 
339b55b3538SParav Pandit 	if (!mlx5_esw_allowed(esw))
340b55b3538SParav Pandit 		return -EPERM;
341b55b3538SParav Pandit 
342b55b3538SParav Pandit 	if (esw->mode != MLX5_ESWITCH_LEGACY)
343b55b3538SParav Pandit 		return -EOPNOTSUPP;
344b55b3538SParav Pandit 
345b55b3538SParav Pandit 	*setting = esw->fdb_table.legacy.vepa_uplink_rule ? 1 : 0;
346b55b3538SParav Pandit 	return 0;
347b55b3538SParav Pandit }
348b55b3538SParav Pandit 
esw_legacy_vport_acl_setup(struct mlx5_eswitch * esw,struct mlx5_vport * vport)349b55b3538SParav Pandit int esw_legacy_vport_acl_setup(struct mlx5_eswitch *esw, struct mlx5_vport *vport)
350b55b3538SParav Pandit {
351b55b3538SParav Pandit 	int ret;
352b55b3538SParav Pandit 
353b55b3538SParav Pandit 	/* Only non manager vports need ACL in legacy mode */
354b55b3538SParav Pandit 	if (mlx5_esw_is_manager_vport(esw, vport->vport))
355b55b3538SParav Pandit 		return 0;
356b55b3538SParav Pandit 
357b55b3538SParav Pandit 	ret = esw_acl_ingress_lgcy_setup(esw, vport);
358b55b3538SParav Pandit 	if (ret)
359b55b3538SParav Pandit 		goto ingress_err;
360b55b3538SParav Pandit 
361b55b3538SParav Pandit 	ret = esw_acl_egress_lgcy_setup(esw, vport);
362b55b3538SParav Pandit 	if (ret)
363b55b3538SParav Pandit 		goto egress_err;
364b55b3538SParav Pandit 
365b55b3538SParav Pandit 	return 0;
366b55b3538SParav Pandit 
367b55b3538SParav Pandit egress_err:
368b55b3538SParav Pandit 	esw_acl_ingress_lgcy_cleanup(esw, vport);
369b55b3538SParav Pandit ingress_err:
370b55b3538SParav Pandit 	return ret;
371b55b3538SParav Pandit }
372b55b3538SParav Pandit 
esw_legacy_vport_acl_cleanup(struct mlx5_eswitch * esw,struct mlx5_vport * vport)373b55b3538SParav Pandit void esw_legacy_vport_acl_cleanup(struct mlx5_eswitch *esw, struct mlx5_vport *vport)
374b55b3538SParav Pandit {
375b55b3538SParav Pandit 	if (mlx5_esw_is_manager_vport(esw, vport->vport))
376b55b3538SParav Pandit 		return;
377b55b3538SParav Pandit 
378b55b3538SParav Pandit 	esw_acl_egress_lgcy_cleanup(esw, vport);
379b55b3538SParav Pandit 	esw_acl_ingress_lgcy_cleanup(esw, vport);
380b55b3538SParav Pandit }
381b55b3538SParav Pandit 
mlx5_esw_query_vport_drop_stats(struct mlx5_core_dev * dev,struct mlx5_vport * vport,struct mlx5_vport_drop_stats * stats)382b55b3538SParav Pandit int mlx5_esw_query_vport_drop_stats(struct mlx5_core_dev *dev,
383b55b3538SParav Pandit 				    struct mlx5_vport *vport,
384b55b3538SParav Pandit 				    struct mlx5_vport_drop_stats *stats)
385b55b3538SParav Pandit {
386b55b3538SParav Pandit 	u64 rx_discard_vport_down, tx_discard_vport_down;
387b55b3538SParav Pandit 	struct mlx5_eswitch *esw = dev->priv.eswitch;
388b55b3538SParav Pandit 	u64 bytes = 0;
389b55b3538SParav Pandit 	int err = 0;
390b55b3538SParav Pandit 
391b55b3538SParav Pandit 	if (esw->mode != MLX5_ESWITCH_LEGACY)
392b55b3538SParav Pandit 		return 0;
393b55b3538SParav Pandit 
394b55b3538SParav Pandit 	mutex_lock(&esw->state_lock);
395b55b3538SParav Pandit 	if (!vport->enabled)
396b55b3538SParav Pandit 		goto unlock;
397b55b3538SParav Pandit 
398b55b3538SParav Pandit 	if (!IS_ERR_OR_NULL(vport->egress.legacy.drop_counter))
399b55b3538SParav Pandit 		mlx5_fc_query(dev, vport->egress.legacy.drop_counter,
400b55b3538SParav Pandit 			      &stats->rx_dropped, &bytes);
401b55b3538SParav Pandit 
402b55b3538SParav Pandit 	if (vport->ingress.legacy.drop_counter)
403b55b3538SParav Pandit 		mlx5_fc_query(dev, vport->ingress.legacy.drop_counter,
404b55b3538SParav Pandit 			      &stats->tx_dropped, &bytes);
405b55b3538SParav Pandit 
406b55b3538SParav Pandit 	if (!MLX5_CAP_GEN(dev, receive_discard_vport_down) &&
407b55b3538SParav Pandit 	    !MLX5_CAP_GEN(dev, transmit_discard_vport_down))
408b55b3538SParav Pandit 		goto unlock;
409b55b3538SParav Pandit 
410b55b3538SParav Pandit 	err = mlx5_query_vport_down_stats(dev, vport->vport, 1,
411b55b3538SParav Pandit 					  &rx_discard_vport_down,
412b55b3538SParav Pandit 					  &tx_discard_vport_down);
413b55b3538SParav Pandit 	if (err)
414b55b3538SParav Pandit 		goto unlock;
415b55b3538SParav Pandit 
416b55b3538SParav Pandit 	if (MLX5_CAP_GEN(dev, receive_discard_vport_down))
417b55b3538SParav Pandit 		stats->rx_dropped += rx_discard_vport_down;
418b55b3538SParav Pandit 	if (MLX5_CAP_GEN(dev, transmit_discard_vport_down))
419b55b3538SParav Pandit 		stats->tx_dropped += tx_discard_vport_down;
420b55b3538SParav Pandit 
421b55b3538SParav Pandit unlock:
422b55b3538SParav Pandit 	mutex_unlock(&esw->state_lock);
423b55b3538SParav Pandit 	return err;
424b55b3538SParav Pandit }
425b55b3538SParav Pandit 
mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch * esw,u16 vport,u16 vlan,u8 qos)426b55b3538SParav Pandit int mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw,
427b55b3538SParav Pandit 				u16 vport, u16 vlan, u8 qos)
428b55b3538SParav Pandit {
429b55b3538SParav Pandit 	u8 set_flags = 0;
430b55b3538SParav Pandit 	int err = 0;
431b55b3538SParav Pandit 
432b55b3538SParav Pandit 	if (!mlx5_esw_allowed(esw))
4337846665dSMaor Dickman 		return vlan ? -EPERM : 0;
434b55b3538SParav Pandit 
435b55b3538SParav Pandit 	if (vlan || qos)
436b55b3538SParav Pandit 		set_flags = SET_VLAN_STRIP | SET_VLAN_INSERT;
437b55b3538SParav Pandit 
438b55b3538SParav Pandit 	mutex_lock(&esw->state_lock);
439b55b3538SParav Pandit 	if (esw->mode != MLX5_ESWITCH_LEGACY) {
440b55b3538SParav Pandit 		if (!vlan)
441b55b3538SParav Pandit 			goto unlock; /* compatibility with libvirt */
442b55b3538SParav Pandit 
443b55b3538SParav Pandit 		err = -EOPNOTSUPP;
444b55b3538SParav Pandit 		goto unlock;
445b55b3538SParav Pandit 	}
446b55b3538SParav Pandit 
447b55b3538SParav Pandit 	err = __mlx5_eswitch_set_vport_vlan(esw, vport, vlan, qos, set_flags);
448b55b3538SParav Pandit 
449b55b3538SParav Pandit unlock:
450b55b3538SParav Pandit 	mutex_unlock(&esw->state_lock);
451b55b3538SParav Pandit 	return err;
452b55b3538SParav Pandit }
453b55b3538SParav Pandit 
mlx5_eswitch_set_vport_spoofchk(struct mlx5_eswitch * esw,u16 vport,bool spoofchk)454b55b3538SParav Pandit int mlx5_eswitch_set_vport_spoofchk(struct mlx5_eswitch *esw,
455b55b3538SParav Pandit 				    u16 vport, bool spoofchk)
456b55b3538SParav Pandit {
457b55b3538SParav Pandit 	struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
458b55b3538SParav Pandit 	bool pschk;
459b55b3538SParav Pandit 	int err = 0;
460b55b3538SParav Pandit 
461b55b3538SParav Pandit 	if (!mlx5_esw_allowed(esw))
462b55b3538SParav Pandit 		return -EPERM;
463b55b3538SParav Pandit 	if (IS_ERR(evport))
464b55b3538SParav Pandit 		return PTR_ERR(evport);
465b55b3538SParav Pandit 
466b55b3538SParav Pandit 	mutex_lock(&esw->state_lock);
467b55b3538SParav Pandit 	if (esw->mode != MLX5_ESWITCH_LEGACY) {
468b55b3538SParav Pandit 		err = -EOPNOTSUPP;
469b55b3538SParav Pandit 		goto unlock;
470b55b3538SParav Pandit 	}
471b55b3538SParav Pandit 	pschk = evport->info.spoofchk;
472b55b3538SParav Pandit 	evport->info.spoofchk = spoofchk;
473b55b3538SParav Pandit 	if (pschk && !is_valid_ether_addr(evport->info.mac))
474b55b3538SParav Pandit 		mlx5_core_warn(esw->dev,
475b55b3538SParav Pandit 			       "Spoofchk in set while MAC is invalid, vport(%d)\n",
476b55b3538SParav Pandit 			       evport->vport);
477b55b3538SParav Pandit 	if (evport->enabled && esw->mode == MLX5_ESWITCH_LEGACY)
478b55b3538SParav Pandit 		err = esw_acl_ingress_lgcy_setup(esw, evport);
479b55b3538SParav Pandit 	if (err)
480b55b3538SParav Pandit 		evport->info.spoofchk = pschk;
481b55b3538SParav Pandit 
482b55b3538SParav Pandit unlock:
483b55b3538SParav Pandit 	mutex_unlock(&esw->state_lock);
484b55b3538SParav Pandit 	return err;
485b55b3538SParav Pandit }
486b55b3538SParav Pandit 
mlx5_eswitch_set_vport_trust(struct mlx5_eswitch * esw,u16 vport,bool setting)487b55b3538SParav Pandit int mlx5_eswitch_set_vport_trust(struct mlx5_eswitch *esw,
488b55b3538SParav Pandit 				 u16 vport, bool setting)
489b55b3538SParav Pandit {
490b55b3538SParav Pandit 	struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
491b55b3538SParav Pandit 	int err = 0;
492b55b3538SParav Pandit 
493b55b3538SParav Pandit 	if (!mlx5_esw_allowed(esw))
494b55b3538SParav Pandit 		return -EPERM;
495b55b3538SParav Pandit 	if (IS_ERR(evport))
496b55b3538SParav Pandit 		return PTR_ERR(evport);
497b55b3538SParav Pandit 
498b55b3538SParav Pandit 	mutex_lock(&esw->state_lock);
499b55b3538SParav Pandit 	if (esw->mode != MLX5_ESWITCH_LEGACY) {
500b55b3538SParav Pandit 		err = -EOPNOTSUPP;
501b55b3538SParav Pandit 		goto unlock;
502b55b3538SParav Pandit 	}
503b55b3538SParav Pandit 	evport->info.trusted = setting;
504b55b3538SParav Pandit 	if (evport->enabled)
505b55b3538SParav Pandit 		esw_vport_change_handle_locked(evport);
506b55b3538SParav Pandit 
507b55b3538SParav Pandit unlock:
508b55b3538SParav Pandit 	mutex_unlock(&esw->state_lock);
509b55b3538SParav Pandit 	return err;
510b55b3538SParav Pandit }
5112d116e3eSDmytro Linkin 
mlx5_eswitch_set_vport_rate(struct mlx5_eswitch * esw,u16 vport,u32 max_rate,u32 min_rate)5122d116e3eSDmytro Linkin int mlx5_eswitch_set_vport_rate(struct mlx5_eswitch *esw, u16 vport,
5132d116e3eSDmytro Linkin 				u32 max_rate, u32 min_rate)
5142d116e3eSDmytro Linkin {
5152d116e3eSDmytro Linkin 	struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
5162d116e3eSDmytro Linkin 	int err;
5172d116e3eSDmytro Linkin 
5182d116e3eSDmytro Linkin 	if (!mlx5_esw_allowed(esw))
5192d116e3eSDmytro Linkin 		return -EPERM;
5202d116e3eSDmytro Linkin 	if (IS_ERR(evport))
5212d116e3eSDmytro Linkin 		return PTR_ERR(evport);
5222d116e3eSDmytro Linkin 
5232d116e3eSDmytro Linkin 	mutex_lock(&esw->state_lock);
524d7df09f5SDmytro Linkin 	err = mlx5_esw_qos_set_vport_rate(esw, evport, max_rate, min_rate);
5252d116e3eSDmytro Linkin 	mutex_unlock(&esw->state_lock);
5262d116e3eSDmytro Linkin 	return err;
5272d116e3eSDmytro Linkin }
528