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_lag_vid_valid(const struct mlxsw_sp_fid *fid)
131 return fid->fid_family->lag_vid_valid;
134 struct mlxsw_sp_fid *mlxsw_sp_fid_lookup_by_index(struct mlxsw_sp *mlxsw_sp,
137 struct mlxsw_sp_fid *fid;
139 fid = rhashtable_lookup_fast(&mlxsw_sp->fid_core->fid_ht, &fid_index,
140 mlxsw_sp_fid_ht_params);
147 int mlxsw_sp_fid_nve_ifindex(const struct mlxsw_sp_fid *fid, int *nve_ifindex)
152 *nve_ifindex = fid->nve_ifindex;
157 int mlxsw_sp_fid_nve_type(const struct mlxsw_sp_fid *fid,
158 enum mlxsw_sp_nve_type *p_type)
163 *p_type = fid->nve_type;
168 struct mlxsw_sp_fid *mlxsw_sp_fid_lookup_by_vni(struct mlxsw_sp *mlxsw_sp,
171 struct mlxsw_sp_fid *fid;
173 fid = rhashtable_lookup_fast(&mlxsw_sp->fid_core->vni_ht, &vni,
174 mlxsw_sp_fid_vni_ht_params);
181 int mlxsw_sp_fid_vni(const struct mlxsw_sp_fid *fid, __be32 *vni)
191 int mlxsw_sp_fid_nve_flood_index_set(struct mlxsw_sp_fid *fid,
194 struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
195 const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
198 if (WARN_ON(!ops->nve_flood_index_set || fid->nve_flood_index_valid))
201 err = ops->nve_flood_index_set(fid, nve_flood_index);
205 fid->nve_flood_index = nve_flood_index;
206 fid->nve_flood_index_valid = true;
211 void mlxsw_sp_fid_nve_flood_index_clear(struct mlxsw_sp_fid *fid)
213 struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
214 const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
216 if (WARN_ON(!ops->nve_flood_index_clear || !fid->nve_flood_index_valid))
219 fid->nve_flood_index_valid = false;
220 ops->nve_flood_index_clear(fid);
223 bool mlxsw_sp_fid_nve_flood_index_is_set(const struct mlxsw_sp_fid *fid)
225 return fid->nve_flood_index_valid;
228 int mlxsw_sp_fid_vni_set(struct mlxsw_sp_fid *fid, enum mlxsw_sp_nve_type type,
229 __be32 vni, int nve_ifindex)
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;
236 if (WARN_ON(!ops->vni_set || fid->vni_valid))
239 fid->nve_type = type;
240 fid->nve_ifindex = nve_ifindex;
242 err = rhashtable_lookup_insert_fast(&mlxsw_sp->fid_core->vni_ht,
244 mlxsw_sp_fid_vni_ht_params);
248 err = ops->vni_set(fid, vni);
252 fid->vni_valid = true;
257 rhashtable_remove_fast(&mlxsw_sp->fid_core->vni_ht, &fid->vni_ht_node,
258 mlxsw_sp_fid_vni_ht_params);
262 void mlxsw_sp_fid_vni_clear(struct mlxsw_sp_fid *fid)
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;
268 if (WARN_ON(!ops->vni_clear || !fid->vni_valid))
271 fid->vni_valid = false;
273 rhashtable_remove_fast(&mlxsw_sp->fid_core->vni_ht, &fid->vni_ht_node,
274 mlxsw_sp_fid_vni_ht_params);
277 bool mlxsw_sp_fid_vni_is_set(const struct mlxsw_sp_fid *fid)
279 return fid->vni_valid;
282 void mlxsw_sp_fid_fdb_clear_offload(const struct mlxsw_sp_fid *fid,
283 const struct net_device *nve_dev)
285 struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
286 const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
288 if (ops->fdb_clear_offload)
289 ops->fdb_clear_offload(fid, nve_dev);
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)
296 struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
299 for (i = 0; i < fid_family->nr_flood_tables; i++) {
300 if (fid_family->flood_tables[i].packet_type != packet_type)
302 return &fid_family->flood_tables[i];
308 int mlxsw_sp_fid_flood_set(struct mlxsw_sp_fid *fid,
309 enum mlxsw_sp_flood_type packet_type, u8 local_port,
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;
318 if (WARN_ON(!fid_family->flood_tables || !ops->flood_index))
321 flood_table = mlxsw_sp_fid_flood_table_lookup(fid, packet_type);
325 sftr_pl = kmalloc(MLXSW_REG_SFTR_LEN, GFP_KERNEL);
329 mlxsw_reg_sftr_pack(sftr_pl, flood_table->table_index,
330 ops->flood_index(fid), flood_table->table_type, 1,
332 err = mlxsw_reg_write(fid_family->mlxsw_sp->core, MLXSW_REG(sftr),
338 int mlxsw_sp_fid_port_vid_map(struct mlxsw_sp_fid *fid,
339 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
341 if (WARN_ON(!fid->fid_family->ops->port_vid_map))
343 return fid->fid_family->ops->port_vid_map(fid, mlxsw_sp_port, vid);
346 void mlxsw_sp_fid_port_vid_unmap(struct mlxsw_sp_fid *fid,
347 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
349 fid->fid_family->ops->port_vid_unmap(fid, mlxsw_sp_port, vid);
352 u16 mlxsw_sp_fid_index(const struct mlxsw_sp_fid *fid)
354 return fid->fid_index;
357 enum mlxsw_sp_fid_type mlxsw_sp_fid_type(const struct mlxsw_sp_fid *fid)
359 return fid->fid_family->type;
362 void mlxsw_sp_fid_rif_set(struct mlxsw_sp_fid *fid, struct mlxsw_sp_rif *rif)
367 struct mlxsw_sp_rif *mlxsw_sp_fid_rif(const struct mlxsw_sp_fid *fid)
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)
376 struct mlxsw_sp_fid_core *fid_core = mlxsw_sp->fid_core;
378 return fid_core->fid_family_arr[type]->rif_type;
381 static struct mlxsw_sp_fid_8021q *
382 mlxsw_sp_fid_8021q_fid(const struct mlxsw_sp_fid *fid)
384 return container_of(fid, struct mlxsw_sp_fid_8021q, common);
387 u16 mlxsw_sp_fid_8021q_vid(const struct mlxsw_sp_fid *fid)
389 return mlxsw_sp_fid_8021q_fid(fid)->vid;
392 static void mlxsw_sp_fid_8021q_setup(struct mlxsw_sp_fid *fid, const void *arg)
394 u16 vid = *(u16 *) arg;
396 mlxsw_sp_fid_8021q_fid(fid)->vid = vid;
399 static enum mlxsw_reg_sfmr_op mlxsw_sp_sfmr_op(bool valid)
401 return valid ? MLXSW_REG_SFMR_OP_CREATE_FID :
402 MLXSW_REG_SFMR_OP_DESTROY_FID;
405 static int mlxsw_sp_fid_op(struct mlxsw_sp *mlxsw_sp, u16 fid_index,
406 u16 fid_offset, bool valid)
408 char sfmr_pl[MLXSW_REG_SFMR_LEN];
410 mlxsw_reg_sfmr_pack(sfmr_pl, mlxsw_sp_sfmr_op(valid), fid_index,
412 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl);
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)
419 char sfmr_pl[MLXSW_REG_SFMR_LEN];
421 mlxsw_reg_sfmr_pack(sfmr_pl, MLXSW_REG_SFMR_OP_CREATE_FID, fid_index,
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);
430 static int mlxsw_sp_fid_vid_map(struct mlxsw_sp *mlxsw_sp, u16 fid_index,
433 enum mlxsw_reg_svfa_mt mt = MLXSW_REG_SVFA_MT_VID_TO_FID;
434 char svfa_pl[MLXSW_REG_SVFA_LEN];
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);
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)
443 enum mlxsw_reg_svfa_mt mt = MLXSW_REG_SVFA_MT_PORT_VID_TO_FID;
444 char svfa_pl[MLXSW_REG_SVFA_LEN];
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);
450 static int mlxsw_sp_fid_8021q_configure(struct mlxsw_sp_fid *fid)
452 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
453 struct mlxsw_sp_fid_8021q *fid_8021q;
456 err = mlxsw_sp_fid_op(mlxsw_sp, fid->fid_index, fid->fid_index, true);
460 fid_8021q = mlxsw_sp_fid_8021q_fid(fid);
461 err = mlxsw_sp_fid_vid_map(mlxsw_sp, fid->fid_index, fid_8021q->vid,
469 mlxsw_sp_fid_op(mlxsw_sp, fid->fid_index, 0, false);
473 static void mlxsw_sp_fid_8021q_deconfigure(struct mlxsw_sp_fid *fid)
475 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
476 struct mlxsw_sp_fid_8021q *fid_8021q;
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);
483 static int mlxsw_sp_fid_8021q_index_alloc(struct mlxsw_sp_fid *fid,
484 const void *arg, u16 *p_fid_index)
486 struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
487 u16 vid = *(u16 *) arg;
489 /* Use 1:1 mapping for simplicity although not a must */
490 if (vid < fid_family->start_index || vid > fid_family->end_index)
498 mlxsw_sp_fid_8021q_compare(const struct mlxsw_sp_fid *fid, const void *arg)
500 u16 vid = *(u16 *) arg;
502 return mlxsw_sp_fid_8021q_fid(fid)->vid == vid;
505 static u16 mlxsw_sp_fid_8021q_flood_index(const struct mlxsw_sp_fid *fid)
507 return fid->fid_index;
510 static int mlxsw_sp_fid_8021q_port_vid_map(struct mlxsw_sp_fid *fid,
511 struct mlxsw_sp_port *mlxsw_sp_port,
514 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
515 u8 local_port = mlxsw_sp_port->local_port;
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.
521 if (mlxsw_sp->fid_core->port_fid_mappings[local_port] == 0)
523 return __mlxsw_sp_fid_port_vid_map(mlxsw_sp, fid->fid_index, local_port,
528 mlxsw_sp_fid_8021q_port_vid_unmap(struct mlxsw_sp_fid *fid,
529 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
531 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
532 u8 local_port = mlxsw_sp_port->local_port;
534 if (mlxsw_sp->fid_core->port_fid_mappings[local_port] == 0)
536 __mlxsw_sp_fid_port_vid_map(mlxsw_sp, fid->fid_index, local_port, vid,
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,
551 static const struct mlxsw_sp_flood_table mlxsw_sp_fid_8021q_flood_tables[] = {
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,
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,
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,
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),
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,
584 static struct mlxsw_sp_fid_8021d *
585 mlxsw_sp_fid_8021d_fid(const struct mlxsw_sp_fid *fid)
587 return container_of(fid, struct mlxsw_sp_fid_8021d, common);
590 static void mlxsw_sp_fid_8021d_setup(struct mlxsw_sp_fid *fid, const void *arg)
592 int br_ifindex = *(int *) arg;
594 mlxsw_sp_fid_8021d_fid(fid)->br_ifindex = br_ifindex;
597 static int mlxsw_sp_fid_8021d_configure(struct mlxsw_sp_fid *fid)
599 struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
601 return mlxsw_sp_fid_op(fid_family->mlxsw_sp, fid->fid_index, 0, true);
604 static void mlxsw_sp_fid_8021d_deconfigure(struct mlxsw_sp_fid *fid)
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);
611 static int mlxsw_sp_fid_8021d_index_alloc(struct mlxsw_sp_fid *fid,
612 const void *arg, u16 *p_fid_index)
614 struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
615 u16 nr_fids, fid_index;
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)
621 *p_fid_index = fid_family->start_index + fid_index;
627 mlxsw_sp_fid_8021d_compare(const struct mlxsw_sp_fid *fid, const void *arg)
629 int br_ifindex = *(int *) arg;
631 return mlxsw_sp_fid_8021d_fid(fid)->br_ifindex == br_ifindex;
634 static u16 mlxsw_sp_fid_8021d_flood_index(const struct mlxsw_sp_fid *fid)
636 return fid->fid_index - VLAN_N_VID;
639 static int mlxsw_sp_port_vp_mode_trans(struct mlxsw_sp_port *mlxsw_sp_port)
641 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
642 struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
645 list_for_each_entry(mlxsw_sp_port_vlan, &mlxsw_sp_port->vlans_list,
647 struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid;
648 u16 vid = mlxsw_sp_port_vlan->vid;
653 err = __mlxsw_sp_fid_port_vid_map(mlxsw_sp, fid->fid_index,
654 mlxsw_sp_port->local_port,
657 goto err_fid_port_vid_map;
660 err = mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, true);
662 goto err_port_vp_mode_set;
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;
676 __mlxsw_sp_fid_port_vid_map(mlxsw_sp, fid->fid_index,
677 mlxsw_sp_port->local_port, vid,
683 static void mlxsw_sp_port_vlan_mode_trans(struct mlxsw_sp_port *mlxsw_sp_port)
685 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
686 struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
688 mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, false);
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;
698 __mlxsw_sp_fid_port_vid_map(mlxsw_sp, fid->fid_index,
699 mlxsw_sp_port->local_port, vid,
704 static int mlxsw_sp_fid_8021d_port_vid_map(struct mlxsw_sp_fid *fid,
705 struct mlxsw_sp_port *mlxsw_sp_port,
708 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
709 u8 local_port = mlxsw_sp_port->local_port;
712 err = __mlxsw_sp_fid_port_vid_map(mlxsw_sp, fid->fid_index,
713 mlxsw_sp_port->local_port, vid, true);
717 if (mlxsw_sp->fid_core->port_fid_mappings[local_port]++ == 0) {
718 err = mlxsw_sp_port_vp_mode_trans(mlxsw_sp_port);
720 goto err_port_vp_mode_trans;
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);
733 mlxsw_sp_fid_8021d_port_vid_unmap(struct mlxsw_sp_fid *fid,
734 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
736 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
737 u8 local_port = mlxsw_sp_port->local_port;
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);
746 static int mlxsw_sp_fid_8021d_vni_set(struct mlxsw_sp_fid *fid, __be32 vni)
748 struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
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);
755 static void mlxsw_sp_fid_8021d_vni_clear(struct mlxsw_sp_fid *fid)
757 struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
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);
763 static int mlxsw_sp_fid_8021d_nve_flood_index_set(struct mlxsw_sp_fid *fid,
766 struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
768 return mlxsw_sp_fid_vni_op(fid_family->mlxsw_sp, fid->fid_index,
769 fid->vni, fid->vni_valid, nve_flood_index,
773 static void mlxsw_sp_fid_8021d_nve_flood_index_clear(struct mlxsw_sp_fid *fid)
775 struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
777 mlxsw_sp_fid_vni_op(fid_family->mlxsw_sp, fid->fid_index, fid->vni,
778 fid->vni_valid, 0, false);
782 mlxsw_sp_fid_8021d_fdb_clear_offload(const struct mlxsw_sp_fid *fid,
783 const struct net_device *nve_dev)
785 br_fdb_clear_offload(nve_dev, 0);
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,
804 static const struct mlxsw_sp_flood_table mlxsw_sp_fid_8021d_flood_tables[] = {
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,
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,
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,
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,
839 mlxsw_sp_fid_8021q_fdb_clear_offload(const struct mlxsw_sp_fid *fid,
840 const struct net_device *nve_dev)
842 br_fdb_clear_offload(nve_dev, mlxsw_sp_fid_8021q_vid(fid));
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,
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 + \
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,
879 static int mlxsw_sp_fid_rfid_configure(struct mlxsw_sp_fid *fid)
881 /* rFIDs are allocated by the device during init */
885 static void mlxsw_sp_fid_rfid_deconfigure(struct mlxsw_sp_fid *fid)
889 static int mlxsw_sp_fid_rfid_index_alloc(struct mlxsw_sp_fid *fid,
890 const void *arg, u16 *p_fid_index)
892 u16 rif_index = *(u16 *) arg;
894 *p_fid_index = fid->fid_family->start_index + rif_index;
899 static bool mlxsw_sp_fid_rfid_compare(const struct mlxsw_sp_fid *fid,
902 u16 rif_index = *(u16 *) arg;
904 return fid->fid_index == rif_index + fid->fid_family->start_index;
907 static int mlxsw_sp_fid_rfid_port_vid_map(struct mlxsw_sp_fid *fid,
908 struct mlxsw_sp_port *mlxsw_sp_port,
911 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
912 u8 local_port = mlxsw_sp_port->local_port;
915 /* We only need to transition the port to virtual mode since
916 * {Port, VID} => FID is done by the firmware upon RIF creation.
918 if (mlxsw_sp->fid_core->port_fid_mappings[local_port]++ == 0) {
919 err = mlxsw_sp_port_vp_mode_trans(mlxsw_sp_port);
921 goto err_port_vp_mode_trans;
926 err_port_vp_mode_trans:
927 mlxsw_sp->fid_core->port_fid_mappings[local_port]--;
932 mlxsw_sp_fid_rfid_port_vid_unmap(struct mlxsw_sp_fid *fid,
933 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
935 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
936 u8 local_port = mlxsw_sp_port->local_port;
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]--;
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,
952 #define MLXSW_SP_RFID_BASE (15 * 1024)
953 #define MLXSW_SP_RFID_MAX 1024
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,
964 static int mlxsw_sp_fid_dummy_configure(struct mlxsw_sp_fid *fid)
966 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
968 return mlxsw_sp_fid_op(mlxsw_sp, fid->fid_index, 0, true);
971 static void mlxsw_sp_fid_dummy_deconfigure(struct mlxsw_sp_fid *fid)
973 mlxsw_sp_fid_op(fid->fid_family->mlxsw_sp, fid->fid_index, 0, false);
976 static int mlxsw_sp_fid_dummy_index_alloc(struct mlxsw_sp_fid *fid,
977 const void *arg, u16 *p_fid_index)
979 *p_fid_index = fid->fid_family->start_index;
984 static bool mlxsw_sp_fid_dummy_compare(const struct mlxsw_sp_fid *fid,
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,
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,
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,
1012 static struct mlxsw_sp_fid *mlxsw_sp_fid_lookup(struct mlxsw_sp *mlxsw_sp,
1013 enum mlxsw_sp_fid_type type,
1016 struct mlxsw_sp_fid_family *fid_family;
1017 struct mlxsw_sp_fid *fid;
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))
1030 static struct mlxsw_sp_fid *mlxsw_sp_fid_get(struct mlxsw_sp *mlxsw_sp,
1031 enum mlxsw_sp_fid_type type,
1034 struct mlxsw_sp_fid_family *fid_family;
1035 struct mlxsw_sp_fid *fid;
1039 fid = mlxsw_sp_fid_lookup(mlxsw_sp, type, arg);
1043 fid_family = mlxsw_sp->fid_core->fid_family_arr[type];
1044 fid = kzalloc(fid_family->fid_size, GFP_KERNEL);
1046 return ERR_PTR(-ENOMEM);
1047 fid->fid_family = fid_family;
1049 err = fid->fid_family->ops->index_alloc(fid, arg, &fid_index);
1051 goto err_index_alloc;
1052 fid->fid_index = fid_index;
1053 __set_bit(fid_index - fid_family->start_index, fid_family->fids_bitmap);
1055 if (fid->fid_family->ops->setup)
1056 fid->fid_family->ops->setup(fid, arg);
1058 err = fid->fid_family->ops->configure(fid);
1062 err = rhashtable_insert_fast(&mlxsw_sp->fid_core->fid_ht, &fid->ht_node,
1063 mlxsw_sp_fid_ht_params);
1065 goto err_rhashtable_insert;
1067 list_add(&fid->list, &fid_family->fids_list);
1071 err_rhashtable_insert:
1072 fid->fid_family->ops->deconfigure(fid);
1074 __clear_bit(fid_index - fid_family->start_index,
1075 fid_family->fids_bitmap);
1078 return ERR_PTR(err);
1081 void mlxsw_sp_fid_put(struct mlxsw_sp_fid *fid)
1083 struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
1084 struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
1086 if (--fid->ref_count != 0)
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);
1098 struct mlxsw_sp_fid *mlxsw_sp_fid_8021q_get(struct mlxsw_sp *mlxsw_sp, u16 vid)
1100 return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_8021Q, &vid);
1103 struct mlxsw_sp_fid *mlxsw_sp_fid_8021d_get(struct mlxsw_sp *mlxsw_sp,
1106 return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_8021D, &br_ifindex);
1109 struct mlxsw_sp_fid *mlxsw_sp_fid_8021q_lookup(struct mlxsw_sp *mlxsw_sp,
1112 return mlxsw_sp_fid_lookup(mlxsw_sp, MLXSW_SP_FID_TYPE_8021Q, &vid);
1115 struct mlxsw_sp_fid *mlxsw_sp_fid_8021d_lookup(struct mlxsw_sp *mlxsw_sp,
1118 return mlxsw_sp_fid_lookup(mlxsw_sp, MLXSW_SP_FID_TYPE_8021D,
1122 struct mlxsw_sp_fid *mlxsw_sp_fid_rfid_get(struct mlxsw_sp *mlxsw_sp,
1125 return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_RFID, &rif_index);
1128 struct mlxsw_sp_fid *mlxsw_sp_fid_dummy_get(struct mlxsw_sp *mlxsw_sp)
1130 return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_DUMMY, NULL);
1134 mlxsw_sp_fid_flood_table_init(struct mlxsw_sp_fid_family *fid_family,
1135 const struct mlxsw_sp_flood_table *flood_table)
1137 enum mlxsw_sp_flood_type packet_type = flood_table->packet_type;
1138 const int *sfgc_packet_types;
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];
1147 if (!sfgc_packet_types[i])
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);
1161 mlxsw_sp_fid_flood_tables_init(struct mlxsw_sp_fid_family *fid_family)
1165 for (i = 0; i < fid_family->nr_flood_tables; i++) {
1166 const struct mlxsw_sp_flood_table *flood_table;
1169 flood_table = &fid_family->flood_tables[i];
1170 err = mlxsw_sp_fid_flood_table_init(fid_family, flood_table);
1178 static int mlxsw_sp_fid_family_register(struct mlxsw_sp *mlxsw_sp,
1179 const struct mlxsw_sp_fid_family *tmpl)
1181 u16 nr_fids = tmpl->end_index - tmpl->start_index + 1;
1182 struct mlxsw_sp_fid_family *fid_family;
1185 fid_family = kmemdup(tmpl, sizeof(*fid_family), GFP_KERNEL);
1189 fid_family->mlxsw_sp = mlxsw_sp;
1190 INIT_LIST_HEAD(&fid_family->fids_list);
1191 fid_family->fids_bitmap = kcalloc(BITS_TO_LONGS(nr_fids),
1192 sizeof(unsigned long), GFP_KERNEL);
1193 if (!fid_family->fids_bitmap) {
1195 goto err_alloc_fids_bitmap;
1198 if (fid_family->flood_tables) {
1199 err = mlxsw_sp_fid_flood_tables_init(fid_family);
1201 goto err_fid_flood_tables_init;
1204 mlxsw_sp->fid_core->fid_family_arr[tmpl->type] = fid_family;
1208 err_fid_flood_tables_init:
1209 kfree(fid_family->fids_bitmap);
1210 err_alloc_fids_bitmap:
1216 mlxsw_sp_fid_family_unregister(struct mlxsw_sp *mlxsw_sp,
1217 struct mlxsw_sp_fid_family *fid_family)
1219 mlxsw_sp->fid_core->fid_family_arr[fid_family->type] = NULL;
1220 kfree(fid_family->fids_bitmap);
1221 WARN_ON_ONCE(!list_empty(&fid_family->fids_list));
1225 int mlxsw_sp_port_fids_init(struct mlxsw_sp_port *mlxsw_sp_port)
1227 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1229 /* Track number of FIDs configured on the port with mapping type
1230 * PORT_VID_TO_FID, so that we know when to transition the port
1231 * back to non-virtual (VLAN) mode.
1233 mlxsw_sp->fid_core->port_fid_mappings[mlxsw_sp_port->local_port] = 0;
1235 return mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, false);
1238 void mlxsw_sp_port_fids_fini(struct mlxsw_sp_port *mlxsw_sp_port)
1240 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1242 mlxsw_sp->fid_core->port_fid_mappings[mlxsw_sp_port->local_port] = 0;
1245 int mlxsw_sp_fids_init(struct mlxsw_sp *mlxsw_sp)
1247 unsigned int max_ports = mlxsw_core_max_ports(mlxsw_sp->core);
1248 struct mlxsw_sp_fid_core *fid_core;
1251 fid_core = kzalloc(sizeof(*mlxsw_sp->fid_core), GFP_KERNEL);
1254 mlxsw_sp->fid_core = fid_core;
1256 err = rhashtable_init(&fid_core->fid_ht, &mlxsw_sp_fid_ht_params);
1258 goto err_rhashtable_fid_init;
1260 err = rhashtable_init(&fid_core->vni_ht, &mlxsw_sp_fid_vni_ht_params);
1262 goto err_rhashtable_vni_init;
1264 fid_core->port_fid_mappings = kcalloc(max_ports, sizeof(unsigned int),
1266 if (!fid_core->port_fid_mappings) {
1268 goto err_alloc_port_fid_mappings;
1271 for (i = 0; i < MLXSW_SP_FID_TYPE_MAX; i++) {
1272 err = mlxsw_sp_fid_family_register(mlxsw_sp,
1273 mlxsw_sp_fid_family_arr[i]);
1276 goto err_fid_ops_register;
1281 err_fid_ops_register:
1282 for (i--; i >= 0; i--) {
1283 struct mlxsw_sp_fid_family *fid_family;
1285 fid_family = fid_core->fid_family_arr[i];
1286 mlxsw_sp_fid_family_unregister(mlxsw_sp, fid_family);
1288 kfree(fid_core->port_fid_mappings);
1289 err_alloc_port_fid_mappings:
1290 rhashtable_destroy(&fid_core->vni_ht);
1291 err_rhashtable_vni_init:
1292 rhashtable_destroy(&fid_core->fid_ht);
1293 err_rhashtable_fid_init:
1298 void mlxsw_sp_fids_fini(struct mlxsw_sp *mlxsw_sp)
1300 struct mlxsw_sp_fid_core *fid_core = mlxsw_sp->fid_core;
1303 for (i = 0; i < MLXSW_SP_FID_TYPE_MAX; i++)
1304 mlxsw_sp_fid_family_unregister(mlxsw_sp,
1305 fid_core->fid_family_arr[i]);
1306 kfree(fid_core->port_fid_mappings);
1307 rhashtable_destroy(&fid_core->vni_ht);
1308 rhashtable_destroy(&fid_core->fid_ht);