1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /* Copyright (c) 2017-2018 Mellanox Technologies. All rights reserved */
3 
4 #include <linux/kernel.h>
5 #include <linux/bitops.h>
6 #include <linux/if_vlan.h>
7 #include <linux/if_bridge.h>
8 #include <linux/netdevice.h>
9 #include <linux/rhashtable.h>
10 #include <linux/rtnetlink.h>
11 #include <linux/refcount.h>
12 
13 #include "spectrum.h"
14 #include "reg.h"
15 
16 struct mlxsw_sp_fid_family;
17 
18 struct mlxsw_sp_fid_core {
19 	struct rhashtable fid_ht;
20 	struct rhashtable vni_ht;
21 	struct mlxsw_sp_fid_family *fid_family_arr[MLXSW_SP_FID_TYPE_MAX];
22 	unsigned int *port_fid_mappings;
23 };
24 
25 struct mlxsw_sp_fid_port_vid {
26 	struct list_head list;
27 	u16 local_port;
28 	u16 vid;
29 };
30 
31 struct mlxsw_sp_fid {
32 	struct list_head list;
33 	struct mlxsw_sp_rif *rif;
34 	refcount_t ref_count;
35 	u16 fid_index;
36 	u16 fid_offset;
37 	struct mlxsw_sp_fid_family *fid_family;
38 	struct rhash_head ht_node;
39 
40 	struct rhash_head vni_ht_node;
41 	enum mlxsw_sp_nve_type nve_type;
42 	__be32 vni;
43 	u32 nve_flood_index;
44 	int nve_ifindex;
45 	u8 vni_valid:1,
46 	   nve_flood_index_valid:1;
47 	struct list_head port_vid_list; /* Ordered by local port. */
48 };
49 
50 struct mlxsw_sp_fid_8021q {
51 	struct mlxsw_sp_fid common;
52 	u16 vid;
53 };
54 
55 struct mlxsw_sp_fid_8021d {
56 	struct mlxsw_sp_fid common;
57 	int br_ifindex;
58 };
59 
60 static const struct rhashtable_params mlxsw_sp_fid_ht_params = {
61 	.key_len = sizeof_field(struct mlxsw_sp_fid, fid_index),
62 	.key_offset = offsetof(struct mlxsw_sp_fid, fid_index),
63 	.head_offset = offsetof(struct mlxsw_sp_fid, ht_node),
64 };
65 
66 static const struct rhashtable_params mlxsw_sp_fid_vni_ht_params = {
67 	.key_len = sizeof_field(struct mlxsw_sp_fid, vni),
68 	.key_offset = offsetof(struct mlxsw_sp_fid, vni),
69 	.head_offset = offsetof(struct mlxsw_sp_fid, vni_ht_node),
70 };
71 
72 struct mlxsw_sp_flood_table {
73 	enum mlxsw_sp_flood_type packet_type;
74 	enum mlxsw_flood_table_type table_type;
75 	int table_index;
76 };
77 
78 struct mlxsw_sp_fid_ops {
79 	void (*setup)(struct mlxsw_sp_fid *fid, const void *arg);
80 	int (*configure)(struct mlxsw_sp_fid *fid);
81 	void (*deconfigure)(struct mlxsw_sp_fid *fid);
82 	int (*index_alloc)(struct mlxsw_sp_fid *fid, const void *arg,
83 			   u16 *p_fid_index);
84 	bool (*compare)(const struct mlxsw_sp_fid *fid,
85 			const void *arg);
86 	u16 (*flood_index)(const struct mlxsw_sp_fid *fid);
87 	int (*port_vid_map)(struct mlxsw_sp_fid *fid,
88 			    struct mlxsw_sp_port *port, u16 vid);
89 	void (*port_vid_unmap)(struct mlxsw_sp_fid *fid,
90 			       struct mlxsw_sp_port *port, u16 vid);
91 	int (*vni_set)(struct mlxsw_sp_fid *fid);
92 	void (*vni_clear)(struct mlxsw_sp_fid *fid);
93 	int (*nve_flood_index_set)(struct mlxsw_sp_fid *fid);
94 	void (*nve_flood_index_clear)(struct mlxsw_sp_fid *fid);
95 	void (*fdb_clear_offload)(const struct mlxsw_sp_fid *fid,
96 				  const struct net_device *nve_dev);
97 };
98 
99 struct mlxsw_sp_fid_family {
100 	enum mlxsw_sp_fid_type type;
101 	size_t fid_size;
102 	u16 start_index;
103 	u16 end_index;
104 	struct list_head fids_list;
105 	unsigned long *fids_bitmap;
106 	const struct mlxsw_sp_flood_table *flood_tables;
107 	int nr_flood_tables;
108 	enum mlxsw_sp_rif_type rif_type;
109 	const struct mlxsw_sp_fid_ops *ops;
110 	struct mlxsw_sp *mlxsw_sp;
111 	bool flood_rsp;
112 	enum mlxsw_reg_bridge_type bridge_type;
113 	u16 pgt_base;
114 };
115 
116 static const int mlxsw_sp_sfgc_uc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = {
117 	[MLXSW_REG_SFGC_TYPE_UNKNOWN_UNICAST]			= 1,
118 };
119 
120 static const int mlxsw_sp_sfgc_bc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = {
121 	[MLXSW_REG_SFGC_TYPE_BROADCAST]				= 1,
122 	[MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_NON_IP]	= 1,
123 	[MLXSW_REG_SFGC_TYPE_IPV4_LINK_LOCAL]			= 1,
124 	[MLXSW_REG_SFGC_TYPE_IPV6_ALL_HOST]			= 1,
125 	[MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV6]	= 1,
126 };
127 
128 static const int mlxsw_sp_sfgc_mc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = {
129 	[MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV4]	= 1,
130 };
131 
132 static const int *mlxsw_sp_packet_type_sfgc_types[] = {
133 	[MLXSW_SP_FLOOD_TYPE_UC]	= mlxsw_sp_sfgc_uc_packet_types,
134 	[MLXSW_SP_FLOOD_TYPE_BC]	= mlxsw_sp_sfgc_bc_packet_types,
135 	[MLXSW_SP_FLOOD_TYPE_MC]	= mlxsw_sp_sfgc_mc_packet_types,
136 };
137 
138 bool mlxsw_sp_fid_is_dummy(struct mlxsw_sp *mlxsw_sp, u16 fid_index)
139 {
140 	enum mlxsw_sp_fid_type fid_type = MLXSW_SP_FID_TYPE_DUMMY;
141 	struct mlxsw_sp_fid_family *fid_family;
142 
143 	fid_family = mlxsw_sp->fid_core->fid_family_arr[fid_type];
144 
145 	return fid_family->start_index == fid_index;
146 }
147 
148 struct mlxsw_sp_fid *mlxsw_sp_fid_lookup_by_index(struct mlxsw_sp *mlxsw_sp,
149 						  u16 fid_index)
150 {
151 	struct mlxsw_sp_fid *fid;
152 
153 	fid = rhashtable_lookup_fast(&mlxsw_sp->fid_core->fid_ht, &fid_index,
154 				     mlxsw_sp_fid_ht_params);
155 	if (fid)
156 		refcount_inc(&fid->ref_count);
157 
158 	return fid;
159 }
160 
161 int mlxsw_sp_fid_nve_ifindex(const struct mlxsw_sp_fid *fid, int *nve_ifindex)
162 {
163 	if (!fid->vni_valid)
164 		return -EINVAL;
165 
166 	*nve_ifindex = fid->nve_ifindex;
167 
168 	return 0;
169 }
170 
171 int mlxsw_sp_fid_nve_type(const struct mlxsw_sp_fid *fid,
172 			  enum mlxsw_sp_nve_type *p_type)
173 {
174 	if (!fid->vni_valid)
175 		return -EINVAL;
176 
177 	*p_type = fid->nve_type;
178 
179 	return 0;
180 }
181 
182 struct mlxsw_sp_fid *mlxsw_sp_fid_lookup_by_vni(struct mlxsw_sp *mlxsw_sp,
183 						__be32 vni)
184 {
185 	struct mlxsw_sp_fid *fid;
186 
187 	fid = rhashtable_lookup_fast(&mlxsw_sp->fid_core->vni_ht, &vni,
188 				     mlxsw_sp_fid_vni_ht_params);
189 	if (fid)
190 		refcount_inc(&fid->ref_count);
191 
192 	return fid;
193 }
194 
195 int mlxsw_sp_fid_vni(const struct mlxsw_sp_fid *fid, __be32 *vni)
196 {
197 	if (!fid->vni_valid)
198 		return -EINVAL;
199 
200 	*vni = fid->vni;
201 
202 	return 0;
203 }
204 
205 int mlxsw_sp_fid_nve_flood_index_set(struct mlxsw_sp_fid *fid,
206 				     u32 nve_flood_index)
207 {
208 	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
209 	const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
210 	int err;
211 
212 	if (WARN_ON(fid->nve_flood_index_valid))
213 		return -EINVAL;
214 
215 	fid->nve_flood_index = nve_flood_index;
216 	fid->nve_flood_index_valid = true;
217 	err = ops->nve_flood_index_set(fid);
218 	if (err)
219 		goto err_nve_flood_index_set;
220 
221 	return 0;
222 
223 err_nve_flood_index_set:
224 	fid->nve_flood_index_valid = false;
225 	return err;
226 }
227 
228 void mlxsw_sp_fid_nve_flood_index_clear(struct mlxsw_sp_fid *fid)
229 {
230 	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
231 	const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
232 
233 	if (WARN_ON(!fid->nve_flood_index_valid))
234 		return;
235 
236 	fid->nve_flood_index_valid = false;
237 	ops->nve_flood_index_clear(fid);
238 }
239 
240 bool mlxsw_sp_fid_nve_flood_index_is_set(const struct mlxsw_sp_fid *fid)
241 {
242 	return fid->nve_flood_index_valid;
243 }
244 
245 int mlxsw_sp_fid_vni_set(struct mlxsw_sp_fid *fid, enum mlxsw_sp_nve_type type,
246 			 __be32 vni, int nve_ifindex)
247 {
248 	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
249 	const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
250 	struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
251 	int err;
252 
253 	if (WARN_ON(fid->vni_valid))
254 		return -EINVAL;
255 
256 	fid->nve_type = type;
257 	fid->nve_ifindex = nve_ifindex;
258 	fid->vni = vni;
259 	err = rhashtable_lookup_insert_fast(&mlxsw_sp->fid_core->vni_ht,
260 					    &fid->vni_ht_node,
261 					    mlxsw_sp_fid_vni_ht_params);
262 	if (err)
263 		return err;
264 
265 	fid->vni_valid = true;
266 	err = ops->vni_set(fid);
267 	if (err)
268 		goto err_vni_set;
269 
270 	return 0;
271 
272 err_vni_set:
273 	fid->vni_valid = false;
274 	rhashtable_remove_fast(&mlxsw_sp->fid_core->vni_ht, &fid->vni_ht_node,
275 			       mlxsw_sp_fid_vni_ht_params);
276 	return err;
277 }
278 
279 void mlxsw_sp_fid_vni_clear(struct mlxsw_sp_fid *fid)
280 {
281 	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
282 	const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
283 	struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
284 
285 	if (WARN_ON(!fid->vni_valid))
286 		return;
287 
288 	fid->vni_valid = false;
289 	ops->vni_clear(fid);
290 	rhashtable_remove_fast(&mlxsw_sp->fid_core->vni_ht, &fid->vni_ht_node,
291 			       mlxsw_sp_fid_vni_ht_params);
292 }
293 
294 bool mlxsw_sp_fid_vni_is_set(const struct mlxsw_sp_fid *fid)
295 {
296 	return fid->vni_valid;
297 }
298 
299 void mlxsw_sp_fid_fdb_clear_offload(const struct mlxsw_sp_fid *fid,
300 				    const struct net_device *nve_dev)
301 {
302 	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
303 	const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
304 
305 	if (ops->fdb_clear_offload)
306 		ops->fdb_clear_offload(fid, nve_dev);
307 }
308 
309 static const struct mlxsw_sp_flood_table *
310 mlxsw_sp_fid_flood_table_lookup(const struct mlxsw_sp_fid *fid,
311 				enum mlxsw_sp_flood_type packet_type)
312 {
313 	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
314 	int i;
315 
316 	for (i = 0; i < fid_family->nr_flood_tables; i++) {
317 		if (fid_family->flood_tables[i].packet_type != packet_type)
318 			continue;
319 		return &fid_family->flood_tables[i];
320 	}
321 
322 	return NULL;
323 }
324 
325 static u16
326 mlxsw_sp_fid_family_num_fids(const struct mlxsw_sp_fid_family *fid_family)
327 {
328 	return fid_family->end_index - fid_family->start_index + 1;
329 }
330 
331 static u16
332 mlxsw_sp_fid_flood_table_mid(const struct mlxsw_sp_fid_family *fid_family,
333 			     const struct mlxsw_sp_flood_table *flood_table,
334 			     u16 fid_offset)
335 {
336 	u16 num_fids;
337 
338 	num_fids = mlxsw_sp_fid_family_num_fids(fid_family);
339 	return fid_family->pgt_base + num_fids * flood_table->table_index +
340 	       fid_offset;
341 }
342 
343 int mlxsw_sp_fid_flood_set(struct mlxsw_sp_fid *fid,
344 			   enum mlxsw_sp_flood_type packet_type, u16 local_port,
345 			   bool member)
346 {
347 	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
348 	const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
349 	const struct mlxsw_sp_flood_table *flood_table;
350 	char *sftr2_pl;
351 	u16 mid_index;
352 	int err;
353 
354 	if (WARN_ON(!fid_family->flood_tables || !ops->flood_index))
355 		return -EINVAL;
356 
357 	flood_table = mlxsw_sp_fid_flood_table_lookup(fid, packet_type);
358 	if (!flood_table)
359 		return -ESRCH;
360 
361 	if (fid_family->mlxsw_sp->ubridge) {
362 		mid_index = mlxsw_sp_fid_flood_table_mid(fid_family,
363 							 flood_table,
364 							 fid->fid_offset);
365 		return mlxsw_sp_pgt_entry_port_set(fid_family->mlxsw_sp,
366 						   mid_index, fid->fid_index,
367 						   local_port, member);
368 	}
369 
370 	sftr2_pl = kmalloc(MLXSW_REG_SFTR2_LEN, GFP_KERNEL);
371 	if (!sftr2_pl)
372 		return -ENOMEM;
373 
374 	mlxsw_reg_sftr2_pack(sftr2_pl, flood_table->table_index,
375 			     ops->flood_index(fid), flood_table->table_type, 1,
376 			     local_port, member);
377 	err = mlxsw_reg_write(fid_family->mlxsw_sp->core, MLXSW_REG(sftr2),
378 			      sftr2_pl);
379 	kfree(sftr2_pl);
380 	return err;
381 }
382 
383 int mlxsw_sp_fid_port_vid_map(struct mlxsw_sp_fid *fid,
384 			      struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
385 {
386 	if (WARN_ON(!fid->fid_family->ops->port_vid_map))
387 		return -EINVAL;
388 	return fid->fid_family->ops->port_vid_map(fid, mlxsw_sp_port, vid);
389 }
390 
391 void mlxsw_sp_fid_port_vid_unmap(struct mlxsw_sp_fid *fid,
392 				 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
393 {
394 	fid->fid_family->ops->port_vid_unmap(fid, mlxsw_sp_port, vid);
395 }
396 
397 u16 mlxsw_sp_fid_index(const struct mlxsw_sp_fid *fid)
398 {
399 	return fid->fid_index;
400 }
401 
402 enum mlxsw_sp_fid_type mlxsw_sp_fid_type(const struct mlxsw_sp_fid *fid)
403 {
404 	return fid->fid_family->type;
405 }
406 
407 void mlxsw_sp_fid_rif_set(struct mlxsw_sp_fid *fid, struct mlxsw_sp_rif *rif)
408 {
409 	fid->rif = rif;
410 }
411 
412 struct mlxsw_sp_rif *mlxsw_sp_fid_rif(const struct mlxsw_sp_fid *fid)
413 {
414 	return fid->rif;
415 }
416 
417 enum mlxsw_sp_rif_type
418 mlxsw_sp_fid_type_rif_type(const struct mlxsw_sp *mlxsw_sp,
419 			   enum mlxsw_sp_fid_type type)
420 {
421 	struct mlxsw_sp_fid_core *fid_core = mlxsw_sp->fid_core;
422 
423 	return fid_core->fid_family_arr[type]->rif_type;
424 }
425 
426 static struct mlxsw_sp_fid_8021q *
427 mlxsw_sp_fid_8021q_fid(const struct mlxsw_sp_fid *fid)
428 {
429 	return container_of(fid, struct mlxsw_sp_fid_8021q, common);
430 }
431 
432 u16 mlxsw_sp_fid_8021q_vid(const struct mlxsw_sp_fid *fid)
433 {
434 	return mlxsw_sp_fid_8021q_fid(fid)->vid;
435 }
436 
437 static void mlxsw_sp_fid_8021q_setup(struct mlxsw_sp_fid *fid, const void *arg)
438 {
439 	u16 vid = *(u16 *) arg;
440 
441 	mlxsw_sp_fid_8021q_fid(fid)->vid = vid;
442 	fid->fid_offset = 0;
443 }
444 
445 static enum mlxsw_reg_sfmr_op mlxsw_sp_sfmr_op(bool valid)
446 {
447 	return valid ? MLXSW_REG_SFMR_OP_CREATE_FID :
448 		       MLXSW_REG_SFMR_OP_DESTROY_FID;
449 }
450 
451 static int mlxsw_sp_fid_op(const struct mlxsw_sp_fid *fid, bool valid)
452 {
453 	struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
454 	enum mlxsw_reg_bridge_type bridge_type = 0;
455 	char sfmr_pl[MLXSW_REG_SFMR_LEN];
456 	bool flood_rsp = false;
457 
458 	if (mlxsw_sp->ubridge) {
459 		flood_rsp = fid->fid_family->flood_rsp;
460 		bridge_type = fid->fid_family->bridge_type;
461 	}
462 
463 	mlxsw_reg_sfmr_pack(sfmr_pl, mlxsw_sp_sfmr_op(valid), fid->fid_index,
464 			    fid->fid_offset, flood_rsp, bridge_type);
465 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl);
466 }
467 
468 static int mlxsw_sp_fid_edit_op(const struct mlxsw_sp_fid *fid)
469 {
470 	struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
471 	enum mlxsw_reg_bridge_type bridge_type = 0;
472 	char sfmr_pl[MLXSW_REG_SFMR_LEN];
473 	bool flood_rsp = false;
474 
475 	if (mlxsw_sp->ubridge) {
476 		flood_rsp = fid->fid_family->flood_rsp;
477 		bridge_type = fid->fid_family->bridge_type;
478 	}
479 
480 	mlxsw_reg_sfmr_pack(sfmr_pl, MLXSW_REG_SFMR_OP_CREATE_FID,
481 			    fid->fid_index, fid->fid_offset, flood_rsp,
482 			    bridge_type);
483 	mlxsw_reg_sfmr_vv_set(sfmr_pl, fid->vni_valid);
484 	mlxsw_reg_sfmr_vni_set(sfmr_pl, be32_to_cpu(fid->vni));
485 	mlxsw_reg_sfmr_vtfp_set(sfmr_pl, fid->nve_flood_index_valid);
486 	mlxsw_reg_sfmr_nve_tunnel_flood_ptr_set(sfmr_pl, fid->nve_flood_index);
487 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl);
488 }
489 
490 static int __mlxsw_sp_fid_port_vid_map(const struct mlxsw_sp_fid *fid,
491 				       u16 local_port, u16 vid, bool valid)
492 {
493 	struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
494 	char svfa_pl[MLXSW_REG_SVFA_LEN];
495 
496 	mlxsw_reg_svfa_port_vid_pack(svfa_pl, local_port, valid, fid->fid_index,
497 				     vid);
498 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl);
499 }
500 
501 static struct mlxsw_sp_fid_8021d *
502 mlxsw_sp_fid_8021d_fid(const struct mlxsw_sp_fid *fid)
503 {
504 	return container_of(fid, struct mlxsw_sp_fid_8021d, common);
505 }
506 
507 static void mlxsw_sp_fid_8021d_setup(struct mlxsw_sp_fid *fid, const void *arg)
508 {
509 	int br_ifindex = *(int *) arg;
510 
511 	mlxsw_sp_fid_8021d_fid(fid)->br_ifindex = br_ifindex;
512 	fid->fid_offset = 0;
513 }
514 
515 static int mlxsw_sp_fid_8021d_configure(struct mlxsw_sp_fid *fid)
516 {
517 	return mlxsw_sp_fid_op(fid, true);
518 }
519 
520 static void mlxsw_sp_fid_8021d_deconfigure(struct mlxsw_sp_fid *fid)
521 {
522 	if (fid->vni_valid)
523 		mlxsw_sp_nve_fid_disable(fid->fid_family->mlxsw_sp, fid);
524 	mlxsw_sp_fid_op(fid, false);
525 }
526 
527 static int mlxsw_sp_fid_8021d_index_alloc(struct mlxsw_sp_fid *fid,
528 					  const void *arg, u16 *p_fid_index)
529 {
530 	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
531 	u16 nr_fids, fid_index;
532 
533 	nr_fids = fid_family->end_index - fid_family->start_index + 1;
534 	fid_index = find_first_zero_bit(fid_family->fids_bitmap, nr_fids);
535 	if (fid_index == nr_fids)
536 		return -ENOBUFS;
537 	*p_fid_index = fid_family->start_index + fid_index;
538 
539 	return 0;
540 }
541 
542 static bool
543 mlxsw_sp_fid_8021d_compare(const struct mlxsw_sp_fid *fid, const void *arg)
544 {
545 	int br_ifindex = *(int *) arg;
546 
547 	return mlxsw_sp_fid_8021d_fid(fid)->br_ifindex == br_ifindex;
548 }
549 
550 static u16 mlxsw_sp_fid_8021d_flood_index(const struct mlxsw_sp_fid *fid)
551 {
552 	return fid->fid_index - VLAN_N_VID;
553 }
554 
555 static int mlxsw_sp_port_vp_mode_trans(struct mlxsw_sp_port *mlxsw_sp_port)
556 {
557 	struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
558 	int err;
559 
560 	list_for_each_entry(mlxsw_sp_port_vlan, &mlxsw_sp_port->vlans_list,
561 			    list) {
562 		struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid;
563 		u16 vid = mlxsw_sp_port_vlan->vid;
564 
565 		if (!fid)
566 			continue;
567 
568 		err = __mlxsw_sp_fid_port_vid_map(fid,
569 						  mlxsw_sp_port->local_port,
570 						  vid, true);
571 		if (err)
572 			goto err_fid_port_vid_map;
573 	}
574 
575 	err = mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, true);
576 	if (err)
577 		goto err_port_vp_mode_set;
578 
579 	return 0;
580 
581 err_port_vp_mode_set:
582 err_fid_port_vid_map:
583 	list_for_each_entry_continue_reverse(mlxsw_sp_port_vlan,
584 					     &mlxsw_sp_port->vlans_list, list) {
585 		struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid;
586 		u16 vid = mlxsw_sp_port_vlan->vid;
587 
588 		if (!fid)
589 			continue;
590 
591 		__mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid,
592 					    false);
593 	}
594 	return err;
595 }
596 
597 static void mlxsw_sp_port_vlan_mode_trans(struct mlxsw_sp_port *mlxsw_sp_port)
598 {
599 	struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
600 
601 	mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, false);
602 
603 	list_for_each_entry_reverse(mlxsw_sp_port_vlan,
604 				    &mlxsw_sp_port->vlans_list, list) {
605 		struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid;
606 		u16 vid = mlxsw_sp_port_vlan->vid;
607 
608 		if (!fid)
609 			continue;
610 
611 		__mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid,
612 					    false);
613 	}
614 }
615 
616 static int
617 mlxsw_sp_fid_port_vid_list_add(struct mlxsw_sp_fid *fid, u16 local_port,
618 			       u16 vid)
619 {
620 	struct mlxsw_sp_fid_port_vid *port_vid, *tmp_port_vid;
621 
622 	port_vid = kzalloc(sizeof(*port_vid), GFP_KERNEL);
623 	if (!port_vid)
624 		return -ENOMEM;
625 
626 	port_vid->local_port = local_port;
627 	port_vid->vid = vid;
628 
629 	list_for_each_entry(tmp_port_vid, &fid->port_vid_list, list) {
630 		if (tmp_port_vid->local_port > local_port)
631 			break;
632 	}
633 
634 	list_add_tail(&port_vid->list, &tmp_port_vid->list);
635 	return 0;
636 }
637 
638 static void
639 mlxsw_sp_fid_port_vid_list_del(struct mlxsw_sp_fid *fid, u16 local_port,
640 			       u16 vid)
641 {
642 	struct mlxsw_sp_fid_port_vid *port_vid, *tmp;
643 
644 	list_for_each_entry_safe(port_vid, tmp, &fid->port_vid_list, list) {
645 		if (port_vid->local_port != local_port || port_vid->vid != vid)
646 			continue;
647 
648 		list_del(&port_vid->list);
649 		kfree(port_vid);
650 		return;
651 	}
652 }
653 
654 static int
655 mlxsw_sp_fid_mpe_table_map(const struct mlxsw_sp_fid *fid, u16 local_port,
656 			   u16 vid, bool valid)
657 {
658 	struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
659 	char smpe_pl[MLXSW_REG_SMPE_LEN];
660 
661 	mlxsw_reg_smpe_pack(smpe_pl, local_port, fid->fid_index,
662 			    valid ? vid : 0);
663 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(smpe), smpe_pl);
664 }
665 
666 static int mlxsw_sp_fid_8021d_port_vid_map(struct mlxsw_sp_fid *fid,
667 					   struct mlxsw_sp_port *mlxsw_sp_port,
668 					   u16 vid)
669 {
670 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
671 	u16 local_port = mlxsw_sp_port->local_port;
672 	int err;
673 
674 	err = __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid,
675 					  true);
676 	if (err)
677 		return err;
678 
679 	if (fid->fid_family->mlxsw_sp->ubridge) {
680 		err = mlxsw_sp_fid_mpe_table_map(fid, local_port, vid, true);
681 		if (err)
682 			goto err_mpe_table_map;
683 	}
684 
685 	err = mlxsw_sp_fid_port_vid_list_add(fid, mlxsw_sp_port->local_port,
686 					     vid);
687 	if (err)
688 		goto err_port_vid_list_add;
689 
690 	if (mlxsw_sp->fid_core->port_fid_mappings[local_port]++ == 0) {
691 		err = mlxsw_sp_port_vp_mode_trans(mlxsw_sp_port);
692 		if (err)
693 			goto err_port_vp_mode_trans;
694 	}
695 
696 	return 0;
697 
698 err_port_vp_mode_trans:
699 	mlxsw_sp->fid_core->port_fid_mappings[local_port]--;
700 	mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid);
701 err_port_vid_list_add:
702 	if (fid->fid_family->mlxsw_sp->ubridge)
703 		mlxsw_sp_fid_mpe_table_map(fid, local_port, vid, false);
704 err_mpe_table_map:
705 	__mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, false);
706 	return err;
707 }
708 
709 static void
710 mlxsw_sp_fid_8021d_port_vid_unmap(struct mlxsw_sp_fid *fid,
711 				  struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
712 {
713 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
714 	u16 local_port = mlxsw_sp_port->local_port;
715 
716 	if (mlxsw_sp->fid_core->port_fid_mappings[local_port] == 1)
717 		mlxsw_sp_port_vlan_mode_trans(mlxsw_sp_port);
718 	mlxsw_sp->fid_core->port_fid_mappings[local_port]--;
719 	mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid);
720 	if (fid->fid_family->mlxsw_sp->ubridge)
721 		mlxsw_sp_fid_mpe_table_map(fid, local_port, vid, false);
722 	__mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, false);
723 }
724 
725 static int mlxsw_sp_fid_8021d_vni_set(struct mlxsw_sp_fid *fid)
726 {
727 	return mlxsw_sp_fid_edit_op(fid);
728 }
729 
730 static void mlxsw_sp_fid_8021d_vni_clear(struct mlxsw_sp_fid *fid)
731 {
732 	mlxsw_sp_fid_edit_op(fid);
733 }
734 
735 static int mlxsw_sp_fid_8021d_nve_flood_index_set(struct mlxsw_sp_fid *fid)
736 {
737 	return mlxsw_sp_fid_edit_op(fid);
738 }
739 
740 static void mlxsw_sp_fid_8021d_nve_flood_index_clear(struct mlxsw_sp_fid *fid)
741 {
742 	mlxsw_sp_fid_edit_op(fid);
743 }
744 
745 static void
746 mlxsw_sp_fid_8021d_fdb_clear_offload(const struct mlxsw_sp_fid *fid,
747 				     const struct net_device *nve_dev)
748 {
749 	br_fdb_clear_offload(nve_dev, 0);
750 }
751 
752 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021d_ops = {
753 	.setup			= mlxsw_sp_fid_8021d_setup,
754 	.configure		= mlxsw_sp_fid_8021d_configure,
755 	.deconfigure		= mlxsw_sp_fid_8021d_deconfigure,
756 	.index_alloc		= mlxsw_sp_fid_8021d_index_alloc,
757 	.compare		= mlxsw_sp_fid_8021d_compare,
758 	.flood_index		= mlxsw_sp_fid_8021d_flood_index,
759 	.port_vid_map		= mlxsw_sp_fid_8021d_port_vid_map,
760 	.port_vid_unmap		= mlxsw_sp_fid_8021d_port_vid_unmap,
761 	.vni_set		= mlxsw_sp_fid_8021d_vni_set,
762 	.vni_clear		= mlxsw_sp_fid_8021d_vni_clear,
763 	.nve_flood_index_set	= mlxsw_sp_fid_8021d_nve_flood_index_set,
764 	.nve_flood_index_clear	= mlxsw_sp_fid_8021d_nve_flood_index_clear,
765 	.fdb_clear_offload	= mlxsw_sp_fid_8021d_fdb_clear_offload,
766 };
767 
768 #define MLXSW_SP_FID_8021Q_MAX (VLAN_N_VID - 2)
769 #define MLXSW_SP_FID_8021Q_PGT_BASE 0
770 #define MLXSW_SP_FID_8021D_PGT_BASE (3 * MLXSW_SP_FID_8021Q_MAX)
771 
772 static const struct mlxsw_sp_flood_table mlxsw_sp_fid_8021d_flood_tables[] = {
773 	{
774 		.packet_type	= MLXSW_SP_FLOOD_TYPE_UC,
775 		.table_type	= MLXSW_REG_SFGC_TABLE_TYPE_FID,
776 		.table_index	= 0,
777 	},
778 	{
779 		.packet_type	= MLXSW_SP_FLOOD_TYPE_MC,
780 		.table_type	= MLXSW_REG_SFGC_TABLE_TYPE_FID,
781 		.table_index	= 1,
782 	},
783 	{
784 		.packet_type	= MLXSW_SP_FLOOD_TYPE_BC,
785 		.table_type	= MLXSW_REG_SFGC_TABLE_TYPE_FID,
786 		.table_index	= 2,
787 	},
788 };
789 
790 /* Range and flood configuration must match mlxsw_config_profile */
791 static const struct mlxsw_sp_fid_family mlxsw_sp_fid_8021d_family = {
792 	.type			= MLXSW_SP_FID_TYPE_8021D,
793 	.fid_size		= sizeof(struct mlxsw_sp_fid_8021d),
794 	.start_index		= VLAN_N_VID,
795 	.end_index		= VLAN_N_VID + MLXSW_SP_FID_8021D_MAX - 1,
796 	.flood_tables		= mlxsw_sp_fid_8021d_flood_tables,
797 	.nr_flood_tables	= ARRAY_SIZE(mlxsw_sp_fid_8021d_flood_tables),
798 	.rif_type		= MLXSW_SP_RIF_TYPE_FID,
799 	.ops			= &mlxsw_sp_fid_8021d_ops,
800 	.bridge_type		= MLXSW_REG_BRIDGE_TYPE_1,
801 	.pgt_base		= MLXSW_SP_FID_8021D_PGT_BASE,
802 };
803 
804 static bool
805 mlxsw_sp_fid_8021q_compare(const struct mlxsw_sp_fid *fid, const void *arg)
806 {
807 	u16 vid = *(u16 *) arg;
808 
809 	return mlxsw_sp_fid_8021q_fid(fid)->vid == vid;
810 }
811 
812 static void
813 mlxsw_sp_fid_8021q_fdb_clear_offload(const struct mlxsw_sp_fid *fid,
814 				     const struct net_device *nve_dev)
815 {
816 	br_fdb_clear_offload(nve_dev, mlxsw_sp_fid_8021q_vid(fid));
817 }
818 
819 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021q_emu_ops = {
820 	.setup			= mlxsw_sp_fid_8021q_setup,
821 	.configure		= mlxsw_sp_fid_8021d_configure,
822 	.deconfigure		= mlxsw_sp_fid_8021d_deconfigure,
823 	.index_alloc		= mlxsw_sp_fid_8021d_index_alloc,
824 	.compare		= mlxsw_sp_fid_8021q_compare,
825 	.flood_index		= mlxsw_sp_fid_8021d_flood_index,
826 	.port_vid_map		= mlxsw_sp_fid_8021d_port_vid_map,
827 	.port_vid_unmap		= mlxsw_sp_fid_8021d_port_vid_unmap,
828 	.vni_set		= mlxsw_sp_fid_8021d_vni_set,
829 	.vni_clear		= mlxsw_sp_fid_8021d_vni_clear,
830 	.nve_flood_index_set	= mlxsw_sp_fid_8021d_nve_flood_index_set,
831 	.nve_flood_index_clear	= mlxsw_sp_fid_8021d_nve_flood_index_clear,
832 	.fdb_clear_offload	= mlxsw_sp_fid_8021q_fdb_clear_offload,
833 };
834 
835 /* There are 4K-2 emulated 802.1Q FIDs, starting right after the 802.1D FIDs */
836 #define MLXSW_SP_FID_8021Q_EMU_START	(VLAN_N_VID + MLXSW_SP_FID_8021D_MAX)
837 #define MLXSW_SP_FID_8021Q_EMU_END	(MLXSW_SP_FID_8021Q_EMU_START + \
838 					 MLXSW_SP_FID_8021Q_MAX - 1)
839 
840 /* Range and flood configuration must match mlxsw_config_profile */
841 static const struct mlxsw_sp_fid_family mlxsw_sp_fid_8021q_emu_family = {
842 	.type			= MLXSW_SP_FID_TYPE_8021Q,
843 	.fid_size		= sizeof(struct mlxsw_sp_fid_8021q),
844 	.start_index		= MLXSW_SP_FID_8021Q_EMU_START,
845 	.end_index		= MLXSW_SP_FID_8021Q_EMU_END,
846 	.flood_tables		= mlxsw_sp_fid_8021d_flood_tables,
847 	.nr_flood_tables	= ARRAY_SIZE(mlxsw_sp_fid_8021d_flood_tables),
848 	.rif_type		= MLXSW_SP_RIF_TYPE_VLAN_EMU,
849 	.ops			= &mlxsw_sp_fid_8021q_emu_ops,
850 	.bridge_type            = MLXSW_REG_BRIDGE_TYPE_1,
851 	.pgt_base		= MLXSW_SP_FID_8021Q_PGT_BASE,
852 };
853 
854 static void mlxsw_sp_fid_rfid_setup(struct mlxsw_sp_fid *fid, const void *arg)
855 {
856 	fid->fid_offset = 0;
857 }
858 
859 static int mlxsw_sp_fid_rfid_configure(struct mlxsw_sp_fid *fid)
860 {
861 	/* rFIDs are allocated by the device during init */
862 	return 0;
863 }
864 
865 static void mlxsw_sp_fid_rfid_deconfigure(struct mlxsw_sp_fid *fid)
866 {
867 }
868 
869 static int mlxsw_sp_fid_rfid_index_alloc(struct mlxsw_sp_fid *fid,
870 					 const void *arg, u16 *p_fid_index)
871 {
872 	u16 rif_index = *(u16 *) arg;
873 
874 	*p_fid_index = fid->fid_family->start_index + rif_index;
875 
876 	return 0;
877 }
878 
879 static bool mlxsw_sp_fid_rfid_compare(const struct mlxsw_sp_fid *fid,
880 				      const void *arg)
881 {
882 	u16 rif_index = *(u16 *) arg;
883 
884 	return fid->fid_index == rif_index + fid->fid_family->start_index;
885 }
886 
887 static int mlxsw_sp_fid_rfid_port_vid_map(struct mlxsw_sp_fid *fid,
888 					  struct mlxsw_sp_port *mlxsw_sp_port,
889 					  u16 vid)
890 {
891 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
892 	u16 local_port = mlxsw_sp_port->local_port;
893 	int err;
894 
895 	err = mlxsw_sp_fid_port_vid_list_add(fid, mlxsw_sp_port->local_port,
896 					     vid);
897 	if (err)
898 		return err;
899 
900 	/* We only need to transition the port to virtual mode since
901 	 * {Port, VID} => FID is done by the firmware upon RIF creation.
902 	 */
903 	if (mlxsw_sp->fid_core->port_fid_mappings[local_port]++ == 0) {
904 		err = mlxsw_sp_port_vp_mode_trans(mlxsw_sp_port);
905 		if (err)
906 			goto err_port_vp_mode_trans;
907 	}
908 
909 	return 0;
910 
911 err_port_vp_mode_trans:
912 	mlxsw_sp->fid_core->port_fid_mappings[local_port]--;
913 	mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid);
914 	return err;
915 }
916 
917 static void
918 mlxsw_sp_fid_rfid_port_vid_unmap(struct mlxsw_sp_fid *fid,
919 				 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
920 {
921 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
922 	u16 local_port = mlxsw_sp_port->local_port;
923 
924 	if (mlxsw_sp->fid_core->port_fid_mappings[local_port] == 1)
925 		mlxsw_sp_port_vlan_mode_trans(mlxsw_sp_port);
926 	mlxsw_sp->fid_core->port_fid_mappings[local_port]--;
927 	mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid);
928 }
929 
930 static int mlxsw_sp_fid_rfid_vni_set(struct mlxsw_sp_fid *fid)
931 {
932 	return -EOPNOTSUPP;
933 }
934 
935 static void mlxsw_sp_fid_rfid_vni_clear(struct mlxsw_sp_fid *fid)
936 {
937 	WARN_ON_ONCE(1);
938 }
939 
940 static int mlxsw_sp_fid_rfid_nve_flood_index_set(struct mlxsw_sp_fid *fid)
941 {
942 	return -EOPNOTSUPP;
943 }
944 
945 static void mlxsw_sp_fid_rfid_nve_flood_index_clear(struct mlxsw_sp_fid *fid)
946 {
947 	WARN_ON_ONCE(1);
948 }
949 
950 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_rfid_ops = {
951 	.setup			= mlxsw_sp_fid_rfid_setup,
952 	.configure		= mlxsw_sp_fid_rfid_configure,
953 	.deconfigure		= mlxsw_sp_fid_rfid_deconfigure,
954 	.index_alloc		= mlxsw_sp_fid_rfid_index_alloc,
955 	.compare		= mlxsw_sp_fid_rfid_compare,
956 	.port_vid_map		= mlxsw_sp_fid_rfid_port_vid_map,
957 	.port_vid_unmap		= mlxsw_sp_fid_rfid_port_vid_unmap,
958 	.vni_set                = mlxsw_sp_fid_rfid_vni_set,
959 	.vni_clear		= mlxsw_sp_fid_rfid_vni_clear,
960 	.nve_flood_index_set	= mlxsw_sp_fid_rfid_nve_flood_index_set,
961 	.nve_flood_index_clear	= mlxsw_sp_fid_rfid_nve_flood_index_clear,
962 };
963 
964 #define MLXSW_SP_RFID_BASE	(15 * 1024)
965 #define MLXSW_SP_RFID_MAX	1024
966 
967 static const struct mlxsw_sp_fid_family mlxsw_sp_fid_rfid_family = {
968 	.type			= MLXSW_SP_FID_TYPE_RFID,
969 	.fid_size		= sizeof(struct mlxsw_sp_fid),
970 	.start_index		= MLXSW_SP_RFID_BASE,
971 	.end_index		= MLXSW_SP_RFID_BASE + MLXSW_SP_RFID_MAX - 1,
972 	.rif_type		= MLXSW_SP_RIF_TYPE_SUBPORT,
973 	.ops			= &mlxsw_sp_fid_rfid_ops,
974 	.flood_rsp		= true,
975 };
976 
977 static void mlxsw_sp_fid_dummy_setup(struct mlxsw_sp_fid *fid, const void *arg)
978 {
979 	fid->fid_offset = 0;
980 }
981 
982 static int mlxsw_sp_fid_dummy_configure(struct mlxsw_sp_fid *fid)
983 {
984 	return mlxsw_sp_fid_op(fid, true);
985 }
986 
987 static void mlxsw_sp_fid_dummy_deconfigure(struct mlxsw_sp_fid *fid)
988 {
989 	mlxsw_sp_fid_op(fid, false);
990 }
991 
992 static int mlxsw_sp_fid_dummy_index_alloc(struct mlxsw_sp_fid *fid,
993 					  const void *arg, u16 *p_fid_index)
994 {
995 	*p_fid_index = fid->fid_family->start_index;
996 
997 	return 0;
998 }
999 
1000 static bool mlxsw_sp_fid_dummy_compare(const struct mlxsw_sp_fid *fid,
1001 				       const void *arg)
1002 {
1003 	return true;
1004 }
1005 
1006 static int mlxsw_sp_fid_dummy_vni_set(struct mlxsw_sp_fid *fid)
1007 {
1008 	return -EOPNOTSUPP;
1009 }
1010 
1011 static void mlxsw_sp_fid_dummy_vni_clear(struct mlxsw_sp_fid *fid)
1012 {
1013 	WARN_ON_ONCE(1);
1014 }
1015 
1016 static int mlxsw_sp_fid_dummy_nve_flood_index_set(struct mlxsw_sp_fid *fid)
1017 {
1018 	return -EOPNOTSUPP;
1019 }
1020 
1021 static void mlxsw_sp_fid_dummy_nve_flood_index_clear(struct mlxsw_sp_fid *fid)
1022 {
1023 	WARN_ON_ONCE(1);
1024 }
1025 
1026 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_dummy_ops = {
1027 	.setup			= mlxsw_sp_fid_dummy_setup,
1028 	.configure		= mlxsw_sp_fid_dummy_configure,
1029 	.deconfigure		= mlxsw_sp_fid_dummy_deconfigure,
1030 	.index_alloc		= mlxsw_sp_fid_dummy_index_alloc,
1031 	.compare		= mlxsw_sp_fid_dummy_compare,
1032 	.vni_set                = mlxsw_sp_fid_dummy_vni_set,
1033 	.vni_clear		= mlxsw_sp_fid_dummy_vni_clear,
1034 	.nve_flood_index_set	= mlxsw_sp_fid_dummy_nve_flood_index_set,
1035 	.nve_flood_index_clear	= mlxsw_sp_fid_dummy_nve_flood_index_clear,
1036 };
1037 
1038 static const struct mlxsw_sp_fid_family mlxsw_sp_fid_dummy_family = {
1039 	.type			= MLXSW_SP_FID_TYPE_DUMMY,
1040 	.fid_size		= sizeof(struct mlxsw_sp_fid),
1041 	.start_index		= VLAN_N_VID - 1,
1042 	.end_index		= VLAN_N_VID - 1,
1043 	.ops			= &mlxsw_sp_fid_dummy_ops,
1044 };
1045 
1046 const struct mlxsw_sp_fid_family *mlxsw_sp1_fid_family_arr[] = {
1047 	[MLXSW_SP_FID_TYPE_8021Q]	= &mlxsw_sp_fid_8021q_emu_family,
1048 	[MLXSW_SP_FID_TYPE_8021D]	= &mlxsw_sp_fid_8021d_family,
1049 	[MLXSW_SP_FID_TYPE_RFID]	= &mlxsw_sp_fid_rfid_family,
1050 	[MLXSW_SP_FID_TYPE_DUMMY]	= &mlxsw_sp_fid_dummy_family,
1051 };
1052 
1053 const struct mlxsw_sp_fid_family *mlxsw_sp2_fid_family_arr[] = {
1054 	[MLXSW_SP_FID_TYPE_8021Q]	= &mlxsw_sp_fid_8021q_emu_family,
1055 	[MLXSW_SP_FID_TYPE_8021D]	= &mlxsw_sp_fid_8021d_family,
1056 	[MLXSW_SP_FID_TYPE_RFID]	= &mlxsw_sp_fid_rfid_family,
1057 	[MLXSW_SP_FID_TYPE_DUMMY]	= &mlxsw_sp_fid_dummy_family,
1058 };
1059 
1060 static struct mlxsw_sp_fid *mlxsw_sp_fid_lookup(struct mlxsw_sp *mlxsw_sp,
1061 						enum mlxsw_sp_fid_type type,
1062 						const void *arg)
1063 {
1064 	struct mlxsw_sp_fid_family *fid_family;
1065 	struct mlxsw_sp_fid *fid;
1066 
1067 	fid_family = mlxsw_sp->fid_core->fid_family_arr[type];
1068 	list_for_each_entry(fid, &fid_family->fids_list, list) {
1069 		if (!fid->fid_family->ops->compare(fid, arg))
1070 			continue;
1071 		refcount_inc(&fid->ref_count);
1072 		return fid;
1073 	}
1074 
1075 	return NULL;
1076 }
1077 
1078 static struct mlxsw_sp_fid *mlxsw_sp_fid_get(struct mlxsw_sp *mlxsw_sp,
1079 					     enum mlxsw_sp_fid_type type,
1080 					     const void *arg)
1081 {
1082 	struct mlxsw_sp_fid_family *fid_family;
1083 	struct mlxsw_sp_fid *fid;
1084 	u16 fid_index;
1085 	int err;
1086 
1087 	fid = mlxsw_sp_fid_lookup(mlxsw_sp, type, arg);
1088 	if (fid)
1089 		return fid;
1090 
1091 	fid_family = mlxsw_sp->fid_core->fid_family_arr[type];
1092 	fid = kzalloc(fid_family->fid_size, GFP_KERNEL);
1093 	if (!fid)
1094 		return ERR_PTR(-ENOMEM);
1095 
1096 	INIT_LIST_HEAD(&fid->port_vid_list);
1097 	fid->fid_family = fid_family;
1098 
1099 	err = fid->fid_family->ops->index_alloc(fid, arg, &fid_index);
1100 	if (err)
1101 		goto err_index_alloc;
1102 	fid->fid_index = fid_index;
1103 	__set_bit(fid_index - fid_family->start_index, fid_family->fids_bitmap);
1104 
1105 	fid->fid_family->ops->setup(fid, arg);
1106 
1107 	err = fid->fid_family->ops->configure(fid);
1108 	if (err)
1109 		goto err_configure;
1110 
1111 	err = rhashtable_insert_fast(&mlxsw_sp->fid_core->fid_ht, &fid->ht_node,
1112 				     mlxsw_sp_fid_ht_params);
1113 	if (err)
1114 		goto err_rhashtable_insert;
1115 
1116 	list_add(&fid->list, &fid_family->fids_list);
1117 	refcount_set(&fid->ref_count, 1);
1118 	return fid;
1119 
1120 err_rhashtable_insert:
1121 	fid->fid_family->ops->deconfigure(fid);
1122 err_configure:
1123 	__clear_bit(fid_index - fid_family->start_index,
1124 		    fid_family->fids_bitmap);
1125 err_index_alloc:
1126 	kfree(fid);
1127 	return ERR_PTR(err);
1128 }
1129 
1130 void mlxsw_sp_fid_put(struct mlxsw_sp_fid *fid)
1131 {
1132 	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
1133 	struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
1134 
1135 	if (!refcount_dec_and_test(&fid->ref_count))
1136 		return;
1137 
1138 	list_del(&fid->list);
1139 	rhashtable_remove_fast(&mlxsw_sp->fid_core->fid_ht,
1140 			       &fid->ht_node, mlxsw_sp_fid_ht_params);
1141 	fid->fid_family->ops->deconfigure(fid);
1142 	__clear_bit(fid->fid_index - fid_family->start_index,
1143 		    fid_family->fids_bitmap);
1144 	WARN_ON_ONCE(!list_empty(&fid->port_vid_list));
1145 	kfree(fid);
1146 }
1147 
1148 struct mlxsw_sp_fid *mlxsw_sp_fid_8021q_get(struct mlxsw_sp *mlxsw_sp, u16 vid)
1149 {
1150 	return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_8021Q, &vid);
1151 }
1152 
1153 struct mlxsw_sp_fid *mlxsw_sp_fid_8021d_get(struct mlxsw_sp *mlxsw_sp,
1154 					    int br_ifindex)
1155 {
1156 	return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_8021D, &br_ifindex);
1157 }
1158 
1159 struct mlxsw_sp_fid *mlxsw_sp_fid_8021q_lookup(struct mlxsw_sp *mlxsw_sp,
1160 					       u16 vid)
1161 {
1162 	return mlxsw_sp_fid_lookup(mlxsw_sp, MLXSW_SP_FID_TYPE_8021Q, &vid);
1163 }
1164 
1165 struct mlxsw_sp_fid *mlxsw_sp_fid_8021d_lookup(struct mlxsw_sp *mlxsw_sp,
1166 					       int br_ifindex)
1167 {
1168 	return mlxsw_sp_fid_lookup(mlxsw_sp, MLXSW_SP_FID_TYPE_8021D,
1169 				   &br_ifindex);
1170 }
1171 
1172 struct mlxsw_sp_fid *mlxsw_sp_fid_rfid_get(struct mlxsw_sp *mlxsw_sp,
1173 					   u16 rif_index)
1174 {
1175 	return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_RFID, &rif_index);
1176 }
1177 
1178 struct mlxsw_sp_fid *mlxsw_sp_fid_dummy_get(struct mlxsw_sp *mlxsw_sp)
1179 {
1180 	return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_DUMMY, NULL);
1181 }
1182 
1183 static int
1184 mlxsw_sp_fid_flood_table_init(struct mlxsw_sp_fid_family *fid_family,
1185 			      const struct mlxsw_sp_flood_table *flood_table)
1186 {
1187 	enum mlxsw_sp_flood_type packet_type = flood_table->packet_type;
1188 	struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
1189 	u16 mid_base, num_fids, table_index;
1190 	const int *sfgc_packet_types;
1191 	int err, i;
1192 
1193 	mid_base = mlxsw_sp_fid_flood_table_mid(fid_family, flood_table, 0);
1194 	num_fids = mlxsw_sp_fid_family_num_fids(fid_family);
1195 	err = mlxsw_sp_pgt_mid_alloc_range(mlxsw_sp, mid_base, num_fids);
1196 	if (err)
1197 		return err;
1198 
1199 	sfgc_packet_types = mlxsw_sp_packet_type_sfgc_types[packet_type];
1200 	for (i = 0; i < MLXSW_REG_SFGC_TYPE_MAX; i++) {
1201 		char sfgc_pl[MLXSW_REG_SFGC_LEN];
1202 
1203 		if (!sfgc_packet_types[i])
1204 			continue;
1205 
1206 		mid_base = mlxsw_sp->ubridge ? mid_base : 0;
1207 		table_index = mlxsw_sp->ubridge ? 0 : flood_table->table_index;
1208 
1209 		mlxsw_reg_sfgc_pack(sfgc_pl, i, fid_family->bridge_type,
1210 				    flood_table->table_type, table_index,
1211 				    mid_base);
1212 
1213 		err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfgc), sfgc_pl);
1214 		if (err)
1215 			goto err_reg_write;
1216 	}
1217 
1218 	return 0;
1219 
1220 err_reg_write:
1221 	mid_base = mlxsw_sp_fid_flood_table_mid(fid_family, flood_table, 0);
1222 	mlxsw_sp_pgt_mid_free_range(mlxsw_sp, mid_base, num_fids);
1223 	return err;
1224 }
1225 
1226 static void
1227 mlxsw_sp_fid_flood_table_fini(struct mlxsw_sp_fid_family *fid_family,
1228 			      const struct mlxsw_sp_flood_table *flood_table)
1229 {
1230 	struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
1231 	u16 num_fids, mid_base;
1232 
1233 	mid_base = mlxsw_sp_fid_flood_table_mid(fid_family, flood_table, 0);
1234 	num_fids = mlxsw_sp_fid_family_num_fids(fid_family);
1235 	mlxsw_sp_pgt_mid_free_range(mlxsw_sp, mid_base, num_fids);
1236 }
1237 
1238 static int
1239 mlxsw_sp_fid_flood_tables_init(struct mlxsw_sp_fid_family *fid_family)
1240 {
1241 	int i;
1242 
1243 	for (i = 0; i < fid_family->nr_flood_tables; i++) {
1244 		const struct mlxsw_sp_flood_table *flood_table;
1245 		int err;
1246 
1247 		flood_table = &fid_family->flood_tables[i];
1248 		err = mlxsw_sp_fid_flood_table_init(fid_family, flood_table);
1249 		if (err)
1250 			return err;
1251 	}
1252 
1253 	return 0;
1254 }
1255 
1256 static void
1257 mlxsw_sp_fid_flood_tables_fini(struct mlxsw_sp_fid_family *fid_family)
1258 {
1259 	int i;
1260 
1261 	for (i = 0; i < fid_family->nr_flood_tables; i++) {
1262 		const struct mlxsw_sp_flood_table *flood_table;
1263 
1264 		flood_table = &fid_family->flood_tables[i];
1265 		mlxsw_sp_fid_flood_table_fini(fid_family, flood_table);
1266 	}
1267 }
1268 
1269 static int mlxsw_sp_fid_family_register(struct mlxsw_sp *mlxsw_sp,
1270 					const struct mlxsw_sp_fid_family *tmpl)
1271 {
1272 	u16 nr_fids = tmpl->end_index - tmpl->start_index + 1;
1273 	struct mlxsw_sp_fid_family *fid_family;
1274 	int err;
1275 
1276 	fid_family = kmemdup(tmpl, sizeof(*fid_family), GFP_KERNEL);
1277 	if (!fid_family)
1278 		return -ENOMEM;
1279 
1280 	fid_family->mlxsw_sp = mlxsw_sp;
1281 	INIT_LIST_HEAD(&fid_family->fids_list);
1282 	fid_family->fids_bitmap = bitmap_zalloc(nr_fids, GFP_KERNEL);
1283 	if (!fid_family->fids_bitmap) {
1284 		err = -ENOMEM;
1285 		goto err_alloc_fids_bitmap;
1286 	}
1287 
1288 	if (fid_family->flood_tables) {
1289 		err = mlxsw_sp_fid_flood_tables_init(fid_family);
1290 		if (err)
1291 			goto err_fid_flood_tables_init;
1292 	}
1293 
1294 	mlxsw_sp->fid_core->fid_family_arr[tmpl->type] = fid_family;
1295 
1296 	return 0;
1297 
1298 err_fid_flood_tables_init:
1299 	bitmap_free(fid_family->fids_bitmap);
1300 err_alloc_fids_bitmap:
1301 	kfree(fid_family);
1302 	return err;
1303 }
1304 
1305 static void
1306 mlxsw_sp_fid_family_unregister(struct mlxsw_sp *mlxsw_sp,
1307 			       struct mlxsw_sp_fid_family *fid_family)
1308 {
1309 	mlxsw_sp->fid_core->fid_family_arr[fid_family->type] = NULL;
1310 
1311 	if (fid_family->flood_tables)
1312 		mlxsw_sp_fid_flood_tables_fini(fid_family);
1313 
1314 	bitmap_free(fid_family->fids_bitmap);
1315 	WARN_ON_ONCE(!list_empty(&fid_family->fids_list));
1316 	kfree(fid_family);
1317 }
1318 
1319 int mlxsw_sp_port_fids_init(struct mlxsw_sp_port *mlxsw_sp_port)
1320 {
1321 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1322 
1323 	/* Track number of FIDs configured on the port with mapping type
1324 	 * PORT_VID_TO_FID, so that we know when to transition the port
1325 	 * back to non-virtual (VLAN) mode.
1326 	 */
1327 	mlxsw_sp->fid_core->port_fid_mappings[mlxsw_sp_port->local_port] = 0;
1328 
1329 	return mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, false);
1330 }
1331 
1332 void mlxsw_sp_port_fids_fini(struct mlxsw_sp_port *mlxsw_sp_port)
1333 {
1334 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1335 
1336 	mlxsw_sp->fid_core->port_fid_mappings[mlxsw_sp_port->local_port] = 0;
1337 }
1338 
1339 int mlxsw_sp_fids_init(struct mlxsw_sp *mlxsw_sp)
1340 {
1341 	unsigned int max_ports = mlxsw_core_max_ports(mlxsw_sp->core);
1342 	struct mlxsw_sp_fid_core *fid_core;
1343 	int err, i;
1344 
1345 	fid_core = kzalloc(sizeof(*mlxsw_sp->fid_core), GFP_KERNEL);
1346 	if (!fid_core)
1347 		return -ENOMEM;
1348 	mlxsw_sp->fid_core = fid_core;
1349 
1350 	err = rhashtable_init(&fid_core->fid_ht, &mlxsw_sp_fid_ht_params);
1351 	if (err)
1352 		goto err_rhashtable_fid_init;
1353 
1354 	err = rhashtable_init(&fid_core->vni_ht, &mlxsw_sp_fid_vni_ht_params);
1355 	if (err)
1356 		goto err_rhashtable_vni_init;
1357 
1358 	fid_core->port_fid_mappings = kcalloc(max_ports, sizeof(unsigned int),
1359 					      GFP_KERNEL);
1360 	if (!fid_core->port_fid_mappings) {
1361 		err = -ENOMEM;
1362 		goto err_alloc_port_fid_mappings;
1363 	}
1364 
1365 	for (i = 0; i < MLXSW_SP_FID_TYPE_MAX; i++) {
1366 		err = mlxsw_sp_fid_family_register(mlxsw_sp,
1367 						   mlxsw_sp->fid_family_arr[i]);
1368 
1369 		if (err)
1370 			goto err_fid_ops_register;
1371 	}
1372 
1373 	return 0;
1374 
1375 err_fid_ops_register:
1376 	for (i--; i >= 0; i--) {
1377 		struct mlxsw_sp_fid_family *fid_family;
1378 
1379 		fid_family = fid_core->fid_family_arr[i];
1380 		mlxsw_sp_fid_family_unregister(mlxsw_sp, fid_family);
1381 	}
1382 	kfree(fid_core->port_fid_mappings);
1383 err_alloc_port_fid_mappings:
1384 	rhashtable_destroy(&fid_core->vni_ht);
1385 err_rhashtable_vni_init:
1386 	rhashtable_destroy(&fid_core->fid_ht);
1387 err_rhashtable_fid_init:
1388 	kfree(fid_core);
1389 	return err;
1390 }
1391 
1392 void mlxsw_sp_fids_fini(struct mlxsw_sp *mlxsw_sp)
1393 {
1394 	struct mlxsw_sp_fid_core *fid_core = mlxsw_sp->fid_core;
1395 	int i;
1396 
1397 	for (i = 0; i < MLXSW_SP_FID_TYPE_MAX; i++)
1398 		mlxsw_sp_fid_family_unregister(mlxsw_sp,
1399 					       fid_core->fid_family_arr[i]);
1400 	kfree(fid_core->port_fid_mappings);
1401 	rhashtable_destroy(&fid_core->vni_ht);
1402 	rhashtable_destroy(&fid_core->fid_ht);
1403 	kfree(fid_core);
1404 }
1405