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