xref: /linux/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c (revision 6373d6fbc2429abbad1cc0f6f0c26fb227ed97cd)
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 "spectrum_router.h"
15 #include "reg.h"
16 
17 struct mlxsw_sp_fid_family;
18 
19 struct mlxsw_sp_fid_core {
20 	struct rhashtable fid_ht;
21 	struct rhashtable vni_ht;
22 	struct mlxsw_sp_fid_family *fid_family_arr[MLXSW_SP_FID_TYPE_MAX];
23 	unsigned int *port_fid_mappings;
24 };
25 
26 struct mlxsw_sp_fid_port_vid {
27 	struct list_head list;
28 	u16 local_port;
29 	u16 vid;
30 };
31 
32 struct mlxsw_sp_fid {
33 	struct list_head list;
34 	struct mlxsw_sp_rif *rif;
35 	refcount_t ref_count;
36 	u16 fid_index;
37 	u16 fid_offset;
38 	struct mlxsw_sp_fid_family *fid_family;
39 	struct rhash_head ht_node;
40 
41 	struct rhash_head vni_ht_node;
42 	enum mlxsw_sp_nve_type nve_type;
43 	__be32 vni;
44 	u32 nve_flood_index;
45 	int nve_ifindex;
46 	u8 vni_valid:1,
47 	   nve_flood_index_valid:1;
48 	struct list_head port_vid_list; /* Ordered by local port. */
49 };
50 
51 struct mlxsw_sp_fid_8021q {
52 	struct mlxsw_sp_fid common;
53 	u16 vid;
54 };
55 
56 struct mlxsw_sp_fid_8021d {
57 	struct mlxsw_sp_fid common;
58 	int br_ifindex;
59 };
60 
61 static const struct rhashtable_params mlxsw_sp_fid_ht_params = {
62 	.key_len = sizeof_field(struct mlxsw_sp_fid, fid_index),
63 	.key_offset = offsetof(struct mlxsw_sp_fid, fid_index),
64 	.head_offset = offsetof(struct mlxsw_sp_fid, ht_node),
65 };
66 
67 static const struct rhashtable_params mlxsw_sp_fid_vni_ht_params = {
68 	.key_len = sizeof_field(struct mlxsw_sp_fid, vni),
69 	.key_offset = offsetof(struct mlxsw_sp_fid, vni),
70 	.head_offset = offsetof(struct mlxsw_sp_fid, vni_ht_node),
71 };
72 
73 struct mlxsw_sp_flood_table {
74 	enum mlxsw_sp_flood_type packet_type;
75 	enum mlxsw_flood_table_type table_type;	/* For flood_mode!=CFF. */
76 	int table_index;
77 };
78 
79 struct mlxsw_sp_fid_ops {
80 	int (*setup)(struct mlxsw_sp_fid *fid, const void *arg);
81 	int (*configure)(struct mlxsw_sp_fid *fid);
82 	void (*deconfigure)(struct mlxsw_sp_fid *fid);
83 	int (*index_alloc)(struct mlxsw_sp_fid *fid, const void *arg,
84 			   u16 *p_fid_index);
85 	bool (*compare)(const struct mlxsw_sp_fid *fid,
86 			const void *arg);
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 	int (*vid_to_fid_rif_update)(const struct mlxsw_sp_fid *fid,
98 				     const struct mlxsw_sp_rif *rif);
99 	int (*flood_table_init)(struct mlxsw_sp_fid_family *fid_family,
100 				const struct mlxsw_sp_flood_table *flood_table);
101 	int (*pgt_size)(const struct mlxsw_sp_fid_family *fid_family,
102 			u16 *p_pgt_size);
103 	u16 (*fid_mid)(const struct mlxsw_sp_fid *fid,
104 		       const struct mlxsw_sp_flood_table *flood_table);
105 	void (*fid_pack)(char *sfmr_pl, const struct mlxsw_sp_fid *fid,
106 			 enum mlxsw_reg_sfmr_op op);
107 
108 	/* These are specific to RFID families and we assume are only
109 	 * implemented by RFID families, if at all.
110 	 */
111 	int (*fid_port_init)(const struct mlxsw_sp_fid_family *fid_family,
112 			     const struct mlxsw_sp_port *mlxsw_sp_port);
113 	void (*fid_port_fini)(const struct mlxsw_sp_fid_family *fid_family,
114 			      const struct mlxsw_sp_port *mlxsw_sp_port);
115 };
116 
117 enum mlxsw_sp_fid_flood_profile_id {
118 	MLXSW_SP_FID_FLOOD_PROFILE_ID_BRIDGE = 1,
119 	MLXSW_SP_FID_FLOOD_PROFILE_ID_RSP,
120 	MLXSW_SP_FID_FLOOD_PROFILE_ID_NVE,
121 };
122 
123 struct mlxsw_sp_fid_flood_profile {
124 	const struct mlxsw_sp_flood_table *flood_tables;
125 	int nr_flood_tables;
126 	const enum mlxsw_sp_fid_flood_profile_id profile_id; /* For CFF mode. */
127 };
128 
129 struct mlxsw_sp_fid_family {
130 	enum mlxsw_sp_fid_type type;
131 	size_t fid_size;
132 	u16 start_index;
133 	u16 end_index;
134 	struct list_head fids_list;
135 	unsigned long *fids_bitmap;
136 	const struct mlxsw_sp_fid_flood_profile *flood_profile;
137 	enum mlxsw_sp_rif_type rif_type;
138 	const struct mlxsw_sp_fid_ops *ops;
139 	struct mlxsw_sp *mlxsw_sp;
140 	bool flood_rsp;	/* For flood_mode!=CFF. */
141 	enum mlxsw_reg_bridge_type bridge_type;
142 	u16 pgt_base;
143 	bool smpe_index_valid;
144 };
145 
146 static const int mlxsw_sp_sfgc_uc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = {
147 	[MLXSW_REG_SFGC_TYPE_UNKNOWN_UNICAST]			= 1,
148 };
149 
150 static const int mlxsw_sp_sfgc_bc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = {
151 	[MLXSW_REG_SFGC_TYPE_BROADCAST]				= 1,
152 	[MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_NON_IP]	= 1,
153 	[MLXSW_REG_SFGC_TYPE_IPV4_LINK_LOCAL]			= 1,
154 	[MLXSW_REG_SFGC_TYPE_IPV6_ALL_HOST]			= 1,
155 	[MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV6]	= 1,
156 };
157 
158 static const int mlxsw_sp_sfgc_mc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = {
159 	[MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV4]	= 1,
160 };
161 
162 static const int mlxsw_sp_sfgc_not_uc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = {
163 	[MLXSW_REG_SFGC_TYPE_BROADCAST]				= 1,
164 	[MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_NON_IP]	= 1,
165 	[MLXSW_REG_SFGC_TYPE_IPV4_LINK_LOCAL]			= 1,
166 	[MLXSW_REG_SFGC_TYPE_IPV6_ALL_HOST]			= 1,
167 	[MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV6]	= 1,
168 	[MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV4]	= 1,
169 };
170 
171 static const int mlxsw_sp_sfgc_any_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = {
172 	[MLXSW_REG_SFGC_TYPE_UNKNOWN_UNICAST]			= 1,
173 	[MLXSW_REG_SFGC_TYPE_BROADCAST]				= 1,
174 	[MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_NON_IP]	= 1,
175 	[MLXSW_REG_SFGC_TYPE_IPV4_LINK_LOCAL]			= 1,
176 	[MLXSW_REG_SFGC_TYPE_IPV6_ALL_HOST]			= 1,
177 	[MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV6]	= 1,
178 	[MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV4]	= 1,
179 };
180 
181 static const int *mlxsw_sp_packet_type_sfgc_types[] = {
182 	[MLXSW_SP_FLOOD_TYPE_UC]	= mlxsw_sp_sfgc_uc_packet_types,
183 	[MLXSW_SP_FLOOD_TYPE_BC]	= mlxsw_sp_sfgc_bc_packet_types,
184 	[MLXSW_SP_FLOOD_TYPE_MC]	= mlxsw_sp_sfgc_mc_packet_types,
185 	[MLXSW_SP_FLOOD_TYPE_NOT_UC]	= mlxsw_sp_sfgc_not_uc_packet_types,
186 	[MLXSW_SP_FLOOD_TYPE_ANY]	= mlxsw_sp_sfgc_any_packet_types,
187 };
188 
189 struct mlxsw_sp_fid *mlxsw_sp_fid_lookup_by_index(struct mlxsw_sp *mlxsw_sp,
190 						  u16 fid_index)
191 {
192 	struct mlxsw_sp_fid *fid;
193 
194 	fid = rhashtable_lookup_fast(&mlxsw_sp->fid_core->fid_ht, &fid_index,
195 				     mlxsw_sp_fid_ht_params);
196 	if (fid)
197 		refcount_inc(&fid->ref_count);
198 
199 	return fid;
200 }
201 
202 int mlxsw_sp_fid_nve_ifindex(const struct mlxsw_sp_fid *fid, int *nve_ifindex)
203 {
204 	if (!fid->vni_valid)
205 		return -EINVAL;
206 
207 	*nve_ifindex = fid->nve_ifindex;
208 
209 	return 0;
210 }
211 
212 int mlxsw_sp_fid_nve_type(const struct mlxsw_sp_fid *fid,
213 			  enum mlxsw_sp_nve_type *p_type)
214 {
215 	if (!fid->vni_valid)
216 		return -EINVAL;
217 
218 	*p_type = fid->nve_type;
219 
220 	return 0;
221 }
222 
223 struct mlxsw_sp_fid *mlxsw_sp_fid_lookup_by_vni(struct mlxsw_sp *mlxsw_sp,
224 						__be32 vni)
225 {
226 	struct mlxsw_sp_fid *fid;
227 
228 	fid = rhashtable_lookup_fast(&mlxsw_sp->fid_core->vni_ht, &vni,
229 				     mlxsw_sp_fid_vni_ht_params);
230 	if (fid)
231 		refcount_inc(&fid->ref_count);
232 
233 	return fid;
234 }
235 
236 int mlxsw_sp_fid_vni(const struct mlxsw_sp_fid *fid, __be32 *vni)
237 {
238 	if (!fid->vni_valid)
239 		return -EINVAL;
240 
241 	*vni = fid->vni;
242 
243 	return 0;
244 }
245 
246 int mlxsw_sp_fid_nve_flood_index_set(struct mlxsw_sp_fid *fid,
247 				     u32 nve_flood_index)
248 {
249 	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
250 	const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
251 	int err;
252 
253 	if (WARN_ON(fid->nve_flood_index_valid))
254 		return -EINVAL;
255 
256 	fid->nve_flood_index = nve_flood_index;
257 	fid->nve_flood_index_valid = true;
258 	err = ops->nve_flood_index_set(fid);
259 	if (err)
260 		goto err_nve_flood_index_set;
261 
262 	return 0;
263 
264 err_nve_flood_index_set:
265 	fid->nve_flood_index_valid = false;
266 	return err;
267 }
268 
269 void mlxsw_sp_fid_nve_flood_index_clear(struct mlxsw_sp_fid *fid)
270 {
271 	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
272 	const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
273 
274 	if (WARN_ON(!fid->nve_flood_index_valid))
275 		return;
276 
277 	fid->nve_flood_index_valid = false;
278 	ops->nve_flood_index_clear(fid);
279 }
280 
281 bool mlxsw_sp_fid_nve_flood_index_is_set(const struct mlxsw_sp_fid *fid)
282 {
283 	return fid->nve_flood_index_valid;
284 }
285 
286 int mlxsw_sp_fid_vni_set(struct mlxsw_sp_fid *fid, enum mlxsw_sp_nve_type type,
287 			 __be32 vni, int nve_ifindex)
288 {
289 	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
290 	const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
291 	struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
292 	int err;
293 
294 	if (WARN_ON(fid->vni_valid))
295 		return -EINVAL;
296 
297 	fid->nve_type = type;
298 	fid->nve_ifindex = nve_ifindex;
299 	fid->vni = vni;
300 	err = rhashtable_lookup_insert_fast(&mlxsw_sp->fid_core->vni_ht,
301 					    &fid->vni_ht_node,
302 					    mlxsw_sp_fid_vni_ht_params);
303 	if (err)
304 		return err;
305 
306 	fid->vni_valid = true;
307 	err = ops->vni_set(fid);
308 	if (err)
309 		goto err_vni_set;
310 
311 	return 0;
312 
313 err_vni_set:
314 	fid->vni_valid = false;
315 	rhashtable_remove_fast(&mlxsw_sp->fid_core->vni_ht, &fid->vni_ht_node,
316 			       mlxsw_sp_fid_vni_ht_params);
317 	return err;
318 }
319 
320 void mlxsw_sp_fid_vni_clear(struct mlxsw_sp_fid *fid)
321 {
322 	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
323 	const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
324 	struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
325 
326 	if (WARN_ON(!fid->vni_valid))
327 		return;
328 
329 	fid->vni_valid = false;
330 	ops->vni_clear(fid);
331 	rhashtable_remove_fast(&mlxsw_sp->fid_core->vni_ht, &fid->vni_ht_node,
332 			       mlxsw_sp_fid_vni_ht_params);
333 }
334 
335 bool mlxsw_sp_fid_vni_is_set(const struct mlxsw_sp_fid *fid)
336 {
337 	return fid->vni_valid;
338 }
339 
340 void mlxsw_sp_fid_fdb_clear_offload(const struct mlxsw_sp_fid *fid,
341 				    const struct net_device *nve_dev)
342 {
343 	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
344 	const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
345 
346 	if (ops->fdb_clear_offload)
347 		ops->fdb_clear_offload(fid, nve_dev);
348 }
349 
350 static const struct mlxsw_sp_flood_table *
351 mlxsw_sp_fid_flood_table_lookup(const struct mlxsw_sp_fid *fid,
352 				enum mlxsw_sp_flood_type packet_type)
353 {
354 	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
355 	int i;
356 
357 	for (i = 0; i < fid_family->flood_profile->nr_flood_tables; i++) {
358 		const struct mlxsw_sp_flood_table *flood_table;
359 
360 		flood_table = &fid_family->flood_profile->flood_tables[i];
361 		if (flood_table->packet_type != packet_type)
362 			continue;
363 		return flood_table;
364 	}
365 
366 	return NULL;
367 }
368 
369 static u16
370 mlxsw_sp_fid_family_num_fids(const struct mlxsw_sp_fid_family *fid_family)
371 {
372 	return fid_family->end_index - fid_family->start_index + 1;
373 }
374 
375 static int
376 mlxsw_sp_fid_8021d_pgt_size(const struct mlxsw_sp_fid_family *fid_family,
377 			    u16 *p_pgt_size)
378 {
379 	u16 num_fids = mlxsw_sp_fid_family_num_fids(fid_family);
380 
381 	*p_pgt_size = num_fids * fid_family->flood_profile->nr_flood_tables;
382 	return 0;
383 }
384 
385 static unsigned int mlxsw_sp_fid_rfid_port_offset_cff(unsigned int local_port)
386 {
387 	/* Port 0 is the CPU port. Since we never create RIFs based off that
388 	 * port, we don't need to count it.
389 	 */
390 	return WARN_ON_ONCE(!local_port) ? 0 : local_port - 1;
391 }
392 
393 static int
394 mlxsw_sp_fid_rfid_pgt_size_cff(const struct mlxsw_sp_fid_family *fid_family,
395 			       u16 *p_pgt_size)
396 {
397 	struct mlxsw_core *core = fid_family->mlxsw_sp->core;
398 	unsigned int max_ports;
399 	u16 pgt_size;
400 	u16 max_lags;
401 	int err;
402 
403 	max_ports = mlxsw_core_max_ports(core);
404 
405 	err = mlxsw_core_max_lag(core, &max_lags);
406 	if (err)
407 		return err;
408 
409 	pgt_size = (mlxsw_sp_fid_rfid_port_offset_cff(max_ports) + max_lags) *
410 		   fid_family->flood_profile->nr_flood_tables;
411 	*p_pgt_size = pgt_size;
412 	return 0;
413 }
414 
415 static u16
416 mlxsw_sp_fid_pgt_base_ctl(const struct mlxsw_sp_fid_family *fid_family,
417 			  const struct mlxsw_sp_flood_table *flood_table)
418 {
419 	u16 num_fids;
420 
421 	num_fids = mlxsw_sp_fid_family_num_fids(fid_family);
422 	return fid_family->pgt_base + num_fids * flood_table->table_index;
423 }
424 
425 static u16
426 mlxsw_sp_fid_fid_mid_ctl(const struct mlxsw_sp_fid *fid,
427 			 const struct mlxsw_sp_flood_table *flood_table)
428 {
429 	return mlxsw_sp_fid_pgt_base_ctl(fid->fid_family, flood_table) +
430 	       fid->fid_offset;
431 }
432 
433 int mlxsw_sp_fid_flood_set(struct mlxsw_sp_fid *fid,
434 			   enum mlxsw_sp_flood_type packet_type, u16 local_port,
435 			   bool member)
436 {
437 	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
438 	const struct mlxsw_sp_flood_table *flood_table;
439 	u16 mid_index;
440 
441 	if (WARN_ON(!fid_family->flood_profile))
442 		return -EINVAL;
443 
444 	flood_table = mlxsw_sp_fid_flood_table_lookup(fid, packet_type);
445 	if (!flood_table)
446 		return -ESRCH;
447 
448 	mid_index = fid_family->ops->fid_mid(fid, flood_table);
449 	return mlxsw_sp_pgt_entry_port_set(fid_family->mlxsw_sp, mid_index,
450 					   fid->fid_index, local_port, member);
451 }
452 
453 int mlxsw_sp_fid_port_vid_map(struct mlxsw_sp_fid *fid,
454 			      struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
455 {
456 	if (WARN_ON(!fid->fid_family->ops->port_vid_map))
457 		return -EINVAL;
458 	return fid->fid_family->ops->port_vid_map(fid, mlxsw_sp_port, vid);
459 }
460 
461 void mlxsw_sp_fid_port_vid_unmap(struct mlxsw_sp_fid *fid,
462 				 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
463 {
464 	fid->fid_family->ops->port_vid_unmap(fid, mlxsw_sp_port, vid);
465 }
466 
467 u16 mlxsw_sp_fid_index(const struct mlxsw_sp_fid *fid)
468 {
469 	return fid->fid_index;
470 }
471 
472 enum mlxsw_sp_fid_type mlxsw_sp_fid_type(const struct mlxsw_sp_fid *fid)
473 {
474 	return fid->fid_family->type;
475 }
476 
477 struct mlxsw_sp_rif *mlxsw_sp_fid_rif(const struct mlxsw_sp_fid *fid)
478 {
479 	return fid->rif;
480 }
481 
482 enum mlxsw_sp_rif_type
483 mlxsw_sp_fid_type_rif_type(const struct mlxsw_sp *mlxsw_sp,
484 			   enum mlxsw_sp_fid_type type)
485 {
486 	struct mlxsw_sp_fid_core *fid_core = mlxsw_sp->fid_core;
487 
488 	return fid_core->fid_family_arr[type]->rif_type;
489 }
490 
491 static struct mlxsw_sp_fid_8021q *
492 mlxsw_sp_fid_8021q_fid(const struct mlxsw_sp_fid *fid)
493 {
494 	return container_of(fid, struct mlxsw_sp_fid_8021q, common);
495 }
496 
497 u16 mlxsw_sp_fid_8021q_vid(const struct mlxsw_sp_fid *fid)
498 {
499 	return mlxsw_sp_fid_8021q_fid(fid)->vid;
500 }
501 
502 static int mlxsw_sp_fid_8021q_setup(struct mlxsw_sp_fid *fid, const void *arg)
503 {
504 	u16 vid = *(u16 *) arg;
505 
506 	mlxsw_sp_fid_8021q_fid(fid)->vid = vid;
507 	fid->fid_offset = fid->fid_index - fid->fid_family->start_index;
508 	return 0;
509 }
510 
511 static enum mlxsw_reg_sfmr_op mlxsw_sp_sfmr_op(bool valid)
512 {
513 	return valid ? MLXSW_REG_SFMR_OP_CREATE_FID :
514 		       MLXSW_REG_SFMR_OP_DESTROY_FID;
515 }
516 
517 static void mlxsw_sp_fid_pack(char *sfmr_pl,
518 			      const struct mlxsw_sp_fid *fid,
519 			      enum mlxsw_reg_sfmr_op op)
520 {
521 	u16 smpe;
522 
523 	smpe = fid->fid_family->smpe_index_valid ? fid->fid_index : 0;
524 
525 	mlxsw_reg_sfmr_pack(sfmr_pl, op, fid->fid_index,
526 			    fid->fid_family->smpe_index_valid, smpe);
527 }
528 
529 static void mlxsw_sp_fid_pack_ctl(char *sfmr_pl,
530 				  const struct mlxsw_sp_fid *fid,
531 				  enum mlxsw_reg_sfmr_op op)
532 {
533 	mlxsw_sp_fid_pack(sfmr_pl, fid, op);
534 	mlxsw_reg_sfmr_fid_offset_set(sfmr_pl, fid->fid_offset);
535 	mlxsw_reg_sfmr_flood_rsp_set(sfmr_pl, fid->fid_family->flood_rsp);
536 	mlxsw_reg_sfmr_flood_bridge_type_set(sfmr_pl,
537 					     fid->fid_family->bridge_type);
538 }
539 
540 static u16
541 mlxsw_sp_fid_off_pgt_base_cff(const struct mlxsw_sp_fid_family *fid_family,
542 			      u16 fid_offset)
543 {
544 	return fid_family->pgt_base +
545 		fid_offset * fid_family->flood_profile->nr_flood_tables;
546 }
547 
548 static u16 mlxsw_sp_fid_pgt_base_cff(const struct mlxsw_sp_fid *fid)
549 {
550 	return mlxsw_sp_fid_off_pgt_base_cff(fid->fid_family, fid->fid_offset);
551 }
552 
553 static void mlxsw_sp_fid_fid_pack_cff(char *sfmr_pl,
554 				      const struct mlxsw_sp_fid *fid,
555 				      enum mlxsw_reg_sfmr_op op)
556 {
557 	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
558 	u16 pgt_base = mlxsw_sp_fid_pgt_base_cff(fid);
559 
560 	mlxsw_sp_fid_pack(sfmr_pl, fid, op);
561 	mlxsw_reg_sfmr_cff_mid_base_set(sfmr_pl, pgt_base);
562 	mlxsw_reg_sfmr_cff_prf_id_set(sfmr_pl,
563 				      fid_family->flood_profile->profile_id);
564 	mlxsw_reg_sfmr_nve_flood_prf_id_set(sfmr_pl,
565 					    MLXSW_SP_FID_FLOOD_PROFILE_ID_NVE);
566 }
567 
568 static u16 mlxsw_sp_fid_rfid_fid_offset_cff(struct mlxsw_sp *mlxsw_sp,
569 					    u16 port_lag_id, bool is_lag)
570 {
571 	u16 max_ports = mlxsw_core_max_ports(mlxsw_sp->core);
572 
573 	if (is_lag)
574 		return mlxsw_sp_fid_rfid_port_offset_cff(max_ports) +
575 		       port_lag_id;
576 	else
577 		return mlxsw_sp_fid_rfid_port_offset_cff(port_lag_id);
578 }
579 
580 static int mlxsw_sp_fid_op(const struct mlxsw_sp_fid *fid, bool valid)
581 {
582 	struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
583 	char sfmr_pl[MLXSW_REG_SFMR_LEN];
584 
585 	fid->fid_family->ops->fid_pack(sfmr_pl, fid,
586 				       mlxsw_sp_sfmr_op(valid));
587 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl);
588 }
589 
590 static int mlxsw_sp_fid_edit_op(const struct mlxsw_sp_fid *fid,
591 				const struct mlxsw_sp_rif *rif)
592 {
593 	struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
594 	char sfmr_pl[MLXSW_REG_SFMR_LEN];
595 
596 	fid->fid_family->ops->fid_pack(sfmr_pl, fid,
597 				       MLXSW_REG_SFMR_OP_CREATE_FID);
598 
599 	mlxsw_reg_sfmr_vv_set(sfmr_pl, fid->vni_valid);
600 	mlxsw_reg_sfmr_vni_set(sfmr_pl, be32_to_cpu(fid->vni));
601 	mlxsw_reg_sfmr_vtfp_set(sfmr_pl, fid->nve_flood_index_valid);
602 	mlxsw_reg_sfmr_nve_tunnel_flood_ptr_set(sfmr_pl, fid->nve_flood_index);
603 
604 	if (rif) {
605 		mlxsw_reg_sfmr_irif_v_set(sfmr_pl, true);
606 		mlxsw_reg_sfmr_irif_set(sfmr_pl, mlxsw_sp_rif_index(rif));
607 	}
608 
609 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl);
610 }
611 
612 static int mlxsw_sp_fid_vni_to_fid_map(const struct mlxsw_sp_fid *fid,
613 				       const struct mlxsw_sp_rif *rif,
614 				       bool valid)
615 {
616 	struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
617 	char svfa_pl[MLXSW_REG_SVFA_LEN];
618 	bool irif_valid;
619 	u16 irif_index;
620 
621 	irif_valid = !!rif;
622 	irif_index = rif ? mlxsw_sp_rif_index(rif) : 0;
623 
624 	mlxsw_reg_svfa_vni_pack(svfa_pl, valid, fid->fid_index,
625 				be32_to_cpu(fid->vni), irif_valid, irif_index);
626 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl);
627 }
628 
629 static int mlxsw_sp_fid_to_fid_rif_update(const struct mlxsw_sp_fid *fid,
630 					  const struct mlxsw_sp_rif *rif)
631 {
632 	return mlxsw_sp_fid_edit_op(fid, rif);
633 }
634 
635 static int mlxsw_sp_fid_vni_to_fid_rif_update(const struct mlxsw_sp_fid *fid,
636 					      const struct mlxsw_sp_rif *rif)
637 {
638 	if (!fid->vni_valid)
639 		return 0;
640 
641 	return mlxsw_sp_fid_vni_to_fid_map(fid, rif, fid->vni_valid);
642 }
643 
644 static int
645 mlxsw_sp_fid_vid_to_fid_map(const struct mlxsw_sp_fid *fid, u16 vid, bool valid,
646 			    const struct mlxsw_sp_rif *rif)
647 {
648 	struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
649 	char svfa_pl[MLXSW_REG_SVFA_LEN];
650 	bool irif_valid;
651 	u16 irif_index;
652 
653 	irif_valid = !!rif;
654 	irif_index = rif ? mlxsw_sp_rif_index(rif) : 0;
655 
656 	mlxsw_reg_svfa_vid_pack(svfa_pl, valid, fid->fid_index, vid, irif_valid,
657 				irif_index);
658 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl);
659 }
660 
661 static int
662 mlxsw_sp_fid_8021q_vid_to_fid_rif_update(const struct mlxsw_sp_fid *fid,
663 					 const struct mlxsw_sp_rif *rif)
664 {
665 	struct mlxsw_sp_fid_8021q *fid_8021q = mlxsw_sp_fid_8021q_fid(fid);
666 
667 	/* Update the global VID => FID mapping we created when the FID was
668 	 * configured.
669 	 */
670 	return mlxsw_sp_fid_vid_to_fid_map(fid, fid_8021q->vid, true, rif);
671 }
672 
673 static int
674 mlxsw_sp_fid_port_vid_to_fid_rif_update_one(const struct mlxsw_sp_fid *fid,
675 					    struct mlxsw_sp_fid_port_vid *pv,
676 					    bool irif_valid, u16 irif_index)
677 {
678 	struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
679 	char svfa_pl[MLXSW_REG_SVFA_LEN];
680 
681 	mlxsw_reg_svfa_port_vid_pack(svfa_pl, pv->local_port, true,
682 				     fid->fid_index, pv->vid, irif_valid,
683 				     irif_index);
684 
685 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl);
686 }
687 
688 static int mlxsw_sp_fid_vid_to_fid_rif_set(const struct mlxsw_sp_fid *fid,
689 					   const struct mlxsw_sp_rif *rif)
690 {
691 	struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
692 	struct mlxsw_sp_fid_port_vid *pv;
693 	u16 irif_index;
694 	int err;
695 
696 	err = fid->fid_family->ops->vid_to_fid_rif_update(fid, rif);
697 	if (err)
698 		return err;
699 
700 	irif_index = mlxsw_sp_rif_index(rif);
701 
702 	list_for_each_entry(pv, &fid->port_vid_list, list) {
703 		/* If port is not in virtual mode, then it does not have any
704 		 * {Port, VID}->FID mappings that need to be updated with the
705 		 * ingress RIF.
706 		 */
707 		if (!mlxsw_sp->fid_core->port_fid_mappings[pv->local_port])
708 			continue;
709 
710 		err = mlxsw_sp_fid_port_vid_to_fid_rif_update_one(fid, pv,
711 								  true,
712 								  irif_index);
713 		if (err)
714 			goto err_port_vid_to_fid_rif_update_one;
715 	}
716 
717 	return 0;
718 
719 err_port_vid_to_fid_rif_update_one:
720 	list_for_each_entry_continue_reverse(pv, &fid->port_vid_list, list) {
721 		if (!mlxsw_sp->fid_core->port_fid_mappings[pv->local_port])
722 			continue;
723 
724 		mlxsw_sp_fid_port_vid_to_fid_rif_update_one(fid, pv, false, 0);
725 	}
726 
727 	fid->fid_family->ops->vid_to_fid_rif_update(fid, NULL);
728 	return err;
729 }
730 
731 static void mlxsw_sp_fid_vid_to_fid_rif_unset(const struct mlxsw_sp_fid *fid)
732 {
733 	struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
734 	struct mlxsw_sp_fid_port_vid *pv;
735 
736 	list_for_each_entry(pv, &fid->port_vid_list, list) {
737 		/* If port is not in virtual mode, then it does not have any
738 		 * {Port, VID}->FID mappings that need to be updated.
739 		 */
740 		if (!mlxsw_sp->fid_core->port_fid_mappings[pv->local_port])
741 			continue;
742 
743 		mlxsw_sp_fid_port_vid_to_fid_rif_update_one(fid, pv, false, 0);
744 	}
745 
746 	fid->fid_family->ops->vid_to_fid_rif_update(fid, NULL);
747 }
748 
749 static int mlxsw_sp_fid_reiv_handle(struct mlxsw_sp_fid *fid, u16 rif_index,
750 				    bool valid, u8 port_page)
751 {
752 	u16 local_port_end = (port_page + 1) * MLXSW_REG_REIV_REC_MAX_COUNT - 1;
753 	u16 local_port_start = port_page * MLXSW_REG_REIV_REC_MAX_COUNT;
754 	struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
755 	struct mlxsw_sp_fid_port_vid *port_vid;
756 	u8 rec_num, entries_num = 0;
757 	char *reiv_pl;
758 	int err;
759 
760 	reiv_pl = kmalloc(MLXSW_REG_REIV_LEN, GFP_KERNEL);
761 	if (!reiv_pl)
762 		return -ENOMEM;
763 
764 	mlxsw_reg_reiv_pack(reiv_pl, port_page, rif_index);
765 
766 	list_for_each_entry(port_vid, &fid->port_vid_list, list) {
767 		/* port_vid_list is sorted by local_port. */
768 		if (port_vid->local_port < local_port_start)
769 			continue;
770 
771 		if (port_vid->local_port > local_port_end)
772 			break;
773 
774 		rec_num = port_vid->local_port % MLXSW_REG_REIV_REC_MAX_COUNT;
775 		mlxsw_reg_reiv_rec_update_set(reiv_pl, rec_num, true);
776 		mlxsw_reg_reiv_rec_evid_set(reiv_pl, rec_num,
777 					    valid ? port_vid->vid : 0);
778 		entries_num++;
779 	}
780 
781 	if (!entries_num) {
782 		kfree(reiv_pl);
783 		return 0;
784 	}
785 
786 	err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(reiv), reiv_pl);
787 	if (err)
788 		goto err_reg_write;
789 
790 	kfree(reiv_pl);
791 	return 0;
792 
793 err_reg_write:
794 	kfree(reiv_pl);
795 	return err;
796 }
797 
798 static int mlxsw_sp_fid_erif_eport_to_vid_map(struct mlxsw_sp_fid *fid,
799 					      u16 rif_index, bool valid)
800 {
801 	struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
802 	u8 num_port_pages;
803 	int err, i;
804 
805 	num_port_pages = mlxsw_core_max_ports(mlxsw_sp->core) /
806 			 MLXSW_REG_REIV_REC_MAX_COUNT + 1;
807 
808 	for (i = 0; i < num_port_pages; i++) {
809 		err = mlxsw_sp_fid_reiv_handle(fid, rif_index, valid, i);
810 		if (err)
811 			goto err_reiv_handle;
812 	}
813 
814 	return 0;
815 
816 err_reiv_handle:
817 	for (; i >= 0; i--)
818 		mlxsw_sp_fid_reiv_handle(fid, rif_index, !valid, i);
819 	return err;
820 }
821 
822 int mlxsw_sp_fid_rif_set(struct mlxsw_sp_fid *fid, struct mlxsw_sp_rif *rif)
823 {
824 	u16 rif_index = mlxsw_sp_rif_index(rif);
825 	int err;
826 
827 	err = mlxsw_sp_fid_to_fid_rif_update(fid, rif);
828 	if (err)
829 		return err;
830 
831 	err = mlxsw_sp_fid_vni_to_fid_rif_update(fid, rif);
832 	if (err)
833 		goto err_vni_to_fid_rif_update;
834 
835 	err = mlxsw_sp_fid_vid_to_fid_rif_set(fid, rif);
836 	if (err)
837 		goto err_vid_to_fid_rif_set;
838 
839 	err = mlxsw_sp_fid_erif_eport_to_vid_map(fid, rif_index, true);
840 	if (err)
841 		goto err_erif_eport_to_vid_map;
842 
843 	fid->rif = rif;
844 	return 0;
845 
846 err_erif_eport_to_vid_map:
847 	mlxsw_sp_fid_vid_to_fid_rif_unset(fid);
848 err_vid_to_fid_rif_set:
849 	mlxsw_sp_fid_vni_to_fid_rif_update(fid, NULL);
850 err_vni_to_fid_rif_update:
851 	mlxsw_sp_fid_to_fid_rif_update(fid, NULL);
852 	return err;
853 }
854 
855 void mlxsw_sp_fid_rif_unset(struct mlxsw_sp_fid *fid)
856 {
857 	u16 rif_index;
858 
859 	if (!fid->rif)
860 		return;
861 
862 	rif_index = mlxsw_sp_rif_index(fid->rif);
863 	fid->rif = NULL;
864 
865 	mlxsw_sp_fid_erif_eport_to_vid_map(fid, rif_index, false);
866 	mlxsw_sp_fid_vid_to_fid_rif_unset(fid);
867 	mlxsw_sp_fid_vni_to_fid_rif_update(fid, NULL);
868 	mlxsw_sp_fid_to_fid_rif_update(fid, NULL);
869 }
870 
871 static int mlxsw_sp_fid_vni_op(const struct mlxsw_sp_fid *fid)
872 {
873 	int err;
874 
875 	err = mlxsw_sp_fid_vni_to_fid_map(fid, fid->rif, fid->vni_valid);
876 	if (err)
877 		return err;
878 
879 	err = mlxsw_sp_fid_edit_op(fid, fid->rif);
880 	if (err)
881 		goto err_fid_edit_op;
882 
883 	return 0;
884 
885 err_fid_edit_op:
886 	mlxsw_sp_fid_vni_to_fid_map(fid, fid->rif, !fid->vni_valid);
887 	return err;
888 }
889 
890 static int __mlxsw_sp_fid_port_vid_map(const struct mlxsw_sp_fid *fid,
891 				       u16 local_port, u16 vid, bool valid)
892 {
893 	struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
894 	char svfa_pl[MLXSW_REG_SVFA_LEN];
895 	bool irif_valid = false;
896 	u16 irif_index = 0;
897 
898 	if (fid->rif) {
899 		irif_valid = true;
900 		irif_index = mlxsw_sp_rif_index(fid->rif);
901 	}
902 
903 	mlxsw_reg_svfa_port_vid_pack(svfa_pl, local_port, valid, fid->fid_index,
904 				     vid, irif_valid, irif_index);
905 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl);
906 }
907 
908 static struct mlxsw_sp_fid_8021d *
909 mlxsw_sp_fid_8021d_fid(const struct mlxsw_sp_fid *fid)
910 {
911 	return container_of(fid, struct mlxsw_sp_fid_8021d, common);
912 }
913 
914 static int mlxsw_sp_fid_8021d_setup(struct mlxsw_sp_fid *fid, const void *arg)
915 {
916 	int br_ifindex = *(int *) arg;
917 
918 	mlxsw_sp_fid_8021d_fid(fid)->br_ifindex = br_ifindex;
919 	fid->fid_offset = fid->fid_index - fid->fid_family->start_index;
920 	return 0;
921 }
922 
923 static int mlxsw_sp_fid_8021d_configure(struct mlxsw_sp_fid *fid)
924 {
925 	return mlxsw_sp_fid_op(fid, true);
926 }
927 
928 static void mlxsw_sp_fid_8021d_deconfigure(struct mlxsw_sp_fid *fid)
929 {
930 	if (fid->vni_valid)
931 		mlxsw_sp_nve_fid_disable(fid->fid_family->mlxsw_sp, fid);
932 	mlxsw_sp_fid_op(fid, false);
933 }
934 
935 static int mlxsw_sp_fid_8021d_index_alloc(struct mlxsw_sp_fid *fid,
936 					  const void *arg, u16 *p_fid_index)
937 {
938 	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
939 	u16 nr_fids, fid_index;
940 
941 	nr_fids = fid_family->end_index - fid_family->start_index + 1;
942 	fid_index = find_first_zero_bit(fid_family->fids_bitmap, nr_fids);
943 	if (fid_index == nr_fids)
944 		return -ENOBUFS;
945 	*p_fid_index = fid_family->start_index + fid_index;
946 
947 	return 0;
948 }
949 
950 static bool
951 mlxsw_sp_fid_8021d_compare(const struct mlxsw_sp_fid *fid, const void *arg)
952 {
953 	int br_ifindex = *(int *) arg;
954 
955 	return mlxsw_sp_fid_8021d_fid(fid)->br_ifindex == br_ifindex;
956 }
957 
958 static int mlxsw_sp_port_vp_mode_trans(struct mlxsw_sp_port *mlxsw_sp_port)
959 {
960 	struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
961 	int err;
962 
963 	list_for_each_entry(mlxsw_sp_port_vlan, &mlxsw_sp_port->vlans_list,
964 			    list) {
965 		struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid;
966 		u16 vid = mlxsw_sp_port_vlan->vid;
967 
968 		if (!fid)
969 			continue;
970 
971 		err = __mlxsw_sp_fid_port_vid_map(fid,
972 						  mlxsw_sp_port->local_port,
973 						  vid, true);
974 		if (err)
975 			goto err_fid_port_vid_map;
976 	}
977 
978 	err = mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, true);
979 	if (err)
980 		goto err_port_vp_mode_set;
981 
982 	return 0;
983 
984 err_port_vp_mode_set:
985 err_fid_port_vid_map:
986 	list_for_each_entry_continue_reverse(mlxsw_sp_port_vlan,
987 					     &mlxsw_sp_port->vlans_list, list) {
988 		struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid;
989 		u16 vid = mlxsw_sp_port_vlan->vid;
990 
991 		if (!fid)
992 			continue;
993 
994 		__mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid,
995 					    false);
996 	}
997 	return err;
998 }
999 
1000 static void mlxsw_sp_port_vlan_mode_trans(struct mlxsw_sp_port *mlxsw_sp_port)
1001 {
1002 	struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
1003 
1004 	mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, false);
1005 
1006 	list_for_each_entry_reverse(mlxsw_sp_port_vlan,
1007 				    &mlxsw_sp_port->vlans_list, list) {
1008 		struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid;
1009 		u16 vid = mlxsw_sp_port_vlan->vid;
1010 
1011 		if (!fid)
1012 			continue;
1013 
1014 		__mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid,
1015 					    false);
1016 	}
1017 }
1018 
1019 static int
1020 mlxsw_sp_fid_port_vid_list_add(struct mlxsw_sp_fid *fid, u16 local_port,
1021 			       u16 vid)
1022 {
1023 	struct mlxsw_sp_fid_port_vid *port_vid, *tmp_port_vid;
1024 	struct list_head *insert_before = &fid->port_vid_list;
1025 
1026 	port_vid = kzalloc_obj(*port_vid);
1027 	if (!port_vid)
1028 		return -ENOMEM;
1029 
1030 	port_vid->local_port = local_port;
1031 	port_vid->vid = vid;
1032 
1033 	list_for_each_entry(tmp_port_vid, &fid->port_vid_list, list) {
1034 		if (tmp_port_vid->local_port > local_port) {
1035 			insert_before = &tmp_port_vid->list;
1036 			break;
1037 		}
1038 	}
1039 
1040 	list_add_tail(&port_vid->list, insert_before);
1041 	return 0;
1042 }
1043 
1044 static void
1045 mlxsw_sp_fid_port_vid_list_del(struct mlxsw_sp_fid *fid, u16 local_port,
1046 			       u16 vid)
1047 {
1048 	struct mlxsw_sp_fid_port_vid *port_vid, *tmp;
1049 
1050 	list_for_each_entry_safe(port_vid, tmp, &fid->port_vid_list, list) {
1051 		if (port_vid->local_port != local_port || port_vid->vid != vid)
1052 			continue;
1053 
1054 		list_del(&port_vid->list);
1055 		kfree(port_vid);
1056 		return;
1057 	}
1058 }
1059 
1060 static int
1061 mlxsw_sp_fid_mpe_table_map(const struct mlxsw_sp_fid *fid, u16 local_port,
1062 			   u16 vid, bool valid)
1063 {
1064 	struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
1065 	char smpe_pl[MLXSW_REG_SMPE_LEN];
1066 
1067 	mlxsw_reg_smpe_pack(smpe_pl, local_port, fid->fid_index,
1068 			    valid ? vid : 0);
1069 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(smpe), smpe_pl);
1070 }
1071 
1072 static int
1073 mlxsw_sp_fid_erif_eport_to_vid_map_one(const struct mlxsw_sp_fid *fid,
1074 				       u16 local_port, u16 vid, bool valid)
1075 {
1076 	u8 port_page = local_port / MLXSW_REG_REIV_REC_MAX_COUNT;
1077 	u8 rec_num = local_port % MLXSW_REG_REIV_REC_MAX_COUNT;
1078 	struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
1079 	u16 rif_index = mlxsw_sp_rif_index(fid->rif);
1080 	char *reiv_pl;
1081 	int err;
1082 
1083 	reiv_pl = kmalloc(MLXSW_REG_REIV_LEN, GFP_KERNEL);
1084 	if (!reiv_pl)
1085 		return -ENOMEM;
1086 
1087 	mlxsw_reg_reiv_pack(reiv_pl, port_page, rif_index);
1088 	mlxsw_reg_reiv_rec_update_set(reiv_pl, rec_num, true);
1089 	mlxsw_reg_reiv_rec_evid_set(reiv_pl, rec_num, valid ? vid : 0);
1090 	err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(reiv), reiv_pl);
1091 	kfree(reiv_pl);
1092 	return err;
1093 }
1094 
1095 static int mlxsw_sp_fid_evid_map(const struct mlxsw_sp_fid *fid, u16 local_port,
1096 				 u16 vid, bool valid)
1097 {
1098 	int err;
1099 
1100 	err = mlxsw_sp_fid_mpe_table_map(fid, local_port, vid, valid);
1101 	if (err)
1102 		return err;
1103 
1104 	if (!fid->rif)
1105 		return 0;
1106 
1107 	err = mlxsw_sp_fid_erif_eport_to_vid_map_one(fid, local_port, vid,
1108 						     valid);
1109 	if (err)
1110 		goto err_erif_eport_to_vid_map_one;
1111 
1112 	return 0;
1113 
1114 err_erif_eport_to_vid_map_one:
1115 	mlxsw_sp_fid_mpe_table_map(fid, local_port, vid, !valid);
1116 	return err;
1117 }
1118 
1119 static int mlxsw_sp_fid_8021d_port_vid_map(struct mlxsw_sp_fid *fid,
1120 					   struct mlxsw_sp_port *mlxsw_sp_port,
1121 					   u16 vid)
1122 {
1123 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1124 	u16 local_port = mlxsw_sp_port->local_port;
1125 	int err;
1126 
1127 	err = __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid,
1128 					  true);
1129 	if (err)
1130 		return err;
1131 
1132 	err = mlxsw_sp_fid_evid_map(fid, local_port, vid, true);
1133 	if (err)
1134 		goto err_fid_evid_map;
1135 
1136 	err = mlxsw_sp_fid_port_vid_list_add(fid, mlxsw_sp_port->local_port,
1137 					     vid);
1138 	if (err)
1139 		goto err_port_vid_list_add;
1140 
1141 	if (mlxsw_sp->fid_core->port_fid_mappings[local_port]++ == 0) {
1142 		err = mlxsw_sp_port_vp_mode_trans(mlxsw_sp_port);
1143 		if (err)
1144 			goto err_port_vp_mode_trans;
1145 	}
1146 
1147 	return 0;
1148 
1149 err_port_vp_mode_trans:
1150 	mlxsw_sp->fid_core->port_fid_mappings[local_port]--;
1151 	mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid);
1152 err_port_vid_list_add:
1153 	mlxsw_sp_fid_evid_map(fid, local_port, vid, false);
1154 err_fid_evid_map:
1155 	__mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, false);
1156 	return err;
1157 }
1158 
1159 static void
1160 mlxsw_sp_fid_8021d_port_vid_unmap(struct mlxsw_sp_fid *fid,
1161 				  struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
1162 {
1163 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1164 	u16 local_port = mlxsw_sp_port->local_port;
1165 
1166 	if (mlxsw_sp->fid_core->port_fid_mappings[local_port] == 1)
1167 		mlxsw_sp_port_vlan_mode_trans(mlxsw_sp_port);
1168 	mlxsw_sp->fid_core->port_fid_mappings[local_port]--;
1169 	mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid);
1170 	mlxsw_sp_fid_evid_map(fid, local_port, vid, false);
1171 	__mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, false);
1172 }
1173 
1174 static int mlxsw_sp_fid_8021d_vni_set(struct mlxsw_sp_fid *fid)
1175 {
1176 	return mlxsw_sp_fid_vni_op(fid);
1177 }
1178 
1179 static void mlxsw_sp_fid_8021d_vni_clear(struct mlxsw_sp_fid *fid)
1180 {
1181 	mlxsw_sp_fid_vni_op(fid);
1182 }
1183 
1184 static int mlxsw_sp_fid_8021d_nve_flood_index_set(struct mlxsw_sp_fid *fid)
1185 {
1186 	return mlxsw_sp_fid_edit_op(fid, fid->rif);
1187 }
1188 
1189 static void mlxsw_sp_fid_8021d_nve_flood_index_clear(struct mlxsw_sp_fid *fid)
1190 {
1191 	mlxsw_sp_fid_edit_op(fid, fid->rif);
1192 }
1193 
1194 static void
1195 mlxsw_sp_fid_8021d_fdb_clear_offload(const struct mlxsw_sp_fid *fid,
1196 				     const struct net_device *nve_dev)
1197 {
1198 	br_fdb_clear_offload(nve_dev, 0);
1199 }
1200 
1201 static int
1202 mlxsw_sp_fid_8021d_vid_to_fid_rif_update(const struct mlxsw_sp_fid *fid,
1203 					 const struct mlxsw_sp_rif *rif)
1204 {
1205 	return 0;
1206 }
1207 
1208 static int
1209 mlxsw_sp_fid_flood_table_init_ctl(struct mlxsw_sp_fid_family *fid_family,
1210 				  const struct mlxsw_sp_flood_table *flood_table)
1211 {
1212 	enum mlxsw_sp_flood_type packet_type = flood_table->packet_type;
1213 	struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
1214 	const int *sfgc_packet_types;
1215 	u16 mid_base;
1216 	int err, i;
1217 
1218 	mid_base = mlxsw_sp_fid_pgt_base_ctl(fid_family, flood_table);
1219 
1220 	sfgc_packet_types = mlxsw_sp_packet_type_sfgc_types[packet_type];
1221 	for (i = 0; i < MLXSW_REG_SFGC_TYPE_MAX; i++) {
1222 		char sfgc_pl[MLXSW_REG_SFGC_LEN];
1223 
1224 		if (!sfgc_packet_types[i])
1225 			continue;
1226 
1227 		mlxsw_reg_sfgc_pack(sfgc_pl, i, fid_family->bridge_type,
1228 				    flood_table->table_type, 0, mid_base);
1229 
1230 		err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfgc), sfgc_pl);
1231 		if (err)
1232 			return err;
1233 	}
1234 
1235 	return 0;
1236 }
1237 
1238 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021d_ops_ctl = {
1239 	.setup			= mlxsw_sp_fid_8021d_setup,
1240 	.configure		= mlxsw_sp_fid_8021d_configure,
1241 	.deconfigure		= mlxsw_sp_fid_8021d_deconfigure,
1242 	.index_alloc		= mlxsw_sp_fid_8021d_index_alloc,
1243 	.compare		= mlxsw_sp_fid_8021d_compare,
1244 	.port_vid_map		= mlxsw_sp_fid_8021d_port_vid_map,
1245 	.port_vid_unmap		= mlxsw_sp_fid_8021d_port_vid_unmap,
1246 	.vni_set		= mlxsw_sp_fid_8021d_vni_set,
1247 	.vni_clear		= mlxsw_sp_fid_8021d_vni_clear,
1248 	.nve_flood_index_set	= mlxsw_sp_fid_8021d_nve_flood_index_set,
1249 	.nve_flood_index_clear	= mlxsw_sp_fid_8021d_nve_flood_index_clear,
1250 	.fdb_clear_offload	= mlxsw_sp_fid_8021d_fdb_clear_offload,
1251 	.vid_to_fid_rif_update  = mlxsw_sp_fid_8021d_vid_to_fid_rif_update,
1252 	.flood_table_init	= mlxsw_sp_fid_flood_table_init_ctl,
1253 	.pgt_size		= mlxsw_sp_fid_8021d_pgt_size,
1254 	.fid_mid		= mlxsw_sp_fid_fid_mid_ctl,
1255 	.fid_pack		= mlxsw_sp_fid_pack_ctl,
1256 };
1257 
1258 static u16
1259 mlxsw_sp_fid_fid_mid_cff(const struct mlxsw_sp_fid *fid,
1260 			 const struct mlxsw_sp_flood_table *flood_table)
1261 {
1262 	return mlxsw_sp_fid_pgt_base_cff(fid) + flood_table->table_index;
1263 }
1264 
1265 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021d_ops_cff = {
1266 	.setup			= mlxsw_sp_fid_8021d_setup,
1267 	.configure		= mlxsw_sp_fid_8021d_configure,
1268 	.deconfigure		= mlxsw_sp_fid_8021d_deconfigure,
1269 	.index_alloc		= mlxsw_sp_fid_8021d_index_alloc,
1270 	.compare		= mlxsw_sp_fid_8021d_compare,
1271 	.port_vid_map		= mlxsw_sp_fid_8021d_port_vid_map,
1272 	.port_vid_unmap		= mlxsw_sp_fid_8021d_port_vid_unmap,
1273 	.vni_set		= mlxsw_sp_fid_8021d_vni_set,
1274 	.vni_clear		= mlxsw_sp_fid_8021d_vni_clear,
1275 	.nve_flood_index_set	= mlxsw_sp_fid_8021d_nve_flood_index_set,
1276 	.nve_flood_index_clear	= mlxsw_sp_fid_8021d_nve_flood_index_clear,
1277 	.fdb_clear_offload	= mlxsw_sp_fid_8021d_fdb_clear_offload,
1278 	.vid_to_fid_rif_update	= mlxsw_sp_fid_8021d_vid_to_fid_rif_update,
1279 	.pgt_size		= mlxsw_sp_fid_8021d_pgt_size,
1280 	.fid_mid		= mlxsw_sp_fid_fid_mid_cff,
1281 	.fid_pack		= mlxsw_sp_fid_fid_pack_cff,
1282 };
1283 
1284 #define MLXSW_SP_FID_8021Q_MAX (VLAN_N_VID - 2)
1285 #define MLXSW_SP_FID_RFID_MAX (11 * 1024)
1286 
1287 static const struct mlxsw_sp_flood_table mlxsw_sp_fid_8021d_flood_tables[] = {
1288 	{
1289 		.packet_type	= MLXSW_SP_FLOOD_TYPE_UC,
1290 		.table_type	= MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFSET,
1291 		.table_index	= 0,
1292 	},
1293 	{
1294 		.packet_type	= MLXSW_SP_FLOOD_TYPE_MC,
1295 		.table_type	= MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFSET,
1296 		.table_index	= 1,
1297 	},
1298 	{
1299 		.packet_type	= MLXSW_SP_FLOOD_TYPE_BC,
1300 		.table_type	= MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFSET,
1301 		.table_index	= 2,
1302 	},
1303 };
1304 
1305 static const
1306 struct mlxsw_sp_fid_flood_profile mlxsw_sp_fid_8021d_flood_profile = {
1307 	.flood_tables		= mlxsw_sp_fid_8021d_flood_tables,
1308 	.nr_flood_tables	= ARRAY_SIZE(mlxsw_sp_fid_8021d_flood_tables),
1309 	.profile_id		= MLXSW_SP_FID_FLOOD_PROFILE_ID_BRIDGE,
1310 };
1311 
1312 static const struct mlxsw_sp_flood_table mlxsw_sp_fid_rsp_flood_tables_cff[] = {
1313 	{
1314 		.packet_type	= MLXSW_SP_FLOOD_TYPE_UC,
1315 		.table_index	= 0,
1316 	},
1317 	{
1318 		.packet_type	= MLXSW_SP_FLOOD_TYPE_NOT_UC,
1319 		.table_index	= 1,
1320 	},
1321 };
1322 
1323 static const
1324 struct mlxsw_sp_fid_flood_profile mlxsw_sp_fid_rsp_flood_profile_cff = {
1325 	.flood_tables		= mlxsw_sp_fid_rsp_flood_tables_cff,
1326 	.nr_flood_tables	= ARRAY_SIZE(mlxsw_sp_fid_rsp_flood_tables_cff),
1327 	.profile_id		= MLXSW_SP_FID_FLOOD_PROFILE_ID_RSP,
1328 };
1329 
1330 static const struct mlxsw_sp_flood_table mlxsw_sp_fid_nve_flood_tables_cff[] = {
1331 	{
1332 		.packet_type	= MLXSW_SP_FLOOD_TYPE_ANY,
1333 		.table_index	= 0,
1334 	},
1335 };
1336 
1337 static const
1338 struct mlxsw_sp_fid_flood_profile mlxsw_sp_fid_nve_flood_profile_cff = {
1339 	.flood_tables		= mlxsw_sp_fid_nve_flood_tables_cff,
1340 	.nr_flood_tables	= ARRAY_SIZE(mlxsw_sp_fid_nve_flood_tables_cff),
1341 	.profile_id		= MLXSW_SP_FID_FLOOD_PROFILE_ID_NVE,
1342 };
1343 
1344 static bool
1345 mlxsw_sp_fid_8021q_compare(const struct mlxsw_sp_fid *fid, const void *arg)
1346 {
1347 	u16 vid = *(u16 *) arg;
1348 
1349 	return mlxsw_sp_fid_8021q_fid(fid)->vid == vid;
1350 }
1351 
1352 static void
1353 mlxsw_sp_fid_8021q_fdb_clear_offload(const struct mlxsw_sp_fid *fid,
1354 				     const struct net_device *nve_dev)
1355 {
1356 	br_fdb_clear_offload(nve_dev, mlxsw_sp_fid_8021q_vid(fid));
1357 }
1358 
1359 static int mlxsw_sp_fid_rfid_setup_ctl(struct mlxsw_sp_fid *fid,
1360 				       const void *arg)
1361 {
1362 	/* In controlled mode, the FW takes care of FID placement. */
1363 	fid->fid_offset = 0;
1364 	return 0;
1365 }
1366 
1367 static int mlxsw_sp_fid_rfid_setup_cff(struct mlxsw_sp_fid *fid,
1368 				       const void *arg)
1369 {
1370 	struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
1371 	u16 rif_index = *(const u16 *)arg;
1372 	struct mlxsw_sp_rif *rif;
1373 	bool is_lag;
1374 	u16 port;
1375 	int err;
1376 
1377 	rif = mlxsw_sp_rif_by_index(mlxsw_sp, rif_index);
1378 	if (!rif)
1379 		return -ENOENT;
1380 
1381 	err = mlxsw_sp_rif_subport_port(rif, &port, &is_lag);
1382 	if (err)
1383 		return err;
1384 
1385 	fid->fid_offset = mlxsw_sp_fid_rfid_fid_offset_cff(mlxsw_sp, port,
1386 							   is_lag);
1387 	return 0;
1388 }
1389 
1390 static int mlxsw_sp_fid_rfid_configure(struct mlxsw_sp_fid *fid)
1391 {
1392 	return mlxsw_sp_fid_op(fid, true);
1393 }
1394 
1395 static void mlxsw_sp_fid_rfid_deconfigure(struct mlxsw_sp_fid *fid)
1396 {
1397 	mlxsw_sp_fid_op(fid, false);
1398 }
1399 
1400 static int mlxsw_sp_fid_rfid_index_alloc(struct mlxsw_sp_fid *fid,
1401 					 const void *arg, u16 *p_fid_index)
1402 {
1403 	u16 rif_index = *(u16 *) arg;
1404 
1405 	*p_fid_index = fid->fid_family->start_index + rif_index;
1406 
1407 	return 0;
1408 }
1409 
1410 static bool mlxsw_sp_fid_rfid_compare(const struct mlxsw_sp_fid *fid,
1411 				      const void *arg)
1412 {
1413 	u16 rif_index = *(u16 *) arg;
1414 
1415 	return fid->fid_index == rif_index + fid->fid_family->start_index;
1416 }
1417 
1418 static int mlxsw_sp_fid_rfid_port_vid_map(struct mlxsw_sp_fid *fid,
1419 					  struct mlxsw_sp_port *mlxsw_sp_port,
1420 					  u16 vid)
1421 {
1422 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1423 	u16 local_port = mlxsw_sp_port->local_port;
1424 	int err;
1425 
1426 	err = mlxsw_sp_fid_port_vid_list_add(fid, mlxsw_sp_port->local_port,
1427 					     vid);
1428 	if (err)
1429 		return err;
1430 
1431 	/* Using legacy bridge model, we only need to transition the port to
1432 	 * virtual mode since {Port, VID} => FID is done by the firmware upon
1433 	 * RIF creation. Using unified bridge model, we need to map
1434 	 * {Port, VID} => FID and map egress VID.
1435 	 */
1436 	err = __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid,
1437 					  true);
1438 	if (err)
1439 		goto err_port_vid_map;
1440 
1441 	if (fid->rif) {
1442 		err = mlxsw_sp_fid_erif_eport_to_vid_map_one(fid, local_port,
1443 							     vid, true);
1444 		if (err)
1445 			goto err_erif_eport_to_vid_map_one;
1446 	}
1447 
1448 	if (mlxsw_sp->fid_core->port_fid_mappings[local_port]++ == 0) {
1449 		err = mlxsw_sp_port_vp_mode_trans(mlxsw_sp_port);
1450 		if (err)
1451 			goto err_port_vp_mode_trans;
1452 	}
1453 
1454 	return 0;
1455 
1456 err_port_vp_mode_trans:
1457 	mlxsw_sp->fid_core->port_fid_mappings[local_port]--;
1458 	if (fid->rif)
1459 		mlxsw_sp_fid_erif_eport_to_vid_map_one(fid, local_port, vid,
1460 						       false);
1461 err_erif_eport_to_vid_map_one:
1462 	__mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, false);
1463 err_port_vid_map:
1464 	mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid);
1465 	return err;
1466 }
1467 
1468 static void
1469 mlxsw_sp_fid_rfid_port_vid_unmap(struct mlxsw_sp_fid *fid,
1470 				 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
1471 {
1472 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1473 	u16 local_port = mlxsw_sp_port->local_port;
1474 
1475 	if (mlxsw_sp->fid_core->port_fid_mappings[local_port] == 1)
1476 		mlxsw_sp_port_vlan_mode_trans(mlxsw_sp_port);
1477 	mlxsw_sp->fid_core->port_fid_mappings[local_port]--;
1478 
1479 	if (fid->rif)
1480 		mlxsw_sp_fid_erif_eport_to_vid_map_one(fid, local_port, vid,
1481 						       false);
1482 	__mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, false);
1483 	mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid);
1484 }
1485 
1486 static int mlxsw_sp_fid_rfid_vni_set(struct mlxsw_sp_fid *fid)
1487 {
1488 	return -EOPNOTSUPP;
1489 }
1490 
1491 static void mlxsw_sp_fid_rfid_vni_clear(struct mlxsw_sp_fid *fid)
1492 {
1493 	WARN_ON_ONCE(1);
1494 }
1495 
1496 static int mlxsw_sp_fid_rfid_nve_flood_index_set(struct mlxsw_sp_fid *fid)
1497 {
1498 	return -EOPNOTSUPP;
1499 }
1500 
1501 static void mlxsw_sp_fid_rfid_nve_flood_index_clear(struct mlxsw_sp_fid *fid)
1502 {
1503 	WARN_ON_ONCE(1);
1504 }
1505 
1506 static int
1507 mlxsw_sp_fid_rfid_vid_to_fid_rif_update(const struct mlxsw_sp_fid *fid,
1508 					const struct mlxsw_sp_rif *rif)
1509 {
1510 	return 0;
1511 }
1512 
1513 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_rfid_ops_ctl = {
1514 	.setup			= mlxsw_sp_fid_rfid_setup_ctl,
1515 	.configure		= mlxsw_sp_fid_rfid_configure,
1516 	.deconfigure		= mlxsw_sp_fid_rfid_deconfigure,
1517 	.index_alloc		= mlxsw_sp_fid_rfid_index_alloc,
1518 	.compare		= mlxsw_sp_fid_rfid_compare,
1519 	.port_vid_map		= mlxsw_sp_fid_rfid_port_vid_map,
1520 	.port_vid_unmap		= mlxsw_sp_fid_rfid_port_vid_unmap,
1521 	.vni_set                = mlxsw_sp_fid_rfid_vni_set,
1522 	.vni_clear		= mlxsw_sp_fid_rfid_vni_clear,
1523 	.nve_flood_index_set	= mlxsw_sp_fid_rfid_nve_flood_index_set,
1524 	.nve_flood_index_clear	= mlxsw_sp_fid_rfid_nve_flood_index_clear,
1525 	.vid_to_fid_rif_update  = mlxsw_sp_fid_rfid_vid_to_fid_rif_update,
1526 	.fid_pack		= mlxsw_sp_fid_pack_ctl,
1527 };
1528 
1529 static int
1530 mlxsw_sp_fid_rfid_port_add_cff(struct mlxsw_sp *mlxsw_sp,
1531 			       const struct mlxsw_sp_flood_table *flood_table,
1532 			       u16 pgt_addr, u16 smpe, unsigned int local_port)
1533 {
1534 	int err;
1535 
1536 	err = mlxsw_sp_pgt_entry_port_set(mlxsw_sp, pgt_addr, smpe,
1537 					  local_port, true);
1538 	if (err)
1539 		return err;
1540 
1541 	if (flood_table->packet_type == MLXSW_SP_FLOOD_TYPE_NOT_UC) {
1542 		u16 router_port = mlxsw_sp_router_port(mlxsw_sp);
1543 
1544 		err = mlxsw_sp_pgt_entry_port_set(mlxsw_sp, pgt_addr, smpe,
1545 						  router_port, true);
1546 		if (err)
1547 			goto err_entry_port_set;
1548 	}
1549 
1550 	return 0;
1551 
1552 err_entry_port_set:
1553 	mlxsw_sp_pgt_entry_port_set(mlxsw_sp, pgt_addr, smpe, local_port,
1554 				    false);
1555 	return err;
1556 }
1557 
1558 static void
1559 mlxsw_sp_fid_rfid_port_del_cff(struct mlxsw_sp *mlxsw_sp,
1560 			       const struct mlxsw_sp_flood_table *flood_table,
1561 			       u16 pgt_addr, u16 smpe, u16 local_port)
1562 {
1563 	if (flood_table->packet_type == MLXSW_SP_FLOOD_TYPE_NOT_UC) {
1564 		u16 router_port = mlxsw_sp_router_port(mlxsw_sp);
1565 
1566 		mlxsw_sp_pgt_entry_port_set(mlxsw_sp, pgt_addr, smpe,
1567 					    router_port, false);
1568 	}
1569 	mlxsw_sp_pgt_entry_port_set(mlxsw_sp, pgt_addr, smpe, local_port,
1570 				    false);
1571 }
1572 
1573 static int
1574 mlxsw_sp_fid_rfid_port_memb_ft_cff(const struct mlxsw_sp_fid_family *fid_family,
1575 				   const struct mlxsw_sp_flood_table *flood_table,
1576 				   const struct mlxsw_sp_port *mlxsw_sp_port,
1577 				   bool member)
1578 {
1579 	struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
1580 	u16 local_port = mlxsw_sp_port->local_port;
1581 	u16 fid_pgt_base;
1582 	u16 fid_offset;
1583 	u16 pgt_addr;
1584 	u16 smpe;
1585 	u16 port;
1586 
1587 	/* In-PGT SMPE is only valid on Spectrum-1, CFF only on Spectrum>1. */
1588 	smpe = 0;
1589 
1590 	port = mlxsw_sp_port->lagged ? mlxsw_sp_port->lag_id : local_port;
1591 	fid_offset = mlxsw_sp_fid_rfid_fid_offset_cff(mlxsw_sp, port,
1592 						      mlxsw_sp_port->lagged);
1593 	fid_pgt_base = mlxsw_sp_fid_off_pgt_base_cff(fid_family, fid_offset);
1594 	pgt_addr = fid_pgt_base + flood_table->table_index;
1595 
1596 	if (member)
1597 		return mlxsw_sp_fid_rfid_port_add_cff(mlxsw_sp, flood_table,
1598 						      pgt_addr, smpe,
1599 						      local_port);
1600 
1601 	mlxsw_sp_fid_rfid_port_del_cff(mlxsw_sp, flood_table, pgt_addr, smpe,
1602 				       local_port);
1603 	return 0;
1604 }
1605 
1606 static int
1607 mlxsw_sp_fid_rfid_port_memb_cff(const struct mlxsw_sp_fid_family *fid_family,
1608 				const struct mlxsw_sp_port *mlxsw_sp_port,
1609 				bool member)
1610 {
1611 	int i;
1612 
1613 	for (i = 0; i < fid_family->flood_profile->nr_flood_tables; i++) {
1614 		const struct mlxsw_sp_flood_table *flood_table =
1615 			&fid_family->flood_profile->flood_tables[i];
1616 		int err;
1617 
1618 		err = mlxsw_sp_fid_rfid_port_memb_ft_cff(fid_family,
1619 							 flood_table,
1620 							 mlxsw_sp_port, member);
1621 		if (err)
1622 			return err;
1623 	}
1624 
1625 	return 0;
1626 }
1627 
1628 static int
1629 mlxsw_sp_fid_rfid_port_init_cff(const struct mlxsw_sp_fid_family *fid_family,
1630 				const struct mlxsw_sp_port *mlxsw_sp_port)
1631 {
1632 	return mlxsw_sp_fid_rfid_port_memb_cff(fid_family, mlxsw_sp_port, true);
1633 }
1634 
1635 static void
1636 mlxsw_sp_fid_rfid_port_fini_cff(const struct mlxsw_sp_fid_family *fid_family,
1637 				const struct mlxsw_sp_port *mlxsw_sp_port)
1638 {
1639 	mlxsw_sp_fid_rfid_port_memb_cff(fid_family, mlxsw_sp_port, false);
1640 }
1641 
1642 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_rfid_ops_cff = {
1643 	.setup			= mlxsw_sp_fid_rfid_setup_cff,
1644 	.configure		= mlxsw_sp_fid_rfid_configure,
1645 	.deconfigure		= mlxsw_sp_fid_rfid_deconfigure,
1646 	.index_alloc		= mlxsw_sp_fid_rfid_index_alloc,
1647 	.compare		= mlxsw_sp_fid_rfid_compare,
1648 	.port_vid_map		= mlxsw_sp_fid_rfid_port_vid_map,
1649 	.port_vid_unmap		= mlxsw_sp_fid_rfid_port_vid_unmap,
1650 	.vni_set		= mlxsw_sp_fid_rfid_vni_set,
1651 	.vni_clear		= mlxsw_sp_fid_rfid_vni_clear,
1652 	.nve_flood_index_set	= mlxsw_sp_fid_rfid_nve_flood_index_set,
1653 	.nve_flood_index_clear	= mlxsw_sp_fid_rfid_nve_flood_index_clear,
1654 	.vid_to_fid_rif_update	= mlxsw_sp_fid_rfid_vid_to_fid_rif_update,
1655 	.pgt_size		= mlxsw_sp_fid_rfid_pgt_size_cff,
1656 	.fid_port_init		= mlxsw_sp_fid_rfid_port_init_cff,
1657 	.fid_port_fini		= mlxsw_sp_fid_rfid_port_fini_cff,
1658 	.fid_mid		= mlxsw_sp_fid_fid_mid_cff,
1659 	.fid_pack		= mlxsw_sp_fid_fid_pack_cff,
1660 };
1661 
1662 static int mlxsw_sp_fid_dummy_setup(struct mlxsw_sp_fid *fid, const void *arg)
1663 {
1664 	fid->fid_offset = 0;
1665 	return 0;
1666 }
1667 
1668 static int mlxsw_sp_fid_dummy_configure(struct mlxsw_sp_fid *fid)
1669 {
1670 	return mlxsw_sp_fid_op(fid, true);
1671 }
1672 
1673 static void mlxsw_sp_fid_dummy_deconfigure(struct mlxsw_sp_fid *fid)
1674 {
1675 	mlxsw_sp_fid_op(fid, false);
1676 }
1677 
1678 static int mlxsw_sp_fid_dummy_index_alloc(struct mlxsw_sp_fid *fid,
1679 					  const void *arg, u16 *p_fid_index)
1680 {
1681 	*p_fid_index = fid->fid_family->start_index;
1682 
1683 	return 0;
1684 }
1685 
1686 static bool mlxsw_sp_fid_dummy_compare(const struct mlxsw_sp_fid *fid,
1687 				       const void *arg)
1688 {
1689 	return true;
1690 }
1691 
1692 static int mlxsw_sp_fid_dummy_vni_set(struct mlxsw_sp_fid *fid)
1693 {
1694 	return -EOPNOTSUPP;
1695 }
1696 
1697 static void mlxsw_sp_fid_dummy_vni_clear(struct mlxsw_sp_fid *fid)
1698 {
1699 	WARN_ON_ONCE(1);
1700 }
1701 
1702 static int mlxsw_sp_fid_dummy_nve_flood_index_set(struct mlxsw_sp_fid *fid)
1703 {
1704 	return -EOPNOTSUPP;
1705 }
1706 
1707 static void mlxsw_sp_fid_dummy_nve_flood_index_clear(struct mlxsw_sp_fid *fid)
1708 {
1709 	WARN_ON_ONCE(1);
1710 }
1711 
1712 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_dummy_ops = {
1713 	.setup			= mlxsw_sp_fid_dummy_setup,
1714 	.configure		= mlxsw_sp_fid_dummy_configure,
1715 	.deconfigure		= mlxsw_sp_fid_dummy_deconfigure,
1716 	.index_alloc		= mlxsw_sp_fid_dummy_index_alloc,
1717 	.compare		= mlxsw_sp_fid_dummy_compare,
1718 	.vni_set                = mlxsw_sp_fid_dummy_vni_set,
1719 	.vni_clear		= mlxsw_sp_fid_dummy_vni_clear,
1720 	.nve_flood_index_set	= mlxsw_sp_fid_dummy_nve_flood_index_set,
1721 	.nve_flood_index_clear	= mlxsw_sp_fid_dummy_nve_flood_index_clear,
1722 	.fid_pack		= mlxsw_sp_fid_pack,
1723 };
1724 
1725 static int mlxsw_sp_fid_8021q_configure(struct mlxsw_sp_fid *fid)
1726 {
1727 	struct mlxsw_sp_fid_8021q *fid_8021q = mlxsw_sp_fid_8021q_fid(fid);
1728 	int err;
1729 
1730 	err = mlxsw_sp_fid_op(fid, true);
1731 	if (err)
1732 		return err;
1733 
1734 	err = mlxsw_sp_fid_vid_to_fid_map(fid, fid_8021q->vid, true, fid->rif);
1735 	if (err)
1736 		goto err_vid_to_fid_map;
1737 
1738 	return 0;
1739 
1740 err_vid_to_fid_map:
1741 	mlxsw_sp_fid_op(fid, false);
1742 	return err;
1743 }
1744 
1745 static void mlxsw_sp_fid_8021q_deconfigure(struct mlxsw_sp_fid *fid)
1746 {
1747 	struct mlxsw_sp_fid_8021q *fid_8021q = mlxsw_sp_fid_8021q_fid(fid);
1748 
1749 	if (fid->vni_valid)
1750 		mlxsw_sp_nve_fid_disable(fid->fid_family->mlxsw_sp, fid);
1751 
1752 	mlxsw_sp_fid_vid_to_fid_map(fid, fid_8021q->vid, false, NULL);
1753 	mlxsw_sp_fid_op(fid, false);
1754 }
1755 
1756 static int mlxsw_sp_fid_8021q_port_vid_map(struct mlxsw_sp_fid *fid,
1757 					   struct mlxsw_sp_port *mlxsw_sp_port,
1758 					   u16 vid)
1759 {
1760 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1761 	u16 local_port = mlxsw_sp_port->local_port;
1762 	int err;
1763 
1764 	/* In case there are no {Port, VID} => FID mappings on the port,
1765 	 * we can use the global VID => FID mapping we created when the
1766 	 * FID was configured, otherwise, configure new mapping.
1767 	 */
1768 	if (mlxsw_sp->fid_core->port_fid_mappings[local_port]) {
1769 		err =  __mlxsw_sp_fid_port_vid_map(fid, local_port, vid, true);
1770 		if (err)
1771 			return err;
1772 	}
1773 
1774 	err = mlxsw_sp_fid_evid_map(fid, local_port, vid, true);
1775 	if (err)
1776 		goto err_fid_evid_map;
1777 
1778 	err = mlxsw_sp_fid_port_vid_list_add(fid, mlxsw_sp_port->local_port,
1779 					     vid);
1780 	if (err)
1781 		goto err_port_vid_list_add;
1782 
1783 	return 0;
1784 
1785 err_port_vid_list_add:
1786 	 mlxsw_sp_fid_evid_map(fid, local_port, vid, false);
1787 err_fid_evid_map:
1788 	if (mlxsw_sp->fid_core->port_fid_mappings[local_port])
1789 		__mlxsw_sp_fid_port_vid_map(fid, local_port, vid, false);
1790 	return err;
1791 }
1792 
1793 static void
1794 mlxsw_sp_fid_8021q_port_vid_unmap(struct mlxsw_sp_fid *fid,
1795 				  struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
1796 {
1797 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1798 	u16 local_port = mlxsw_sp_port->local_port;
1799 
1800 	mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid);
1801 	mlxsw_sp_fid_evid_map(fid, local_port, vid, false);
1802 	if (mlxsw_sp->fid_core->port_fid_mappings[local_port])
1803 		__mlxsw_sp_fid_port_vid_map(fid, local_port, vid, false);
1804 }
1805 
1806 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021q_ops_ctl = {
1807 	.setup			= mlxsw_sp_fid_8021q_setup,
1808 	.configure		= mlxsw_sp_fid_8021q_configure,
1809 	.deconfigure		= mlxsw_sp_fid_8021q_deconfigure,
1810 	.index_alloc		= mlxsw_sp_fid_8021d_index_alloc,
1811 	.compare		= mlxsw_sp_fid_8021q_compare,
1812 	.port_vid_map		= mlxsw_sp_fid_8021q_port_vid_map,
1813 	.port_vid_unmap		= mlxsw_sp_fid_8021q_port_vid_unmap,
1814 	.vni_set		= mlxsw_sp_fid_8021d_vni_set,
1815 	.vni_clear		= mlxsw_sp_fid_8021d_vni_clear,
1816 	.nve_flood_index_set	= mlxsw_sp_fid_8021d_nve_flood_index_set,
1817 	.nve_flood_index_clear	= mlxsw_sp_fid_8021d_nve_flood_index_clear,
1818 	.fdb_clear_offload	= mlxsw_sp_fid_8021q_fdb_clear_offload,
1819 	.vid_to_fid_rif_update  = mlxsw_sp_fid_8021q_vid_to_fid_rif_update,
1820 	.flood_table_init	= mlxsw_sp_fid_flood_table_init_ctl,
1821 	.pgt_size		= mlxsw_sp_fid_8021d_pgt_size,
1822 	.fid_mid		= mlxsw_sp_fid_fid_mid_ctl,
1823 	.fid_pack		= mlxsw_sp_fid_pack_ctl,
1824 };
1825 
1826 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021q_ops_cff = {
1827 	.setup			= mlxsw_sp_fid_8021q_setup,
1828 	.configure		= mlxsw_sp_fid_8021q_configure,
1829 	.deconfigure		= mlxsw_sp_fid_8021q_deconfigure,
1830 	.index_alloc		= mlxsw_sp_fid_8021d_index_alloc,
1831 	.compare		= mlxsw_sp_fid_8021q_compare,
1832 	.port_vid_map		= mlxsw_sp_fid_8021q_port_vid_map,
1833 	.port_vid_unmap		= mlxsw_sp_fid_8021q_port_vid_unmap,
1834 	.vni_set		= mlxsw_sp_fid_8021d_vni_set,
1835 	.vni_clear		= mlxsw_sp_fid_8021d_vni_clear,
1836 	.nve_flood_index_set	= mlxsw_sp_fid_8021d_nve_flood_index_set,
1837 	.nve_flood_index_clear	= mlxsw_sp_fid_8021d_nve_flood_index_clear,
1838 	.fdb_clear_offload	= mlxsw_sp_fid_8021q_fdb_clear_offload,
1839 	.vid_to_fid_rif_update	= mlxsw_sp_fid_8021q_vid_to_fid_rif_update,
1840 	.pgt_size		= mlxsw_sp_fid_8021d_pgt_size,
1841 	.fid_mid		= mlxsw_sp_fid_fid_mid_cff,
1842 	.fid_pack		= mlxsw_sp_fid_fid_pack_cff,
1843 };
1844 
1845 /* There are 4K-2 802.1Q FIDs */
1846 #define MLXSW_SP_FID_8021Q_START	1 /* FID 0 is reserved. */
1847 #define MLXSW_SP_FID_8021Q_END		(MLXSW_SP_FID_8021Q_START + \
1848 					 MLXSW_SP_FID_8021Q_MAX - 1)
1849 
1850 /* There are 1K 802.1D FIDs */
1851 #define MLXSW_SP_FID_8021D_START	(MLXSW_SP_FID_8021Q_END + 1)
1852 #define MLXSW_SP_FID_8021D_END		(MLXSW_SP_FID_8021D_START + \
1853 					 MLXSW_SP_FID_8021D_MAX - 1)
1854 
1855 /* There is one dummy FID */
1856 #define MLXSW_SP_FID_DUMMY		(MLXSW_SP_FID_8021D_END + 1)
1857 
1858 /* There are 11K rFIDs */
1859 #define MLXSW_SP_RFID_START		(MLXSW_SP_FID_DUMMY + 1)
1860 #define MLXSW_SP_RFID_END		(MLXSW_SP_RFID_START + \
1861 					 MLXSW_SP_FID_RFID_MAX - 1)
1862 
1863 static const struct mlxsw_sp_fid_family mlxsw_sp1_fid_8021q_family = {
1864 	.type			= MLXSW_SP_FID_TYPE_8021Q,
1865 	.fid_size		= sizeof(struct mlxsw_sp_fid_8021q),
1866 	.start_index		= MLXSW_SP_FID_8021Q_START,
1867 	.end_index		= MLXSW_SP_FID_8021Q_END,
1868 	.flood_profile		= &mlxsw_sp_fid_8021d_flood_profile,
1869 	.rif_type		= MLXSW_SP_RIF_TYPE_VLAN,
1870 	.ops			= &mlxsw_sp_fid_8021q_ops_ctl,
1871 	.flood_rsp              = false,
1872 	.bridge_type            = MLXSW_REG_BRIDGE_TYPE_0,
1873 	.smpe_index_valid	= false,
1874 };
1875 
1876 static const struct mlxsw_sp_fid_family mlxsw_sp1_fid_8021d_family = {
1877 	.type			= MLXSW_SP_FID_TYPE_8021D,
1878 	.fid_size		= sizeof(struct mlxsw_sp_fid_8021d),
1879 	.start_index		= MLXSW_SP_FID_8021D_START,
1880 	.end_index		= MLXSW_SP_FID_8021D_END,
1881 	.flood_profile		= &mlxsw_sp_fid_8021d_flood_profile,
1882 	.rif_type		= MLXSW_SP_RIF_TYPE_FID,
1883 	.ops			= &mlxsw_sp_fid_8021d_ops_ctl,
1884 	.bridge_type            = MLXSW_REG_BRIDGE_TYPE_1,
1885 	.smpe_index_valid       = false,
1886 };
1887 
1888 static const struct mlxsw_sp_fid_family mlxsw_sp1_fid_dummy_family = {
1889 	.type			= MLXSW_SP_FID_TYPE_DUMMY,
1890 	.fid_size		= sizeof(struct mlxsw_sp_fid),
1891 	.start_index		= MLXSW_SP_FID_DUMMY,
1892 	.end_index		= MLXSW_SP_FID_DUMMY,
1893 	.ops			= &mlxsw_sp_fid_dummy_ops,
1894 	.smpe_index_valid       = false,
1895 };
1896 
1897 static const struct mlxsw_sp_fid_family mlxsw_sp_fid_rfid_family_ctl = {
1898 	.type			= MLXSW_SP_FID_TYPE_RFID,
1899 	.fid_size		= sizeof(struct mlxsw_sp_fid),
1900 	.start_index		= MLXSW_SP_RFID_START,
1901 	.end_index		= MLXSW_SP_RFID_END,
1902 	.rif_type		= MLXSW_SP_RIF_TYPE_SUBPORT,
1903 	.ops			= &mlxsw_sp_fid_rfid_ops_ctl,
1904 	.flood_rsp              = true,
1905 	.smpe_index_valid       = false,
1906 };
1907 
1908 static const struct mlxsw_sp_fid_family *mlxsw_sp1_fid_family_arr[] = {
1909 	[MLXSW_SP_FID_TYPE_8021Q]	= &mlxsw_sp1_fid_8021q_family,
1910 	[MLXSW_SP_FID_TYPE_8021D]	= &mlxsw_sp1_fid_8021d_family,
1911 	[MLXSW_SP_FID_TYPE_DUMMY]	= &mlxsw_sp1_fid_dummy_family,
1912 	[MLXSW_SP_FID_TYPE_RFID]	= &mlxsw_sp_fid_rfid_family_ctl,
1913 };
1914 
1915 static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_8021q_family_ctl = {
1916 	.type			= MLXSW_SP_FID_TYPE_8021Q,
1917 	.fid_size		= sizeof(struct mlxsw_sp_fid_8021q),
1918 	.start_index		= MLXSW_SP_FID_8021Q_START,
1919 	.end_index		= MLXSW_SP_FID_8021Q_END,
1920 	.flood_profile		= &mlxsw_sp_fid_8021d_flood_profile,
1921 	.rif_type		= MLXSW_SP_RIF_TYPE_VLAN,
1922 	.ops			= &mlxsw_sp_fid_8021q_ops_ctl,
1923 	.flood_rsp              = false,
1924 	.bridge_type            = MLXSW_REG_BRIDGE_TYPE_0,
1925 	.smpe_index_valid	= true,
1926 };
1927 
1928 static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_8021d_family_ctl = {
1929 	.type			= MLXSW_SP_FID_TYPE_8021D,
1930 	.fid_size		= sizeof(struct mlxsw_sp_fid_8021d),
1931 	.start_index		= MLXSW_SP_FID_8021D_START,
1932 	.end_index		= MLXSW_SP_FID_8021D_END,
1933 	.flood_profile		= &mlxsw_sp_fid_8021d_flood_profile,
1934 	.rif_type		= MLXSW_SP_RIF_TYPE_FID,
1935 	.ops			= &mlxsw_sp_fid_8021d_ops_ctl,
1936 	.bridge_type            = MLXSW_REG_BRIDGE_TYPE_1,
1937 	.smpe_index_valid       = true,
1938 };
1939 
1940 static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_dummy_family = {
1941 	.type			= MLXSW_SP_FID_TYPE_DUMMY,
1942 	.fid_size		= sizeof(struct mlxsw_sp_fid),
1943 	.start_index		= MLXSW_SP_FID_DUMMY,
1944 	.end_index		= MLXSW_SP_FID_DUMMY,
1945 	.ops			= &mlxsw_sp_fid_dummy_ops,
1946 	.smpe_index_valid       = false,
1947 };
1948 
1949 static const struct mlxsw_sp_fid_family *mlxsw_sp2_fid_family_arr_ctl[] = {
1950 	[MLXSW_SP_FID_TYPE_8021Q]	= &mlxsw_sp2_fid_8021q_family_ctl,
1951 	[MLXSW_SP_FID_TYPE_8021D]	= &mlxsw_sp2_fid_8021d_family_ctl,
1952 	[MLXSW_SP_FID_TYPE_DUMMY]	= &mlxsw_sp2_fid_dummy_family,
1953 	[MLXSW_SP_FID_TYPE_RFID]	= &mlxsw_sp_fid_rfid_family_ctl,
1954 };
1955 
1956 static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_8021q_family_cff = {
1957 	.type			= MLXSW_SP_FID_TYPE_8021Q,
1958 	.fid_size		= sizeof(struct mlxsw_sp_fid_8021q),
1959 	.start_index		= MLXSW_SP_FID_8021Q_START,
1960 	.end_index		= MLXSW_SP_FID_8021Q_END,
1961 	.flood_profile		= &mlxsw_sp_fid_8021d_flood_profile,
1962 	.rif_type		= MLXSW_SP_RIF_TYPE_VLAN,
1963 	.ops			= &mlxsw_sp_fid_8021q_ops_cff,
1964 	.smpe_index_valid	= true,
1965 };
1966 
1967 static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_8021d_family_cff = {
1968 	.type			= MLXSW_SP_FID_TYPE_8021D,
1969 	.fid_size		= sizeof(struct mlxsw_sp_fid_8021d),
1970 	.start_index		= MLXSW_SP_FID_8021D_START,
1971 	.end_index		= MLXSW_SP_FID_8021D_END,
1972 	.flood_profile		= &mlxsw_sp_fid_8021d_flood_profile,
1973 	.rif_type		= MLXSW_SP_RIF_TYPE_FID,
1974 	.ops			= &mlxsw_sp_fid_8021d_ops_cff,
1975 	.smpe_index_valid	= true,
1976 };
1977 
1978 static const struct mlxsw_sp_fid_family mlxsw_sp_fid_rfid_family_cff = {
1979 	.type			= MLXSW_SP_FID_TYPE_RFID,
1980 	.fid_size		= sizeof(struct mlxsw_sp_fid),
1981 	.start_index		= MLXSW_SP_RFID_START,
1982 	.end_index		= MLXSW_SP_RFID_END,
1983 	.flood_profile		= &mlxsw_sp_fid_rsp_flood_profile_cff,
1984 	.rif_type		= MLXSW_SP_RIF_TYPE_SUBPORT,
1985 	.ops			= &mlxsw_sp_fid_rfid_ops_cff,
1986 	.smpe_index_valid	= false,
1987 };
1988 
1989 static const struct mlxsw_sp_fid_family *mlxsw_sp2_fid_family_arr_cff[] = {
1990 	[MLXSW_SP_FID_TYPE_8021Q]	= &mlxsw_sp2_fid_8021q_family_cff,
1991 	[MLXSW_SP_FID_TYPE_8021D]	= &mlxsw_sp2_fid_8021d_family_cff,
1992 	[MLXSW_SP_FID_TYPE_DUMMY]	= &mlxsw_sp2_fid_dummy_family,
1993 	[MLXSW_SP_FID_TYPE_RFID]	= &mlxsw_sp_fid_rfid_family_cff,
1994 };
1995 
1996 static struct mlxsw_sp_fid *mlxsw_sp_fid_lookup(struct mlxsw_sp *mlxsw_sp,
1997 						enum mlxsw_sp_fid_type type,
1998 						const void *arg)
1999 {
2000 	struct mlxsw_sp_fid_family *fid_family;
2001 	struct mlxsw_sp_fid *fid;
2002 
2003 	fid_family = mlxsw_sp->fid_core->fid_family_arr[type];
2004 	list_for_each_entry(fid, &fid_family->fids_list, list) {
2005 		if (!fid->fid_family->ops->compare(fid, arg))
2006 			continue;
2007 		refcount_inc(&fid->ref_count);
2008 		return fid;
2009 	}
2010 
2011 	return NULL;
2012 }
2013 
2014 static struct mlxsw_sp_fid *mlxsw_sp_fid_get(struct mlxsw_sp *mlxsw_sp,
2015 					     enum mlxsw_sp_fid_type type,
2016 					     const void *arg)
2017 {
2018 	struct mlxsw_sp_fid_family *fid_family;
2019 	struct mlxsw_sp_fid *fid;
2020 	u16 fid_index;
2021 	int err;
2022 
2023 	fid = mlxsw_sp_fid_lookup(mlxsw_sp, type, arg);
2024 	if (fid)
2025 		return fid;
2026 
2027 	fid_family = mlxsw_sp->fid_core->fid_family_arr[type];
2028 	fid = kzalloc(fid_family->fid_size, GFP_KERNEL);
2029 	if (!fid)
2030 		return ERR_PTR(-ENOMEM);
2031 
2032 	INIT_LIST_HEAD(&fid->port_vid_list);
2033 	fid->fid_family = fid_family;
2034 
2035 	err = fid->fid_family->ops->index_alloc(fid, arg, &fid_index);
2036 	if (err)
2037 		goto err_index_alloc;
2038 	fid->fid_index = fid_index;
2039 	__set_bit(fid_index - fid_family->start_index, fid_family->fids_bitmap);
2040 
2041 	err = fid->fid_family->ops->setup(fid, arg);
2042 	if (err)
2043 		goto err_setup;
2044 
2045 	err = fid->fid_family->ops->configure(fid);
2046 	if (err)
2047 		goto err_configure;
2048 
2049 	err = rhashtable_insert_fast(&mlxsw_sp->fid_core->fid_ht, &fid->ht_node,
2050 				     mlxsw_sp_fid_ht_params);
2051 	if (err)
2052 		goto err_rhashtable_insert;
2053 
2054 	list_add(&fid->list, &fid_family->fids_list);
2055 	refcount_set(&fid->ref_count, 1);
2056 	return fid;
2057 
2058 err_rhashtable_insert:
2059 	fid->fid_family->ops->deconfigure(fid);
2060 err_configure:
2061 err_setup:
2062 	__clear_bit(fid_index - fid_family->start_index,
2063 		    fid_family->fids_bitmap);
2064 err_index_alloc:
2065 	kfree(fid);
2066 	return ERR_PTR(err);
2067 }
2068 
2069 void mlxsw_sp_fid_put(struct mlxsw_sp_fid *fid)
2070 {
2071 	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
2072 	struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
2073 
2074 	if (!refcount_dec_and_test(&fid->ref_count))
2075 		return;
2076 
2077 	list_del(&fid->list);
2078 	rhashtable_remove_fast(&mlxsw_sp->fid_core->fid_ht,
2079 			       &fid->ht_node, mlxsw_sp_fid_ht_params);
2080 	fid->fid_family->ops->deconfigure(fid);
2081 	__clear_bit(fid->fid_index - fid_family->start_index,
2082 		    fid_family->fids_bitmap);
2083 	WARN_ON_ONCE(!list_empty(&fid->port_vid_list));
2084 	kfree(fid);
2085 }
2086 
2087 struct mlxsw_sp_fid *mlxsw_sp_fid_8021q_get(struct mlxsw_sp *mlxsw_sp, u16 vid)
2088 {
2089 	return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_8021Q, &vid);
2090 }
2091 
2092 struct mlxsw_sp_fid *mlxsw_sp_fid_8021d_get(struct mlxsw_sp *mlxsw_sp,
2093 					    int br_ifindex)
2094 {
2095 	return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_8021D, &br_ifindex);
2096 }
2097 
2098 struct mlxsw_sp_fid *mlxsw_sp_fid_8021q_lookup(struct mlxsw_sp *mlxsw_sp,
2099 					       u16 vid)
2100 {
2101 	return mlxsw_sp_fid_lookup(mlxsw_sp, MLXSW_SP_FID_TYPE_8021Q, &vid);
2102 }
2103 
2104 struct mlxsw_sp_fid *mlxsw_sp_fid_8021d_lookup(struct mlxsw_sp *mlxsw_sp,
2105 					       int br_ifindex)
2106 {
2107 	return mlxsw_sp_fid_lookup(mlxsw_sp, MLXSW_SP_FID_TYPE_8021D,
2108 				   &br_ifindex);
2109 }
2110 
2111 struct mlxsw_sp_fid *mlxsw_sp_fid_rfid_get(struct mlxsw_sp *mlxsw_sp,
2112 					   u16 rif_index)
2113 {
2114 	return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_RFID, &rif_index);
2115 }
2116 
2117 struct mlxsw_sp_fid *mlxsw_sp_fid_dummy_get(struct mlxsw_sp *mlxsw_sp)
2118 {
2119 	return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_DUMMY, NULL);
2120 }
2121 
2122 static int
2123 mlxsw_sp_fid_flood_tables_init(struct mlxsw_sp_fid_family *fid_family)
2124 {
2125 	struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
2126 	u16 pgt_size;
2127 	int err;
2128 	int i;
2129 
2130 	err = fid_family->ops->pgt_size(fid_family, &pgt_size);
2131 	if (err)
2132 		return err;
2133 
2134 	err = mlxsw_sp_pgt_mid_alloc_range(mlxsw_sp, &fid_family->pgt_base,
2135 					   pgt_size);
2136 	if (err)
2137 		return err;
2138 
2139 	if (!fid_family->flood_profile)
2140 		return 0;
2141 
2142 	for (i = 0; i < fid_family->flood_profile->nr_flood_tables; i++) {
2143 		const struct mlxsw_sp_flood_table *flood_table;
2144 
2145 		flood_table = &fid_family->flood_profile->flood_tables[i];
2146 		if (fid_family->ops->flood_table_init) {
2147 			err = fid_family->ops->flood_table_init(fid_family,
2148 								flood_table);
2149 			if (err)
2150 				goto err_flood_table_init;
2151 		}
2152 	}
2153 
2154 	return 0;
2155 
2156 err_flood_table_init:
2157 	mlxsw_sp_pgt_mid_free_range(mlxsw_sp, fid_family->pgt_base, pgt_size);
2158 	return err;
2159 }
2160 
2161 static void
2162 mlxsw_sp_fid_flood_tables_fini(struct mlxsw_sp_fid_family *fid_family)
2163 {
2164 	struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
2165 	u16 pgt_size;
2166 	int err;
2167 
2168 	err = fid_family->ops->pgt_size(fid_family, &pgt_size);
2169 	if (WARN_ON_ONCE(err))
2170 		return;
2171 
2172 	mlxsw_sp_pgt_mid_free_range(mlxsw_sp, fid_family->pgt_base, pgt_size);
2173 }
2174 
2175 static int mlxsw_sp_fid_family_register(struct mlxsw_sp *mlxsw_sp,
2176 					const struct mlxsw_sp_fid_family *tmpl)
2177 {
2178 	u16 nr_fids = tmpl->end_index - tmpl->start_index + 1;
2179 	struct mlxsw_sp_fid_family *fid_family;
2180 	int err;
2181 
2182 	fid_family = kmemdup(tmpl, sizeof(*fid_family), GFP_KERNEL);
2183 	if (!fid_family)
2184 		return -ENOMEM;
2185 
2186 	fid_family->mlxsw_sp = mlxsw_sp;
2187 	INIT_LIST_HEAD(&fid_family->fids_list);
2188 	fid_family->fids_bitmap = bitmap_zalloc(nr_fids, GFP_KERNEL);
2189 	if (!fid_family->fids_bitmap) {
2190 		err = -ENOMEM;
2191 		goto err_alloc_fids_bitmap;
2192 	}
2193 
2194 	if (fid_family->flood_profile) {
2195 		err = mlxsw_sp_fid_flood_tables_init(fid_family);
2196 		if (err)
2197 			goto err_fid_flood_tables_init;
2198 	}
2199 
2200 	mlxsw_sp->fid_core->fid_family_arr[tmpl->type] = fid_family;
2201 
2202 	return 0;
2203 
2204 err_fid_flood_tables_init:
2205 	bitmap_free(fid_family->fids_bitmap);
2206 err_alloc_fids_bitmap:
2207 	kfree(fid_family);
2208 	return err;
2209 }
2210 
2211 static void
2212 mlxsw_sp_fid_family_unregister(struct mlxsw_sp *mlxsw_sp,
2213 			       struct mlxsw_sp_fid_family *fid_family)
2214 {
2215 	mlxsw_sp->fid_core->fid_family_arr[fid_family->type] = NULL;
2216 
2217 	if (fid_family->flood_profile)
2218 		mlxsw_sp_fid_flood_tables_fini(fid_family);
2219 
2220 	bitmap_free(fid_family->fids_bitmap);
2221 	WARN_ON_ONCE(!list_empty(&fid_family->fids_list));
2222 	kfree(fid_family);
2223 }
2224 
2225 static int mlxsw_sp_fid_port_init(const struct mlxsw_sp_port *mlxsw_sp_port)
2226 {
2227 	const enum mlxsw_sp_fid_type type_rfid = MLXSW_SP_FID_TYPE_RFID;
2228 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
2229 	struct mlxsw_sp_fid_family *rfid_family;
2230 
2231 	rfid_family = mlxsw_sp->fid_core->fid_family_arr[type_rfid];
2232 	if (rfid_family->ops->fid_port_init)
2233 		return rfid_family->ops->fid_port_init(rfid_family,
2234 						       mlxsw_sp_port);
2235 	return 0;
2236 }
2237 
2238 static void mlxsw_sp_fid_port_fini(const struct mlxsw_sp_port *mlxsw_sp_port)
2239 {
2240 	const enum mlxsw_sp_fid_type type_rfid = MLXSW_SP_FID_TYPE_RFID;
2241 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
2242 	struct mlxsw_sp_fid_family *rfid_family;
2243 
2244 	rfid_family = mlxsw_sp->fid_core->fid_family_arr[type_rfid];
2245 	if (rfid_family->ops->fid_port_fini)
2246 		rfid_family->ops->fid_port_fini(rfid_family, mlxsw_sp_port);
2247 }
2248 
2249 int mlxsw_sp_port_fids_init(struct mlxsw_sp_port *mlxsw_sp_port)
2250 {
2251 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
2252 	int err;
2253 
2254 	/* Track number of FIDs configured on the port with mapping type
2255 	 * PORT_VID_TO_FID, so that we know when to transition the port
2256 	 * back to non-virtual (VLAN) mode.
2257 	 */
2258 	mlxsw_sp->fid_core->port_fid_mappings[mlxsw_sp_port->local_port] = 0;
2259 
2260 	err = mlxsw_sp_fid_port_init(mlxsw_sp_port);
2261 	if (err)
2262 		return err;
2263 
2264 	err = mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, false);
2265 	if (err)
2266 		goto err_vp_mode_set;
2267 
2268 	return 0;
2269 
2270 err_vp_mode_set:
2271 	mlxsw_sp_fid_port_fini(mlxsw_sp_port);
2272 	return err;
2273 }
2274 
2275 void mlxsw_sp_port_fids_fini(struct mlxsw_sp_port *mlxsw_sp_port)
2276 {
2277 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
2278 
2279 	mlxsw_sp_fid_port_fini(mlxsw_sp_port);
2280 	mlxsw_sp->fid_core->port_fid_mappings[mlxsw_sp_port->local_port] = 0;
2281 }
2282 
2283 int mlxsw_sp_fid_port_join_lag(const struct mlxsw_sp_port *mlxsw_sp_port)
2284 {
2285 	return mlxsw_sp_fid_port_init(mlxsw_sp_port);
2286 }
2287 
2288 void mlxsw_sp_fid_port_leave_lag(const struct mlxsw_sp_port *mlxsw_sp_port)
2289 {
2290 	mlxsw_sp_fid_port_fini(mlxsw_sp_port);
2291 }
2292 
2293 static int
2294 mlxsw_sp_fids_init(struct mlxsw_sp *mlxsw_sp,
2295 		   const struct mlxsw_sp_fid_family *fid_family_arr[])
2296 {
2297 	unsigned int max_ports = mlxsw_core_max_ports(mlxsw_sp->core);
2298 	struct mlxsw_sp_fid_core *fid_core;
2299 	int err, i;
2300 
2301 	fid_core = kzalloc_obj(*mlxsw_sp->fid_core);
2302 	if (!fid_core)
2303 		return -ENOMEM;
2304 	mlxsw_sp->fid_core = fid_core;
2305 
2306 	err = rhashtable_init(&fid_core->fid_ht, &mlxsw_sp_fid_ht_params);
2307 	if (err)
2308 		goto err_rhashtable_fid_init;
2309 
2310 	err = rhashtable_init(&fid_core->vni_ht, &mlxsw_sp_fid_vni_ht_params);
2311 	if (err)
2312 		goto err_rhashtable_vni_init;
2313 
2314 	fid_core->port_fid_mappings = kcalloc(max_ports, sizeof(unsigned int),
2315 					      GFP_KERNEL);
2316 	if (!fid_core->port_fid_mappings) {
2317 		err = -ENOMEM;
2318 		goto err_alloc_port_fid_mappings;
2319 	}
2320 
2321 	for (i = 0; i < MLXSW_SP_FID_TYPE_MAX; i++) {
2322 		err = mlxsw_sp_fid_family_register(mlxsw_sp, fid_family_arr[i]);
2323 
2324 		if (err)
2325 			goto err_fid_ops_register;
2326 	}
2327 
2328 	return 0;
2329 
2330 err_fid_ops_register:
2331 	for (i--; i >= 0; i--) {
2332 		struct mlxsw_sp_fid_family *fid_family;
2333 
2334 		fid_family = fid_core->fid_family_arr[i];
2335 		mlxsw_sp_fid_family_unregister(mlxsw_sp, fid_family);
2336 	}
2337 	kfree(fid_core->port_fid_mappings);
2338 err_alloc_port_fid_mappings:
2339 	rhashtable_destroy(&fid_core->vni_ht);
2340 err_rhashtable_vni_init:
2341 	rhashtable_destroy(&fid_core->fid_ht);
2342 err_rhashtable_fid_init:
2343 	kfree(fid_core);
2344 	return err;
2345 }
2346 
2347 static void mlxsw_sp_fids_fini(struct mlxsw_sp *mlxsw_sp)
2348 {
2349 	struct mlxsw_sp_fid_core *fid_core = mlxsw_sp->fid_core;
2350 	int i;
2351 
2352 	for (i = 0; i < MLXSW_SP_FID_TYPE_MAX; i++)
2353 		mlxsw_sp_fid_family_unregister(mlxsw_sp,
2354 					       fid_core->fid_family_arr[i]);
2355 	kfree(fid_core->port_fid_mappings);
2356 	rhashtable_destroy(&fid_core->vni_ht);
2357 	rhashtable_destroy(&fid_core->fid_ht);
2358 	kfree(fid_core);
2359 }
2360 
2361 static int mlxsw_sp1_fids_init(struct mlxsw_sp *mlxsw_sp)
2362 {
2363 	return mlxsw_sp_fids_init(mlxsw_sp, mlxsw_sp1_fid_family_arr);
2364 }
2365 
2366 const struct mlxsw_sp_fid_core_ops mlxsw_sp1_fid_core_ops = {
2367 	.init = mlxsw_sp1_fids_init,
2368 	.fini = mlxsw_sp_fids_fini,
2369 };
2370 
2371 static int mlxsw_sp_fid_check_flood_profile_id(struct mlxsw_sp *mlxsw_sp,
2372 					       int profile_id)
2373 {
2374 	u32 max_profiles;
2375 
2376 	if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_NVE_FLOOD_PRF))
2377 		return -EIO;
2378 
2379 	max_profiles = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_NVE_FLOOD_PRF);
2380 	if (WARN_ON_ONCE(!profile_id) ||
2381 	    WARN_ON_ONCE(profile_id >= max_profiles))
2382 		return -EINVAL;
2383 
2384 	return 0;
2385 }
2386 
2387 static int
2388 mlxsw_sp2_fids_init_flood_table(struct mlxsw_sp *mlxsw_sp,
2389 				enum mlxsw_sp_fid_flood_profile_id profile_id,
2390 				const struct mlxsw_sp_flood_table *flood_table)
2391 {
2392 	enum mlxsw_sp_flood_type packet_type = flood_table->packet_type;
2393 	const int *sfgc_packet_types;
2394 	int err;
2395 	int i;
2396 
2397 	sfgc_packet_types = mlxsw_sp_packet_type_sfgc_types[packet_type];
2398 	for (i = 0; i < MLXSW_REG_SFGC_TYPE_MAX; i++) {
2399 		char sffp_pl[MLXSW_REG_SFFP_LEN];
2400 
2401 		if (!sfgc_packet_types[i])
2402 			continue;
2403 
2404 		mlxsw_reg_sffp_pack(sffp_pl, profile_id, i,
2405 				    flood_table->table_index);
2406 		err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sffp), sffp_pl);
2407 		if (err)
2408 			return err;
2409 	}
2410 
2411 	return 0;
2412 }
2413 
2414 static int
2415 mlxsw_sp2_fids_init_flood_profile(struct mlxsw_sp *mlxsw_sp,
2416 				  const struct mlxsw_sp_fid_flood_profile *
2417 					flood_profile)
2418 {
2419 	int err;
2420 	int i;
2421 
2422 	err = mlxsw_sp_fid_check_flood_profile_id(mlxsw_sp,
2423 						  flood_profile->profile_id);
2424 	if (err)
2425 		return err;
2426 
2427 	for (i = 0; i < flood_profile->nr_flood_tables; i++) {
2428 		const struct mlxsw_sp_flood_table *flood_table;
2429 
2430 		flood_table = &flood_profile->flood_tables[i];
2431 		err = mlxsw_sp2_fids_init_flood_table(mlxsw_sp,
2432 						      flood_profile->profile_id,
2433 						      flood_table);
2434 		if (err)
2435 			return err;
2436 	}
2437 
2438 	return 0;
2439 }
2440 
2441 static const
2442 struct mlxsw_sp_fid_flood_profile *mlxsw_sp_fid_flood_profiles[] = {
2443 	&mlxsw_sp_fid_8021d_flood_profile,
2444 	&mlxsw_sp_fid_rsp_flood_profile_cff,
2445 	&mlxsw_sp_fid_nve_flood_profile_cff,
2446 };
2447 
2448 static int
2449 mlxsw_sp2_fids_init_flood_profiles(struct mlxsw_sp *mlxsw_sp)
2450 {
2451 	int err;
2452 	int i;
2453 
2454 	for (i = 0; i < ARRAY_SIZE(mlxsw_sp_fid_flood_profiles); i++) {
2455 		const struct mlxsw_sp_fid_flood_profile *flood_profile;
2456 
2457 		flood_profile = mlxsw_sp_fid_flood_profiles[i];
2458 		err = mlxsw_sp2_fids_init_flood_profile(mlxsw_sp,
2459 							flood_profile);
2460 		if (err)
2461 			return err;
2462 	}
2463 
2464 	return 0;
2465 }
2466 
2467 static int mlxsw_sp2_fids_init_ctl(struct mlxsw_sp *mlxsw_sp)
2468 {
2469 	return mlxsw_sp_fids_init(mlxsw_sp, mlxsw_sp2_fid_family_arr_ctl);
2470 }
2471 
2472 static int mlxsw_sp2_fids_init_cff(struct mlxsw_sp *mlxsw_sp)
2473 {
2474 	int err;
2475 
2476 	err = mlxsw_sp2_fids_init_flood_profiles(mlxsw_sp);
2477 	if (err)
2478 		return err;
2479 
2480 	return mlxsw_sp_fids_init(mlxsw_sp, mlxsw_sp2_fid_family_arr_cff);
2481 }
2482 
2483 static int mlxsw_sp2_fids_init(struct mlxsw_sp *mlxsw_sp)
2484 {
2485 	switch (mlxsw_core_flood_mode(mlxsw_sp->core)) {
2486 	case MLXSW_CMD_MBOX_CONFIG_PROFILE_FLOOD_MODE_CONTROLLED:
2487 		return mlxsw_sp2_fids_init_ctl(mlxsw_sp);
2488 	case MLXSW_CMD_MBOX_CONFIG_PROFILE_FLOOD_MODE_CFF:
2489 		return mlxsw_sp2_fids_init_cff(mlxsw_sp);
2490 	default:
2491 		WARN_ON_ONCE(1);
2492 		return -EINVAL;
2493 	}
2494 }
2495 
2496 const struct mlxsw_sp_fid_core_ops mlxsw_sp2_fid_core_ops = {
2497 	.init = mlxsw_sp2_fids_init,
2498 	.fini = mlxsw_sp_fids_fini,
2499 };
2500