1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /* Copyright (c) 2017-2018 Mellanox Technologies. All rights reserved */
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>
15 struct mlxsw_sp_fid_family;
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;
25 struct list_head list;
26 struct mlxsw_sp_rif *rif;
27 unsigned int ref_count;
29 struct mlxsw_sp_fid_family *fid_family;
30 struct rhash_head ht_node;
32 struct rhash_head vni_ht_node;
33 enum mlxsw_sp_nve_type nve_type;
38 nve_flood_index_valid:1;
41 struct mlxsw_sp_fid_8021q {
42 struct mlxsw_sp_fid common;
46 struct mlxsw_sp_fid_8021d {
47 struct mlxsw_sp_fid common;
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),
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),
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;
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,
76 bool (*compare)(const struct mlxsw_sp_fid *fid,
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,
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);
92 struct mlxsw_sp_fid_family {
93 enum mlxsw_sp_fid_type type;
97 struct list_head fids_list;
98 unsigned long *fids_bitmap;
99 const struct mlxsw_sp_flood_table *flood_tables;
101 enum mlxsw_sp_rif_type rif_type;
102 const struct mlxsw_sp_fid_ops *ops;
103 struct mlxsw_sp *mlxsw_sp;
107 static const int mlxsw_sp_sfgc_uc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = {
108 [MLXSW_REG_SFGC_TYPE_UNKNOWN_UNICAST] = 1,
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,
119 static const int mlxsw_sp_sfgc_mc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = {
120 [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV4] = 1,
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,
129 bool mlxsw_sp_fid_is_dummy(struct mlxsw_sp *mlxsw_sp, u16 fid_index)
131 enum mlxsw_sp_fid_type fid_type = MLXSW_SP_FID_TYPE_DUMMY;
132 struct mlxsw_sp_fid_family *fid_family;
134 fid_family = mlxsw_sp->fid_core->fid_family_arr[fid_type];
136 return fid_family->start_index == fid_index;
139 bool mlxsw_sp_fid_lag_vid_valid(const struct mlxsw_sp_fid *fid)
141 return fid->fid_family->lag_vid_valid;
144 struct mlxsw_sp_fid *mlxsw_sp_fid_lookup_by_index(struct mlxsw_sp *mlxsw_sp,
147 struct mlxsw_sp_fid *fid;
149 fid = rhashtable_lookup_fast(&mlxsw_sp->fid_core->fid_ht, &fid_index,
150 mlxsw_sp_fid_ht_params);
157 int mlxsw_sp_fid_nve_ifindex(const struct mlxsw_sp_fid *fid, int *nve_ifindex)
162 *nve_ifindex = fid->nve_ifindex;
167 int mlxsw_sp_fid_nve_type(const struct mlxsw_sp_fid *fid,
168 enum mlxsw_sp_nve_type *p_type)
173 *p_type = fid->nve_type;
178 struct mlxsw_sp_fid *mlxsw_sp_fid_lookup_by_vni(struct mlxsw_sp *mlxsw_sp,
181 struct mlxsw_sp_fid *fid;
183 fid = rhashtable_lookup_fast(&mlxsw_sp->fid_core->vni_ht, &vni,
184 mlxsw_sp_fid_vni_ht_params);
191 int mlxsw_sp_fid_vni(const struct mlxsw_sp_fid *fid, __be32 *vni)
201 int mlxsw_sp_fid_nve_flood_index_set(struct mlxsw_sp_fid *fid,
204 struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
205 const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
208 if (WARN_ON(!ops->nve_flood_index_set || fid->nve_flood_index_valid))
211 err = ops->nve_flood_index_set(fid, nve_flood_index);
215 fid->nve_flood_index = nve_flood_index;
216 fid->nve_flood_index_valid = true;
221 void mlxsw_sp_fid_nve_flood_index_clear(struct mlxsw_sp_fid *fid)
223 struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
224 const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
226 if (WARN_ON(!ops->nve_flood_index_clear || !fid->nve_flood_index_valid))
229 fid->nve_flood_index_valid = false;
230 ops->nve_flood_index_clear(fid);
233 bool mlxsw_sp_fid_nve_flood_index_is_set(const struct mlxsw_sp_fid *fid)
235 return fid->nve_flood_index_valid;
238 int mlxsw_sp_fid_vni_set(struct mlxsw_sp_fid *fid, enum mlxsw_sp_nve_type type,
239 __be32 vni, int nve_ifindex)
241 struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
242 const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
243 struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
246 if (WARN_ON(!ops->vni_set || fid->vni_valid))
249 fid->nve_type = type;
250 fid->nve_ifindex = nve_ifindex;
252 err = rhashtable_lookup_insert_fast(&mlxsw_sp->fid_core->vni_ht,
254 mlxsw_sp_fid_vni_ht_params);
258 err = ops->vni_set(fid, vni);
262 fid->vni_valid = true;
267 rhashtable_remove_fast(&mlxsw_sp->fid_core->vni_ht, &fid->vni_ht_node,
268 mlxsw_sp_fid_vni_ht_params);
272 void mlxsw_sp_fid_vni_clear(struct mlxsw_sp_fid *fid)
274 struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
275 const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
276 struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
278 if (WARN_ON(!ops->vni_clear || !fid->vni_valid))
281 fid->vni_valid = false;
283 rhashtable_remove_fast(&mlxsw_sp->fid_core->vni_ht, &fid->vni_ht_node,
284 mlxsw_sp_fid_vni_ht_params);
287 bool mlxsw_sp_fid_vni_is_set(const struct mlxsw_sp_fid *fid)
289 return fid->vni_valid;
292 void mlxsw_sp_fid_fdb_clear_offload(const struct mlxsw_sp_fid *fid,
293 const struct net_device *nve_dev)
295 struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
296 const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
298 if (ops->fdb_clear_offload)
299 ops->fdb_clear_offload(fid, nve_dev);
302 static const struct mlxsw_sp_flood_table *
303 mlxsw_sp_fid_flood_table_lookup(const struct mlxsw_sp_fid *fid,
304 enum mlxsw_sp_flood_type packet_type)
306 struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
309 for (i = 0; i < fid_family->nr_flood_tables; i++) {
310 if (fid_family->flood_tables[i].packet_type != packet_type)
312 return &fid_family->flood_tables[i];
318 int mlxsw_sp_fid_flood_set(struct mlxsw_sp_fid *fid,
319 enum mlxsw_sp_flood_type packet_type, u8 local_port,
322 struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
323 const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
324 const struct mlxsw_sp_flood_table *flood_table;
328 if (WARN_ON(!fid_family->flood_tables || !ops->flood_index))
331 flood_table = mlxsw_sp_fid_flood_table_lookup(fid, packet_type);
335 sftr_pl = kmalloc(MLXSW_REG_SFTR_LEN, GFP_KERNEL);
339 mlxsw_reg_sftr_pack(sftr_pl, flood_table->table_index,
340 ops->flood_index(fid), flood_table->table_type, 1,
342 err = mlxsw_reg_write(fid_family->mlxsw_sp->core, MLXSW_REG(sftr),
348 int mlxsw_sp_fid_port_vid_map(struct mlxsw_sp_fid *fid,
349 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
351 if (WARN_ON(!fid->fid_family->ops->port_vid_map))
353 return fid->fid_family->ops->port_vid_map(fid, mlxsw_sp_port, vid);
356 void mlxsw_sp_fid_port_vid_unmap(struct mlxsw_sp_fid *fid,
357 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
359 fid->fid_family->ops->port_vid_unmap(fid, mlxsw_sp_port, vid);
362 u16 mlxsw_sp_fid_index(const struct mlxsw_sp_fid *fid)
364 return fid->fid_index;
367 enum mlxsw_sp_fid_type mlxsw_sp_fid_type(const struct mlxsw_sp_fid *fid)
369 return fid->fid_family->type;
372 void mlxsw_sp_fid_rif_set(struct mlxsw_sp_fid *fid, struct mlxsw_sp_rif *rif)
377 struct mlxsw_sp_rif *mlxsw_sp_fid_rif(const struct mlxsw_sp_fid *fid)
382 enum mlxsw_sp_rif_type
383 mlxsw_sp_fid_type_rif_type(const struct mlxsw_sp *mlxsw_sp,
384 enum mlxsw_sp_fid_type type)
386 struct mlxsw_sp_fid_core *fid_core = mlxsw_sp->fid_core;
388 return fid_core->fid_family_arr[type]->rif_type;
391 static struct mlxsw_sp_fid_8021q *
392 mlxsw_sp_fid_8021q_fid(const struct mlxsw_sp_fid *fid)
394 return container_of(fid, struct mlxsw_sp_fid_8021q, common);
397 u16 mlxsw_sp_fid_8021q_vid(const struct mlxsw_sp_fid *fid)
399 return mlxsw_sp_fid_8021q_fid(fid)->vid;
402 static void mlxsw_sp_fid_8021q_setup(struct mlxsw_sp_fid *fid, const void *arg)
404 u16 vid = *(u16 *) arg;
406 mlxsw_sp_fid_8021q_fid(fid)->vid = vid;
409 static enum mlxsw_reg_sfmr_op mlxsw_sp_sfmr_op(bool valid)
411 return valid ? MLXSW_REG_SFMR_OP_CREATE_FID :
412 MLXSW_REG_SFMR_OP_DESTROY_FID;
415 static int mlxsw_sp_fid_op(struct mlxsw_sp *mlxsw_sp, u16 fid_index,
416 u16 fid_offset, bool valid)
418 char sfmr_pl[MLXSW_REG_SFMR_LEN];
420 mlxsw_reg_sfmr_pack(sfmr_pl, mlxsw_sp_sfmr_op(valid), fid_index,
422 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl);
425 static int mlxsw_sp_fid_vni_op(struct mlxsw_sp *mlxsw_sp, u16 fid_index,
426 __be32 vni, bool vni_valid, u32 nve_flood_index,
427 bool nve_flood_index_valid)
429 char sfmr_pl[MLXSW_REG_SFMR_LEN];
431 mlxsw_reg_sfmr_pack(sfmr_pl, MLXSW_REG_SFMR_OP_CREATE_FID, fid_index,
433 mlxsw_reg_sfmr_vv_set(sfmr_pl, vni_valid);
434 mlxsw_reg_sfmr_vni_set(sfmr_pl, be32_to_cpu(vni));
435 mlxsw_reg_sfmr_vtfp_set(sfmr_pl, nve_flood_index_valid);
436 mlxsw_reg_sfmr_nve_tunnel_flood_ptr_set(sfmr_pl, nve_flood_index);
437 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl);
440 static int mlxsw_sp_fid_vid_map(struct mlxsw_sp *mlxsw_sp, u16 fid_index,
443 enum mlxsw_reg_svfa_mt mt = MLXSW_REG_SVFA_MT_VID_TO_FID;
444 char svfa_pl[MLXSW_REG_SVFA_LEN];
446 mlxsw_reg_svfa_pack(svfa_pl, 0, mt, valid, fid_index, vid);
447 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl);
450 static int __mlxsw_sp_fid_port_vid_map(struct mlxsw_sp *mlxsw_sp, u16 fid_index,
451 u8 local_port, u16 vid, bool valid)
453 enum mlxsw_reg_svfa_mt mt = MLXSW_REG_SVFA_MT_PORT_VID_TO_FID;
454 char svfa_pl[MLXSW_REG_SVFA_LEN];
456 mlxsw_reg_svfa_pack(svfa_pl, local_port, mt, valid, fid_index, vid);
457 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl);
460 static int mlxsw_sp_fid_8021q_configure(struct mlxsw_sp_fid *fid)
462 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
463 struct mlxsw_sp_fid_8021q *fid_8021q;
466 err = mlxsw_sp_fid_op(mlxsw_sp, fid->fid_index, fid->fid_index, true);
470 fid_8021q = mlxsw_sp_fid_8021q_fid(fid);
471 err = mlxsw_sp_fid_vid_map(mlxsw_sp, fid->fid_index, fid_8021q->vid,
479 mlxsw_sp_fid_op(mlxsw_sp, fid->fid_index, 0, false);
483 static void mlxsw_sp_fid_8021q_deconfigure(struct mlxsw_sp_fid *fid)
485 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
486 struct mlxsw_sp_fid_8021q *fid_8021q;
488 fid_8021q = mlxsw_sp_fid_8021q_fid(fid);
489 mlxsw_sp_fid_vid_map(mlxsw_sp, fid->fid_index, fid_8021q->vid, false);
490 mlxsw_sp_fid_op(mlxsw_sp, fid->fid_index, 0, false);
493 static int mlxsw_sp_fid_8021q_index_alloc(struct mlxsw_sp_fid *fid,
494 const void *arg, u16 *p_fid_index)
496 struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
497 u16 vid = *(u16 *) arg;
499 /* Use 1:1 mapping for simplicity although not a must */
500 if (vid < fid_family->start_index || vid > fid_family->end_index)
508 mlxsw_sp_fid_8021q_compare(const struct mlxsw_sp_fid *fid, const void *arg)
510 u16 vid = *(u16 *) arg;
512 return mlxsw_sp_fid_8021q_fid(fid)->vid == vid;
515 static u16 mlxsw_sp_fid_8021q_flood_index(const struct mlxsw_sp_fid *fid)
517 return fid->fid_index;
520 static int mlxsw_sp_fid_8021q_port_vid_map(struct mlxsw_sp_fid *fid,
521 struct mlxsw_sp_port *mlxsw_sp_port,
524 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
525 u8 local_port = mlxsw_sp_port->local_port;
527 /* In case there are no {Port, VID} => FID mappings on the port,
528 * we can use the global VID => FID mapping we created when the
529 * FID was configured.
531 if (mlxsw_sp->fid_core->port_fid_mappings[local_port] == 0)
533 return __mlxsw_sp_fid_port_vid_map(mlxsw_sp, fid->fid_index, local_port,
538 mlxsw_sp_fid_8021q_port_vid_unmap(struct mlxsw_sp_fid *fid,
539 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
541 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
542 u8 local_port = mlxsw_sp_port->local_port;
544 if (mlxsw_sp->fid_core->port_fid_mappings[local_port] == 0)
546 __mlxsw_sp_fid_port_vid_map(mlxsw_sp, fid->fid_index, local_port, vid,
550 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021q_ops = {
551 .setup = mlxsw_sp_fid_8021q_setup,
552 .configure = mlxsw_sp_fid_8021q_configure,
553 .deconfigure = mlxsw_sp_fid_8021q_deconfigure,
554 .index_alloc = mlxsw_sp_fid_8021q_index_alloc,
555 .compare = mlxsw_sp_fid_8021q_compare,
556 .flood_index = mlxsw_sp_fid_8021q_flood_index,
557 .port_vid_map = mlxsw_sp_fid_8021q_port_vid_map,
558 .port_vid_unmap = mlxsw_sp_fid_8021q_port_vid_unmap,
561 static const struct mlxsw_sp_flood_table mlxsw_sp_fid_8021q_flood_tables[] = {
563 .packet_type = MLXSW_SP_FLOOD_TYPE_UC,
564 .bridge_type = MLXSW_REG_SFGC_BRIDGE_TYPE_1Q_FID,
565 .table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFSET,
569 .packet_type = MLXSW_SP_FLOOD_TYPE_MC,
570 .bridge_type = MLXSW_REG_SFGC_BRIDGE_TYPE_1Q_FID,
571 .table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFSET,
575 .packet_type = MLXSW_SP_FLOOD_TYPE_BC,
576 .bridge_type = MLXSW_REG_SFGC_BRIDGE_TYPE_1Q_FID,
577 .table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFSET,
582 /* Range and flood configuration must match mlxsw_config_profile */
583 static const struct mlxsw_sp_fid_family mlxsw_sp_fid_8021q_family = {
584 .type = MLXSW_SP_FID_TYPE_8021Q,
585 .fid_size = sizeof(struct mlxsw_sp_fid_8021q),
587 .end_index = VLAN_VID_MASK,
588 .flood_tables = mlxsw_sp_fid_8021q_flood_tables,
589 .nr_flood_tables = ARRAY_SIZE(mlxsw_sp_fid_8021q_flood_tables),
590 .rif_type = MLXSW_SP_RIF_TYPE_VLAN,
591 .ops = &mlxsw_sp_fid_8021q_ops,
594 static struct mlxsw_sp_fid_8021d *
595 mlxsw_sp_fid_8021d_fid(const struct mlxsw_sp_fid *fid)
597 return container_of(fid, struct mlxsw_sp_fid_8021d, common);
600 static void mlxsw_sp_fid_8021d_setup(struct mlxsw_sp_fid *fid, const void *arg)
602 int br_ifindex = *(int *) arg;
604 mlxsw_sp_fid_8021d_fid(fid)->br_ifindex = br_ifindex;
607 static int mlxsw_sp_fid_8021d_configure(struct mlxsw_sp_fid *fid)
609 struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
611 return mlxsw_sp_fid_op(fid_family->mlxsw_sp, fid->fid_index, 0, true);
614 static void mlxsw_sp_fid_8021d_deconfigure(struct mlxsw_sp_fid *fid)
617 mlxsw_sp_nve_fid_disable(fid->fid_family->mlxsw_sp, fid);
618 mlxsw_sp_fid_op(fid->fid_family->mlxsw_sp, fid->fid_index, 0, false);
621 static int mlxsw_sp_fid_8021d_index_alloc(struct mlxsw_sp_fid *fid,
622 const void *arg, u16 *p_fid_index)
624 struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
625 u16 nr_fids, fid_index;
627 nr_fids = fid_family->end_index - fid_family->start_index + 1;
628 fid_index = find_first_zero_bit(fid_family->fids_bitmap, nr_fids);
629 if (fid_index == nr_fids)
631 *p_fid_index = fid_family->start_index + fid_index;
637 mlxsw_sp_fid_8021d_compare(const struct mlxsw_sp_fid *fid, const void *arg)
639 int br_ifindex = *(int *) arg;
641 return mlxsw_sp_fid_8021d_fid(fid)->br_ifindex == br_ifindex;
644 static u16 mlxsw_sp_fid_8021d_flood_index(const struct mlxsw_sp_fid *fid)
646 return fid->fid_index - VLAN_N_VID;
649 static int mlxsw_sp_port_vp_mode_trans(struct mlxsw_sp_port *mlxsw_sp_port)
651 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
652 struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
655 list_for_each_entry(mlxsw_sp_port_vlan, &mlxsw_sp_port->vlans_list,
657 struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid;
658 u16 vid = mlxsw_sp_port_vlan->vid;
663 err = __mlxsw_sp_fid_port_vid_map(mlxsw_sp, fid->fid_index,
664 mlxsw_sp_port->local_port,
667 goto err_fid_port_vid_map;
670 err = mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, true);
672 goto err_port_vp_mode_set;
676 err_port_vp_mode_set:
677 err_fid_port_vid_map:
678 list_for_each_entry_continue_reverse(mlxsw_sp_port_vlan,
679 &mlxsw_sp_port->vlans_list, list) {
680 struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid;
681 u16 vid = mlxsw_sp_port_vlan->vid;
686 __mlxsw_sp_fid_port_vid_map(mlxsw_sp, fid->fid_index,
687 mlxsw_sp_port->local_port, vid,
693 static void mlxsw_sp_port_vlan_mode_trans(struct mlxsw_sp_port *mlxsw_sp_port)
695 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
696 struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
698 mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, false);
700 list_for_each_entry_reverse(mlxsw_sp_port_vlan,
701 &mlxsw_sp_port->vlans_list, list) {
702 struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid;
703 u16 vid = mlxsw_sp_port_vlan->vid;
708 __mlxsw_sp_fid_port_vid_map(mlxsw_sp, fid->fid_index,
709 mlxsw_sp_port->local_port, vid,
714 static int mlxsw_sp_fid_8021d_port_vid_map(struct mlxsw_sp_fid *fid,
715 struct mlxsw_sp_port *mlxsw_sp_port,
718 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
719 u8 local_port = mlxsw_sp_port->local_port;
722 err = __mlxsw_sp_fid_port_vid_map(mlxsw_sp, fid->fid_index,
723 mlxsw_sp_port->local_port, vid, true);
727 if (mlxsw_sp->fid_core->port_fid_mappings[local_port]++ == 0) {
728 err = mlxsw_sp_port_vp_mode_trans(mlxsw_sp_port);
730 goto err_port_vp_mode_trans;
735 err_port_vp_mode_trans:
736 mlxsw_sp->fid_core->port_fid_mappings[local_port]--;
737 __mlxsw_sp_fid_port_vid_map(mlxsw_sp, fid->fid_index,
738 mlxsw_sp_port->local_port, vid, false);
743 mlxsw_sp_fid_8021d_port_vid_unmap(struct mlxsw_sp_fid *fid,
744 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
746 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
747 u8 local_port = mlxsw_sp_port->local_port;
749 if (mlxsw_sp->fid_core->port_fid_mappings[local_port] == 1)
750 mlxsw_sp_port_vlan_mode_trans(mlxsw_sp_port);
751 mlxsw_sp->fid_core->port_fid_mappings[local_port]--;
752 __mlxsw_sp_fid_port_vid_map(mlxsw_sp, fid->fid_index,
753 mlxsw_sp_port->local_port, vid, false);
756 static int mlxsw_sp_fid_8021d_vni_set(struct mlxsw_sp_fid *fid, __be32 vni)
758 struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
760 return mlxsw_sp_fid_vni_op(fid_family->mlxsw_sp, fid->fid_index, vni,
761 true, fid->nve_flood_index,
762 fid->nve_flood_index_valid);
765 static void mlxsw_sp_fid_8021d_vni_clear(struct mlxsw_sp_fid *fid)
767 struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
769 mlxsw_sp_fid_vni_op(fid_family->mlxsw_sp, fid->fid_index, 0, false,
770 fid->nve_flood_index, fid->nve_flood_index_valid);
773 static int mlxsw_sp_fid_8021d_nve_flood_index_set(struct mlxsw_sp_fid *fid,
776 struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
778 return mlxsw_sp_fid_vni_op(fid_family->mlxsw_sp, fid->fid_index,
779 fid->vni, fid->vni_valid, nve_flood_index,
783 static void mlxsw_sp_fid_8021d_nve_flood_index_clear(struct mlxsw_sp_fid *fid)
785 struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
787 mlxsw_sp_fid_vni_op(fid_family->mlxsw_sp, fid->fid_index, fid->vni,
788 fid->vni_valid, 0, false);
792 mlxsw_sp_fid_8021d_fdb_clear_offload(const struct mlxsw_sp_fid *fid,
793 const struct net_device *nve_dev)
795 br_fdb_clear_offload(nve_dev, 0);
798 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021d_ops = {
799 .setup = mlxsw_sp_fid_8021d_setup,
800 .configure = mlxsw_sp_fid_8021d_configure,
801 .deconfigure = mlxsw_sp_fid_8021d_deconfigure,
802 .index_alloc = mlxsw_sp_fid_8021d_index_alloc,
803 .compare = mlxsw_sp_fid_8021d_compare,
804 .flood_index = mlxsw_sp_fid_8021d_flood_index,
805 .port_vid_map = mlxsw_sp_fid_8021d_port_vid_map,
806 .port_vid_unmap = mlxsw_sp_fid_8021d_port_vid_unmap,
807 .vni_set = mlxsw_sp_fid_8021d_vni_set,
808 .vni_clear = mlxsw_sp_fid_8021d_vni_clear,
809 .nve_flood_index_set = mlxsw_sp_fid_8021d_nve_flood_index_set,
810 .nve_flood_index_clear = mlxsw_sp_fid_8021d_nve_flood_index_clear,
811 .fdb_clear_offload = mlxsw_sp_fid_8021d_fdb_clear_offload,
814 static const struct mlxsw_sp_flood_table mlxsw_sp_fid_8021d_flood_tables[] = {
816 .packet_type = MLXSW_SP_FLOOD_TYPE_UC,
817 .bridge_type = MLXSW_REG_SFGC_BRIDGE_TYPE_VFID,
818 .table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID,
822 .packet_type = MLXSW_SP_FLOOD_TYPE_MC,
823 .bridge_type = MLXSW_REG_SFGC_BRIDGE_TYPE_VFID,
824 .table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID,
828 .packet_type = MLXSW_SP_FLOOD_TYPE_BC,
829 .bridge_type = MLXSW_REG_SFGC_BRIDGE_TYPE_VFID,
830 .table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID,
835 /* Range and flood configuration must match mlxsw_config_profile */
836 static const struct mlxsw_sp_fid_family mlxsw_sp_fid_8021d_family = {
837 .type = MLXSW_SP_FID_TYPE_8021D,
838 .fid_size = sizeof(struct mlxsw_sp_fid_8021d),
839 .start_index = VLAN_N_VID,
840 .end_index = VLAN_N_VID + MLXSW_SP_FID_8021D_MAX - 1,
841 .flood_tables = mlxsw_sp_fid_8021d_flood_tables,
842 .nr_flood_tables = ARRAY_SIZE(mlxsw_sp_fid_8021d_flood_tables),
843 .rif_type = MLXSW_SP_RIF_TYPE_FID,
844 .ops = &mlxsw_sp_fid_8021d_ops,
849 mlxsw_sp_fid_8021q_fdb_clear_offload(const struct mlxsw_sp_fid *fid,
850 const struct net_device *nve_dev)
852 br_fdb_clear_offload(nve_dev, mlxsw_sp_fid_8021q_vid(fid));
855 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021q_emu_ops = {
856 .setup = mlxsw_sp_fid_8021q_setup,
857 .configure = mlxsw_sp_fid_8021d_configure,
858 .deconfigure = mlxsw_sp_fid_8021d_deconfigure,
859 .index_alloc = mlxsw_sp_fid_8021d_index_alloc,
860 .compare = mlxsw_sp_fid_8021q_compare,
861 .flood_index = mlxsw_sp_fid_8021d_flood_index,
862 .port_vid_map = mlxsw_sp_fid_8021d_port_vid_map,
863 .port_vid_unmap = mlxsw_sp_fid_8021d_port_vid_unmap,
864 .vni_set = mlxsw_sp_fid_8021d_vni_set,
865 .vni_clear = mlxsw_sp_fid_8021d_vni_clear,
866 .nve_flood_index_set = mlxsw_sp_fid_8021d_nve_flood_index_set,
867 .nve_flood_index_clear = mlxsw_sp_fid_8021d_nve_flood_index_clear,
868 .fdb_clear_offload = mlxsw_sp_fid_8021q_fdb_clear_offload,
871 /* There are 4K-2 emulated 802.1Q FIDs, starting right after the 802.1D FIDs */
872 #define MLXSW_SP_FID_8021Q_EMU_START (VLAN_N_VID + MLXSW_SP_FID_8021D_MAX)
873 #define MLXSW_SP_FID_8021Q_EMU_END (MLXSW_SP_FID_8021Q_EMU_START + \
876 /* Range and flood configuration must match mlxsw_config_profile */
877 static const struct mlxsw_sp_fid_family mlxsw_sp_fid_8021q_emu_family = {
878 .type = MLXSW_SP_FID_TYPE_8021Q,
879 .fid_size = sizeof(struct mlxsw_sp_fid_8021q),
880 .start_index = MLXSW_SP_FID_8021Q_EMU_START,
881 .end_index = MLXSW_SP_FID_8021Q_EMU_END,
882 .flood_tables = mlxsw_sp_fid_8021d_flood_tables,
883 .nr_flood_tables = ARRAY_SIZE(mlxsw_sp_fid_8021d_flood_tables),
884 .rif_type = MLXSW_SP_RIF_TYPE_VLAN,
885 .ops = &mlxsw_sp_fid_8021q_emu_ops,
889 static int mlxsw_sp_fid_rfid_configure(struct mlxsw_sp_fid *fid)
891 /* rFIDs are allocated by the device during init */
895 static void mlxsw_sp_fid_rfid_deconfigure(struct mlxsw_sp_fid *fid)
899 static int mlxsw_sp_fid_rfid_index_alloc(struct mlxsw_sp_fid *fid,
900 const void *arg, u16 *p_fid_index)
902 u16 rif_index = *(u16 *) arg;
904 *p_fid_index = fid->fid_family->start_index + rif_index;
909 static bool mlxsw_sp_fid_rfid_compare(const struct mlxsw_sp_fid *fid,
912 u16 rif_index = *(u16 *) arg;
914 return fid->fid_index == rif_index + fid->fid_family->start_index;
917 static int mlxsw_sp_fid_rfid_port_vid_map(struct mlxsw_sp_fid *fid,
918 struct mlxsw_sp_port *mlxsw_sp_port,
921 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
922 u8 local_port = mlxsw_sp_port->local_port;
925 /* We only need to transition the port to virtual mode since
926 * {Port, VID} => FID is done by the firmware upon RIF creation.
928 if (mlxsw_sp->fid_core->port_fid_mappings[local_port]++ == 0) {
929 err = mlxsw_sp_port_vp_mode_trans(mlxsw_sp_port);
931 goto err_port_vp_mode_trans;
936 err_port_vp_mode_trans:
937 mlxsw_sp->fid_core->port_fid_mappings[local_port]--;
942 mlxsw_sp_fid_rfid_port_vid_unmap(struct mlxsw_sp_fid *fid,
943 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
945 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
946 u8 local_port = mlxsw_sp_port->local_port;
948 if (mlxsw_sp->fid_core->port_fid_mappings[local_port] == 1)
949 mlxsw_sp_port_vlan_mode_trans(mlxsw_sp_port);
950 mlxsw_sp->fid_core->port_fid_mappings[local_port]--;
953 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_rfid_ops = {
954 .configure = mlxsw_sp_fid_rfid_configure,
955 .deconfigure = mlxsw_sp_fid_rfid_deconfigure,
956 .index_alloc = mlxsw_sp_fid_rfid_index_alloc,
957 .compare = mlxsw_sp_fid_rfid_compare,
958 .port_vid_map = mlxsw_sp_fid_rfid_port_vid_map,
959 .port_vid_unmap = mlxsw_sp_fid_rfid_port_vid_unmap,
962 #define MLXSW_SP_RFID_BASE (15 * 1024)
963 #define MLXSW_SP_RFID_MAX 1024
965 static const struct mlxsw_sp_fid_family mlxsw_sp_fid_rfid_family = {
966 .type = MLXSW_SP_FID_TYPE_RFID,
967 .fid_size = sizeof(struct mlxsw_sp_fid),
968 .start_index = MLXSW_SP_RFID_BASE,
969 .end_index = MLXSW_SP_RFID_BASE + MLXSW_SP_RFID_MAX - 1,
970 .rif_type = MLXSW_SP_RIF_TYPE_SUBPORT,
971 .ops = &mlxsw_sp_fid_rfid_ops,
974 static int mlxsw_sp_fid_dummy_configure(struct mlxsw_sp_fid *fid)
976 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
978 return mlxsw_sp_fid_op(mlxsw_sp, fid->fid_index, 0, true);
981 static void mlxsw_sp_fid_dummy_deconfigure(struct mlxsw_sp_fid *fid)
983 mlxsw_sp_fid_op(fid->fid_family->mlxsw_sp, fid->fid_index, 0, false);
986 static int mlxsw_sp_fid_dummy_index_alloc(struct mlxsw_sp_fid *fid,
987 const void *arg, u16 *p_fid_index)
989 *p_fid_index = fid->fid_family->start_index;
994 static bool mlxsw_sp_fid_dummy_compare(const struct mlxsw_sp_fid *fid,
1000 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_dummy_ops = {
1001 .configure = mlxsw_sp_fid_dummy_configure,
1002 .deconfigure = mlxsw_sp_fid_dummy_deconfigure,
1003 .index_alloc = mlxsw_sp_fid_dummy_index_alloc,
1004 .compare = mlxsw_sp_fid_dummy_compare,
1007 static const struct mlxsw_sp_fid_family mlxsw_sp_fid_dummy_family = {
1008 .type = MLXSW_SP_FID_TYPE_DUMMY,
1009 .fid_size = sizeof(struct mlxsw_sp_fid),
1010 .start_index = VLAN_N_VID - 1,
1011 .end_index = VLAN_N_VID - 1,
1012 .ops = &mlxsw_sp_fid_dummy_ops,
1015 static const struct mlxsw_sp_fid_family *mlxsw_sp_fid_family_arr[] = {
1016 [MLXSW_SP_FID_TYPE_8021Q] = &mlxsw_sp_fid_8021q_emu_family,
1017 [MLXSW_SP_FID_TYPE_8021D] = &mlxsw_sp_fid_8021d_family,
1018 [MLXSW_SP_FID_TYPE_RFID] = &mlxsw_sp_fid_rfid_family,
1019 [MLXSW_SP_FID_TYPE_DUMMY] = &mlxsw_sp_fid_dummy_family,
1022 static struct mlxsw_sp_fid *mlxsw_sp_fid_lookup(struct mlxsw_sp *mlxsw_sp,
1023 enum mlxsw_sp_fid_type type,
1026 struct mlxsw_sp_fid_family *fid_family;
1027 struct mlxsw_sp_fid *fid;
1029 fid_family = mlxsw_sp->fid_core->fid_family_arr[type];
1030 list_for_each_entry(fid, &fid_family->fids_list, list) {
1031 if (!fid->fid_family->ops->compare(fid, arg))
1040 static struct mlxsw_sp_fid *mlxsw_sp_fid_get(struct mlxsw_sp *mlxsw_sp,
1041 enum mlxsw_sp_fid_type type,
1044 struct mlxsw_sp_fid_family *fid_family;
1045 struct mlxsw_sp_fid *fid;
1049 fid = mlxsw_sp_fid_lookup(mlxsw_sp, type, arg);
1053 fid_family = mlxsw_sp->fid_core->fid_family_arr[type];
1054 fid = kzalloc(fid_family->fid_size, GFP_KERNEL);
1056 return ERR_PTR(-ENOMEM);
1057 fid->fid_family = fid_family;
1059 err = fid->fid_family->ops->index_alloc(fid, arg, &fid_index);
1061 goto err_index_alloc;
1062 fid->fid_index = fid_index;
1063 __set_bit(fid_index - fid_family->start_index, fid_family->fids_bitmap);
1065 if (fid->fid_family->ops->setup)
1066 fid->fid_family->ops->setup(fid, arg);
1068 err = fid->fid_family->ops->configure(fid);
1072 err = rhashtable_insert_fast(&mlxsw_sp->fid_core->fid_ht, &fid->ht_node,
1073 mlxsw_sp_fid_ht_params);
1075 goto err_rhashtable_insert;
1077 list_add(&fid->list, &fid_family->fids_list);
1081 err_rhashtable_insert:
1082 fid->fid_family->ops->deconfigure(fid);
1084 __clear_bit(fid_index - fid_family->start_index,
1085 fid_family->fids_bitmap);
1088 return ERR_PTR(err);
1091 void mlxsw_sp_fid_put(struct mlxsw_sp_fid *fid)
1093 struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
1094 struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
1096 if (--fid->ref_count != 0)
1099 list_del(&fid->list);
1100 rhashtable_remove_fast(&mlxsw_sp->fid_core->fid_ht,
1101 &fid->ht_node, mlxsw_sp_fid_ht_params);
1102 fid->fid_family->ops->deconfigure(fid);
1103 __clear_bit(fid->fid_index - fid_family->start_index,
1104 fid_family->fids_bitmap);
1108 struct mlxsw_sp_fid *mlxsw_sp_fid_8021q_get(struct mlxsw_sp *mlxsw_sp, u16 vid)
1110 return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_8021Q, &vid);
1113 struct mlxsw_sp_fid *mlxsw_sp_fid_8021d_get(struct mlxsw_sp *mlxsw_sp,
1116 return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_8021D, &br_ifindex);
1119 struct mlxsw_sp_fid *mlxsw_sp_fid_8021q_lookup(struct mlxsw_sp *mlxsw_sp,
1122 return mlxsw_sp_fid_lookup(mlxsw_sp, MLXSW_SP_FID_TYPE_8021Q, &vid);
1125 struct mlxsw_sp_fid *mlxsw_sp_fid_8021d_lookup(struct mlxsw_sp *mlxsw_sp,
1128 return mlxsw_sp_fid_lookup(mlxsw_sp, MLXSW_SP_FID_TYPE_8021D,
1132 struct mlxsw_sp_fid *mlxsw_sp_fid_rfid_get(struct mlxsw_sp *mlxsw_sp,
1135 return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_RFID, &rif_index);
1138 struct mlxsw_sp_fid *mlxsw_sp_fid_dummy_get(struct mlxsw_sp *mlxsw_sp)
1140 return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_DUMMY, NULL);
1144 mlxsw_sp_fid_flood_table_init(struct mlxsw_sp_fid_family *fid_family,
1145 const struct mlxsw_sp_flood_table *flood_table)
1147 enum mlxsw_sp_flood_type packet_type = flood_table->packet_type;
1148 const int *sfgc_packet_types;
1151 sfgc_packet_types = mlxsw_sp_packet_type_sfgc_types[packet_type];
1152 for (i = 0; i < MLXSW_REG_SFGC_TYPE_MAX; i++) {
1153 struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
1154 char sfgc_pl[MLXSW_REG_SFGC_LEN];
1157 if (!sfgc_packet_types[i])
1159 mlxsw_reg_sfgc_pack(sfgc_pl, i, flood_table->bridge_type,
1160 flood_table->table_type,
1161 flood_table->table_index);
1162 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfgc), sfgc_pl);
1171 mlxsw_sp_fid_flood_tables_init(struct mlxsw_sp_fid_family *fid_family)
1175 for (i = 0; i < fid_family->nr_flood_tables; i++) {
1176 const struct mlxsw_sp_flood_table *flood_table;
1179 flood_table = &fid_family->flood_tables[i];
1180 err = mlxsw_sp_fid_flood_table_init(fid_family, flood_table);
1188 static int mlxsw_sp_fid_family_register(struct mlxsw_sp *mlxsw_sp,
1189 const struct mlxsw_sp_fid_family *tmpl)
1191 u16 nr_fids = tmpl->end_index - tmpl->start_index + 1;
1192 struct mlxsw_sp_fid_family *fid_family;
1195 fid_family = kmemdup(tmpl, sizeof(*fid_family), GFP_KERNEL);
1199 fid_family->mlxsw_sp = mlxsw_sp;
1200 INIT_LIST_HEAD(&fid_family->fids_list);
1201 fid_family->fids_bitmap = bitmap_zalloc(nr_fids, GFP_KERNEL);
1202 if (!fid_family->fids_bitmap) {
1204 goto err_alloc_fids_bitmap;
1207 if (fid_family->flood_tables) {
1208 err = mlxsw_sp_fid_flood_tables_init(fid_family);
1210 goto err_fid_flood_tables_init;
1213 mlxsw_sp->fid_core->fid_family_arr[tmpl->type] = fid_family;
1217 err_fid_flood_tables_init:
1218 bitmap_free(fid_family->fids_bitmap);
1219 err_alloc_fids_bitmap:
1225 mlxsw_sp_fid_family_unregister(struct mlxsw_sp *mlxsw_sp,
1226 struct mlxsw_sp_fid_family *fid_family)
1228 mlxsw_sp->fid_core->fid_family_arr[fid_family->type] = NULL;
1229 bitmap_free(fid_family->fids_bitmap);
1230 WARN_ON_ONCE(!list_empty(&fid_family->fids_list));
1234 int mlxsw_sp_port_fids_init(struct mlxsw_sp_port *mlxsw_sp_port)
1236 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1238 /* Track number of FIDs configured on the port with mapping type
1239 * PORT_VID_TO_FID, so that we know when to transition the port
1240 * back to non-virtual (VLAN) mode.
1242 mlxsw_sp->fid_core->port_fid_mappings[mlxsw_sp_port->local_port] = 0;
1244 return mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, false);
1247 void mlxsw_sp_port_fids_fini(struct mlxsw_sp_port *mlxsw_sp_port)
1249 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1251 mlxsw_sp->fid_core->port_fid_mappings[mlxsw_sp_port->local_port] = 0;
1254 int mlxsw_sp_fids_init(struct mlxsw_sp *mlxsw_sp)
1256 unsigned int max_ports = mlxsw_core_max_ports(mlxsw_sp->core);
1257 struct mlxsw_sp_fid_core *fid_core;
1260 fid_core = kzalloc(sizeof(*mlxsw_sp->fid_core), GFP_KERNEL);
1263 mlxsw_sp->fid_core = fid_core;
1265 err = rhashtable_init(&fid_core->fid_ht, &mlxsw_sp_fid_ht_params);
1267 goto err_rhashtable_fid_init;
1269 err = rhashtable_init(&fid_core->vni_ht, &mlxsw_sp_fid_vni_ht_params);
1271 goto err_rhashtable_vni_init;
1273 fid_core->port_fid_mappings = kcalloc(max_ports, sizeof(unsigned int),
1275 if (!fid_core->port_fid_mappings) {
1277 goto err_alloc_port_fid_mappings;
1280 for (i = 0; i < MLXSW_SP_FID_TYPE_MAX; i++) {
1281 err = mlxsw_sp_fid_family_register(mlxsw_sp,
1282 mlxsw_sp_fid_family_arr[i]);
1285 goto err_fid_ops_register;
1290 err_fid_ops_register:
1291 for (i--; i >= 0; i--) {
1292 struct mlxsw_sp_fid_family *fid_family;
1294 fid_family = fid_core->fid_family_arr[i];
1295 mlxsw_sp_fid_family_unregister(mlxsw_sp, fid_family);
1297 kfree(fid_core->port_fid_mappings);
1298 err_alloc_port_fid_mappings:
1299 rhashtable_destroy(&fid_core->vni_ht);
1300 err_rhashtable_vni_init:
1301 rhashtable_destroy(&fid_core->fid_ht);
1302 err_rhashtable_fid_init:
1307 void mlxsw_sp_fids_fini(struct mlxsw_sp *mlxsw_sp)
1309 struct mlxsw_sp_fid_core *fid_core = mlxsw_sp->fid_core;
1312 for (i = 0; i < MLXSW_SP_FID_TYPE_MAX; i++)
1313 mlxsw_sp_fid_family_unregister(mlxsw_sp,
1314 fid_core->fid_family_arr[i]);
1315 kfree(fid_core->port_fid_mappings);
1316 rhashtable_destroy(&fid_core->vni_ht);
1317 rhashtable_destroy(&fid_core->fid_ht);