xref: /linux/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c (revision 011f129fee4bd064a3db30ca1a0139548a619482)
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 	int (*port_vid_map)(struct mlxsw_sp_fid *fid,
87 			    struct mlxsw_sp_port *port, u16 vid);
88 	void (*port_vid_unmap)(struct mlxsw_sp_fid *fid,
89 			       struct mlxsw_sp_port *port, u16 vid);
90 	int (*vni_set)(struct mlxsw_sp_fid *fid);
91 	void (*vni_clear)(struct mlxsw_sp_fid *fid);
92 	int (*nve_flood_index_set)(struct mlxsw_sp_fid *fid);
93 	void (*nve_flood_index_clear)(struct mlxsw_sp_fid *fid);
94 	void (*fdb_clear_offload)(const struct mlxsw_sp_fid *fid,
95 				  const struct net_device *nve_dev);
96 	int (*vid_to_fid_rif_update)(const struct mlxsw_sp_fid *fid,
97 				     const struct mlxsw_sp_rif *rif);
98 };
99 
100 struct mlxsw_sp_fid_family {
101 	enum mlxsw_sp_fid_type type;
102 	size_t fid_size;
103 	u16 start_index;
104 	u16 end_index;
105 	struct list_head fids_list;
106 	unsigned long *fids_bitmap;
107 	const struct mlxsw_sp_flood_table *flood_tables;
108 	int nr_flood_tables;
109 	enum mlxsw_sp_rif_type rif_type;
110 	const struct mlxsw_sp_fid_ops *ops;
111 	struct mlxsw_sp *mlxsw_sp;
112 	bool flood_rsp;
113 	enum mlxsw_reg_bridge_type bridge_type;
114 	u16 pgt_base;
115 	bool smpe_index_valid;
116 };
117 
118 static const int mlxsw_sp_sfgc_uc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = {
119 	[MLXSW_REG_SFGC_TYPE_UNKNOWN_UNICAST]			= 1,
120 };
121 
122 static const int mlxsw_sp_sfgc_bc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = {
123 	[MLXSW_REG_SFGC_TYPE_BROADCAST]				= 1,
124 	[MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_NON_IP]	= 1,
125 	[MLXSW_REG_SFGC_TYPE_IPV4_LINK_LOCAL]			= 1,
126 	[MLXSW_REG_SFGC_TYPE_IPV6_ALL_HOST]			= 1,
127 	[MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV6]	= 1,
128 };
129 
130 static const int mlxsw_sp_sfgc_mc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = {
131 	[MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV4]	= 1,
132 };
133 
134 static const int *mlxsw_sp_packet_type_sfgc_types[] = {
135 	[MLXSW_SP_FLOOD_TYPE_UC]	= mlxsw_sp_sfgc_uc_packet_types,
136 	[MLXSW_SP_FLOOD_TYPE_BC]	= mlxsw_sp_sfgc_bc_packet_types,
137 	[MLXSW_SP_FLOOD_TYPE_MC]	= mlxsw_sp_sfgc_mc_packet_types,
138 };
139 
140 struct mlxsw_sp_fid *mlxsw_sp_fid_lookup_by_index(struct mlxsw_sp *mlxsw_sp,
141 						  u16 fid_index)
142 {
143 	struct mlxsw_sp_fid *fid;
144 
145 	fid = rhashtable_lookup_fast(&mlxsw_sp->fid_core->fid_ht, &fid_index,
146 				     mlxsw_sp_fid_ht_params);
147 	if (fid)
148 		refcount_inc(&fid->ref_count);
149 
150 	return fid;
151 }
152 
153 int mlxsw_sp_fid_nve_ifindex(const struct mlxsw_sp_fid *fid, int *nve_ifindex)
154 {
155 	if (!fid->vni_valid)
156 		return -EINVAL;
157 
158 	*nve_ifindex = fid->nve_ifindex;
159 
160 	return 0;
161 }
162 
163 int mlxsw_sp_fid_nve_type(const struct mlxsw_sp_fid *fid,
164 			  enum mlxsw_sp_nve_type *p_type)
165 {
166 	if (!fid->vni_valid)
167 		return -EINVAL;
168 
169 	*p_type = fid->nve_type;
170 
171 	return 0;
172 }
173 
174 struct mlxsw_sp_fid *mlxsw_sp_fid_lookup_by_vni(struct mlxsw_sp *mlxsw_sp,
175 						__be32 vni)
176 {
177 	struct mlxsw_sp_fid *fid;
178 
179 	fid = rhashtable_lookup_fast(&mlxsw_sp->fid_core->vni_ht, &vni,
180 				     mlxsw_sp_fid_vni_ht_params);
181 	if (fid)
182 		refcount_inc(&fid->ref_count);
183 
184 	return fid;
185 }
186 
187 int mlxsw_sp_fid_vni(const struct mlxsw_sp_fid *fid, __be32 *vni)
188 {
189 	if (!fid->vni_valid)
190 		return -EINVAL;
191 
192 	*vni = fid->vni;
193 
194 	return 0;
195 }
196 
197 int mlxsw_sp_fid_nve_flood_index_set(struct mlxsw_sp_fid *fid,
198 				     u32 nve_flood_index)
199 {
200 	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
201 	const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
202 	int err;
203 
204 	if (WARN_ON(fid->nve_flood_index_valid))
205 		return -EINVAL;
206 
207 	fid->nve_flood_index = nve_flood_index;
208 	fid->nve_flood_index_valid = true;
209 	err = ops->nve_flood_index_set(fid);
210 	if (err)
211 		goto err_nve_flood_index_set;
212 
213 	return 0;
214 
215 err_nve_flood_index_set:
216 	fid->nve_flood_index_valid = false;
217 	return err;
218 }
219 
220 void mlxsw_sp_fid_nve_flood_index_clear(struct mlxsw_sp_fid *fid)
221 {
222 	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
223 	const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
224 
225 	if (WARN_ON(!fid->nve_flood_index_valid))
226 		return;
227 
228 	fid->nve_flood_index_valid = false;
229 	ops->nve_flood_index_clear(fid);
230 }
231 
232 bool mlxsw_sp_fid_nve_flood_index_is_set(const struct mlxsw_sp_fid *fid)
233 {
234 	return fid->nve_flood_index_valid;
235 }
236 
237 int mlxsw_sp_fid_vni_set(struct mlxsw_sp_fid *fid, enum mlxsw_sp_nve_type type,
238 			 __be32 vni, int nve_ifindex)
239 {
240 	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
241 	const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
242 	struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
243 	int err;
244 
245 	if (WARN_ON(fid->vni_valid))
246 		return -EINVAL;
247 
248 	fid->nve_type = type;
249 	fid->nve_ifindex = nve_ifindex;
250 	fid->vni = vni;
251 	err = rhashtable_lookup_insert_fast(&mlxsw_sp->fid_core->vni_ht,
252 					    &fid->vni_ht_node,
253 					    mlxsw_sp_fid_vni_ht_params);
254 	if (err)
255 		return err;
256 
257 	fid->vni_valid = true;
258 	err = ops->vni_set(fid);
259 	if (err)
260 		goto err_vni_set;
261 
262 	return 0;
263 
264 err_vni_set:
265 	fid->vni_valid = false;
266 	rhashtable_remove_fast(&mlxsw_sp->fid_core->vni_ht, &fid->vni_ht_node,
267 			       mlxsw_sp_fid_vni_ht_params);
268 	return err;
269 }
270 
271 void mlxsw_sp_fid_vni_clear(struct mlxsw_sp_fid *fid)
272 {
273 	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
274 	const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
275 	struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
276 
277 	if (WARN_ON(!fid->vni_valid))
278 		return;
279 
280 	fid->vni_valid = false;
281 	ops->vni_clear(fid);
282 	rhashtable_remove_fast(&mlxsw_sp->fid_core->vni_ht, &fid->vni_ht_node,
283 			       mlxsw_sp_fid_vni_ht_params);
284 }
285 
286 bool mlxsw_sp_fid_vni_is_set(const struct mlxsw_sp_fid *fid)
287 {
288 	return fid->vni_valid;
289 }
290 
291 void mlxsw_sp_fid_fdb_clear_offload(const struct mlxsw_sp_fid *fid,
292 				    const struct net_device *nve_dev)
293 {
294 	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
295 	const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
296 
297 	if (ops->fdb_clear_offload)
298 		ops->fdb_clear_offload(fid, nve_dev);
299 }
300 
301 static const struct mlxsw_sp_flood_table *
302 mlxsw_sp_fid_flood_table_lookup(const struct mlxsw_sp_fid *fid,
303 				enum mlxsw_sp_flood_type packet_type)
304 {
305 	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
306 	int i;
307 
308 	for (i = 0; i < fid_family->nr_flood_tables; i++) {
309 		if (fid_family->flood_tables[i].packet_type != packet_type)
310 			continue;
311 		return &fid_family->flood_tables[i];
312 	}
313 
314 	return NULL;
315 }
316 
317 static u16
318 mlxsw_sp_fid_family_num_fids(const struct mlxsw_sp_fid_family *fid_family)
319 {
320 	return fid_family->end_index - fid_family->start_index + 1;
321 }
322 
323 static u16
324 mlxsw_sp_fid_family_pgt_size(const struct mlxsw_sp_fid_family *fid_family)
325 {
326 	u16 num_fids = mlxsw_sp_fid_family_num_fids(fid_family);
327 
328 	return num_fids * fid_family->nr_flood_tables;
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_flood_table *flood_table;
349 	u16 mid_index;
350 
351 	if (WARN_ON(!fid_family->flood_tables))
352 		return -EINVAL;
353 
354 	flood_table = mlxsw_sp_fid_flood_table_lookup(fid, packet_type);
355 	if (!flood_table)
356 		return -ESRCH;
357 
358 	mid_index = mlxsw_sp_fid_flood_table_mid(fid_family, flood_table,
359 						 fid->fid_offset);
360 	return mlxsw_sp_pgt_entry_port_set(fid_family->mlxsw_sp, mid_index,
361 					   fid->fid_index, local_port, member);
362 }
363 
364 int mlxsw_sp_fid_port_vid_map(struct mlxsw_sp_fid *fid,
365 			      struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
366 {
367 	if (WARN_ON(!fid->fid_family->ops->port_vid_map))
368 		return -EINVAL;
369 	return fid->fid_family->ops->port_vid_map(fid, mlxsw_sp_port, vid);
370 }
371 
372 void mlxsw_sp_fid_port_vid_unmap(struct mlxsw_sp_fid *fid,
373 				 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
374 {
375 	fid->fid_family->ops->port_vid_unmap(fid, mlxsw_sp_port, vid);
376 }
377 
378 u16 mlxsw_sp_fid_index(const struct mlxsw_sp_fid *fid)
379 {
380 	return fid->fid_index;
381 }
382 
383 enum mlxsw_sp_fid_type mlxsw_sp_fid_type(const struct mlxsw_sp_fid *fid)
384 {
385 	return fid->fid_family->type;
386 }
387 
388 struct mlxsw_sp_rif *mlxsw_sp_fid_rif(const struct mlxsw_sp_fid *fid)
389 {
390 	return fid->rif;
391 }
392 
393 enum mlxsw_sp_rif_type
394 mlxsw_sp_fid_type_rif_type(const struct mlxsw_sp *mlxsw_sp,
395 			   enum mlxsw_sp_fid_type type)
396 {
397 	struct mlxsw_sp_fid_core *fid_core = mlxsw_sp->fid_core;
398 
399 	return fid_core->fid_family_arr[type]->rif_type;
400 }
401 
402 static struct mlxsw_sp_fid_8021q *
403 mlxsw_sp_fid_8021q_fid(const struct mlxsw_sp_fid *fid)
404 {
405 	return container_of(fid, struct mlxsw_sp_fid_8021q, common);
406 }
407 
408 u16 mlxsw_sp_fid_8021q_vid(const struct mlxsw_sp_fid *fid)
409 {
410 	return mlxsw_sp_fid_8021q_fid(fid)->vid;
411 }
412 
413 static void mlxsw_sp_fid_8021q_setup(struct mlxsw_sp_fid *fid, const void *arg)
414 {
415 	u16 vid = *(u16 *) arg;
416 
417 	mlxsw_sp_fid_8021q_fid(fid)->vid = vid;
418 	fid->fid_offset = fid->fid_index - fid->fid_family->start_index;
419 }
420 
421 static enum mlxsw_reg_sfmr_op mlxsw_sp_sfmr_op(bool valid)
422 {
423 	return valid ? MLXSW_REG_SFMR_OP_CREATE_FID :
424 		       MLXSW_REG_SFMR_OP_DESTROY_FID;
425 }
426 
427 static int mlxsw_sp_fid_op(const struct mlxsw_sp_fid *fid, bool valid)
428 {
429 	struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
430 	char sfmr_pl[MLXSW_REG_SFMR_LEN];
431 	u16 smpe;
432 
433 	smpe = fid->fid_family->smpe_index_valid ? fid->fid_index : 0;
434 
435 	mlxsw_reg_sfmr_pack(sfmr_pl, mlxsw_sp_sfmr_op(valid), fid->fid_index,
436 			    fid->fid_offset, fid->fid_family->flood_rsp,
437 			    fid->fid_family->bridge_type,
438 			    fid->fid_family->smpe_index_valid, smpe);
439 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl);
440 }
441 
442 static int mlxsw_sp_fid_edit_op(const struct mlxsw_sp_fid *fid,
443 				const struct mlxsw_sp_rif *rif)
444 {
445 	struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
446 	char sfmr_pl[MLXSW_REG_SFMR_LEN];
447 	u16 smpe;
448 
449 	smpe = fid->fid_family->smpe_index_valid ? fid->fid_index : 0;
450 
451 	mlxsw_reg_sfmr_pack(sfmr_pl, MLXSW_REG_SFMR_OP_CREATE_FID,
452 			    fid->fid_index, fid->fid_offset,
453 			    fid->fid_family->flood_rsp,
454 			    fid->fid_family->bridge_type,
455 			    fid->fid_family->smpe_index_valid, smpe);
456 	mlxsw_reg_sfmr_vv_set(sfmr_pl, fid->vni_valid);
457 	mlxsw_reg_sfmr_vni_set(sfmr_pl, be32_to_cpu(fid->vni));
458 	mlxsw_reg_sfmr_vtfp_set(sfmr_pl, fid->nve_flood_index_valid);
459 	mlxsw_reg_sfmr_nve_tunnel_flood_ptr_set(sfmr_pl, fid->nve_flood_index);
460 
461 	if (rif) {
462 		mlxsw_reg_sfmr_irif_v_set(sfmr_pl, true);
463 		mlxsw_reg_sfmr_irif_set(sfmr_pl, mlxsw_sp_rif_index(rif));
464 	}
465 
466 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl);
467 }
468 
469 static int mlxsw_sp_fid_vni_to_fid_map(const struct mlxsw_sp_fid *fid,
470 				       const struct mlxsw_sp_rif *rif,
471 				       bool valid)
472 {
473 	struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
474 	char svfa_pl[MLXSW_REG_SVFA_LEN];
475 	bool irif_valid;
476 	u16 irif_index;
477 
478 	irif_valid = !!rif;
479 	irif_index = rif ? mlxsw_sp_rif_index(rif) : 0;
480 
481 	mlxsw_reg_svfa_vni_pack(svfa_pl, valid, fid->fid_index,
482 				be32_to_cpu(fid->vni), irif_valid, irif_index);
483 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl);
484 }
485 
486 static int mlxsw_sp_fid_to_fid_rif_update(const struct mlxsw_sp_fid *fid,
487 					  const struct mlxsw_sp_rif *rif)
488 {
489 	return mlxsw_sp_fid_edit_op(fid, rif);
490 }
491 
492 static int mlxsw_sp_fid_vni_to_fid_rif_update(const struct mlxsw_sp_fid *fid,
493 					      const struct mlxsw_sp_rif *rif)
494 {
495 	if (!fid->vni_valid)
496 		return 0;
497 
498 	return mlxsw_sp_fid_vni_to_fid_map(fid, rif, fid->vni_valid);
499 }
500 
501 static int
502 mlxsw_sp_fid_vid_to_fid_map(const struct mlxsw_sp_fid *fid, u16 vid, bool valid,
503 			    const struct mlxsw_sp_rif *rif)
504 {
505 	struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
506 	char svfa_pl[MLXSW_REG_SVFA_LEN];
507 	bool irif_valid;
508 	u16 irif_index;
509 
510 	irif_valid = !!rif;
511 	irif_index = rif ? mlxsw_sp_rif_index(rif) : 0;
512 
513 	mlxsw_reg_svfa_vid_pack(svfa_pl, valid, fid->fid_index, vid, irif_valid,
514 				irif_index);
515 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl);
516 }
517 
518 static int
519 mlxsw_sp_fid_8021q_vid_to_fid_rif_update(const struct mlxsw_sp_fid *fid,
520 					 const struct mlxsw_sp_rif *rif)
521 {
522 	struct mlxsw_sp_fid_8021q *fid_8021q = mlxsw_sp_fid_8021q_fid(fid);
523 
524 	/* Update the global VID => FID mapping we created when the FID was
525 	 * configured.
526 	 */
527 	return mlxsw_sp_fid_vid_to_fid_map(fid, fid_8021q->vid, true, rif);
528 }
529 
530 static int
531 mlxsw_sp_fid_port_vid_to_fid_rif_update_one(const struct mlxsw_sp_fid *fid,
532 					    struct mlxsw_sp_fid_port_vid *pv,
533 					    bool irif_valid, u16 irif_index)
534 {
535 	struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
536 	char svfa_pl[MLXSW_REG_SVFA_LEN];
537 
538 	mlxsw_reg_svfa_port_vid_pack(svfa_pl, pv->local_port, true,
539 				     fid->fid_index, pv->vid, irif_valid,
540 				     irif_index);
541 
542 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl);
543 }
544 
545 static int mlxsw_sp_fid_vid_to_fid_rif_set(const struct mlxsw_sp_fid *fid,
546 					   const struct mlxsw_sp_rif *rif)
547 {
548 	struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
549 	struct mlxsw_sp_fid_port_vid *pv;
550 	u16 irif_index;
551 	int err;
552 
553 	err = fid->fid_family->ops->vid_to_fid_rif_update(fid, rif);
554 	if (err)
555 		return err;
556 
557 	irif_index = mlxsw_sp_rif_index(rif);
558 
559 	list_for_each_entry(pv, &fid->port_vid_list, list) {
560 		/* If port is not in virtual mode, then it does not have any
561 		 * {Port, VID}->FID mappings that need to be updated with the
562 		 * ingress RIF.
563 		 */
564 		if (!mlxsw_sp->fid_core->port_fid_mappings[pv->local_port])
565 			continue;
566 
567 		err = mlxsw_sp_fid_port_vid_to_fid_rif_update_one(fid, pv,
568 								  true,
569 								  irif_index);
570 		if (err)
571 			goto err_port_vid_to_fid_rif_update_one;
572 	}
573 
574 	return 0;
575 
576 err_port_vid_to_fid_rif_update_one:
577 	list_for_each_entry_continue_reverse(pv, &fid->port_vid_list, list) {
578 		if (!mlxsw_sp->fid_core->port_fid_mappings[pv->local_port])
579 			continue;
580 
581 		mlxsw_sp_fid_port_vid_to_fid_rif_update_one(fid, pv, false, 0);
582 	}
583 
584 	fid->fid_family->ops->vid_to_fid_rif_update(fid, NULL);
585 	return err;
586 }
587 
588 static void mlxsw_sp_fid_vid_to_fid_rif_unset(const struct mlxsw_sp_fid *fid)
589 {
590 	struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
591 	struct mlxsw_sp_fid_port_vid *pv;
592 
593 	list_for_each_entry(pv, &fid->port_vid_list, list) {
594 		/* If port is not in virtual mode, then it does not have any
595 		 * {Port, VID}->FID mappings that need to be updated.
596 		 */
597 		if (!mlxsw_sp->fid_core->port_fid_mappings[pv->local_port])
598 			continue;
599 
600 		mlxsw_sp_fid_port_vid_to_fid_rif_update_one(fid, pv, false, 0);
601 	}
602 
603 	fid->fid_family->ops->vid_to_fid_rif_update(fid, NULL);
604 }
605 
606 static int mlxsw_sp_fid_reiv_handle(struct mlxsw_sp_fid *fid, u16 rif_index,
607 				    bool valid, u8 port_page)
608 {
609 	u16 local_port_end = (port_page + 1) * MLXSW_REG_REIV_REC_MAX_COUNT - 1;
610 	u16 local_port_start = port_page * MLXSW_REG_REIV_REC_MAX_COUNT;
611 	struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
612 	struct mlxsw_sp_fid_port_vid *port_vid;
613 	u8 rec_num, entries_num = 0;
614 	char *reiv_pl;
615 	int err;
616 
617 	reiv_pl = kmalloc(MLXSW_REG_REIV_LEN, GFP_KERNEL);
618 	if (!reiv_pl)
619 		return -ENOMEM;
620 
621 	mlxsw_reg_reiv_pack(reiv_pl, port_page, rif_index);
622 
623 	list_for_each_entry(port_vid, &fid->port_vid_list, list) {
624 		/* port_vid_list is sorted by local_port. */
625 		if (port_vid->local_port < local_port_start)
626 			continue;
627 
628 		if (port_vid->local_port > local_port_end)
629 			break;
630 
631 		rec_num = port_vid->local_port % MLXSW_REG_REIV_REC_MAX_COUNT;
632 		mlxsw_reg_reiv_rec_update_set(reiv_pl, rec_num, true);
633 		mlxsw_reg_reiv_rec_evid_set(reiv_pl, rec_num,
634 					    valid ? port_vid->vid : 0);
635 		entries_num++;
636 	}
637 
638 	if (!entries_num) {
639 		kfree(reiv_pl);
640 		return 0;
641 	}
642 
643 	err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(reiv), reiv_pl);
644 	if (err)
645 		goto err_reg_write;
646 
647 	kfree(reiv_pl);
648 	return 0;
649 
650 err_reg_write:
651 	kfree(reiv_pl);
652 	return err;
653 }
654 
655 static int mlxsw_sp_fid_erif_eport_to_vid_map(struct mlxsw_sp_fid *fid,
656 					      u16 rif_index, bool valid)
657 {
658 	struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
659 	u8 num_port_pages;
660 	int err, i;
661 
662 	num_port_pages = mlxsw_core_max_ports(mlxsw_sp->core) /
663 			 MLXSW_REG_REIV_REC_MAX_COUNT + 1;
664 
665 	for (i = 0; i < num_port_pages; i++) {
666 		err = mlxsw_sp_fid_reiv_handle(fid, rif_index, valid, i);
667 		if (err)
668 			goto err_reiv_handle;
669 	}
670 
671 	return 0;
672 
673 err_reiv_handle:
674 	for (; i >= 0; i--)
675 		mlxsw_sp_fid_reiv_handle(fid, rif_index, !valid, i);
676 	return err;
677 }
678 
679 int mlxsw_sp_fid_rif_set(struct mlxsw_sp_fid *fid, struct mlxsw_sp_rif *rif)
680 {
681 	u16 rif_index = mlxsw_sp_rif_index(rif);
682 	int err;
683 
684 	err = mlxsw_sp_fid_to_fid_rif_update(fid, rif);
685 	if (err)
686 		return err;
687 
688 	err = mlxsw_sp_fid_vni_to_fid_rif_update(fid, rif);
689 	if (err)
690 		goto err_vni_to_fid_rif_update;
691 
692 	err = mlxsw_sp_fid_vid_to_fid_rif_set(fid, rif);
693 	if (err)
694 		goto err_vid_to_fid_rif_set;
695 
696 	err = mlxsw_sp_fid_erif_eport_to_vid_map(fid, rif_index, true);
697 	if (err)
698 		goto err_erif_eport_to_vid_map;
699 
700 	fid->rif = rif;
701 	return 0;
702 
703 err_erif_eport_to_vid_map:
704 	mlxsw_sp_fid_vid_to_fid_rif_unset(fid);
705 err_vid_to_fid_rif_set:
706 	mlxsw_sp_fid_vni_to_fid_rif_update(fid, NULL);
707 err_vni_to_fid_rif_update:
708 	mlxsw_sp_fid_to_fid_rif_update(fid, NULL);
709 	return err;
710 }
711 
712 void mlxsw_sp_fid_rif_unset(struct mlxsw_sp_fid *fid)
713 {
714 	u16 rif_index;
715 
716 	if (!fid->rif)
717 		return;
718 
719 	rif_index = mlxsw_sp_rif_index(fid->rif);
720 	fid->rif = NULL;
721 
722 	mlxsw_sp_fid_erif_eport_to_vid_map(fid, rif_index, false);
723 	mlxsw_sp_fid_vid_to_fid_rif_unset(fid);
724 	mlxsw_sp_fid_vni_to_fid_rif_update(fid, NULL);
725 	mlxsw_sp_fid_to_fid_rif_update(fid, NULL);
726 }
727 
728 static int mlxsw_sp_fid_vni_op(const struct mlxsw_sp_fid *fid)
729 {
730 	int err;
731 
732 	err = mlxsw_sp_fid_vni_to_fid_map(fid, fid->rif, fid->vni_valid);
733 	if (err)
734 		return err;
735 
736 	err = mlxsw_sp_fid_edit_op(fid, fid->rif);
737 	if (err)
738 		goto err_fid_edit_op;
739 
740 	return 0;
741 
742 err_fid_edit_op:
743 	mlxsw_sp_fid_vni_to_fid_map(fid, fid->rif, !fid->vni_valid);
744 	return err;
745 }
746 
747 static int __mlxsw_sp_fid_port_vid_map(const struct mlxsw_sp_fid *fid,
748 				       u16 local_port, u16 vid, bool valid)
749 {
750 	struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
751 	char svfa_pl[MLXSW_REG_SVFA_LEN];
752 	bool irif_valid = false;
753 	u16 irif_index = 0;
754 
755 	if (fid->rif) {
756 		irif_valid = true;
757 		irif_index = mlxsw_sp_rif_index(fid->rif);
758 	}
759 
760 	mlxsw_reg_svfa_port_vid_pack(svfa_pl, local_port, valid, fid->fid_index,
761 				     vid, irif_valid, irif_index);
762 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl);
763 }
764 
765 static struct mlxsw_sp_fid_8021d *
766 mlxsw_sp_fid_8021d_fid(const struct mlxsw_sp_fid *fid)
767 {
768 	return container_of(fid, struct mlxsw_sp_fid_8021d, common);
769 }
770 
771 static void mlxsw_sp_fid_8021d_setup(struct mlxsw_sp_fid *fid, const void *arg)
772 {
773 	int br_ifindex = *(int *) arg;
774 
775 	mlxsw_sp_fid_8021d_fid(fid)->br_ifindex = br_ifindex;
776 	fid->fid_offset = fid->fid_index - fid->fid_family->start_index;
777 }
778 
779 static int mlxsw_sp_fid_8021d_configure(struct mlxsw_sp_fid *fid)
780 {
781 	return mlxsw_sp_fid_op(fid, true);
782 }
783 
784 static void mlxsw_sp_fid_8021d_deconfigure(struct mlxsw_sp_fid *fid)
785 {
786 	if (fid->vni_valid)
787 		mlxsw_sp_nve_fid_disable(fid->fid_family->mlxsw_sp, fid);
788 	mlxsw_sp_fid_op(fid, false);
789 }
790 
791 static int mlxsw_sp_fid_8021d_index_alloc(struct mlxsw_sp_fid *fid,
792 					  const void *arg, u16 *p_fid_index)
793 {
794 	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
795 	u16 nr_fids, fid_index;
796 
797 	nr_fids = fid_family->end_index - fid_family->start_index + 1;
798 	fid_index = find_first_zero_bit(fid_family->fids_bitmap, nr_fids);
799 	if (fid_index == nr_fids)
800 		return -ENOBUFS;
801 	*p_fid_index = fid_family->start_index + fid_index;
802 
803 	return 0;
804 }
805 
806 static bool
807 mlxsw_sp_fid_8021d_compare(const struct mlxsw_sp_fid *fid, const void *arg)
808 {
809 	int br_ifindex = *(int *) arg;
810 
811 	return mlxsw_sp_fid_8021d_fid(fid)->br_ifindex == br_ifindex;
812 }
813 
814 static int mlxsw_sp_port_vp_mode_trans(struct mlxsw_sp_port *mlxsw_sp_port)
815 {
816 	struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
817 	int err;
818 
819 	list_for_each_entry(mlxsw_sp_port_vlan, &mlxsw_sp_port->vlans_list,
820 			    list) {
821 		struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid;
822 		u16 vid = mlxsw_sp_port_vlan->vid;
823 
824 		if (!fid)
825 			continue;
826 
827 		err = __mlxsw_sp_fid_port_vid_map(fid,
828 						  mlxsw_sp_port->local_port,
829 						  vid, true);
830 		if (err)
831 			goto err_fid_port_vid_map;
832 	}
833 
834 	err = mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, true);
835 	if (err)
836 		goto err_port_vp_mode_set;
837 
838 	return 0;
839 
840 err_port_vp_mode_set:
841 err_fid_port_vid_map:
842 	list_for_each_entry_continue_reverse(mlxsw_sp_port_vlan,
843 					     &mlxsw_sp_port->vlans_list, list) {
844 		struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid;
845 		u16 vid = mlxsw_sp_port_vlan->vid;
846 
847 		if (!fid)
848 			continue;
849 
850 		__mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid,
851 					    false);
852 	}
853 	return err;
854 }
855 
856 static void mlxsw_sp_port_vlan_mode_trans(struct mlxsw_sp_port *mlxsw_sp_port)
857 {
858 	struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
859 
860 	mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, false);
861 
862 	list_for_each_entry_reverse(mlxsw_sp_port_vlan,
863 				    &mlxsw_sp_port->vlans_list, list) {
864 		struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid;
865 		u16 vid = mlxsw_sp_port_vlan->vid;
866 
867 		if (!fid)
868 			continue;
869 
870 		__mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid,
871 					    false);
872 	}
873 }
874 
875 static int
876 mlxsw_sp_fid_port_vid_list_add(struct mlxsw_sp_fid *fid, u16 local_port,
877 			       u16 vid)
878 {
879 	struct mlxsw_sp_fid_port_vid *port_vid, *tmp_port_vid;
880 
881 	port_vid = kzalloc(sizeof(*port_vid), GFP_KERNEL);
882 	if (!port_vid)
883 		return -ENOMEM;
884 
885 	port_vid->local_port = local_port;
886 	port_vid->vid = vid;
887 
888 	list_for_each_entry(tmp_port_vid, &fid->port_vid_list, list) {
889 		if (tmp_port_vid->local_port > local_port)
890 			break;
891 	}
892 
893 	list_add_tail(&port_vid->list, &tmp_port_vid->list);
894 	return 0;
895 }
896 
897 static void
898 mlxsw_sp_fid_port_vid_list_del(struct mlxsw_sp_fid *fid, u16 local_port,
899 			       u16 vid)
900 {
901 	struct mlxsw_sp_fid_port_vid *port_vid, *tmp;
902 
903 	list_for_each_entry_safe(port_vid, tmp, &fid->port_vid_list, list) {
904 		if (port_vid->local_port != local_port || port_vid->vid != vid)
905 			continue;
906 
907 		list_del(&port_vid->list);
908 		kfree(port_vid);
909 		return;
910 	}
911 }
912 
913 static int
914 mlxsw_sp_fid_mpe_table_map(const struct mlxsw_sp_fid *fid, u16 local_port,
915 			   u16 vid, bool valid)
916 {
917 	struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
918 	char smpe_pl[MLXSW_REG_SMPE_LEN];
919 
920 	mlxsw_reg_smpe_pack(smpe_pl, local_port, fid->fid_index,
921 			    valid ? vid : 0);
922 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(smpe), smpe_pl);
923 }
924 
925 static int
926 mlxsw_sp_fid_erif_eport_to_vid_map_one(const struct mlxsw_sp_fid *fid,
927 				       u16 local_port, u16 vid, bool valid)
928 {
929 	u8 port_page = local_port / MLXSW_REG_REIV_REC_MAX_COUNT;
930 	u8 rec_num = local_port % MLXSW_REG_REIV_REC_MAX_COUNT;
931 	struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
932 	u16 rif_index = mlxsw_sp_rif_index(fid->rif);
933 	char *reiv_pl;
934 	int err;
935 
936 	reiv_pl = kmalloc(MLXSW_REG_REIV_LEN, GFP_KERNEL);
937 	if (!reiv_pl)
938 		return -ENOMEM;
939 
940 	mlxsw_reg_reiv_pack(reiv_pl, port_page, rif_index);
941 	mlxsw_reg_reiv_rec_update_set(reiv_pl, rec_num, true);
942 	mlxsw_reg_reiv_rec_evid_set(reiv_pl, rec_num, valid ? vid : 0);
943 	err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(reiv), reiv_pl);
944 	kfree(reiv_pl);
945 	return err;
946 }
947 
948 static int mlxsw_sp_fid_evid_map(const struct mlxsw_sp_fid *fid, u16 local_port,
949 				 u16 vid, bool valid)
950 {
951 	int err;
952 
953 	err = mlxsw_sp_fid_mpe_table_map(fid, local_port, vid, valid);
954 	if (err)
955 		return err;
956 
957 	if (!fid->rif)
958 		return 0;
959 
960 	err = mlxsw_sp_fid_erif_eport_to_vid_map_one(fid, local_port, vid,
961 						     valid);
962 	if (err)
963 		goto err_erif_eport_to_vid_map_one;
964 
965 	return 0;
966 
967 err_erif_eport_to_vid_map_one:
968 	mlxsw_sp_fid_mpe_table_map(fid, local_port, vid, !valid);
969 	return err;
970 }
971 
972 static int mlxsw_sp_fid_8021d_port_vid_map(struct mlxsw_sp_fid *fid,
973 					   struct mlxsw_sp_port *mlxsw_sp_port,
974 					   u16 vid)
975 {
976 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
977 	u16 local_port = mlxsw_sp_port->local_port;
978 	int err;
979 
980 	err = __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid,
981 					  true);
982 	if (err)
983 		return err;
984 
985 	err = mlxsw_sp_fid_evid_map(fid, local_port, vid, true);
986 	if (err)
987 		goto err_fid_evid_map;
988 
989 	err = mlxsw_sp_fid_port_vid_list_add(fid, mlxsw_sp_port->local_port,
990 					     vid);
991 	if (err)
992 		goto err_port_vid_list_add;
993 
994 	if (mlxsw_sp->fid_core->port_fid_mappings[local_port]++ == 0) {
995 		err = mlxsw_sp_port_vp_mode_trans(mlxsw_sp_port);
996 		if (err)
997 			goto err_port_vp_mode_trans;
998 	}
999 
1000 	return 0;
1001 
1002 err_port_vp_mode_trans:
1003 	mlxsw_sp->fid_core->port_fid_mappings[local_port]--;
1004 	mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid);
1005 err_port_vid_list_add:
1006 	mlxsw_sp_fid_evid_map(fid, local_port, vid, false);
1007 err_fid_evid_map:
1008 	__mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, false);
1009 	return err;
1010 }
1011 
1012 static void
1013 mlxsw_sp_fid_8021d_port_vid_unmap(struct mlxsw_sp_fid *fid,
1014 				  struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
1015 {
1016 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1017 	u16 local_port = mlxsw_sp_port->local_port;
1018 
1019 	if (mlxsw_sp->fid_core->port_fid_mappings[local_port] == 1)
1020 		mlxsw_sp_port_vlan_mode_trans(mlxsw_sp_port);
1021 	mlxsw_sp->fid_core->port_fid_mappings[local_port]--;
1022 	mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid);
1023 	mlxsw_sp_fid_evid_map(fid, local_port, vid, false);
1024 	__mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, false);
1025 }
1026 
1027 static int mlxsw_sp_fid_8021d_vni_set(struct mlxsw_sp_fid *fid)
1028 {
1029 	return mlxsw_sp_fid_vni_op(fid);
1030 }
1031 
1032 static void mlxsw_sp_fid_8021d_vni_clear(struct mlxsw_sp_fid *fid)
1033 {
1034 	mlxsw_sp_fid_vni_op(fid);
1035 }
1036 
1037 static int mlxsw_sp_fid_8021d_nve_flood_index_set(struct mlxsw_sp_fid *fid)
1038 {
1039 	return mlxsw_sp_fid_edit_op(fid, fid->rif);
1040 }
1041 
1042 static void mlxsw_sp_fid_8021d_nve_flood_index_clear(struct mlxsw_sp_fid *fid)
1043 {
1044 	mlxsw_sp_fid_edit_op(fid, fid->rif);
1045 }
1046 
1047 static void
1048 mlxsw_sp_fid_8021d_fdb_clear_offload(const struct mlxsw_sp_fid *fid,
1049 				     const struct net_device *nve_dev)
1050 {
1051 	br_fdb_clear_offload(nve_dev, 0);
1052 }
1053 
1054 static int
1055 mlxsw_sp_fid_8021d_vid_to_fid_rif_update(const struct mlxsw_sp_fid *fid,
1056 					 const struct mlxsw_sp_rif *rif)
1057 {
1058 	return 0;
1059 }
1060 
1061 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021d_ops = {
1062 	.setup			= mlxsw_sp_fid_8021d_setup,
1063 	.configure		= mlxsw_sp_fid_8021d_configure,
1064 	.deconfigure		= mlxsw_sp_fid_8021d_deconfigure,
1065 	.index_alloc		= mlxsw_sp_fid_8021d_index_alloc,
1066 	.compare		= mlxsw_sp_fid_8021d_compare,
1067 	.port_vid_map		= mlxsw_sp_fid_8021d_port_vid_map,
1068 	.port_vid_unmap		= mlxsw_sp_fid_8021d_port_vid_unmap,
1069 	.vni_set		= mlxsw_sp_fid_8021d_vni_set,
1070 	.vni_clear		= mlxsw_sp_fid_8021d_vni_clear,
1071 	.nve_flood_index_set	= mlxsw_sp_fid_8021d_nve_flood_index_set,
1072 	.nve_flood_index_clear	= mlxsw_sp_fid_8021d_nve_flood_index_clear,
1073 	.fdb_clear_offload	= mlxsw_sp_fid_8021d_fdb_clear_offload,
1074 	.vid_to_fid_rif_update  = mlxsw_sp_fid_8021d_vid_to_fid_rif_update,
1075 };
1076 
1077 #define MLXSW_SP_FID_8021Q_MAX (VLAN_N_VID - 2)
1078 #define MLXSW_SP_FID_RFID_MAX (11 * 1024)
1079 
1080 static const struct mlxsw_sp_flood_table mlxsw_sp_fid_8021d_flood_tables[] = {
1081 	{
1082 		.packet_type	= MLXSW_SP_FLOOD_TYPE_UC,
1083 		.table_type	= MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFSET,
1084 		.table_index	= 0,
1085 	},
1086 	{
1087 		.packet_type	= MLXSW_SP_FLOOD_TYPE_MC,
1088 		.table_type	= MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFSET,
1089 		.table_index	= 1,
1090 	},
1091 	{
1092 		.packet_type	= MLXSW_SP_FLOOD_TYPE_BC,
1093 		.table_type	= MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFSET,
1094 		.table_index	= 2,
1095 	},
1096 };
1097 
1098 static bool
1099 mlxsw_sp_fid_8021q_compare(const struct mlxsw_sp_fid *fid, const void *arg)
1100 {
1101 	u16 vid = *(u16 *) arg;
1102 
1103 	return mlxsw_sp_fid_8021q_fid(fid)->vid == vid;
1104 }
1105 
1106 static void
1107 mlxsw_sp_fid_8021q_fdb_clear_offload(const struct mlxsw_sp_fid *fid,
1108 				     const struct net_device *nve_dev)
1109 {
1110 	br_fdb_clear_offload(nve_dev, mlxsw_sp_fid_8021q_vid(fid));
1111 }
1112 
1113 static void mlxsw_sp_fid_rfid_setup(struct mlxsw_sp_fid *fid, const void *arg)
1114 {
1115 	fid->fid_offset = 0;
1116 }
1117 
1118 static int mlxsw_sp_fid_rfid_configure(struct mlxsw_sp_fid *fid)
1119 {
1120 	return mlxsw_sp_fid_op(fid, true);
1121 }
1122 
1123 static void mlxsw_sp_fid_rfid_deconfigure(struct mlxsw_sp_fid *fid)
1124 {
1125 	mlxsw_sp_fid_op(fid, false);
1126 }
1127 
1128 static int mlxsw_sp_fid_rfid_index_alloc(struct mlxsw_sp_fid *fid,
1129 					 const void *arg, u16 *p_fid_index)
1130 {
1131 	u16 rif_index = *(u16 *) arg;
1132 
1133 	*p_fid_index = fid->fid_family->start_index + rif_index;
1134 
1135 	return 0;
1136 }
1137 
1138 static bool mlxsw_sp_fid_rfid_compare(const struct mlxsw_sp_fid *fid,
1139 				      const void *arg)
1140 {
1141 	u16 rif_index = *(u16 *) arg;
1142 
1143 	return fid->fid_index == rif_index + fid->fid_family->start_index;
1144 }
1145 
1146 static int mlxsw_sp_fid_rfid_port_vid_map(struct mlxsw_sp_fid *fid,
1147 					  struct mlxsw_sp_port *mlxsw_sp_port,
1148 					  u16 vid)
1149 {
1150 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1151 	u16 local_port = mlxsw_sp_port->local_port;
1152 	int err;
1153 
1154 	err = mlxsw_sp_fid_port_vid_list_add(fid, mlxsw_sp_port->local_port,
1155 					     vid);
1156 	if (err)
1157 		return err;
1158 
1159 	/* Using legacy bridge model, we only need to transition the port to
1160 	 * virtual mode since {Port, VID} => FID is done by the firmware upon
1161 	 * RIF creation. Using unified bridge model, we need to map
1162 	 * {Port, VID} => FID and map egress VID.
1163 	 */
1164 	err = __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid,
1165 					  true);
1166 	if (err)
1167 		goto err_port_vid_map;
1168 
1169 	if (fid->rif) {
1170 		err = mlxsw_sp_fid_erif_eport_to_vid_map_one(fid, local_port,
1171 							     vid, true);
1172 		if (err)
1173 			goto err_erif_eport_to_vid_map_one;
1174 	}
1175 
1176 	if (mlxsw_sp->fid_core->port_fid_mappings[local_port]++ == 0) {
1177 		err = mlxsw_sp_port_vp_mode_trans(mlxsw_sp_port);
1178 		if (err)
1179 			goto err_port_vp_mode_trans;
1180 	}
1181 
1182 	return 0;
1183 
1184 err_port_vp_mode_trans:
1185 	mlxsw_sp->fid_core->port_fid_mappings[local_port]--;
1186 	if (fid->rif)
1187 		mlxsw_sp_fid_erif_eport_to_vid_map_one(fid, local_port, vid,
1188 						       false);
1189 err_erif_eport_to_vid_map_one:
1190 	__mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, false);
1191 err_port_vid_map:
1192 	mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid);
1193 	return err;
1194 }
1195 
1196 static void
1197 mlxsw_sp_fid_rfid_port_vid_unmap(struct mlxsw_sp_fid *fid,
1198 				 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
1199 {
1200 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1201 	u16 local_port = mlxsw_sp_port->local_port;
1202 
1203 	if (mlxsw_sp->fid_core->port_fid_mappings[local_port] == 1)
1204 		mlxsw_sp_port_vlan_mode_trans(mlxsw_sp_port);
1205 	mlxsw_sp->fid_core->port_fid_mappings[local_port]--;
1206 
1207 	if (fid->rif)
1208 		mlxsw_sp_fid_erif_eport_to_vid_map_one(fid, local_port, vid,
1209 						       false);
1210 	__mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, false);
1211 	mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid);
1212 }
1213 
1214 static int mlxsw_sp_fid_rfid_vni_set(struct mlxsw_sp_fid *fid)
1215 {
1216 	return -EOPNOTSUPP;
1217 }
1218 
1219 static void mlxsw_sp_fid_rfid_vni_clear(struct mlxsw_sp_fid *fid)
1220 {
1221 	WARN_ON_ONCE(1);
1222 }
1223 
1224 static int mlxsw_sp_fid_rfid_nve_flood_index_set(struct mlxsw_sp_fid *fid)
1225 {
1226 	return -EOPNOTSUPP;
1227 }
1228 
1229 static void mlxsw_sp_fid_rfid_nve_flood_index_clear(struct mlxsw_sp_fid *fid)
1230 {
1231 	WARN_ON_ONCE(1);
1232 }
1233 
1234 static int
1235 mlxsw_sp_fid_rfid_vid_to_fid_rif_update(const struct mlxsw_sp_fid *fid,
1236 					const struct mlxsw_sp_rif *rif)
1237 {
1238 	return 0;
1239 }
1240 
1241 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_rfid_ops = {
1242 	.setup			= mlxsw_sp_fid_rfid_setup,
1243 	.configure		= mlxsw_sp_fid_rfid_configure,
1244 	.deconfigure		= mlxsw_sp_fid_rfid_deconfigure,
1245 	.index_alloc		= mlxsw_sp_fid_rfid_index_alloc,
1246 	.compare		= mlxsw_sp_fid_rfid_compare,
1247 	.port_vid_map		= mlxsw_sp_fid_rfid_port_vid_map,
1248 	.port_vid_unmap		= mlxsw_sp_fid_rfid_port_vid_unmap,
1249 	.vni_set                = mlxsw_sp_fid_rfid_vni_set,
1250 	.vni_clear		= mlxsw_sp_fid_rfid_vni_clear,
1251 	.nve_flood_index_set	= mlxsw_sp_fid_rfid_nve_flood_index_set,
1252 	.nve_flood_index_clear	= mlxsw_sp_fid_rfid_nve_flood_index_clear,
1253 	.vid_to_fid_rif_update  = mlxsw_sp_fid_rfid_vid_to_fid_rif_update,
1254 };
1255 
1256 static void mlxsw_sp_fid_dummy_setup(struct mlxsw_sp_fid *fid, const void *arg)
1257 {
1258 	fid->fid_offset = 0;
1259 }
1260 
1261 static int mlxsw_sp_fid_dummy_configure(struct mlxsw_sp_fid *fid)
1262 {
1263 	return mlxsw_sp_fid_op(fid, true);
1264 }
1265 
1266 static void mlxsw_sp_fid_dummy_deconfigure(struct mlxsw_sp_fid *fid)
1267 {
1268 	mlxsw_sp_fid_op(fid, false);
1269 }
1270 
1271 static int mlxsw_sp_fid_dummy_index_alloc(struct mlxsw_sp_fid *fid,
1272 					  const void *arg, u16 *p_fid_index)
1273 {
1274 	*p_fid_index = fid->fid_family->start_index;
1275 
1276 	return 0;
1277 }
1278 
1279 static bool mlxsw_sp_fid_dummy_compare(const struct mlxsw_sp_fid *fid,
1280 				       const void *arg)
1281 {
1282 	return true;
1283 }
1284 
1285 static int mlxsw_sp_fid_dummy_vni_set(struct mlxsw_sp_fid *fid)
1286 {
1287 	return -EOPNOTSUPP;
1288 }
1289 
1290 static void mlxsw_sp_fid_dummy_vni_clear(struct mlxsw_sp_fid *fid)
1291 {
1292 	WARN_ON_ONCE(1);
1293 }
1294 
1295 static int mlxsw_sp_fid_dummy_nve_flood_index_set(struct mlxsw_sp_fid *fid)
1296 {
1297 	return -EOPNOTSUPP;
1298 }
1299 
1300 static void mlxsw_sp_fid_dummy_nve_flood_index_clear(struct mlxsw_sp_fid *fid)
1301 {
1302 	WARN_ON_ONCE(1);
1303 }
1304 
1305 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_dummy_ops = {
1306 	.setup			= mlxsw_sp_fid_dummy_setup,
1307 	.configure		= mlxsw_sp_fid_dummy_configure,
1308 	.deconfigure		= mlxsw_sp_fid_dummy_deconfigure,
1309 	.index_alloc		= mlxsw_sp_fid_dummy_index_alloc,
1310 	.compare		= mlxsw_sp_fid_dummy_compare,
1311 	.vni_set                = mlxsw_sp_fid_dummy_vni_set,
1312 	.vni_clear		= mlxsw_sp_fid_dummy_vni_clear,
1313 	.nve_flood_index_set	= mlxsw_sp_fid_dummy_nve_flood_index_set,
1314 	.nve_flood_index_clear	= mlxsw_sp_fid_dummy_nve_flood_index_clear,
1315 };
1316 
1317 static int mlxsw_sp_fid_8021q_configure(struct mlxsw_sp_fid *fid)
1318 {
1319 	struct mlxsw_sp_fid_8021q *fid_8021q = mlxsw_sp_fid_8021q_fid(fid);
1320 	int err;
1321 
1322 	err = mlxsw_sp_fid_op(fid, true);
1323 	if (err)
1324 		return err;
1325 
1326 	err = mlxsw_sp_fid_vid_to_fid_map(fid, fid_8021q->vid, true, fid->rif);
1327 	if (err)
1328 		goto err_vid_to_fid_map;
1329 
1330 	return 0;
1331 
1332 err_vid_to_fid_map:
1333 	mlxsw_sp_fid_op(fid, false);
1334 	return err;
1335 }
1336 
1337 static void mlxsw_sp_fid_8021q_deconfigure(struct mlxsw_sp_fid *fid)
1338 {
1339 	struct mlxsw_sp_fid_8021q *fid_8021q = mlxsw_sp_fid_8021q_fid(fid);
1340 
1341 	if (fid->vni_valid)
1342 		mlxsw_sp_nve_fid_disable(fid->fid_family->mlxsw_sp, fid);
1343 
1344 	mlxsw_sp_fid_vid_to_fid_map(fid, fid_8021q->vid, false, NULL);
1345 	mlxsw_sp_fid_op(fid, false);
1346 }
1347 
1348 static int mlxsw_sp_fid_8021q_port_vid_map(struct mlxsw_sp_fid *fid,
1349 					   struct mlxsw_sp_port *mlxsw_sp_port,
1350 					   u16 vid)
1351 {
1352 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1353 	u16 local_port = mlxsw_sp_port->local_port;
1354 	int err;
1355 
1356 	/* In case there are no {Port, VID} => FID mappings on the port,
1357 	 * we can use the global VID => FID mapping we created when the
1358 	 * FID was configured, otherwise, configure new mapping.
1359 	 */
1360 	if (mlxsw_sp->fid_core->port_fid_mappings[local_port]) {
1361 		err =  __mlxsw_sp_fid_port_vid_map(fid, local_port, vid, true);
1362 		if (err)
1363 			return err;
1364 	}
1365 
1366 	err = mlxsw_sp_fid_evid_map(fid, local_port, vid, true);
1367 	if (err)
1368 		goto err_fid_evid_map;
1369 
1370 	err = mlxsw_sp_fid_port_vid_list_add(fid, mlxsw_sp_port->local_port,
1371 					     vid);
1372 	if (err)
1373 		goto err_port_vid_list_add;
1374 
1375 	return 0;
1376 
1377 err_port_vid_list_add:
1378 	 mlxsw_sp_fid_evid_map(fid, local_port, vid, false);
1379 err_fid_evid_map:
1380 	if (mlxsw_sp->fid_core->port_fid_mappings[local_port])
1381 		__mlxsw_sp_fid_port_vid_map(fid, local_port, vid, false);
1382 	return err;
1383 }
1384 
1385 static void
1386 mlxsw_sp_fid_8021q_port_vid_unmap(struct mlxsw_sp_fid *fid,
1387 				  struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
1388 {
1389 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1390 	u16 local_port = mlxsw_sp_port->local_port;
1391 
1392 	mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid);
1393 	mlxsw_sp_fid_evid_map(fid, local_port, vid, false);
1394 	if (mlxsw_sp->fid_core->port_fid_mappings[local_port])
1395 		__mlxsw_sp_fid_port_vid_map(fid, local_port, vid, false);
1396 }
1397 
1398 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021q_ops = {
1399 	.setup			= mlxsw_sp_fid_8021q_setup,
1400 	.configure		= mlxsw_sp_fid_8021q_configure,
1401 	.deconfigure		= mlxsw_sp_fid_8021q_deconfigure,
1402 	.index_alloc		= mlxsw_sp_fid_8021d_index_alloc,
1403 	.compare		= mlxsw_sp_fid_8021q_compare,
1404 	.port_vid_map		= mlxsw_sp_fid_8021q_port_vid_map,
1405 	.port_vid_unmap		= mlxsw_sp_fid_8021q_port_vid_unmap,
1406 	.vni_set		= mlxsw_sp_fid_8021d_vni_set,
1407 	.vni_clear		= mlxsw_sp_fid_8021d_vni_clear,
1408 	.nve_flood_index_set	= mlxsw_sp_fid_8021d_nve_flood_index_set,
1409 	.nve_flood_index_clear	= mlxsw_sp_fid_8021d_nve_flood_index_clear,
1410 	.fdb_clear_offload	= mlxsw_sp_fid_8021q_fdb_clear_offload,
1411 	.vid_to_fid_rif_update  = mlxsw_sp_fid_8021q_vid_to_fid_rif_update,
1412 };
1413 
1414 /* There are 4K-2 802.1Q FIDs */
1415 #define MLXSW_SP_FID_8021Q_START	1 /* FID 0 is reserved. */
1416 #define MLXSW_SP_FID_8021Q_END		(MLXSW_SP_FID_8021Q_START + \
1417 					 MLXSW_SP_FID_8021Q_MAX - 1)
1418 
1419 /* There are 1K 802.1D FIDs */
1420 #define MLXSW_SP_FID_8021D_START	(MLXSW_SP_FID_8021Q_END + 1)
1421 #define MLXSW_SP_FID_8021D_END		(MLXSW_SP_FID_8021D_START + \
1422 					 MLXSW_SP_FID_8021D_MAX - 1)
1423 
1424 /* There is one dummy FID */
1425 #define MLXSW_SP_FID_DUMMY		(MLXSW_SP_FID_8021D_END + 1)
1426 
1427 /* There are 11K rFIDs */
1428 #define MLXSW_SP_RFID_START		(MLXSW_SP_FID_DUMMY + 1)
1429 #define MLXSW_SP_RFID_END		(MLXSW_SP_RFID_START + \
1430 					 MLXSW_SP_FID_RFID_MAX - 1)
1431 
1432 static const struct mlxsw_sp_fid_family mlxsw_sp1_fid_8021q_family = {
1433 	.type			= MLXSW_SP_FID_TYPE_8021Q,
1434 	.fid_size		= sizeof(struct mlxsw_sp_fid_8021q),
1435 	.start_index		= MLXSW_SP_FID_8021Q_START,
1436 	.end_index		= MLXSW_SP_FID_8021Q_END,
1437 	.flood_tables		= mlxsw_sp_fid_8021d_flood_tables,
1438 	.nr_flood_tables	= ARRAY_SIZE(mlxsw_sp_fid_8021d_flood_tables),
1439 	.rif_type		= MLXSW_SP_RIF_TYPE_VLAN,
1440 	.ops			= &mlxsw_sp_fid_8021q_ops,
1441 	.flood_rsp              = false,
1442 	.bridge_type            = MLXSW_REG_BRIDGE_TYPE_0,
1443 	.smpe_index_valid	= false,
1444 };
1445 
1446 static const struct mlxsw_sp_fid_family mlxsw_sp1_fid_8021d_family = {
1447 	.type			= MLXSW_SP_FID_TYPE_8021D,
1448 	.fid_size		= sizeof(struct mlxsw_sp_fid_8021d),
1449 	.start_index		= MLXSW_SP_FID_8021D_START,
1450 	.end_index		= MLXSW_SP_FID_8021D_END,
1451 	.flood_tables		= mlxsw_sp_fid_8021d_flood_tables,
1452 	.nr_flood_tables	= ARRAY_SIZE(mlxsw_sp_fid_8021d_flood_tables),
1453 	.rif_type		= MLXSW_SP_RIF_TYPE_FID,
1454 	.ops			= &mlxsw_sp_fid_8021d_ops,
1455 	.bridge_type            = MLXSW_REG_BRIDGE_TYPE_1,
1456 	.smpe_index_valid       = false,
1457 };
1458 
1459 static const struct mlxsw_sp_fid_family mlxsw_sp1_fid_dummy_family = {
1460 	.type			= MLXSW_SP_FID_TYPE_DUMMY,
1461 	.fid_size		= sizeof(struct mlxsw_sp_fid),
1462 	.start_index		= MLXSW_SP_FID_DUMMY,
1463 	.end_index		= MLXSW_SP_FID_DUMMY,
1464 	.ops			= &mlxsw_sp_fid_dummy_ops,
1465 	.smpe_index_valid       = false,
1466 };
1467 
1468 static const struct mlxsw_sp_fid_family mlxsw_sp_fid_rfid_family = {
1469 	.type			= MLXSW_SP_FID_TYPE_RFID,
1470 	.fid_size		= sizeof(struct mlxsw_sp_fid),
1471 	.start_index		= MLXSW_SP_RFID_START,
1472 	.end_index		= MLXSW_SP_RFID_END,
1473 	.rif_type		= MLXSW_SP_RIF_TYPE_SUBPORT,
1474 	.ops			= &mlxsw_sp_fid_rfid_ops,
1475 	.flood_rsp              = true,
1476 	.smpe_index_valid       = false,
1477 };
1478 
1479 const struct mlxsw_sp_fid_family *mlxsw_sp1_fid_family_arr[] = {
1480 	[MLXSW_SP_FID_TYPE_8021Q]	= &mlxsw_sp1_fid_8021q_family,
1481 	[MLXSW_SP_FID_TYPE_8021D]	= &mlxsw_sp1_fid_8021d_family,
1482 	[MLXSW_SP_FID_TYPE_DUMMY]	= &mlxsw_sp1_fid_dummy_family,
1483 	[MLXSW_SP_FID_TYPE_RFID]	= &mlxsw_sp_fid_rfid_family,
1484 };
1485 
1486 static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_8021q_family = {
1487 	.type			= MLXSW_SP_FID_TYPE_8021Q,
1488 	.fid_size		= sizeof(struct mlxsw_sp_fid_8021q),
1489 	.start_index		= MLXSW_SP_FID_8021Q_START,
1490 	.end_index		= MLXSW_SP_FID_8021Q_END,
1491 	.flood_tables		= mlxsw_sp_fid_8021d_flood_tables,
1492 	.nr_flood_tables	= ARRAY_SIZE(mlxsw_sp_fid_8021d_flood_tables),
1493 	.rif_type		= MLXSW_SP_RIF_TYPE_VLAN,
1494 	.ops			= &mlxsw_sp_fid_8021q_ops,
1495 	.flood_rsp              = false,
1496 	.bridge_type            = MLXSW_REG_BRIDGE_TYPE_0,
1497 	.smpe_index_valid	= true,
1498 };
1499 
1500 static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_8021d_family = {
1501 	.type			= MLXSW_SP_FID_TYPE_8021D,
1502 	.fid_size		= sizeof(struct mlxsw_sp_fid_8021d),
1503 	.start_index		= MLXSW_SP_FID_8021D_START,
1504 	.end_index		= MLXSW_SP_FID_8021D_END,
1505 	.flood_tables		= mlxsw_sp_fid_8021d_flood_tables,
1506 	.nr_flood_tables	= ARRAY_SIZE(mlxsw_sp_fid_8021d_flood_tables),
1507 	.rif_type		= MLXSW_SP_RIF_TYPE_FID,
1508 	.ops			= &mlxsw_sp_fid_8021d_ops,
1509 	.bridge_type            = MLXSW_REG_BRIDGE_TYPE_1,
1510 	.smpe_index_valid       = true,
1511 };
1512 
1513 static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_dummy_family = {
1514 	.type			= MLXSW_SP_FID_TYPE_DUMMY,
1515 	.fid_size		= sizeof(struct mlxsw_sp_fid),
1516 	.start_index		= MLXSW_SP_FID_DUMMY,
1517 	.end_index		= MLXSW_SP_FID_DUMMY,
1518 	.ops			= &mlxsw_sp_fid_dummy_ops,
1519 	.smpe_index_valid       = false,
1520 };
1521 
1522 const struct mlxsw_sp_fid_family *mlxsw_sp2_fid_family_arr[] = {
1523 	[MLXSW_SP_FID_TYPE_8021Q]	= &mlxsw_sp2_fid_8021q_family,
1524 	[MLXSW_SP_FID_TYPE_8021D]	= &mlxsw_sp2_fid_8021d_family,
1525 	[MLXSW_SP_FID_TYPE_DUMMY]	= &mlxsw_sp2_fid_dummy_family,
1526 	[MLXSW_SP_FID_TYPE_RFID]	= &mlxsw_sp_fid_rfid_family,
1527 };
1528 
1529 static struct mlxsw_sp_fid *mlxsw_sp_fid_lookup(struct mlxsw_sp *mlxsw_sp,
1530 						enum mlxsw_sp_fid_type type,
1531 						const void *arg)
1532 {
1533 	struct mlxsw_sp_fid_family *fid_family;
1534 	struct mlxsw_sp_fid *fid;
1535 
1536 	fid_family = mlxsw_sp->fid_core->fid_family_arr[type];
1537 	list_for_each_entry(fid, &fid_family->fids_list, list) {
1538 		if (!fid->fid_family->ops->compare(fid, arg))
1539 			continue;
1540 		refcount_inc(&fid->ref_count);
1541 		return fid;
1542 	}
1543 
1544 	return NULL;
1545 }
1546 
1547 static struct mlxsw_sp_fid *mlxsw_sp_fid_get(struct mlxsw_sp *mlxsw_sp,
1548 					     enum mlxsw_sp_fid_type type,
1549 					     const void *arg)
1550 {
1551 	struct mlxsw_sp_fid_family *fid_family;
1552 	struct mlxsw_sp_fid *fid;
1553 	u16 fid_index;
1554 	int err;
1555 
1556 	fid = mlxsw_sp_fid_lookup(mlxsw_sp, type, arg);
1557 	if (fid)
1558 		return fid;
1559 
1560 	fid_family = mlxsw_sp->fid_core->fid_family_arr[type];
1561 	fid = kzalloc(fid_family->fid_size, GFP_KERNEL);
1562 	if (!fid)
1563 		return ERR_PTR(-ENOMEM);
1564 
1565 	INIT_LIST_HEAD(&fid->port_vid_list);
1566 	fid->fid_family = fid_family;
1567 
1568 	err = fid->fid_family->ops->index_alloc(fid, arg, &fid_index);
1569 	if (err)
1570 		goto err_index_alloc;
1571 	fid->fid_index = fid_index;
1572 	__set_bit(fid_index - fid_family->start_index, fid_family->fids_bitmap);
1573 
1574 	fid->fid_family->ops->setup(fid, arg);
1575 
1576 	err = fid->fid_family->ops->configure(fid);
1577 	if (err)
1578 		goto err_configure;
1579 
1580 	err = rhashtable_insert_fast(&mlxsw_sp->fid_core->fid_ht, &fid->ht_node,
1581 				     mlxsw_sp_fid_ht_params);
1582 	if (err)
1583 		goto err_rhashtable_insert;
1584 
1585 	list_add(&fid->list, &fid_family->fids_list);
1586 	refcount_set(&fid->ref_count, 1);
1587 	return fid;
1588 
1589 err_rhashtable_insert:
1590 	fid->fid_family->ops->deconfigure(fid);
1591 err_configure:
1592 	__clear_bit(fid_index - fid_family->start_index,
1593 		    fid_family->fids_bitmap);
1594 err_index_alloc:
1595 	kfree(fid);
1596 	return ERR_PTR(err);
1597 }
1598 
1599 void mlxsw_sp_fid_put(struct mlxsw_sp_fid *fid)
1600 {
1601 	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
1602 	struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
1603 
1604 	if (!refcount_dec_and_test(&fid->ref_count))
1605 		return;
1606 
1607 	list_del(&fid->list);
1608 	rhashtable_remove_fast(&mlxsw_sp->fid_core->fid_ht,
1609 			       &fid->ht_node, mlxsw_sp_fid_ht_params);
1610 	fid->fid_family->ops->deconfigure(fid);
1611 	__clear_bit(fid->fid_index - fid_family->start_index,
1612 		    fid_family->fids_bitmap);
1613 	WARN_ON_ONCE(!list_empty(&fid->port_vid_list));
1614 	kfree(fid);
1615 }
1616 
1617 struct mlxsw_sp_fid *mlxsw_sp_fid_8021q_get(struct mlxsw_sp *mlxsw_sp, u16 vid)
1618 {
1619 	return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_8021Q, &vid);
1620 }
1621 
1622 struct mlxsw_sp_fid *mlxsw_sp_fid_8021d_get(struct mlxsw_sp *mlxsw_sp,
1623 					    int br_ifindex)
1624 {
1625 	return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_8021D, &br_ifindex);
1626 }
1627 
1628 struct mlxsw_sp_fid *mlxsw_sp_fid_8021q_lookup(struct mlxsw_sp *mlxsw_sp,
1629 					       u16 vid)
1630 {
1631 	return mlxsw_sp_fid_lookup(mlxsw_sp, MLXSW_SP_FID_TYPE_8021Q, &vid);
1632 }
1633 
1634 struct mlxsw_sp_fid *mlxsw_sp_fid_8021d_lookup(struct mlxsw_sp *mlxsw_sp,
1635 					       int br_ifindex)
1636 {
1637 	return mlxsw_sp_fid_lookup(mlxsw_sp, MLXSW_SP_FID_TYPE_8021D,
1638 				   &br_ifindex);
1639 }
1640 
1641 struct mlxsw_sp_fid *mlxsw_sp_fid_rfid_get(struct mlxsw_sp *mlxsw_sp,
1642 					   u16 rif_index)
1643 {
1644 	return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_RFID, &rif_index);
1645 }
1646 
1647 struct mlxsw_sp_fid *mlxsw_sp_fid_dummy_get(struct mlxsw_sp *mlxsw_sp)
1648 {
1649 	return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_DUMMY, NULL);
1650 }
1651 
1652 static int
1653 mlxsw_sp_fid_flood_table_init(struct mlxsw_sp_fid_family *fid_family,
1654 			      const struct mlxsw_sp_flood_table *flood_table)
1655 {
1656 	enum mlxsw_sp_flood_type packet_type = flood_table->packet_type;
1657 	struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
1658 	const int *sfgc_packet_types;
1659 	u16 mid_base;
1660 	int err, i;
1661 
1662 	mid_base = mlxsw_sp_fid_flood_table_mid(fid_family, flood_table, 0);
1663 
1664 	sfgc_packet_types = mlxsw_sp_packet_type_sfgc_types[packet_type];
1665 	for (i = 0; i < MLXSW_REG_SFGC_TYPE_MAX; i++) {
1666 		char sfgc_pl[MLXSW_REG_SFGC_LEN];
1667 
1668 		if (!sfgc_packet_types[i])
1669 			continue;
1670 
1671 		mlxsw_reg_sfgc_pack(sfgc_pl, i, fid_family->bridge_type,
1672 				    flood_table->table_type, 0, mid_base);
1673 
1674 		err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfgc), sfgc_pl);
1675 		if (err)
1676 			return err;
1677 	}
1678 
1679 	return 0;
1680 }
1681 
1682 static int
1683 mlxsw_sp_fid_flood_tables_init(struct mlxsw_sp_fid_family *fid_family)
1684 {
1685 	struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
1686 	u16 pgt_size;
1687 	int err;
1688 	int i;
1689 
1690 	if (!fid_family->nr_flood_tables)
1691 		return 0;
1692 
1693 	pgt_size = mlxsw_sp_fid_family_pgt_size(fid_family);
1694 	err = mlxsw_sp_pgt_mid_alloc_range(mlxsw_sp, &fid_family->pgt_base,
1695 					   pgt_size);
1696 	if (err)
1697 		return err;
1698 
1699 	for (i = 0; i < fid_family->nr_flood_tables; i++) {
1700 		const struct mlxsw_sp_flood_table *flood_table;
1701 
1702 		flood_table = &fid_family->flood_tables[i];
1703 		err = mlxsw_sp_fid_flood_table_init(fid_family, flood_table);
1704 		if (err)
1705 			goto err_flood_table_init;
1706 	}
1707 
1708 	return 0;
1709 
1710 err_flood_table_init:
1711 	mlxsw_sp_pgt_mid_free_range(mlxsw_sp, fid_family->pgt_base, pgt_size);
1712 	return err;
1713 }
1714 
1715 static void
1716 mlxsw_sp_fid_flood_tables_fini(struct mlxsw_sp_fid_family *fid_family)
1717 {
1718 	struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
1719 	u16 pgt_size;
1720 
1721 	if (!fid_family->nr_flood_tables)
1722 		return;
1723 
1724 	pgt_size = mlxsw_sp_fid_family_pgt_size(fid_family);
1725 	mlxsw_sp_pgt_mid_free_range(mlxsw_sp, fid_family->pgt_base, pgt_size);
1726 }
1727 
1728 static int mlxsw_sp_fid_family_register(struct mlxsw_sp *mlxsw_sp,
1729 					const struct mlxsw_sp_fid_family *tmpl)
1730 {
1731 	u16 nr_fids = tmpl->end_index - tmpl->start_index + 1;
1732 	struct mlxsw_sp_fid_family *fid_family;
1733 	int err;
1734 
1735 	fid_family = kmemdup(tmpl, sizeof(*fid_family), GFP_KERNEL);
1736 	if (!fid_family)
1737 		return -ENOMEM;
1738 
1739 	fid_family->mlxsw_sp = mlxsw_sp;
1740 	INIT_LIST_HEAD(&fid_family->fids_list);
1741 	fid_family->fids_bitmap = bitmap_zalloc(nr_fids, GFP_KERNEL);
1742 	if (!fid_family->fids_bitmap) {
1743 		err = -ENOMEM;
1744 		goto err_alloc_fids_bitmap;
1745 	}
1746 
1747 	if (fid_family->flood_tables) {
1748 		err = mlxsw_sp_fid_flood_tables_init(fid_family);
1749 		if (err)
1750 			goto err_fid_flood_tables_init;
1751 	}
1752 
1753 	mlxsw_sp->fid_core->fid_family_arr[tmpl->type] = fid_family;
1754 
1755 	return 0;
1756 
1757 err_fid_flood_tables_init:
1758 	bitmap_free(fid_family->fids_bitmap);
1759 err_alloc_fids_bitmap:
1760 	kfree(fid_family);
1761 	return err;
1762 }
1763 
1764 static void
1765 mlxsw_sp_fid_family_unregister(struct mlxsw_sp *mlxsw_sp,
1766 			       struct mlxsw_sp_fid_family *fid_family)
1767 {
1768 	mlxsw_sp->fid_core->fid_family_arr[fid_family->type] = NULL;
1769 
1770 	if (fid_family->flood_tables)
1771 		mlxsw_sp_fid_flood_tables_fini(fid_family);
1772 
1773 	bitmap_free(fid_family->fids_bitmap);
1774 	WARN_ON_ONCE(!list_empty(&fid_family->fids_list));
1775 	kfree(fid_family);
1776 }
1777 
1778 int mlxsw_sp_port_fids_init(struct mlxsw_sp_port *mlxsw_sp_port)
1779 {
1780 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1781 
1782 	/* Track number of FIDs configured on the port with mapping type
1783 	 * PORT_VID_TO_FID, so that we know when to transition the port
1784 	 * back to non-virtual (VLAN) mode.
1785 	 */
1786 	mlxsw_sp->fid_core->port_fid_mappings[mlxsw_sp_port->local_port] = 0;
1787 
1788 	return mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, false);
1789 }
1790 
1791 void mlxsw_sp_port_fids_fini(struct mlxsw_sp_port *mlxsw_sp_port)
1792 {
1793 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1794 
1795 	mlxsw_sp->fid_core->port_fid_mappings[mlxsw_sp_port->local_port] = 0;
1796 }
1797 
1798 int mlxsw_sp_fids_init(struct mlxsw_sp *mlxsw_sp)
1799 {
1800 	unsigned int max_ports = mlxsw_core_max_ports(mlxsw_sp->core);
1801 	struct mlxsw_sp_fid_core *fid_core;
1802 	int err, i;
1803 
1804 	fid_core = kzalloc(sizeof(*mlxsw_sp->fid_core), GFP_KERNEL);
1805 	if (!fid_core)
1806 		return -ENOMEM;
1807 	mlxsw_sp->fid_core = fid_core;
1808 
1809 	err = rhashtable_init(&fid_core->fid_ht, &mlxsw_sp_fid_ht_params);
1810 	if (err)
1811 		goto err_rhashtable_fid_init;
1812 
1813 	err = rhashtable_init(&fid_core->vni_ht, &mlxsw_sp_fid_vni_ht_params);
1814 	if (err)
1815 		goto err_rhashtable_vni_init;
1816 
1817 	fid_core->port_fid_mappings = kcalloc(max_ports, sizeof(unsigned int),
1818 					      GFP_KERNEL);
1819 	if (!fid_core->port_fid_mappings) {
1820 		err = -ENOMEM;
1821 		goto err_alloc_port_fid_mappings;
1822 	}
1823 
1824 	for (i = 0; i < MLXSW_SP_FID_TYPE_MAX; i++) {
1825 		err = mlxsw_sp_fid_family_register(mlxsw_sp,
1826 						   mlxsw_sp->fid_family_arr[i]);
1827 
1828 		if (err)
1829 			goto err_fid_ops_register;
1830 	}
1831 
1832 	return 0;
1833 
1834 err_fid_ops_register:
1835 	for (i--; i >= 0; i--) {
1836 		struct mlxsw_sp_fid_family *fid_family;
1837 
1838 		fid_family = fid_core->fid_family_arr[i];
1839 		mlxsw_sp_fid_family_unregister(mlxsw_sp, fid_family);
1840 	}
1841 	kfree(fid_core->port_fid_mappings);
1842 err_alloc_port_fid_mappings:
1843 	rhashtable_destroy(&fid_core->vni_ht);
1844 err_rhashtable_vni_init:
1845 	rhashtable_destroy(&fid_core->fid_ht);
1846 err_rhashtable_fid_init:
1847 	kfree(fid_core);
1848 	return err;
1849 }
1850 
1851 void mlxsw_sp_fids_fini(struct mlxsw_sp *mlxsw_sp)
1852 {
1853 	struct mlxsw_sp_fid_core *fid_core = mlxsw_sp->fid_core;
1854 	int i;
1855 
1856 	for (i = 0; i < MLXSW_SP_FID_TYPE_MAX; i++)
1857 		mlxsw_sp_fid_family_unregister(mlxsw_sp,
1858 					       fid_core->fid_family_arr[i]);
1859 	kfree(fid_core->port_fid_mappings);
1860 	rhashtable_destroy(&fid_core->vni_ht);
1861 	rhashtable_destroy(&fid_core->fid_ht);
1862 	kfree(fid_core);
1863 }
1864