1 /*
2  * drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
3  * Copyright (c) 2015 Mellanox Technologies. All rights reserved.
4  * Copyright (c) 2015 Jiri Pirko <jiri@mellanox.com>
5  * Copyright (c) 2015 Ido Schimmel <idosch@mellanox.com>
6  * Copyright (c) 2015 Elad Raz <eladr@mellanox.com>
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. Neither the names of the copyright holders nor the names of its
17  *    contributors may be used to endorse or promote products derived from
18  *    this software without specific prior written permission.
19  *
20  * Alternatively, this software may be distributed under the terms of the
21  * GNU General Public License ("GPL") version 2 as published by the Free
22  * Software Foundation.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  */
36 
37 #include <linux/kernel.h>
38 #include <linux/types.h>
39 #include <linux/netdevice.h>
40 #include <linux/etherdevice.h>
41 #include <linux/slab.h>
42 #include <linux/device.h>
43 #include <linux/skbuff.h>
44 #include <linux/if_vlan.h>
45 #include <linux/if_bridge.h>
46 #include <linux/workqueue.h>
47 #include <linux/jiffies.h>
48 #include <linux/rtnetlink.h>
49 #include <net/switchdev.h>
50 
51 #include "spectrum.h"
52 #include "core.h"
53 #include "reg.h"
54 
55 static u16 mlxsw_sp_port_vid_to_fid_get(struct mlxsw_sp_port *mlxsw_sp_port,
56 					u16 vid)
57 {
58 	struct mlxsw_sp_fid *f = mlxsw_sp_vport_fid_get(mlxsw_sp_port);
59 	u16 fid = vid;
60 
61 	fid = f ? f->fid : fid;
62 
63 	if (!fid)
64 		fid = mlxsw_sp_port->pvid;
65 
66 	return fid;
67 }
68 
69 static struct mlxsw_sp_port *
70 mlxsw_sp_port_orig_get(struct net_device *dev,
71 		       struct mlxsw_sp_port *mlxsw_sp_port)
72 {
73 	struct mlxsw_sp_port *mlxsw_sp_vport;
74 	u16 vid;
75 
76 	if (!is_vlan_dev(dev))
77 		return mlxsw_sp_port;
78 
79 	vid = vlan_dev_vlan_id(dev);
80 	mlxsw_sp_vport = mlxsw_sp_port_vport_find(mlxsw_sp_port, vid);
81 	WARN_ON(!mlxsw_sp_vport);
82 
83 	return mlxsw_sp_vport;
84 }
85 
86 static int mlxsw_sp_port_attr_get(struct net_device *dev,
87 				  struct switchdev_attr *attr)
88 {
89 	struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
90 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
91 
92 	mlxsw_sp_port = mlxsw_sp_port_orig_get(attr->orig_dev, mlxsw_sp_port);
93 	if (!mlxsw_sp_port)
94 		return -EINVAL;
95 
96 	switch (attr->id) {
97 	case SWITCHDEV_ATTR_ID_PORT_PARENT_ID:
98 		attr->u.ppid.id_len = sizeof(mlxsw_sp->base_mac);
99 		memcpy(&attr->u.ppid.id, &mlxsw_sp->base_mac,
100 		       attr->u.ppid.id_len);
101 		break;
102 	case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS:
103 		attr->u.brport_flags =
104 			(mlxsw_sp_port->learning ? BR_LEARNING : 0) |
105 			(mlxsw_sp_port->learning_sync ? BR_LEARNING_SYNC : 0) |
106 			(mlxsw_sp_port->uc_flood ? BR_FLOOD : 0);
107 		break;
108 	default:
109 		return -EOPNOTSUPP;
110 	}
111 
112 	return 0;
113 }
114 
115 static int mlxsw_sp_port_stp_state_set(struct mlxsw_sp_port *mlxsw_sp_port,
116 				       u8 state)
117 {
118 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
119 	enum mlxsw_reg_spms_state spms_state;
120 	char *spms_pl;
121 	u16 vid;
122 	int err;
123 
124 	switch (state) {
125 	case BR_STATE_FORWARDING:
126 		spms_state = MLXSW_REG_SPMS_STATE_FORWARDING;
127 		break;
128 	case BR_STATE_LEARNING:
129 		spms_state = MLXSW_REG_SPMS_STATE_LEARNING;
130 		break;
131 	case BR_STATE_LISTENING: /* fall-through */
132 	case BR_STATE_DISABLED: /* fall-through */
133 	case BR_STATE_BLOCKING:
134 		spms_state = MLXSW_REG_SPMS_STATE_DISCARDING;
135 		break;
136 	default:
137 		BUG();
138 	}
139 
140 	spms_pl = kmalloc(MLXSW_REG_SPMS_LEN, GFP_KERNEL);
141 	if (!spms_pl)
142 		return -ENOMEM;
143 	mlxsw_reg_spms_pack(spms_pl, mlxsw_sp_port->local_port);
144 
145 	if (mlxsw_sp_port_is_vport(mlxsw_sp_port)) {
146 		vid = mlxsw_sp_vport_vid_get(mlxsw_sp_port);
147 		mlxsw_reg_spms_vid_pack(spms_pl, vid, spms_state);
148 	} else {
149 		for_each_set_bit(vid, mlxsw_sp_port->active_vlans, VLAN_N_VID)
150 			mlxsw_reg_spms_vid_pack(spms_pl, vid, spms_state);
151 	}
152 
153 	err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(spms), spms_pl);
154 	kfree(spms_pl);
155 	return err;
156 }
157 
158 static int mlxsw_sp_port_attr_stp_state_set(struct mlxsw_sp_port *mlxsw_sp_port,
159 					    struct switchdev_trans *trans,
160 					    u8 state)
161 {
162 	if (switchdev_trans_ph_prepare(trans))
163 		return 0;
164 
165 	mlxsw_sp_port->stp_state = state;
166 	return mlxsw_sp_port_stp_state_set(mlxsw_sp_port, state);
167 }
168 
169 static int __mlxsw_sp_port_flood_set(struct mlxsw_sp_port *mlxsw_sp_port,
170 				     u16 idx_begin, u16 idx_end, bool uc_set,
171 				     bool bm_set)
172 {
173 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
174 	u16 local_port = mlxsw_sp_port->local_port;
175 	enum mlxsw_flood_table_type table_type;
176 	u16 range = idx_end - idx_begin + 1;
177 	char *sftr_pl;
178 	int err;
179 
180 	if (mlxsw_sp_port_is_vport(mlxsw_sp_port))
181 		table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID;
182 	else
183 		table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFEST;
184 
185 	sftr_pl = kmalloc(MLXSW_REG_SFTR_LEN, GFP_KERNEL);
186 	if (!sftr_pl)
187 		return -ENOMEM;
188 
189 	mlxsw_reg_sftr_pack(sftr_pl, MLXSW_SP_FLOOD_TABLE_UC, idx_begin,
190 			    table_type, range, local_port, uc_set);
191 	err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sftr), sftr_pl);
192 	if (err)
193 		goto buffer_out;
194 
195 	mlxsw_reg_sftr_pack(sftr_pl, MLXSW_SP_FLOOD_TABLE_BM, idx_begin,
196 			    table_type, range, local_port, bm_set);
197 	err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sftr), sftr_pl);
198 	if (err)
199 		goto err_flood_bm_set;
200 
201 	goto buffer_out;
202 
203 err_flood_bm_set:
204 	mlxsw_reg_sftr_pack(sftr_pl, MLXSW_SP_FLOOD_TABLE_UC, idx_begin,
205 			    table_type, range, local_port, !uc_set);
206 	mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sftr), sftr_pl);
207 buffer_out:
208 	kfree(sftr_pl);
209 	return err;
210 }
211 
212 static int mlxsw_sp_port_uc_flood_set(struct mlxsw_sp_port *mlxsw_sp_port,
213 				      bool set)
214 {
215 	struct net_device *dev = mlxsw_sp_port->dev;
216 	u16 vid, last_visited_vid;
217 	int err;
218 
219 	if (mlxsw_sp_port_is_vport(mlxsw_sp_port)) {
220 		u16 fid = mlxsw_sp_vport_fid_get(mlxsw_sp_port)->fid;
221 		u16 vfid = mlxsw_sp_fid_to_vfid(fid);
222 
223 		return  __mlxsw_sp_port_flood_set(mlxsw_sp_port, vfid, vfid,
224 						  set, true);
225 	}
226 
227 	for_each_set_bit(vid, mlxsw_sp_port->active_vlans, VLAN_N_VID) {
228 		err = __mlxsw_sp_port_flood_set(mlxsw_sp_port, vid, vid, set,
229 						true);
230 		if (err) {
231 			last_visited_vid = vid;
232 			goto err_port_flood_set;
233 		}
234 	}
235 
236 	return 0;
237 
238 err_port_flood_set:
239 	for_each_set_bit(vid, mlxsw_sp_port->active_vlans, last_visited_vid)
240 		__mlxsw_sp_port_flood_set(mlxsw_sp_port, vid, vid, !set, true);
241 	netdev_err(dev, "Failed to configure unicast flooding\n");
242 	return err;
243 }
244 
245 int mlxsw_sp_vport_flood_set(struct mlxsw_sp_port *mlxsw_sp_vport, u16 fid,
246 			     bool set)
247 {
248 	u16 vfid;
249 
250 	/* In case of vFIDs, index into the flooding table is relative to
251 	 * the start of the vFIDs range.
252 	 */
253 	vfid = mlxsw_sp_fid_to_vfid(fid);
254 	return __mlxsw_sp_port_flood_set(mlxsw_sp_vport, vfid, vfid, set, set);
255 }
256 
257 static int mlxsw_sp_port_learning_set(struct mlxsw_sp_port *mlxsw_sp_port,
258 				      bool set)
259 {
260 	u16 vid;
261 	int err;
262 
263 	if (mlxsw_sp_port_is_vport(mlxsw_sp_port)) {
264 		vid = mlxsw_sp_vport_vid_get(mlxsw_sp_port);
265 
266 		return __mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid, vid,
267 							set);
268 	}
269 
270 	for_each_set_bit(vid, mlxsw_sp_port->active_vlans, VLAN_N_VID) {
271 		err = __mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid, vid,
272 						       set);
273 		if (err)
274 			goto err_port_vid_learning_set;
275 	}
276 
277 	return 0;
278 
279 err_port_vid_learning_set:
280 	for_each_set_bit(vid, mlxsw_sp_port->active_vlans, VLAN_N_VID)
281 		__mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid, vid, !set);
282 	return err;
283 }
284 
285 static int mlxsw_sp_port_attr_br_flags_set(struct mlxsw_sp_port *mlxsw_sp_port,
286 					   struct switchdev_trans *trans,
287 					   unsigned long brport_flags)
288 {
289 	unsigned long learning = mlxsw_sp_port->learning ? BR_LEARNING : 0;
290 	unsigned long uc_flood = mlxsw_sp_port->uc_flood ? BR_FLOOD : 0;
291 	int err;
292 
293 	if (!mlxsw_sp_port->bridged)
294 		return -EINVAL;
295 
296 	if (switchdev_trans_ph_prepare(trans))
297 		return 0;
298 
299 	if ((uc_flood ^ brport_flags) & BR_FLOOD) {
300 		err = mlxsw_sp_port_uc_flood_set(mlxsw_sp_port,
301 						 !mlxsw_sp_port->uc_flood);
302 		if (err)
303 			return err;
304 	}
305 
306 	if ((learning ^ brport_flags) & BR_LEARNING) {
307 		err = mlxsw_sp_port_learning_set(mlxsw_sp_port,
308 						 !mlxsw_sp_port->learning);
309 		if (err)
310 			goto err_port_learning_set;
311 	}
312 
313 	mlxsw_sp_port->uc_flood = brport_flags & BR_FLOOD ? 1 : 0;
314 	mlxsw_sp_port->learning = brport_flags & BR_LEARNING ? 1 : 0;
315 	mlxsw_sp_port->learning_sync = brport_flags & BR_LEARNING_SYNC ? 1 : 0;
316 
317 	return 0;
318 
319 err_port_learning_set:
320 	if ((uc_flood ^ brport_flags) & BR_FLOOD)
321 		mlxsw_sp_port_uc_flood_set(mlxsw_sp_port,
322 					   mlxsw_sp_port->uc_flood);
323 	return err;
324 }
325 
326 static int mlxsw_sp_ageing_set(struct mlxsw_sp *mlxsw_sp, u32 ageing_time)
327 {
328 	char sfdat_pl[MLXSW_REG_SFDAT_LEN];
329 	int err;
330 
331 	mlxsw_reg_sfdat_pack(sfdat_pl, ageing_time);
332 	err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfdat), sfdat_pl);
333 	if (err)
334 		return err;
335 	mlxsw_sp->ageing_time = ageing_time;
336 	return 0;
337 }
338 
339 static int mlxsw_sp_port_attr_br_ageing_set(struct mlxsw_sp_port *mlxsw_sp_port,
340 					    struct switchdev_trans *trans,
341 					    unsigned long ageing_clock_t)
342 {
343 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
344 	unsigned long ageing_jiffies = clock_t_to_jiffies(ageing_clock_t);
345 	u32 ageing_time = jiffies_to_msecs(ageing_jiffies) / 1000;
346 
347 	if (switchdev_trans_ph_prepare(trans)) {
348 		if (ageing_time < MLXSW_SP_MIN_AGEING_TIME ||
349 		    ageing_time > MLXSW_SP_MAX_AGEING_TIME)
350 			return -ERANGE;
351 		else
352 			return 0;
353 	}
354 
355 	return mlxsw_sp_ageing_set(mlxsw_sp, ageing_time);
356 }
357 
358 static int mlxsw_sp_port_attr_br_vlan_set(struct mlxsw_sp_port *mlxsw_sp_port,
359 					  struct switchdev_trans *trans,
360 					  struct net_device *orig_dev,
361 					  bool vlan_enabled)
362 {
363 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
364 
365 	/* SWITCHDEV_TRANS_PREPARE phase */
366 	if ((!vlan_enabled) && (mlxsw_sp->master_bridge.dev == orig_dev)) {
367 		netdev_err(mlxsw_sp_port->dev, "Bridge must be vlan-aware\n");
368 		return -EINVAL;
369 	}
370 
371 	return 0;
372 }
373 
374 static int mlxsw_sp_port_attr_set(struct net_device *dev,
375 				  const struct switchdev_attr *attr,
376 				  struct switchdev_trans *trans)
377 {
378 	struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
379 	int err = 0;
380 
381 	mlxsw_sp_port = mlxsw_sp_port_orig_get(attr->orig_dev, mlxsw_sp_port);
382 	if (!mlxsw_sp_port)
383 		return -EINVAL;
384 
385 	switch (attr->id) {
386 	case SWITCHDEV_ATTR_ID_PORT_STP_STATE:
387 		err = mlxsw_sp_port_attr_stp_state_set(mlxsw_sp_port, trans,
388 						       attr->u.stp_state);
389 		break;
390 	case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS:
391 		err = mlxsw_sp_port_attr_br_flags_set(mlxsw_sp_port, trans,
392 						      attr->u.brport_flags);
393 		break;
394 	case SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME:
395 		err = mlxsw_sp_port_attr_br_ageing_set(mlxsw_sp_port, trans,
396 						       attr->u.ageing_time);
397 		break;
398 	case SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING:
399 		err = mlxsw_sp_port_attr_br_vlan_set(mlxsw_sp_port, trans,
400 						     attr->orig_dev,
401 						     attr->u.vlan_filtering);
402 		break;
403 	default:
404 		err = -EOPNOTSUPP;
405 		break;
406 	}
407 
408 	return err;
409 }
410 
411 static int mlxsw_sp_fid_op(struct mlxsw_sp *mlxsw_sp, u16 fid, bool create)
412 {
413 	char sfmr_pl[MLXSW_REG_SFMR_LEN];
414 
415 	mlxsw_reg_sfmr_pack(sfmr_pl, !create, fid, fid);
416 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl);
417 }
418 
419 static int mlxsw_sp_fid_map(struct mlxsw_sp *mlxsw_sp, u16 fid, bool valid)
420 {
421 	enum mlxsw_reg_svfa_mt mt = MLXSW_REG_SVFA_MT_VID_TO_FID;
422 	char svfa_pl[MLXSW_REG_SVFA_LEN];
423 
424 	mlxsw_reg_svfa_pack(svfa_pl, 0, mt, valid, fid, fid);
425 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl);
426 }
427 
428 static struct mlxsw_sp_fid *mlxsw_sp_fid_alloc(u16 fid)
429 {
430 	struct mlxsw_sp_fid *f;
431 
432 	f = kzalloc(sizeof(*f), GFP_KERNEL);
433 	if (!f)
434 		return NULL;
435 
436 	f->fid = fid;
437 
438 	return f;
439 }
440 
441 struct mlxsw_sp_fid *mlxsw_sp_fid_create(struct mlxsw_sp *mlxsw_sp, u16 fid)
442 {
443 	struct mlxsw_sp_fid *f;
444 	int err;
445 
446 	err = mlxsw_sp_fid_op(mlxsw_sp, fid, true);
447 	if (err)
448 		return ERR_PTR(err);
449 
450 	/* Although all the ports member in the FID might be using a
451 	 * {Port, VID} to FID mapping, we create a global VID-to-FID
452 	 * mapping. This allows a port to transition to VLAN mode,
453 	 * knowing the global mapping exists.
454 	 */
455 	err = mlxsw_sp_fid_map(mlxsw_sp, fid, true);
456 	if (err)
457 		goto err_fid_map;
458 
459 	f = mlxsw_sp_fid_alloc(fid);
460 	if (!f) {
461 		err = -ENOMEM;
462 		goto err_allocate_fid;
463 	}
464 
465 	list_add(&f->list, &mlxsw_sp->fids);
466 
467 	return f;
468 
469 err_allocate_fid:
470 	mlxsw_sp_fid_map(mlxsw_sp, fid, false);
471 err_fid_map:
472 	mlxsw_sp_fid_op(mlxsw_sp, fid, false);
473 	return ERR_PTR(err);
474 }
475 
476 void mlxsw_sp_fid_destroy(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_fid *f)
477 {
478 	u16 fid = f->fid;
479 
480 	list_del(&f->list);
481 
482 	if (f->r)
483 		mlxsw_sp_rif_bridge_destroy(mlxsw_sp, f->r);
484 
485 	kfree(f);
486 
487 	mlxsw_sp_fid_map(mlxsw_sp, fid, false);
488 
489 	mlxsw_sp_fid_op(mlxsw_sp, fid, false);
490 }
491 
492 static int __mlxsw_sp_port_fid_join(struct mlxsw_sp_port *mlxsw_sp_port,
493 				    u16 fid)
494 {
495 	struct mlxsw_sp_fid *f;
496 
497 	if (test_bit(fid, mlxsw_sp_port->active_vlans))
498 		return 0;
499 
500 	f = mlxsw_sp_fid_find(mlxsw_sp_port->mlxsw_sp, fid);
501 	if (!f) {
502 		f = mlxsw_sp_fid_create(mlxsw_sp_port->mlxsw_sp, fid);
503 		if (IS_ERR(f))
504 			return PTR_ERR(f);
505 	}
506 
507 	f->ref_count++;
508 
509 	netdev_dbg(mlxsw_sp_port->dev, "Joined FID=%d\n", fid);
510 
511 	return 0;
512 }
513 
514 static void __mlxsw_sp_port_fid_leave(struct mlxsw_sp_port *mlxsw_sp_port,
515 				      u16 fid)
516 {
517 	struct mlxsw_sp_fid *f;
518 
519 	f = mlxsw_sp_fid_find(mlxsw_sp_port->mlxsw_sp, fid);
520 	if (WARN_ON(!f))
521 		return;
522 
523 	netdev_dbg(mlxsw_sp_port->dev, "Left FID=%d\n", fid);
524 
525 	mlxsw_sp_port_fdb_flush(mlxsw_sp_port, fid);
526 
527 	if (--f->ref_count == 0)
528 		mlxsw_sp_fid_destroy(mlxsw_sp_port->mlxsw_sp, f);
529 }
530 
531 static int mlxsw_sp_port_fid_map(struct mlxsw_sp_port *mlxsw_sp_port, u16 fid,
532 				 bool valid)
533 {
534 	enum mlxsw_reg_svfa_mt mt = MLXSW_REG_SVFA_MT_PORT_VID_TO_FID;
535 
536 	/* If port doesn't have vPorts, then it can use the global
537 	 * VID-to-FID mapping.
538 	 */
539 	if (list_empty(&mlxsw_sp_port->vports_list))
540 		return 0;
541 
542 	return mlxsw_sp_port_vid_to_fid_set(mlxsw_sp_port, mt, valid, fid, fid);
543 }
544 
545 static int mlxsw_sp_port_fid_join(struct mlxsw_sp_port *mlxsw_sp_port,
546 				  u16 fid_begin, u16 fid_end)
547 {
548 	int fid, err;
549 
550 	for (fid = fid_begin; fid <= fid_end; fid++) {
551 		err = __mlxsw_sp_port_fid_join(mlxsw_sp_port, fid);
552 		if (err)
553 			goto err_port_fid_join;
554 	}
555 
556 	err = __mlxsw_sp_port_flood_set(mlxsw_sp_port, fid_begin, fid_end,
557 					mlxsw_sp_port->uc_flood, true);
558 	if (err)
559 		goto err_port_flood_set;
560 
561 	for (fid = fid_begin; fid <= fid_end; fid++) {
562 		err = mlxsw_sp_port_fid_map(mlxsw_sp_port, fid, true);
563 		if (err)
564 			goto err_port_fid_map;
565 	}
566 
567 	return 0;
568 
569 err_port_fid_map:
570 	for (fid--; fid >= fid_begin; fid--)
571 		mlxsw_sp_port_fid_map(mlxsw_sp_port, fid, false);
572 	__mlxsw_sp_port_flood_set(mlxsw_sp_port, fid_begin, fid_end, false,
573 				  false);
574 err_port_flood_set:
575 	fid = fid_end;
576 err_port_fid_join:
577 	for (fid--; fid >= fid_begin; fid--)
578 		__mlxsw_sp_port_fid_leave(mlxsw_sp_port, fid);
579 	return err;
580 }
581 
582 static void mlxsw_sp_port_fid_leave(struct mlxsw_sp_port *mlxsw_sp_port,
583 				    u16 fid_begin, u16 fid_end)
584 {
585 	int fid;
586 
587 	for (fid = fid_begin; fid <= fid_end; fid++)
588 		mlxsw_sp_port_fid_map(mlxsw_sp_port, fid, false);
589 
590 	__mlxsw_sp_port_flood_set(mlxsw_sp_port, fid_begin, fid_end, false,
591 				  false);
592 
593 	for (fid = fid_begin; fid <= fid_end; fid++)
594 		__mlxsw_sp_port_fid_leave(mlxsw_sp_port, fid);
595 }
596 
597 static int __mlxsw_sp_port_pvid_set(struct mlxsw_sp_port *mlxsw_sp_port,
598 				    u16 vid)
599 {
600 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
601 	char spvid_pl[MLXSW_REG_SPVID_LEN];
602 
603 	mlxsw_reg_spvid_pack(spvid_pl, mlxsw_sp_port->local_port, vid);
604 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(spvid), spvid_pl);
605 }
606 
607 static int mlxsw_sp_port_allow_untagged_set(struct mlxsw_sp_port *mlxsw_sp_port,
608 					    bool allow)
609 {
610 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
611 	char spaft_pl[MLXSW_REG_SPAFT_LEN];
612 
613 	mlxsw_reg_spaft_pack(spaft_pl, mlxsw_sp_port->local_port, allow);
614 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(spaft), spaft_pl);
615 }
616 
617 int mlxsw_sp_port_pvid_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
618 {
619 	struct net_device *dev = mlxsw_sp_port->dev;
620 	int err;
621 
622 	if (!vid) {
623 		err = mlxsw_sp_port_allow_untagged_set(mlxsw_sp_port, false);
624 		if (err) {
625 			netdev_err(dev, "Failed to disallow untagged traffic\n");
626 			return err;
627 		}
628 	} else {
629 		err = __mlxsw_sp_port_pvid_set(mlxsw_sp_port, vid);
630 		if (err) {
631 			netdev_err(dev, "Failed to set PVID\n");
632 			return err;
633 		}
634 
635 		/* Only allow if not already allowed. */
636 		if (!mlxsw_sp_port->pvid) {
637 			err = mlxsw_sp_port_allow_untagged_set(mlxsw_sp_port,
638 							       true);
639 			if (err) {
640 				netdev_err(dev, "Failed to allow untagged traffic\n");
641 				goto err_port_allow_untagged_set;
642 			}
643 		}
644 	}
645 
646 	mlxsw_sp_port->pvid = vid;
647 	return 0;
648 
649 err_port_allow_untagged_set:
650 	__mlxsw_sp_port_pvid_set(mlxsw_sp_port, mlxsw_sp_port->pvid);
651 	return err;
652 }
653 
654 static int __mlxsw_sp_port_vlans_set(struct mlxsw_sp_port *mlxsw_sp_port,
655 				     u16 vid_begin, u16 vid_end, bool is_member,
656 				     bool untagged)
657 {
658 	u16 vid, vid_e;
659 	int err;
660 
661 	for (vid = vid_begin; vid <= vid_end;
662 	     vid += MLXSW_REG_SPVM_REC_MAX_COUNT) {
663 		vid_e = min((u16) (vid + MLXSW_REG_SPVM_REC_MAX_COUNT - 1),
664 			    vid_end);
665 
666 		err = mlxsw_sp_port_vlan_set(mlxsw_sp_port, vid, vid_e,
667 					     is_member, untagged);
668 		if (err)
669 			return err;
670 	}
671 
672 	return 0;
673 }
674 
675 static int mlxsw_sp_port_vid_learning_set(struct mlxsw_sp_port *mlxsw_sp_port,
676 					  u16 vid_begin, u16 vid_end,
677 					  bool learn_enable)
678 {
679 	u16 vid, vid_e;
680 	int err;
681 
682 	for (vid = vid_begin; vid <= vid_end;
683 	     vid += MLXSW_REG_SPVMLR_REC_MAX_COUNT) {
684 		vid_e = min((u16) (vid + MLXSW_REG_SPVMLR_REC_MAX_COUNT - 1),
685 			    vid_end);
686 
687 		err = __mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid,
688 						       vid_e, learn_enable);
689 		if (err)
690 			return err;
691 	}
692 
693 	return 0;
694 }
695 
696 static int __mlxsw_sp_port_vlans_add(struct mlxsw_sp_port *mlxsw_sp_port,
697 				     u16 vid_begin, u16 vid_end,
698 				     bool flag_untagged, bool flag_pvid)
699 {
700 	struct net_device *dev = mlxsw_sp_port->dev;
701 	u16 vid, old_pvid;
702 	int err;
703 
704 	if (!mlxsw_sp_port->bridged)
705 		return -EINVAL;
706 
707 	err = mlxsw_sp_port_fid_join(mlxsw_sp_port, vid_begin, vid_end);
708 	if (err) {
709 		netdev_err(dev, "Failed to join FIDs\n");
710 		return err;
711 	}
712 
713 	err = __mlxsw_sp_port_vlans_set(mlxsw_sp_port, vid_begin, vid_end,
714 					true, flag_untagged);
715 	if (err) {
716 		netdev_err(dev, "Unable to add VIDs %d-%d\n", vid_begin,
717 			   vid_end);
718 		goto err_port_vlans_set;
719 	}
720 
721 	old_pvid = mlxsw_sp_port->pvid;
722 	if (flag_pvid && old_pvid != vid_begin) {
723 		err = mlxsw_sp_port_pvid_set(mlxsw_sp_port, vid_begin);
724 		if (err) {
725 			netdev_err(dev, "Unable to add PVID %d\n", vid_begin);
726 			goto err_port_pvid_set;
727 		}
728 	} else if (!flag_pvid && old_pvid >= vid_begin && old_pvid <= vid_end) {
729 		err = mlxsw_sp_port_pvid_set(mlxsw_sp_port, 0);
730 		if (err) {
731 			netdev_err(dev, "Unable to del PVID\n");
732 			goto err_port_pvid_set;
733 		}
734 	}
735 
736 	err = mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid_begin, vid_end,
737 					     mlxsw_sp_port->learning);
738 	if (err) {
739 		netdev_err(dev, "Failed to set learning for VIDs %d-%d\n",
740 			   vid_begin, vid_end);
741 		goto err_port_vid_learning_set;
742 	}
743 
744 	/* Changing activity bits only if HW operation succeded */
745 	for (vid = vid_begin; vid <= vid_end; vid++) {
746 		set_bit(vid, mlxsw_sp_port->active_vlans);
747 		if (flag_untagged)
748 			set_bit(vid, mlxsw_sp_port->untagged_vlans);
749 		else
750 			clear_bit(vid, mlxsw_sp_port->untagged_vlans);
751 	}
752 
753 	/* STP state change must be done after we set active VLANs */
754 	err = mlxsw_sp_port_stp_state_set(mlxsw_sp_port,
755 					  mlxsw_sp_port->stp_state);
756 	if (err) {
757 		netdev_err(dev, "Failed to set STP state\n");
758 		goto err_port_stp_state_set;
759 	}
760 
761 	return 0;
762 
763 err_port_stp_state_set:
764 	for (vid = vid_begin; vid <= vid_end; vid++)
765 		clear_bit(vid, mlxsw_sp_port->active_vlans);
766 	mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid_begin, vid_end,
767 				       false);
768 err_port_vid_learning_set:
769 	if (old_pvid != mlxsw_sp_port->pvid)
770 		mlxsw_sp_port_pvid_set(mlxsw_sp_port, old_pvid);
771 err_port_pvid_set:
772 	__mlxsw_sp_port_vlans_set(mlxsw_sp_port, vid_begin, vid_end, false,
773 				  false);
774 err_port_vlans_set:
775 	mlxsw_sp_port_fid_leave(mlxsw_sp_port, vid_begin, vid_end);
776 	return err;
777 }
778 
779 static int mlxsw_sp_port_vlans_add(struct mlxsw_sp_port *mlxsw_sp_port,
780 				   const struct switchdev_obj_port_vlan *vlan,
781 				   struct switchdev_trans *trans)
782 {
783 	bool flag_untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
784 	bool flag_pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
785 
786 	if (switchdev_trans_ph_prepare(trans))
787 		return 0;
788 
789 	return __mlxsw_sp_port_vlans_add(mlxsw_sp_port,
790 					 vlan->vid_begin, vlan->vid_end,
791 					 flag_untagged, flag_pvid);
792 }
793 
794 static enum mlxsw_reg_sfd_rec_policy mlxsw_sp_sfd_rec_policy(bool dynamic)
795 {
796 	return dynamic ? MLXSW_REG_SFD_REC_POLICY_DYNAMIC_ENTRY_INGRESS :
797 			 MLXSW_REG_SFD_REC_POLICY_STATIC_ENTRY;
798 }
799 
800 static enum mlxsw_reg_sfd_op mlxsw_sp_sfd_op(bool adding)
801 {
802 	return adding ? MLXSW_REG_SFD_OP_WRITE_EDIT :
803 			MLXSW_REG_SFD_OP_WRITE_REMOVE;
804 }
805 
806 static int __mlxsw_sp_port_fdb_uc_op(struct mlxsw_sp *mlxsw_sp, u8 local_port,
807 				     const char *mac, u16 fid, bool adding,
808 				     enum mlxsw_reg_sfd_rec_action action,
809 				     bool dynamic)
810 {
811 	char *sfd_pl;
812 	int err;
813 
814 	sfd_pl = kmalloc(MLXSW_REG_SFD_LEN, GFP_KERNEL);
815 	if (!sfd_pl)
816 		return -ENOMEM;
817 
818 	mlxsw_reg_sfd_pack(sfd_pl, mlxsw_sp_sfd_op(adding), 0);
819 	mlxsw_reg_sfd_uc_pack(sfd_pl, 0, mlxsw_sp_sfd_rec_policy(dynamic),
820 			      mac, fid, action, local_port);
821 	err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfd), sfd_pl);
822 	kfree(sfd_pl);
823 
824 	return err;
825 }
826 
827 static int mlxsw_sp_port_fdb_uc_op(struct mlxsw_sp *mlxsw_sp, u8 local_port,
828 				   const char *mac, u16 fid, bool adding,
829 				   bool dynamic)
830 {
831 	return __mlxsw_sp_port_fdb_uc_op(mlxsw_sp, local_port, mac, fid, adding,
832 					 MLXSW_REG_SFD_REC_ACTION_NOP, dynamic);
833 }
834 
835 int mlxsw_sp_rif_fdb_op(struct mlxsw_sp *mlxsw_sp, const char *mac, u16 fid,
836 			bool adding)
837 {
838 	return __mlxsw_sp_port_fdb_uc_op(mlxsw_sp, 0, mac, fid, adding,
839 					 MLXSW_REG_SFD_REC_ACTION_FORWARD_IP_ROUTER,
840 					 false);
841 }
842 
843 static int mlxsw_sp_port_fdb_uc_lag_op(struct mlxsw_sp *mlxsw_sp, u16 lag_id,
844 				       const char *mac, u16 fid, u16 lag_vid,
845 				       bool adding, bool dynamic)
846 {
847 	char *sfd_pl;
848 	int err;
849 
850 	sfd_pl = kmalloc(MLXSW_REG_SFD_LEN, GFP_KERNEL);
851 	if (!sfd_pl)
852 		return -ENOMEM;
853 
854 	mlxsw_reg_sfd_pack(sfd_pl, mlxsw_sp_sfd_op(adding), 0);
855 	mlxsw_reg_sfd_uc_lag_pack(sfd_pl, 0, mlxsw_sp_sfd_rec_policy(dynamic),
856 				  mac, fid, MLXSW_REG_SFD_REC_ACTION_NOP,
857 				  lag_vid, lag_id);
858 	err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfd), sfd_pl);
859 	kfree(sfd_pl);
860 
861 	return err;
862 }
863 
864 static int
865 mlxsw_sp_port_fdb_static_add(struct mlxsw_sp_port *mlxsw_sp_port,
866 			     const struct switchdev_obj_port_fdb *fdb,
867 			     struct switchdev_trans *trans)
868 {
869 	u16 fid = mlxsw_sp_port_vid_to_fid_get(mlxsw_sp_port, fdb->vid);
870 	u16 lag_vid = 0;
871 
872 	if (switchdev_trans_ph_prepare(trans))
873 		return 0;
874 
875 	if (mlxsw_sp_port_is_vport(mlxsw_sp_port)) {
876 		lag_vid = mlxsw_sp_vport_vid_get(mlxsw_sp_port);
877 	}
878 
879 	if (!mlxsw_sp_port->lagged)
880 		return mlxsw_sp_port_fdb_uc_op(mlxsw_sp_port->mlxsw_sp,
881 					       mlxsw_sp_port->local_port,
882 					       fdb->addr, fid, true, false);
883 	else
884 		return mlxsw_sp_port_fdb_uc_lag_op(mlxsw_sp_port->mlxsw_sp,
885 						   mlxsw_sp_port->lag_id,
886 						   fdb->addr, fid, lag_vid,
887 						   true, false);
888 }
889 
890 static int mlxsw_sp_port_mdb_op(struct mlxsw_sp *mlxsw_sp, const char *addr,
891 				u16 fid, u16 mid, bool adding)
892 {
893 	char *sfd_pl;
894 	int err;
895 
896 	sfd_pl = kmalloc(MLXSW_REG_SFD_LEN, GFP_KERNEL);
897 	if (!sfd_pl)
898 		return -ENOMEM;
899 
900 	mlxsw_reg_sfd_pack(sfd_pl, mlxsw_sp_sfd_op(adding), 0);
901 	mlxsw_reg_sfd_mc_pack(sfd_pl, 0, addr, fid,
902 			      MLXSW_REG_SFD_REC_ACTION_NOP, mid);
903 	err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfd), sfd_pl);
904 	kfree(sfd_pl);
905 	return err;
906 }
907 
908 static int mlxsw_sp_port_smid_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 mid,
909 				  bool add, bool clear_all_ports)
910 {
911 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
912 	char *smid_pl;
913 	int err, i;
914 
915 	smid_pl = kmalloc(MLXSW_REG_SMID_LEN, GFP_KERNEL);
916 	if (!smid_pl)
917 		return -ENOMEM;
918 
919 	mlxsw_reg_smid_pack(smid_pl, mid, mlxsw_sp_port->local_port, add);
920 	if (clear_all_ports) {
921 		for (i = 1; i < MLXSW_PORT_MAX_PORTS; i++)
922 			if (mlxsw_sp->ports[i])
923 				mlxsw_reg_smid_port_mask_set(smid_pl, i, 1);
924 	}
925 	err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(smid), smid_pl);
926 	kfree(smid_pl);
927 	return err;
928 }
929 
930 static struct mlxsw_sp_mid *__mlxsw_sp_mc_get(struct mlxsw_sp *mlxsw_sp,
931 					      const unsigned char *addr,
932 					      u16 vid)
933 {
934 	struct mlxsw_sp_mid *mid;
935 
936 	list_for_each_entry(mid, &mlxsw_sp->br_mids.list, list) {
937 		if (ether_addr_equal(mid->addr, addr) && mid->vid == vid)
938 			return mid;
939 	}
940 	return NULL;
941 }
942 
943 static struct mlxsw_sp_mid *__mlxsw_sp_mc_alloc(struct mlxsw_sp *mlxsw_sp,
944 						const unsigned char *addr,
945 						u16 vid)
946 {
947 	struct mlxsw_sp_mid *mid;
948 	u16 mid_idx;
949 
950 	mid_idx = find_first_zero_bit(mlxsw_sp->br_mids.mapped,
951 				      MLXSW_SP_MID_MAX);
952 	if (mid_idx == MLXSW_SP_MID_MAX)
953 		return NULL;
954 
955 	mid = kzalloc(sizeof(*mid), GFP_KERNEL);
956 	if (!mid)
957 		return NULL;
958 
959 	set_bit(mid_idx, mlxsw_sp->br_mids.mapped);
960 	ether_addr_copy(mid->addr, addr);
961 	mid->vid = vid;
962 	mid->mid = mid_idx;
963 	mid->ref_count = 0;
964 	list_add_tail(&mid->list, &mlxsw_sp->br_mids.list);
965 
966 	return mid;
967 }
968 
969 static int __mlxsw_sp_mc_dec_ref(struct mlxsw_sp *mlxsw_sp,
970 				 struct mlxsw_sp_mid *mid)
971 {
972 	if (--mid->ref_count == 0) {
973 		list_del(&mid->list);
974 		clear_bit(mid->mid, mlxsw_sp->br_mids.mapped);
975 		kfree(mid);
976 		return 1;
977 	}
978 	return 0;
979 }
980 
981 static int mlxsw_sp_port_mdb_add(struct mlxsw_sp_port *mlxsw_sp_port,
982 				 const struct switchdev_obj_port_mdb *mdb,
983 				 struct switchdev_trans *trans)
984 {
985 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
986 	struct net_device *dev = mlxsw_sp_port->dev;
987 	struct mlxsw_sp_mid *mid;
988 	u16 fid = mlxsw_sp_port_vid_to_fid_get(mlxsw_sp_port, mdb->vid);
989 	int err = 0;
990 
991 	if (switchdev_trans_ph_prepare(trans))
992 		return 0;
993 
994 	mid = __mlxsw_sp_mc_get(mlxsw_sp, mdb->addr, mdb->vid);
995 	if (!mid) {
996 		mid = __mlxsw_sp_mc_alloc(mlxsw_sp, mdb->addr, mdb->vid);
997 		if (!mid) {
998 			netdev_err(dev, "Unable to allocate MC group\n");
999 			return -ENOMEM;
1000 		}
1001 	}
1002 	mid->ref_count++;
1003 
1004 	err = mlxsw_sp_port_smid_set(mlxsw_sp_port, mid->mid, true,
1005 				     mid->ref_count == 1);
1006 	if (err) {
1007 		netdev_err(dev, "Unable to set SMID\n");
1008 		goto err_out;
1009 	}
1010 
1011 	if (mid->ref_count == 1) {
1012 		err = mlxsw_sp_port_mdb_op(mlxsw_sp, mdb->addr, fid, mid->mid,
1013 					   true);
1014 		if (err) {
1015 			netdev_err(dev, "Unable to set MC SFD\n");
1016 			goto err_out;
1017 		}
1018 	}
1019 
1020 	return 0;
1021 
1022 err_out:
1023 	__mlxsw_sp_mc_dec_ref(mlxsw_sp, mid);
1024 	return err;
1025 }
1026 
1027 static int mlxsw_sp_port_obj_add(struct net_device *dev,
1028 				 const struct switchdev_obj *obj,
1029 				 struct switchdev_trans *trans)
1030 {
1031 	struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
1032 	int err = 0;
1033 
1034 	mlxsw_sp_port = mlxsw_sp_port_orig_get(obj->orig_dev, mlxsw_sp_port);
1035 	if (!mlxsw_sp_port)
1036 		return -EINVAL;
1037 
1038 	switch (obj->id) {
1039 	case SWITCHDEV_OBJ_ID_PORT_VLAN:
1040 		if (mlxsw_sp_port_is_vport(mlxsw_sp_port))
1041 			return 0;
1042 
1043 		err = mlxsw_sp_port_vlans_add(mlxsw_sp_port,
1044 					      SWITCHDEV_OBJ_PORT_VLAN(obj),
1045 					      trans);
1046 		break;
1047 	case SWITCHDEV_OBJ_ID_PORT_FDB:
1048 		err = mlxsw_sp_port_fdb_static_add(mlxsw_sp_port,
1049 						   SWITCHDEV_OBJ_PORT_FDB(obj),
1050 						   trans);
1051 		break;
1052 	case SWITCHDEV_OBJ_ID_PORT_MDB:
1053 		err = mlxsw_sp_port_mdb_add(mlxsw_sp_port,
1054 					    SWITCHDEV_OBJ_PORT_MDB(obj),
1055 					    trans);
1056 		break;
1057 	default:
1058 		err = -EOPNOTSUPP;
1059 		break;
1060 	}
1061 
1062 	return err;
1063 }
1064 
1065 static int __mlxsw_sp_port_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port,
1066 				     u16 vid_begin, u16 vid_end)
1067 {
1068 	u16 vid, pvid;
1069 
1070 	if (!mlxsw_sp_port->bridged)
1071 		return -EINVAL;
1072 
1073 	mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid_begin, vid_end,
1074 				       false);
1075 
1076 	pvid = mlxsw_sp_port->pvid;
1077 	if (pvid >= vid_begin && pvid <= vid_end)
1078 		mlxsw_sp_port_pvid_set(mlxsw_sp_port, 0);
1079 
1080 	__mlxsw_sp_port_vlans_set(mlxsw_sp_port, vid_begin, vid_end, false,
1081 				  false);
1082 
1083 	mlxsw_sp_port_fid_leave(mlxsw_sp_port, vid_begin, vid_end);
1084 
1085 	/* Changing activity bits only if HW operation succeded */
1086 	for (vid = vid_begin; vid <= vid_end; vid++)
1087 		clear_bit(vid, mlxsw_sp_port->active_vlans);
1088 
1089 	return 0;
1090 }
1091 
1092 static int mlxsw_sp_port_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port,
1093 				   const struct switchdev_obj_port_vlan *vlan)
1094 {
1095 	return __mlxsw_sp_port_vlans_del(mlxsw_sp_port, vlan->vid_begin,
1096 					 vlan->vid_end);
1097 }
1098 
1099 void mlxsw_sp_port_active_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port)
1100 {
1101 	u16 vid;
1102 
1103 	for_each_set_bit(vid, mlxsw_sp_port->active_vlans, VLAN_N_VID)
1104 		__mlxsw_sp_port_vlans_del(mlxsw_sp_port, vid, vid);
1105 }
1106 
1107 static int
1108 mlxsw_sp_port_fdb_static_del(struct mlxsw_sp_port *mlxsw_sp_port,
1109 			     const struct switchdev_obj_port_fdb *fdb)
1110 {
1111 	u16 fid = mlxsw_sp_port_vid_to_fid_get(mlxsw_sp_port, fdb->vid);
1112 	u16 lag_vid = 0;
1113 
1114 	if (mlxsw_sp_port_is_vport(mlxsw_sp_port)) {
1115 		lag_vid = mlxsw_sp_vport_vid_get(mlxsw_sp_port);
1116 	}
1117 
1118 	if (!mlxsw_sp_port->lagged)
1119 		return mlxsw_sp_port_fdb_uc_op(mlxsw_sp_port->mlxsw_sp,
1120 					       mlxsw_sp_port->local_port,
1121 					       fdb->addr, fid,
1122 					       false, false);
1123 	else
1124 		return mlxsw_sp_port_fdb_uc_lag_op(mlxsw_sp_port->mlxsw_sp,
1125 						   mlxsw_sp_port->lag_id,
1126 						   fdb->addr, fid, lag_vid,
1127 						   false, false);
1128 }
1129 
1130 static int mlxsw_sp_port_mdb_del(struct mlxsw_sp_port *mlxsw_sp_port,
1131 				 const struct switchdev_obj_port_mdb *mdb)
1132 {
1133 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1134 	struct net_device *dev = mlxsw_sp_port->dev;
1135 	struct mlxsw_sp_mid *mid;
1136 	u16 fid = mlxsw_sp_port_vid_to_fid_get(mlxsw_sp_port, mdb->vid);
1137 	u16 mid_idx;
1138 	int err = 0;
1139 
1140 	mid = __mlxsw_sp_mc_get(mlxsw_sp, mdb->addr, mdb->vid);
1141 	if (!mid) {
1142 		netdev_err(dev, "Unable to remove port from MC DB\n");
1143 		return -EINVAL;
1144 	}
1145 
1146 	err = mlxsw_sp_port_smid_set(mlxsw_sp_port, mid->mid, false, false);
1147 	if (err)
1148 		netdev_err(dev, "Unable to remove port from SMID\n");
1149 
1150 	mid_idx = mid->mid;
1151 	if (__mlxsw_sp_mc_dec_ref(mlxsw_sp, mid)) {
1152 		err = mlxsw_sp_port_mdb_op(mlxsw_sp, mdb->addr, fid, mid_idx,
1153 					   false);
1154 		if (err)
1155 			netdev_err(dev, "Unable to remove MC SFD\n");
1156 	}
1157 
1158 	return err;
1159 }
1160 
1161 static int mlxsw_sp_port_obj_del(struct net_device *dev,
1162 				 const struct switchdev_obj *obj)
1163 {
1164 	struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
1165 	int err = 0;
1166 
1167 	mlxsw_sp_port = mlxsw_sp_port_orig_get(obj->orig_dev, mlxsw_sp_port);
1168 	if (!mlxsw_sp_port)
1169 		return -EINVAL;
1170 
1171 	switch (obj->id) {
1172 	case SWITCHDEV_OBJ_ID_PORT_VLAN:
1173 		if (mlxsw_sp_port_is_vport(mlxsw_sp_port))
1174 			return 0;
1175 
1176 		err = mlxsw_sp_port_vlans_del(mlxsw_sp_port,
1177 					      SWITCHDEV_OBJ_PORT_VLAN(obj));
1178 		break;
1179 	case SWITCHDEV_OBJ_ID_PORT_FDB:
1180 		err = mlxsw_sp_port_fdb_static_del(mlxsw_sp_port,
1181 						   SWITCHDEV_OBJ_PORT_FDB(obj));
1182 		break;
1183 	case SWITCHDEV_OBJ_ID_PORT_MDB:
1184 		err = mlxsw_sp_port_mdb_del(mlxsw_sp_port,
1185 					    SWITCHDEV_OBJ_PORT_MDB(obj));
1186 		break;
1187 	default:
1188 		err = -EOPNOTSUPP;
1189 		break;
1190 	}
1191 
1192 	return err;
1193 }
1194 
1195 static struct mlxsw_sp_port *mlxsw_sp_lag_rep_port(struct mlxsw_sp *mlxsw_sp,
1196 						   u16 lag_id)
1197 {
1198 	struct mlxsw_sp_port *mlxsw_sp_port;
1199 	struct mlxsw_resources *resources;
1200 	int i;
1201 
1202 	resources = mlxsw_core_resources_get(mlxsw_sp->core);
1203 	for (i = 0; i < resources->max_ports_in_lag; i++) {
1204 		mlxsw_sp_port = mlxsw_sp_port_lagged_get(mlxsw_sp, lag_id, i);
1205 		if (mlxsw_sp_port)
1206 			return mlxsw_sp_port;
1207 	}
1208 	return NULL;
1209 }
1210 
1211 static int mlxsw_sp_port_fdb_dump(struct mlxsw_sp_port *mlxsw_sp_port,
1212 				  struct switchdev_obj_port_fdb *fdb,
1213 				  switchdev_obj_dump_cb_t *cb,
1214 				  struct net_device *orig_dev)
1215 {
1216 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1217 	struct mlxsw_sp_port *tmp;
1218 	struct mlxsw_sp_fid *f;
1219 	u16 vport_fid;
1220 	char *sfd_pl;
1221 	char mac[ETH_ALEN];
1222 	u16 fid;
1223 	u8 local_port;
1224 	u16 lag_id;
1225 	u8 num_rec;
1226 	int stored_err = 0;
1227 	int i;
1228 	int err;
1229 
1230 	sfd_pl = kmalloc(MLXSW_REG_SFD_LEN, GFP_KERNEL);
1231 	if (!sfd_pl)
1232 		return -ENOMEM;
1233 
1234 	f = mlxsw_sp_vport_fid_get(mlxsw_sp_port);
1235 	vport_fid = f ? f->fid : 0;
1236 
1237 	mlxsw_reg_sfd_pack(sfd_pl, MLXSW_REG_SFD_OP_QUERY_DUMP, 0);
1238 	do {
1239 		mlxsw_reg_sfd_num_rec_set(sfd_pl, MLXSW_REG_SFD_REC_MAX_COUNT);
1240 		err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(sfd), sfd_pl);
1241 		if (err)
1242 			goto out;
1243 
1244 		num_rec = mlxsw_reg_sfd_num_rec_get(sfd_pl);
1245 
1246 		/* Even in case of error, we have to run the dump to the end
1247 		 * so the session in firmware is finished.
1248 		 */
1249 		if (stored_err)
1250 			continue;
1251 
1252 		for (i = 0; i < num_rec; i++) {
1253 			switch (mlxsw_reg_sfd_rec_type_get(sfd_pl, i)) {
1254 			case MLXSW_REG_SFD_REC_TYPE_UNICAST:
1255 				mlxsw_reg_sfd_uc_unpack(sfd_pl, i, mac, &fid,
1256 							&local_port);
1257 				if (local_port == mlxsw_sp_port->local_port) {
1258 					if (vport_fid && vport_fid == fid)
1259 						fdb->vid = 0;
1260 					else if (!vport_fid &&
1261 						 !mlxsw_sp_fid_is_vfid(fid))
1262 						fdb->vid = fid;
1263 					else
1264 						continue;
1265 					ether_addr_copy(fdb->addr, mac);
1266 					fdb->ndm_state = NUD_REACHABLE;
1267 					err = cb(&fdb->obj);
1268 					if (err)
1269 						stored_err = err;
1270 				}
1271 				break;
1272 			case MLXSW_REG_SFD_REC_TYPE_UNICAST_LAG:
1273 				mlxsw_reg_sfd_uc_lag_unpack(sfd_pl, i,
1274 							    mac, &fid, &lag_id);
1275 				tmp = mlxsw_sp_lag_rep_port(mlxsw_sp, lag_id);
1276 				if (tmp && tmp->local_port ==
1277 				    mlxsw_sp_port->local_port) {
1278 					/* LAG records can only point to LAG
1279 					 * devices or VLAN devices on top.
1280 					 */
1281 					if (!netif_is_lag_master(orig_dev) &&
1282 					    !is_vlan_dev(orig_dev))
1283 						continue;
1284 					if (vport_fid && vport_fid == fid)
1285 						fdb->vid = 0;
1286 					else if (!vport_fid &&
1287 						 !mlxsw_sp_fid_is_vfid(fid))
1288 						fdb->vid = fid;
1289 					else
1290 						continue;
1291 					ether_addr_copy(fdb->addr, mac);
1292 					fdb->ndm_state = NUD_REACHABLE;
1293 					err = cb(&fdb->obj);
1294 					if (err)
1295 						stored_err = err;
1296 				}
1297 				break;
1298 			}
1299 		}
1300 	} while (num_rec == MLXSW_REG_SFD_REC_MAX_COUNT);
1301 
1302 out:
1303 	kfree(sfd_pl);
1304 	return stored_err ? stored_err : err;
1305 }
1306 
1307 static int mlxsw_sp_port_vlan_dump(struct mlxsw_sp_port *mlxsw_sp_port,
1308 				   struct switchdev_obj_port_vlan *vlan,
1309 				   switchdev_obj_dump_cb_t *cb)
1310 {
1311 	u16 vid;
1312 	int err = 0;
1313 
1314 	if (mlxsw_sp_port_is_vport(mlxsw_sp_port)) {
1315 		vlan->flags = 0;
1316 		vlan->vid_begin = mlxsw_sp_vport_vid_get(mlxsw_sp_port);
1317 		vlan->vid_end = mlxsw_sp_vport_vid_get(mlxsw_sp_port);
1318 		return cb(&vlan->obj);
1319 	}
1320 
1321 	for_each_set_bit(vid, mlxsw_sp_port->active_vlans, VLAN_N_VID) {
1322 		vlan->flags = 0;
1323 		if (vid == mlxsw_sp_port->pvid)
1324 			vlan->flags |= BRIDGE_VLAN_INFO_PVID;
1325 		if (test_bit(vid, mlxsw_sp_port->untagged_vlans))
1326 			vlan->flags |= BRIDGE_VLAN_INFO_UNTAGGED;
1327 		vlan->vid_begin = vid;
1328 		vlan->vid_end = vid;
1329 		err = cb(&vlan->obj);
1330 		if (err)
1331 			break;
1332 	}
1333 	return err;
1334 }
1335 
1336 static int mlxsw_sp_port_obj_dump(struct net_device *dev,
1337 				  struct switchdev_obj *obj,
1338 				  switchdev_obj_dump_cb_t *cb)
1339 {
1340 	struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
1341 	int err = 0;
1342 
1343 	mlxsw_sp_port = mlxsw_sp_port_orig_get(obj->orig_dev, mlxsw_sp_port);
1344 	if (!mlxsw_sp_port)
1345 		return -EINVAL;
1346 
1347 	switch (obj->id) {
1348 	case SWITCHDEV_OBJ_ID_PORT_VLAN:
1349 		err = mlxsw_sp_port_vlan_dump(mlxsw_sp_port,
1350 					      SWITCHDEV_OBJ_PORT_VLAN(obj), cb);
1351 		break;
1352 	case SWITCHDEV_OBJ_ID_PORT_FDB:
1353 		err = mlxsw_sp_port_fdb_dump(mlxsw_sp_port,
1354 					     SWITCHDEV_OBJ_PORT_FDB(obj), cb,
1355 					     obj->orig_dev);
1356 		break;
1357 	default:
1358 		err = -EOPNOTSUPP;
1359 		break;
1360 	}
1361 
1362 	return err;
1363 }
1364 
1365 static const struct switchdev_ops mlxsw_sp_port_switchdev_ops = {
1366 	.switchdev_port_attr_get	= mlxsw_sp_port_attr_get,
1367 	.switchdev_port_attr_set	= mlxsw_sp_port_attr_set,
1368 	.switchdev_port_obj_add		= mlxsw_sp_port_obj_add,
1369 	.switchdev_port_obj_del		= mlxsw_sp_port_obj_del,
1370 	.switchdev_port_obj_dump	= mlxsw_sp_port_obj_dump,
1371 };
1372 
1373 static void mlxsw_sp_fdb_call_notifiers(bool learning_sync, bool adding,
1374 					char *mac, u16 vid,
1375 					struct net_device *dev)
1376 {
1377 	struct switchdev_notifier_fdb_info info;
1378 	unsigned long notifier_type;
1379 
1380 	if (learning_sync) {
1381 		info.addr = mac;
1382 		info.vid = vid;
1383 		notifier_type = adding ? SWITCHDEV_FDB_ADD : SWITCHDEV_FDB_DEL;
1384 		call_switchdev_notifiers(notifier_type, dev, &info.info);
1385 	}
1386 }
1387 
1388 static void mlxsw_sp_fdb_notify_mac_process(struct mlxsw_sp *mlxsw_sp,
1389 					    char *sfn_pl, int rec_index,
1390 					    bool adding)
1391 {
1392 	struct mlxsw_sp_port *mlxsw_sp_port;
1393 	char mac[ETH_ALEN];
1394 	u8 local_port;
1395 	u16 vid, fid;
1396 	bool do_notification = true;
1397 	int err;
1398 
1399 	mlxsw_reg_sfn_mac_unpack(sfn_pl, rec_index, mac, &fid, &local_port);
1400 	mlxsw_sp_port = mlxsw_sp->ports[local_port];
1401 	if (!mlxsw_sp_port) {
1402 		dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Incorrect local port in FDB notification\n");
1403 		goto just_remove;
1404 	}
1405 
1406 	if (mlxsw_sp_fid_is_vfid(fid)) {
1407 		struct mlxsw_sp_port *mlxsw_sp_vport;
1408 
1409 		mlxsw_sp_vport = mlxsw_sp_port_vport_find_by_fid(mlxsw_sp_port,
1410 								 fid);
1411 		if (!mlxsw_sp_vport) {
1412 			netdev_err(mlxsw_sp_port->dev, "Failed to find a matching vPort following FDB notification\n");
1413 			goto just_remove;
1414 		}
1415 		vid = 0;
1416 		/* Override the physical port with the vPort. */
1417 		mlxsw_sp_port = mlxsw_sp_vport;
1418 	} else {
1419 		vid = fid;
1420 	}
1421 
1422 do_fdb_op:
1423 	err = mlxsw_sp_port_fdb_uc_op(mlxsw_sp, local_port, mac, fid,
1424 				      adding, true);
1425 	if (err) {
1426 		if (net_ratelimit())
1427 			netdev_err(mlxsw_sp_port->dev, "Failed to set FDB entry\n");
1428 		return;
1429 	}
1430 
1431 	if (!do_notification)
1432 		return;
1433 	mlxsw_sp_fdb_call_notifiers(mlxsw_sp_port->learning_sync,
1434 				    adding, mac, vid, mlxsw_sp_port->dev);
1435 	return;
1436 
1437 just_remove:
1438 	adding = false;
1439 	do_notification = false;
1440 	goto do_fdb_op;
1441 }
1442 
1443 static void mlxsw_sp_fdb_notify_mac_lag_process(struct mlxsw_sp *mlxsw_sp,
1444 						char *sfn_pl, int rec_index,
1445 						bool adding)
1446 {
1447 	struct mlxsw_sp_port *mlxsw_sp_port;
1448 	struct net_device *dev;
1449 	char mac[ETH_ALEN];
1450 	u16 lag_vid = 0;
1451 	u16 lag_id;
1452 	u16 vid, fid;
1453 	bool do_notification = true;
1454 	int err;
1455 
1456 	mlxsw_reg_sfn_mac_lag_unpack(sfn_pl, rec_index, mac, &fid, &lag_id);
1457 	mlxsw_sp_port = mlxsw_sp_lag_rep_port(mlxsw_sp, lag_id);
1458 	if (!mlxsw_sp_port) {
1459 		dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Cannot find port representor for LAG\n");
1460 		goto just_remove;
1461 	}
1462 
1463 	if (mlxsw_sp_fid_is_vfid(fid)) {
1464 		struct mlxsw_sp_port *mlxsw_sp_vport;
1465 
1466 		mlxsw_sp_vport = mlxsw_sp_port_vport_find_by_fid(mlxsw_sp_port,
1467 								 fid);
1468 		if (!mlxsw_sp_vport) {
1469 			netdev_err(mlxsw_sp_port->dev, "Failed to find a matching vPort following FDB notification\n");
1470 			goto just_remove;
1471 		}
1472 
1473 		lag_vid = mlxsw_sp_vport_vid_get(mlxsw_sp_vport);
1474 		dev = mlxsw_sp_vport->dev;
1475 		vid = 0;
1476 		/* Override the physical port with the vPort. */
1477 		mlxsw_sp_port = mlxsw_sp_vport;
1478 	} else {
1479 		dev = mlxsw_sp_lag_get(mlxsw_sp, lag_id)->dev;
1480 		vid = fid;
1481 	}
1482 
1483 do_fdb_op:
1484 	err = mlxsw_sp_port_fdb_uc_lag_op(mlxsw_sp, lag_id, mac, fid, lag_vid,
1485 					  adding, true);
1486 	if (err) {
1487 		if (net_ratelimit())
1488 			netdev_err(mlxsw_sp_port->dev, "Failed to set FDB entry\n");
1489 		return;
1490 	}
1491 
1492 	if (!do_notification)
1493 		return;
1494 	mlxsw_sp_fdb_call_notifiers(mlxsw_sp_port->learning_sync, adding, mac,
1495 				    vid, dev);
1496 	return;
1497 
1498 just_remove:
1499 	adding = false;
1500 	do_notification = false;
1501 	goto do_fdb_op;
1502 }
1503 
1504 static void mlxsw_sp_fdb_notify_rec_process(struct mlxsw_sp *mlxsw_sp,
1505 					    char *sfn_pl, int rec_index)
1506 {
1507 	switch (mlxsw_reg_sfn_rec_type_get(sfn_pl, rec_index)) {
1508 	case MLXSW_REG_SFN_REC_TYPE_LEARNED_MAC:
1509 		mlxsw_sp_fdb_notify_mac_process(mlxsw_sp, sfn_pl,
1510 						rec_index, true);
1511 		break;
1512 	case MLXSW_REG_SFN_REC_TYPE_AGED_OUT_MAC:
1513 		mlxsw_sp_fdb_notify_mac_process(mlxsw_sp, sfn_pl,
1514 						rec_index, false);
1515 		break;
1516 	case MLXSW_REG_SFN_REC_TYPE_LEARNED_MAC_LAG:
1517 		mlxsw_sp_fdb_notify_mac_lag_process(mlxsw_sp, sfn_pl,
1518 						    rec_index, true);
1519 		break;
1520 	case MLXSW_REG_SFN_REC_TYPE_AGED_OUT_MAC_LAG:
1521 		mlxsw_sp_fdb_notify_mac_lag_process(mlxsw_sp, sfn_pl,
1522 						    rec_index, false);
1523 		break;
1524 	}
1525 }
1526 
1527 static void mlxsw_sp_fdb_notify_work_schedule(struct mlxsw_sp *mlxsw_sp)
1528 {
1529 	mlxsw_core_schedule_dw(&mlxsw_sp->fdb_notify.dw,
1530 			       msecs_to_jiffies(mlxsw_sp->fdb_notify.interval));
1531 }
1532 
1533 static void mlxsw_sp_fdb_notify_work(struct work_struct *work)
1534 {
1535 	struct mlxsw_sp *mlxsw_sp;
1536 	char *sfn_pl;
1537 	u8 num_rec;
1538 	int i;
1539 	int err;
1540 
1541 	sfn_pl = kmalloc(MLXSW_REG_SFN_LEN, GFP_KERNEL);
1542 	if (!sfn_pl)
1543 		return;
1544 
1545 	mlxsw_sp = container_of(work, struct mlxsw_sp, fdb_notify.dw.work);
1546 
1547 	rtnl_lock();
1548 	mlxsw_reg_sfn_pack(sfn_pl);
1549 	err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(sfn), sfn_pl);
1550 	if (err) {
1551 		dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Failed to get FDB notifications\n");
1552 		goto out;
1553 	}
1554 	num_rec = mlxsw_reg_sfn_num_rec_get(sfn_pl);
1555 	for (i = 0; i < num_rec; i++)
1556 		mlxsw_sp_fdb_notify_rec_process(mlxsw_sp, sfn_pl, i);
1557 
1558 out:
1559 	rtnl_unlock();
1560 	kfree(sfn_pl);
1561 	mlxsw_sp_fdb_notify_work_schedule(mlxsw_sp);
1562 }
1563 
1564 static int mlxsw_sp_fdb_init(struct mlxsw_sp *mlxsw_sp)
1565 {
1566 	int err;
1567 
1568 	err = mlxsw_sp_ageing_set(mlxsw_sp, MLXSW_SP_DEFAULT_AGEING_TIME);
1569 	if (err) {
1570 		dev_err(mlxsw_sp->bus_info->dev, "Failed to set default ageing time\n");
1571 		return err;
1572 	}
1573 	INIT_DELAYED_WORK(&mlxsw_sp->fdb_notify.dw, mlxsw_sp_fdb_notify_work);
1574 	mlxsw_sp->fdb_notify.interval = MLXSW_SP_DEFAULT_LEARNING_INTERVAL;
1575 	mlxsw_sp_fdb_notify_work_schedule(mlxsw_sp);
1576 	return 0;
1577 }
1578 
1579 static void mlxsw_sp_fdb_fini(struct mlxsw_sp *mlxsw_sp)
1580 {
1581 	cancel_delayed_work_sync(&mlxsw_sp->fdb_notify.dw);
1582 }
1583 
1584 int mlxsw_sp_switchdev_init(struct mlxsw_sp *mlxsw_sp)
1585 {
1586 	return mlxsw_sp_fdb_init(mlxsw_sp);
1587 }
1588 
1589 void mlxsw_sp_switchdev_fini(struct mlxsw_sp *mlxsw_sp)
1590 {
1591 	mlxsw_sp_fdb_fini(mlxsw_sp);
1592 }
1593 
1594 void mlxsw_sp_port_switchdev_init(struct mlxsw_sp_port *mlxsw_sp_port)
1595 {
1596 	mlxsw_sp_port->dev->switchdev_ops = &mlxsw_sp_port_switchdev_ops;
1597 }
1598 
1599 void mlxsw_sp_port_switchdev_fini(struct mlxsw_sp_port *mlxsw_sp_port)
1600 {
1601 }
1602