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>
11 #include <linux/refcount.h>
16 struct mlxsw_sp_fid_family;
18 struct mlxsw_sp_fid_core {
19 struct rhashtable fid_ht;
20 struct rhashtable vni_ht;
21 struct mlxsw_sp_fid_family *fid_family_arr[MLXSW_SP_FID_TYPE_MAX];
22 unsigned int *port_fid_mappings;
25 struct mlxsw_sp_fid_port_vid {
26 struct list_head list;
32 struct list_head list;
33 struct mlxsw_sp_rif *rif;
37 struct mlxsw_sp_fid_family *fid_family;
38 struct rhash_head ht_node;
40 struct rhash_head vni_ht_node;
41 enum mlxsw_sp_nve_type nve_type;
46 nve_flood_index_valid:1;
47 struct list_head port_vid_list; /* Ordered by local port. */
50 struct mlxsw_sp_fid_8021q {
51 struct mlxsw_sp_fid common;
55 struct mlxsw_sp_fid_8021d {
56 struct mlxsw_sp_fid common;
60 static const struct rhashtable_params mlxsw_sp_fid_ht_params = {
61 .key_len = sizeof_field(struct mlxsw_sp_fid, fid_index),
62 .key_offset = offsetof(struct mlxsw_sp_fid, fid_index),
63 .head_offset = offsetof(struct mlxsw_sp_fid, ht_node),
66 static const struct rhashtable_params mlxsw_sp_fid_vni_ht_params = {
67 .key_len = sizeof_field(struct mlxsw_sp_fid, vni),
68 .key_offset = offsetof(struct mlxsw_sp_fid, vni),
69 .head_offset = offsetof(struct mlxsw_sp_fid, vni_ht_node),
72 struct mlxsw_sp_flood_table {
73 enum mlxsw_sp_flood_type packet_type;
74 enum mlxsw_flood_table_type table_type;
78 struct mlxsw_sp_fid_ops {
79 void (*setup)(struct mlxsw_sp_fid *fid, const void *arg);
80 int (*configure)(struct mlxsw_sp_fid *fid);
81 void (*deconfigure)(struct mlxsw_sp_fid *fid);
82 int (*index_alloc)(struct mlxsw_sp_fid *fid, const void *arg,
84 bool (*compare)(const struct mlxsw_sp_fid *fid,
86 u16 (*flood_index)(const struct mlxsw_sp_fid *fid);
87 int (*port_vid_map)(struct mlxsw_sp_fid *fid,
88 struct mlxsw_sp_port *port, u16 vid);
89 void (*port_vid_unmap)(struct mlxsw_sp_fid *fid,
90 struct mlxsw_sp_port *port, u16 vid);
91 int (*vni_set)(struct mlxsw_sp_fid *fid);
92 void (*vni_clear)(struct mlxsw_sp_fid *fid);
93 int (*nve_flood_index_set)(struct mlxsw_sp_fid *fid);
94 void (*nve_flood_index_clear)(struct mlxsw_sp_fid *fid);
95 void (*fdb_clear_offload)(const struct mlxsw_sp_fid *fid,
96 const struct net_device *nve_dev);
99 struct mlxsw_sp_fid_family {
100 enum mlxsw_sp_fid_type type;
104 struct list_head fids_list;
105 unsigned long *fids_bitmap;
106 const struct mlxsw_sp_flood_table *flood_tables;
108 enum mlxsw_sp_rif_type rif_type;
109 const struct mlxsw_sp_fid_ops *ops;
110 struct mlxsw_sp *mlxsw_sp;
112 enum mlxsw_reg_bridge_type bridge_type;
116 static const int mlxsw_sp_sfgc_uc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = {
117 [MLXSW_REG_SFGC_TYPE_UNKNOWN_UNICAST] = 1,
120 static const int mlxsw_sp_sfgc_bc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = {
121 [MLXSW_REG_SFGC_TYPE_BROADCAST] = 1,
122 [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_NON_IP] = 1,
123 [MLXSW_REG_SFGC_TYPE_IPV4_LINK_LOCAL] = 1,
124 [MLXSW_REG_SFGC_TYPE_IPV6_ALL_HOST] = 1,
125 [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV6] = 1,
128 static const int mlxsw_sp_sfgc_mc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = {
129 [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV4] = 1,
132 static const int *mlxsw_sp_packet_type_sfgc_types[] = {
133 [MLXSW_SP_FLOOD_TYPE_UC] = mlxsw_sp_sfgc_uc_packet_types,
134 [MLXSW_SP_FLOOD_TYPE_BC] = mlxsw_sp_sfgc_bc_packet_types,
135 [MLXSW_SP_FLOOD_TYPE_MC] = mlxsw_sp_sfgc_mc_packet_types,
138 bool mlxsw_sp_fid_is_dummy(struct mlxsw_sp *mlxsw_sp, u16 fid_index)
140 enum mlxsw_sp_fid_type fid_type = MLXSW_SP_FID_TYPE_DUMMY;
141 struct mlxsw_sp_fid_family *fid_family;
143 fid_family = mlxsw_sp->fid_core->fid_family_arr[fid_type];
145 return fid_family->start_index == fid_index;
148 struct mlxsw_sp_fid *mlxsw_sp_fid_lookup_by_index(struct mlxsw_sp *mlxsw_sp,
151 struct mlxsw_sp_fid *fid;
153 fid = rhashtable_lookup_fast(&mlxsw_sp->fid_core->fid_ht, &fid_index,
154 mlxsw_sp_fid_ht_params);
156 refcount_inc(&fid->ref_count);
161 int mlxsw_sp_fid_nve_ifindex(const struct mlxsw_sp_fid *fid, int *nve_ifindex)
166 *nve_ifindex = fid->nve_ifindex;
171 int mlxsw_sp_fid_nve_type(const struct mlxsw_sp_fid *fid,
172 enum mlxsw_sp_nve_type *p_type)
177 *p_type = fid->nve_type;
182 struct mlxsw_sp_fid *mlxsw_sp_fid_lookup_by_vni(struct mlxsw_sp *mlxsw_sp,
185 struct mlxsw_sp_fid *fid;
187 fid = rhashtable_lookup_fast(&mlxsw_sp->fid_core->vni_ht, &vni,
188 mlxsw_sp_fid_vni_ht_params);
190 refcount_inc(&fid->ref_count);
195 int mlxsw_sp_fid_vni(const struct mlxsw_sp_fid *fid, __be32 *vni)
205 int mlxsw_sp_fid_nve_flood_index_set(struct mlxsw_sp_fid *fid,
208 struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
209 const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
212 if (WARN_ON(fid->nve_flood_index_valid))
215 fid->nve_flood_index = nve_flood_index;
216 fid->nve_flood_index_valid = true;
217 err = ops->nve_flood_index_set(fid);
219 goto err_nve_flood_index_set;
223 err_nve_flood_index_set:
224 fid->nve_flood_index_valid = false;
228 void mlxsw_sp_fid_nve_flood_index_clear(struct mlxsw_sp_fid *fid)
230 struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
231 const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
233 if (WARN_ON(!fid->nve_flood_index_valid))
236 fid->nve_flood_index_valid = false;
237 ops->nve_flood_index_clear(fid);
240 bool mlxsw_sp_fid_nve_flood_index_is_set(const struct mlxsw_sp_fid *fid)
242 return fid->nve_flood_index_valid;
245 int mlxsw_sp_fid_vni_set(struct mlxsw_sp_fid *fid, enum mlxsw_sp_nve_type type,
246 __be32 vni, int nve_ifindex)
248 struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
249 const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
250 struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
253 if (WARN_ON(fid->vni_valid))
256 fid->nve_type = type;
257 fid->nve_ifindex = nve_ifindex;
259 err = rhashtable_lookup_insert_fast(&mlxsw_sp->fid_core->vni_ht,
261 mlxsw_sp_fid_vni_ht_params);
265 fid->vni_valid = true;
266 err = ops->vni_set(fid);
273 fid->vni_valid = false;
274 rhashtable_remove_fast(&mlxsw_sp->fid_core->vni_ht, &fid->vni_ht_node,
275 mlxsw_sp_fid_vni_ht_params);
279 void mlxsw_sp_fid_vni_clear(struct mlxsw_sp_fid *fid)
281 struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
282 const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
283 struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
285 if (WARN_ON(!fid->vni_valid))
288 fid->vni_valid = false;
290 rhashtable_remove_fast(&mlxsw_sp->fid_core->vni_ht, &fid->vni_ht_node,
291 mlxsw_sp_fid_vni_ht_params);
294 bool mlxsw_sp_fid_vni_is_set(const struct mlxsw_sp_fid *fid)
296 return fid->vni_valid;
299 void mlxsw_sp_fid_fdb_clear_offload(const struct mlxsw_sp_fid *fid,
300 const struct net_device *nve_dev)
302 struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
303 const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
305 if (ops->fdb_clear_offload)
306 ops->fdb_clear_offload(fid, nve_dev);
309 static const struct mlxsw_sp_flood_table *
310 mlxsw_sp_fid_flood_table_lookup(const struct mlxsw_sp_fid *fid,
311 enum mlxsw_sp_flood_type packet_type)
313 struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
316 for (i = 0; i < fid_family->nr_flood_tables; i++) {
317 if (fid_family->flood_tables[i].packet_type != packet_type)
319 return &fid_family->flood_tables[i];
326 mlxsw_sp_fid_family_num_fids(const struct mlxsw_sp_fid_family *fid_family)
328 return fid_family->end_index - fid_family->start_index + 1;
332 mlxsw_sp_fid_flood_table_mid(const struct mlxsw_sp_fid_family *fid_family,
333 const struct mlxsw_sp_flood_table *flood_table,
338 num_fids = mlxsw_sp_fid_family_num_fids(fid_family);
339 return fid_family->pgt_base + num_fids * flood_table->table_index +
343 int mlxsw_sp_fid_flood_set(struct mlxsw_sp_fid *fid,
344 enum mlxsw_sp_flood_type packet_type, u16 local_port,
347 struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
348 const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
349 const struct mlxsw_sp_flood_table *flood_table;
354 if (WARN_ON(!fid_family->flood_tables || !ops->flood_index))
357 flood_table = mlxsw_sp_fid_flood_table_lookup(fid, packet_type);
361 if (fid_family->mlxsw_sp->ubridge) {
362 mid_index = mlxsw_sp_fid_flood_table_mid(fid_family,
365 return mlxsw_sp_pgt_entry_port_set(fid_family->mlxsw_sp,
366 mid_index, fid->fid_index,
370 sftr2_pl = kmalloc(MLXSW_REG_SFTR2_LEN, GFP_KERNEL);
374 mlxsw_reg_sftr2_pack(sftr2_pl, flood_table->table_index,
375 ops->flood_index(fid), flood_table->table_type, 1,
377 err = mlxsw_reg_write(fid_family->mlxsw_sp->core, MLXSW_REG(sftr2),
383 int mlxsw_sp_fid_port_vid_map(struct mlxsw_sp_fid *fid,
384 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
386 if (WARN_ON(!fid->fid_family->ops->port_vid_map))
388 return fid->fid_family->ops->port_vid_map(fid, mlxsw_sp_port, vid);
391 void mlxsw_sp_fid_port_vid_unmap(struct mlxsw_sp_fid *fid,
392 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
394 fid->fid_family->ops->port_vid_unmap(fid, mlxsw_sp_port, vid);
397 u16 mlxsw_sp_fid_index(const struct mlxsw_sp_fid *fid)
399 return fid->fid_index;
402 enum mlxsw_sp_fid_type mlxsw_sp_fid_type(const struct mlxsw_sp_fid *fid)
404 return fid->fid_family->type;
407 struct mlxsw_sp_rif *mlxsw_sp_fid_rif(const struct mlxsw_sp_fid *fid)
412 enum mlxsw_sp_rif_type
413 mlxsw_sp_fid_type_rif_type(const struct mlxsw_sp *mlxsw_sp,
414 enum mlxsw_sp_fid_type type)
416 struct mlxsw_sp_fid_core *fid_core = mlxsw_sp->fid_core;
418 return fid_core->fid_family_arr[type]->rif_type;
421 static struct mlxsw_sp_fid_8021q *
422 mlxsw_sp_fid_8021q_fid(const struct mlxsw_sp_fid *fid)
424 return container_of(fid, struct mlxsw_sp_fid_8021q, common);
427 u16 mlxsw_sp_fid_8021q_vid(const struct mlxsw_sp_fid *fid)
429 return mlxsw_sp_fid_8021q_fid(fid)->vid;
432 static void mlxsw_sp_fid_8021q_setup(struct mlxsw_sp_fid *fid, const void *arg)
434 u16 vid = *(u16 *) arg;
436 mlxsw_sp_fid_8021q_fid(fid)->vid = vid;
440 static enum mlxsw_reg_sfmr_op mlxsw_sp_sfmr_op(bool valid)
442 return valid ? MLXSW_REG_SFMR_OP_CREATE_FID :
443 MLXSW_REG_SFMR_OP_DESTROY_FID;
446 static int mlxsw_sp_fid_op(const struct mlxsw_sp_fid *fid, bool valid)
448 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
449 enum mlxsw_reg_bridge_type bridge_type = 0;
450 char sfmr_pl[MLXSW_REG_SFMR_LEN];
451 bool flood_rsp = false;
453 if (mlxsw_sp->ubridge) {
454 flood_rsp = fid->fid_family->flood_rsp;
455 bridge_type = fid->fid_family->bridge_type;
458 mlxsw_reg_sfmr_pack(sfmr_pl, mlxsw_sp_sfmr_op(valid), fid->fid_index,
459 fid->fid_offset, flood_rsp, bridge_type);
460 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl);
463 static int mlxsw_sp_fid_edit_op(const struct mlxsw_sp_fid *fid,
464 const struct mlxsw_sp_rif *rif)
466 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
467 enum mlxsw_reg_bridge_type bridge_type = 0;
468 char sfmr_pl[MLXSW_REG_SFMR_LEN];
469 bool flood_rsp = false;
471 if (mlxsw_sp->ubridge) {
472 flood_rsp = fid->fid_family->flood_rsp;
473 bridge_type = fid->fid_family->bridge_type;
476 mlxsw_reg_sfmr_pack(sfmr_pl, MLXSW_REG_SFMR_OP_CREATE_FID,
477 fid->fid_index, fid->fid_offset, flood_rsp,
479 mlxsw_reg_sfmr_vv_set(sfmr_pl, fid->vni_valid);
480 mlxsw_reg_sfmr_vni_set(sfmr_pl, be32_to_cpu(fid->vni));
481 mlxsw_reg_sfmr_vtfp_set(sfmr_pl, fid->nve_flood_index_valid);
482 mlxsw_reg_sfmr_nve_tunnel_flood_ptr_set(sfmr_pl, fid->nve_flood_index);
484 if (mlxsw_sp->ubridge && rif) {
485 mlxsw_reg_sfmr_irif_v_set(sfmr_pl, true);
486 mlxsw_reg_sfmr_irif_set(sfmr_pl, mlxsw_sp_rif_index(rif));
489 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl);
492 static int mlxsw_sp_fid_vni_to_fid_map(const struct mlxsw_sp_fid *fid,
493 const struct mlxsw_sp_rif *rif,
496 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
497 char svfa_pl[MLXSW_REG_SVFA_LEN];
502 irif_index = rif ? mlxsw_sp_rif_index(rif) : 0;
504 mlxsw_reg_svfa_vni_pack(svfa_pl, valid, fid->fid_index,
505 be32_to_cpu(fid->vni), irif_valid, irif_index);
506 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl);
509 static int mlxsw_sp_fid_to_fid_rif_update(const struct mlxsw_sp_fid *fid,
510 const struct mlxsw_sp_rif *rif)
512 return mlxsw_sp_fid_edit_op(fid, rif);
515 static int mlxsw_sp_fid_vni_to_fid_rif_update(const struct mlxsw_sp_fid *fid,
516 const struct mlxsw_sp_rif *rif)
521 return mlxsw_sp_fid_vni_to_fid_map(fid, rif, fid->vni_valid);
525 mlxsw_sp_fid_port_vid_to_fid_rif_update_one(const struct mlxsw_sp_fid *fid,
526 struct mlxsw_sp_fid_port_vid *pv,
527 bool irif_valid, u16 irif_index)
529 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
530 char svfa_pl[MLXSW_REG_SVFA_LEN];
532 mlxsw_reg_svfa_port_vid_pack(svfa_pl, pv->local_port, true,
533 fid->fid_index, pv->vid, irif_valid,
536 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl);
539 static int mlxsw_sp_fid_vid_to_fid_rif_set(const struct mlxsw_sp_fid *fid,
540 const struct mlxsw_sp_rif *rif)
542 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
543 struct mlxsw_sp_fid_port_vid *pv;
547 irif_index = mlxsw_sp_rif_index(rif);
549 list_for_each_entry(pv, &fid->port_vid_list, list) {
550 /* If port is not in virtual mode, then it does not have any
551 * {Port, VID}->FID mappings that need to be updated with the
554 if (!mlxsw_sp->fid_core->port_fid_mappings[pv->local_port])
557 err = mlxsw_sp_fid_port_vid_to_fid_rif_update_one(fid, pv,
561 goto err_port_vid_to_fid_rif_update_one;
566 err_port_vid_to_fid_rif_update_one:
567 list_for_each_entry_continue_reverse(pv, &fid->port_vid_list, list) {
568 if (!mlxsw_sp->fid_core->port_fid_mappings[pv->local_port])
571 mlxsw_sp_fid_port_vid_to_fid_rif_update_one(fid, pv, false, 0);
577 static void mlxsw_sp_fid_vid_to_fid_rif_unset(const struct mlxsw_sp_fid *fid)
579 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
580 struct mlxsw_sp_fid_port_vid *pv;
582 list_for_each_entry(pv, &fid->port_vid_list, list) {
583 /* If port is not in virtual mode, then it does not have any
584 * {Port, VID}->FID mappings that need to be updated.
586 if (!mlxsw_sp->fid_core->port_fid_mappings[pv->local_port])
589 mlxsw_sp_fid_port_vid_to_fid_rif_update_one(fid, pv, false, 0);
593 static int mlxsw_sp_fid_reiv_handle(struct mlxsw_sp_fid *fid, u16 rif_index,
594 bool valid, u8 port_page)
596 u16 local_port_end = (port_page + 1) * MLXSW_REG_REIV_REC_MAX_COUNT - 1;
597 u16 local_port_start = port_page * MLXSW_REG_REIV_REC_MAX_COUNT;
598 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
599 struct mlxsw_sp_fid_port_vid *port_vid;
600 u8 rec_num, entries_num = 0;
604 reiv_pl = kmalloc(MLXSW_REG_REIV_LEN, GFP_KERNEL);
608 mlxsw_reg_reiv_pack(reiv_pl, port_page, rif_index);
610 list_for_each_entry(port_vid, &fid->port_vid_list, list) {
611 /* port_vid_list is sorted by local_port. */
612 if (port_vid->local_port < local_port_start)
615 if (port_vid->local_port > local_port_end)
618 rec_num = port_vid->local_port % MLXSW_REG_REIV_REC_MAX_COUNT;
619 mlxsw_reg_reiv_rec_update_set(reiv_pl, rec_num, true);
620 mlxsw_reg_reiv_rec_evid_set(reiv_pl, rec_num,
621 valid ? port_vid->vid : 0);
630 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(reiv), reiv_pl);
642 static int mlxsw_sp_fid_erif_eport_to_vid_map(struct mlxsw_sp_fid *fid,
643 u16 rif_index, bool valid)
645 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
649 num_port_pages = mlxsw_core_max_ports(mlxsw_sp->core) /
650 MLXSW_REG_REIV_REC_MAX_COUNT + 1;
652 for (i = 0; i < num_port_pages; i++) {
653 err = mlxsw_sp_fid_reiv_handle(fid, rif_index, valid, i);
655 goto err_reiv_handle;
662 mlxsw_sp_fid_reiv_handle(fid, rif_index, !valid, i);
666 int mlxsw_sp_fid_rif_set(struct mlxsw_sp_fid *fid, struct mlxsw_sp_rif *rif)
668 u16 rif_index = mlxsw_sp_rif_index(rif);
671 if (!fid->fid_family->mlxsw_sp->ubridge) {
676 err = mlxsw_sp_fid_to_fid_rif_update(fid, rif);
680 err = mlxsw_sp_fid_vni_to_fid_rif_update(fid, rif);
682 goto err_vni_to_fid_rif_update;
684 err = mlxsw_sp_fid_vid_to_fid_rif_set(fid, rif);
686 goto err_vid_to_fid_rif_set;
688 err = mlxsw_sp_fid_erif_eport_to_vid_map(fid, rif_index, true);
690 goto err_erif_eport_to_vid_map;
695 err_erif_eport_to_vid_map:
696 mlxsw_sp_fid_vid_to_fid_rif_unset(fid);
697 err_vid_to_fid_rif_set:
698 mlxsw_sp_fid_vni_to_fid_rif_update(fid, NULL);
699 err_vni_to_fid_rif_update:
700 mlxsw_sp_fid_to_fid_rif_update(fid, NULL);
704 void mlxsw_sp_fid_rif_unset(struct mlxsw_sp_fid *fid)
708 if (!fid->fid_family->mlxsw_sp->ubridge) {
716 rif_index = mlxsw_sp_rif_index(fid->rif);
719 mlxsw_sp_fid_erif_eport_to_vid_map(fid, rif_index, false);
720 mlxsw_sp_fid_vid_to_fid_rif_unset(fid);
721 mlxsw_sp_fid_vni_to_fid_rif_update(fid, NULL);
722 mlxsw_sp_fid_to_fid_rif_update(fid, NULL);
725 static int mlxsw_sp_fid_vni_op(const struct mlxsw_sp_fid *fid)
727 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
730 if (mlxsw_sp->ubridge) {
731 err = mlxsw_sp_fid_vni_to_fid_map(fid, fid->rif,
737 err = mlxsw_sp_fid_edit_op(fid, fid->rif);
739 goto err_fid_edit_op;
744 if (mlxsw_sp->ubridge)
745 mlxsw_sp_fid_vni_to_fid_map(fid, fid->rif, !fid->vni_valid);
749 static int __mlxsw_sp_fid_port_vid_map(const struct mlxsw_sp_fid *fid,
750 u16 local_port, u16 vid, bool valid)
752 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
753 char svfa_pl[MLXSW_REG_SVFA_LEN];
754 bool irif_valid = false;
757 if (mlxsw_sp->ubridge && fid->rif) {
759 irif_index = mlxsw_sp_rif_index(fid->rif);
762 mlxsw_reg_svfa_port_vid_pack(svfa_pl, local_port, valid, fid->fid_index,
763 vid, irif_valid, irif_index);
764 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl);
767 static struct mlxsw_sp_fid_8021d *
768 mlxsw_sp_fid_8021d_fid(const struct mlxsw_sp_fid *fid)
770 return container_of(fid, struct mlxsw_sp_fid_8021d, common);
773 static void mlxsw_sp_fid_8021d_setup(struct mlxsw_sp_fid *fid, const void *arg)
775 int br_ifindex = *(int *) arg;
777 mlxsw_sp_fid_8021d_fid(fid)->br_ifindex = br_ifindex;
781 static int mlxsw_sp_fid_8021d_configure(struct mlxsw_sp_fid *fid)
783 return mlxsw_sp_fid_op(fid, true);
786 static void mlxsw_sp_fid_8021d_deconfigure(struct mlxsw_sp_fid *fid)
789 mlxsw_sp_nve_fid_disable(fid->fid_family->mlxsw_sp, fid);
790 mlxsw_sp_fid_op(fid, false);
793 static int mlxsw_sp_fid_8021d_index_alloc(struct mlxsw_sp_fid *fid,
794 const void *arg, u16 *p_fid_index)
796 struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
797 u16 nr_fids, fid_index;
799 nr_fids = fid_family->end_index - fid_family->start_index + 1;
800 fid_index = find_first_zero_bit(fid_family->fids_bitmap, nr_fids);
801 if (fid_index == nr_fids)
803 *p_fid_index = fid_family->start_index + fid_index;
809 mlxsw_sp_fid_8021d_compare(const struct mlxsw_sp_fid *fid, const void *arg)
811 int br_ifindex = *(int *) arg;
813 return mlxsw_sp_fid_8021d_fid(fid)->br_ifindex == br_ifindex;
816 static u16 mlxsw_sp_fid_8021d_flood_index(const struct mlxsw_sp_fid *fid)
818 return fid->fid_index - VLAN_N_VID;
821 static int mlxsw_sp_port_vp_mode_trans(struct mlxsw_sp_port *mlxsw_sp_port)
823 struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
826 list_for_each_entry(mlxsw_sp_port_vlan, &mlxsw_sp_port->vlans_list,
828 struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid;
829 u16 vid = mlxsw_sp_port_vlan->vid;
834 err = __mlxsw_sp_fid_port_vid_map(fid,
835 mlxsw_sp_port->local_port,
838 goto err_fid_port_vid_map;
841 err = mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, true);
843 goto err_port_vp_mode_set;
847 err_port_vp_mode_set:
848 err_fid_port_vid_map:
849 list_for_each_entry_continue_reverse(mlxsw_sp_port_vlan,
850 &mlxsw_sp_port->vlans_list, list) {
851 struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid;
852 u16 vid = mlxsw_sp_port_vlan->vid;
857 __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid,
863 static void mlxsw_sp_port_vlan_mode_trans(struct mlxsw_sp_port *mlxsw_sp_port)
865 struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
867 mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, false);
869 list_for_each_entry_reverse(mlxsw_sp_port_vlan,
870 &mlxsw_sp_port->vlans_list, list) {
871 struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid;
872 u16 vid = mlxsw_sp_port_vlan->vid;
877 __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid,
883 mlxsw_sp_fid_port_vid_list_add(struct mlxsw_sp_fid *fid, u16 local_port,
886 struct mlxsw_sp_fid_port_vid *port_vid, *tmp_port_vid;
888 port_vid = kzalloc(sizeof(*port_vid), GFP_KERNEL);
892 port_vid->local_port = local_port;
895 list_for_each_entry(tmp_port_vid, &fid->port_vid_list, list) {
896 if (tmp_port_vid->local_port > local_port)
900 list_add_tail(&port_vid->list, &tmp_port_vid->list);
905 mlxsw_sp_fid_port_vid_list_del(struct mlxsw_sp_fid *fid, u16 local_port,
908 struct mlxsw_sp_fid_port_vid *port_vid, *tmp;
910 list_for_each_entry_safe(port_vid, tmp, &fid->port_vid_list, list) {
911 if (port_vid->local_port != local_port || port_vid->vid != vid)
914 list_del(&port_vid->list);
921 mlxsw_sp_fid_mpe_table_map(const struct mlxsw_sp_fid *fid, u16 local_port,
924 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
925 char smpe_pl[MLXSW_REG_SMPE_LEN];
927 mlxsw_reg_smpe_pack(smpe_pl, local_port, fid->fid_index,
929 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(smpe), smpe_pl);
933 mlxsw_sp_fid_erif_eport_to_vid_map_one(const struct mlxsw_sp_fid *fid,
934 u16 local_port, u16 vid, bool valid)
936 u8 port_page = local_port / MLXSW_REG_REIV_REC_MAX_COUNT;
937 u8 rec_num = local_port % MLXSW_REG_REIV_REC_MAX_COUNT;
938 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
939 u16 rif_index = mlxsw_sp_rif_index(fid->rif);
943 reiv_pl = kmalloc(MLXSW_REG_REIV_LEN, GFP_KERNEL);
947 mlxsw_reg_reiv_pack(reiv_pl, port_page, rif_index);
948 mlxsw_reg_reiv_rec_update_set(reiv_pl, rec_num, true);
949 mlxsw_reg_reiv_rec_evid_set(reiv_pl, rec_num, valid ? vid : 0);
950 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(reiv), reiv_pl);
955 static int mlxsw_sp_fid_evid_map(const struct mlxsw_sp_fid *fid, u16 local_port,
960 err = mlxsw_sp_fid_mpe_table_map(fid, local_port, vid, valid);
967 err = mlxsw_sp_fid_erif_eport_to_vid_map_one(fid, local_port, vid,
970 goto err_erif_eport_to_vid_map_one;
974 err_erif_eport_to_vid_map_one:
975 mlxsw_sp_fid_mpe_table_map(fid, local_port, vid, !valid);
979 static int mlxsw_sp_fid_8021d_port_vid_map(struct mlxsw_sp_fid *fid,
980 struct mlxsw_sp_port *mlxsw_sp_port,
983 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
984 u16 local_port = mlxsw_sp_port->local_port;
987 err = __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid,
992 if (fid->fid_family->mlxsw_sp->ubridge) {
993 err = mlxsw_sp_fid_evid_map(fid, local_port, vid, true);
995 goto err_fid_evid_map;
998 err = mlxsw_sp_fid_port_vid_list_add(fid, mlxsw_sp_port->local_port,
1001 goto err_port_vid_list_add;
1003 if (mlxsw_sp->fid_core->port_fid_mappings[local_port]++ == 0) {
1004 err = mlxsw_sp_port_vp_mode_trans(mlxsw_sp_port);
1006 goto err_port_vp_mode_trans;
1011 err_port_vp_mode_trans:
1012 mlxsw_sp->fid_core->port_fid_mappings[local_port]--;
1013 mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid);
1014 err_port_vid_list_add:
1015 if (fid->fid_family->mlxsw_sp->ubridge)
1016 mlxsw_sp_fid_evid_map(fid, local_port, vid, false);
1018 __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, false);
1023 mlxsw_sp_fid_8021d_port_vid_unmap(struct mlxsw_sp_fid *fid,
1024 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
1026 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1027 u16 local_port = mlxsw_sp_port->local_port;
1029 if (mlxsw_sp->fid_core->port_fid_mappings[local_port] == 1)
1030 mlxsw_sp_port_vlan_mode_trans(mlxsw_sp_port);
1031 mlxsw_sp->fid_core->port_fid_mappings[local_port]--;
1032 mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid);
1033 if (fid->fid_family->mlxsw_sp->ubridge)
1034 mlxsw_sp_fid_evid_map(fid, local_port, vid, false);
1035 __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, false);
1038 static int mlxsw_sp_fid_8021d_vni_set(struct mlxsw_sp_fid *fid)
1040 return mlxsw_sp_fid_vni_op(fid);
1043 static void mlxsw_sp_fid_8021d_vni_clear(struct mlxsw_sp_fid *fid)
1045 mlxsw_sp_fid_vni_op(fid);
1048 static int mlxsw_sp_fid_8021d_nve_flood_index_set(struct mlxsw_sp_fid *fid)
1050 return mlxsw_sp_fid_edit_op(fid, fid->rif);
1053 static void mlxsw_sp_fid_8021d_nve_flood_index_clear(struct mlxsw_sp_fid *fid)
1055 mlxsw_sp_fid_edit_op(fid, fid->rif);
1059 mlxsw_sp_fid_8021d_fdb_clear_offload(const struct mlxsw_sp_fid *fid,
1060 const struct net_device *nve_dev)
1062 br_fdb_clear_offload(nve_dev, 0);
1065 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021d_ops = {
1066 .setup = mlxsw_sp_fid_8021d_setup,
1067 .configure = mlxsw_sp_fid_8021d_configure,
1068 .deconfigure = mlxsw_sp_fid_8021d_deconfigure,
1069 .index_alloc = mlxsw_sp_fid_8021d_index_alloc,
1070 .compare = mlxsw_sp_fid_8021d_compare,
1071 .flood_index = mlxsw_sp_fid_8021d_flood_index,
1072 .port_vid_map = mlxsw_sp_fid_8021d_port_vid_map,
1073 .port_vid_unmap = mlxsw_sp_fid_8021d_port_vid_unmap,
1074 .vni_set = mlxsw_sp_fid_8021d_vni_set,
1075 .vni_clear = mlxsw_sp_fid_8021d_vni_clear,
1076 .nve_flood_index_set = mlxsw_sp_fid_8021d_nve_flood_index_set,
1077 .nve_flood_index_clear = mlxsw_sp_fid_8021d_nve_flood_index_clear,
1078 .fdb_clear_offload = mlxsw_sp_fid_8021d_fdb_clear_offload,
1081 #define MLXSW_SP_FID_8021Q_MAX (VLAN_N_VID - 2)
1082 #define MLXSW_SP_FID_8021Q_PGT_BASE 0
1083 #define MLXSW_SP_FID_8021D_PGT_BASE (3 * MLXSW_SP_FID_8021Q_MAX)
1085 static const struct mlxsw_sp_flood_table mlxsw_sp_fid_8021d_flood_tables[] = {
1087 .packet_type = MLXSW_SP_FLOOD_TYPE_UC,
1088 .table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID,
1092 .packet_type = MLXSW_SP_FLOOD_TYPE_MC,
1093 .table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID,
1097 .packet_type = MLXSW_SP_FLOOD_TYPE_BC,
1098 .table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID,
1103 /* Range and flood configuration must match mlxsw_config_profile */
1104 static const struct mlxsw_sp_fid_family mlxsw_sp_fid_8021d_family = {
1105 .type = MLXSW_SP_FID_TYPE_8021D,
1106 .fid_size = sizeof(struct mlxsw_sp_fid_8021d),
1107 .start_index = VLAN_N_VID,
1108 .end_index = VLAN_N_VID + MLXSW_SP_FID_8021D_MAX - 1,
1109 .flood_tables = mlxsw_sp_fid_8021d_flood_tables,
1110 .nr_flood_tables = ARRAY_SIZE(mlxsw_sp_fid_8021d_flood_tables),
1111 .rif_type = MLXSW_SP_RIF_TYPE_FID,
1112 .ops = &mlxsw_sp_fid_8021d_ops,
1113 .bridge_type = MLXSW_REG_BRIDGE_TYPE_1,
1114 .pgt_base = MLXSW_SP_FID_8021D_PGT_BASE,
1118 mlxsw_sp_fid_8021q_compare(const struct mlxsw_sp_fid *fid, const void *arg)
1120 u16 vid = *(u16 *) arg;
1122 return mlxsw_sp_fid_8021q_fid(fid)->vid == vid;
1126 mlxsw_sp_fid_8021q_fdb_clear_offload(const struct mlxsw_sp_fid *fid,
1127 const struct net_device *nve_dev)
1129 br_fdb_clear_offload(nve_dev, mlxsw_sp_fid_8021q_vid(fid));
1132 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021q_emu_ops = {
1133 .setup = mlxsw_sp_fid_8021q_setup,
1134 .configure = mlxsw_sp_fid_8021d_configure,
1135 .deconfigure = mlxsw_sp_fid_8021d_deconfigure,
1136 .index_alloc = mlxsw_sp_fid_8021d_index_alloc,
1137 .compare = mlxsw_sp_fid_8021q_compare,
1138 .flood_index = mlxsw_sp_fid_8021d_flood_index,
1139 .port_vid_map = mlxsw_sp_fid_8021d_port_vid_map,
1140 .port_vid_unmap = mlxsw_sp_fid_8021d_port_vid_unmap,
1141 .vni_set = mlxsw_sp_fid_8021d_vni_set,
1142 .vni_clear = mlxsw_sp_fid_8021d_vni_clear,
1143 .nve_flood_index_set = mlxsw_sp_fid_8021d_nve_flood_index_set,
1144 .nve_flood_index_clear = mlxsw_sp_fid_8021d_nve_flood_index_clear,
1145 .fdb_clear_offload = mlxsw_sp_fid_8021q_fdb_clear_offload,
1148 /* There are 4K-2 emulated 802.1Q FIDs, starting right after the 802.1D FIDs */
1149 #define MLXSW_SP_FID_8021Q_EMU_START (VLAN_N_VID + MLXSW_SP_FID_8021D_MAX)
1150 #define MLXSW_SP_FID_8021Q_EMU_END (MLXSW_SP_FID_8021Q_EMU_START + \
1151 MLXSW_SP_FID_8021Q_MAX - 1)
1153 /* Range and flood configuration must match mlxsw_config_profile */
1154 static const struct mlxsw_sp_fid_family mlxsw_sp_fid_8021q_emu_family = {
1155 .type = MLXSW_SP_FID_TYPE_8021Q,
1156 .fid_size = sizeof(struct mlxsw_sp_fid_8021q),
1157 .start_index = MLXSW_SP_FID_8021Q_EMU_START,
1158 .end_index = MLXSW_SP_FID_8021Q_EMU_END,
1159 .flood_tables = mlxsw_sp_fid_8021d_flood_tables,
1160 .nr_flood_tables = ARRAY_SIZE(mlxsw_sp_fid_8021d_flood_tables),
1161 .rif_type = MLXSW_SP_RIF_TYPE_VLAN_EMU,
1162 .ops = &mlxsw_sp_fid_8021q_emu_ops,
1163 .bridge_type = MLXSW_REG_BRIDGE_TYPE_1,
1164 .pgt_base = MLXSW_SP_FID_8021Q_PGT_BASE,
1167 static void mlxsw_sp_fid_rfid_setup(struct mlxsw_sp_fid *fid, const void *arg)
1169 fid->fid_offset = 0;
1172 static int mlxsw_sp_fid_rfid_configure(struct mlxsw_sp_fid *fid)
1174 /* rFIDs are allocated by the device during init */
1178 static void mlxsw_sp_fid_rfid_deconfigure(struct mlxsw_sp_fid *fid)
1182 static int mlxsw_sp_fid_rfid_index_alloc(struct mlxsw_sp_fid *fid,
1183 const void *arg, u16 *p_fid_index)
1185 u16 rif_index = *(u16 *) arg;
1187 *p_fid_index = fid->fid_family->start_index + rif_index;
1192 static bool mlxsw_sp_fid_rfid_compare(const struct mlxsw_sp_fid *fid,
1195 u16 rif_index = *(u16 *) arg;
1197 return fid->fid_index == rif_index + fid->fid_family->start_index;
1200 static int mlxsw_sp_fid_rfid_port_vid_map(struct mlxsw_sp_fid *fid,
1201 struct mlxsw_sp_port *mlxsw_sp_port,
1204 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1205 u16 local_port = mlxsw_sp_port->local_port;
1208 err = mlxsw_sp_fid_port_vid_list_add(fid, mlxsw_sp_port->local_port,
1213 /* We only need to transition the port to virtual mode since
1214 * {Port, VID} => FID is done by the firmware upon RIF creation.
1216 if (mlxsw_sp->fid_core->port_fid_mappings[local_port]++ == 0) {
1217 err = mlxsw_sp_port_vp_mode_trans(mlxsw_sp_port);
1219 goto err_port_vp_mode_trans;
1224 err_port_vp_mode_trans:
1225 mlxsw_sp->fid_core->port_fid_mappings[local_port]--;
1226 mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid);
1231 mlxsw_sp_fid_rfid_port_vid_unmap(struct mlxsw_sp_fid *fid,
1232 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
1234 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1235 u16 local_port = mlxsw_sp_port->local_port;
1237 if (mlxsw_sp->fid_core->port_fid_mappings[local_port] == 1)
1238 mlxsw_sp_port_vlan_mode_trans(mlxsw_sp_port);
1239 mlxsw_sp->fid_core->port_fid_mappings[local_port]--;
1240 mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid);
1243 static int mlxsw_sp_fid_rfid_vni_set(struct mlxsw_sp_fid *fid)
1248 static void mlxsw_sp_fid_rfid_vni_clear(struct mlxsw_sp_fid *fid)
1253 static int mlxsw_sp_fid_rfid_nve_flood_index_set(struct mlxsw_sp_fid *fid)
1258 static void mlxsw_sp_fid_rfid_nve_flood_index_clear(struct mlxsw_sp_fid *fid)
1263 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_rfid_ops = {
1264 .setup = mlxsw_sp_fid_rfid_setup,
1265 .configure = mlxsw_sp_fid_rfid_configure,
1266 .deconfigure = mlxsw_sp_fid_rfid_deconfigure,
1267 .index_alloc = mlxsw_sp_fid_rfid_index_alloc,
1268 .compare = mlxsw_sp_fid_rfid_compare,
1269 .port_vid_map = mlxsw_sp_fid_rfid_port_vid_map,
1270 .port_vid_unmap = mlxsw_sp_fid_rfid_port_vid_unmap,
1271 .vni_set = mlxsw_sp_fid_rfid_vni_set,
1272 .vni_clear = mlxsw_sp_fid_rfid_vni_clear,
1273 .nve_flood_index_set = mlxsw_sp_fid_rfid_nve_flood_index_set,
1274 .nve_flood_index_clear = mlxsw_sp_fid_rfid_nve_flood_index_clear,
1277 #define MLXSW_SP_RFID_BASE (15 * 1024)
1278 #define MLXSW_SP_RFID_MAX 1024
1280 static const struct mlxsw_sp_fid_family mlxsw_sp_fid_rfid_family = {
1281 .type = MLXSW_SP_FID_TYPE_RFID,
1282 .fid_size = sizeof(struct mlxsw_sp_fid),
1283 .start_index = MLXSW_SP_RFID_BASE,
1284 .end_index = MLXSW_SP_RFID_BASE + MLXSW_SP_RFID_MAX - 1,
1285 .rif_type = MLXSW_SP_RIF_TYPE_SUBPORT,
1286 .ops = &mlxsw_sp_fid_rfid_ops,
1290 static void mlxsw_sp_fid_dummy_setup(struct mlxsw_sp_fid *fid, const void *arg)
1292 fid->fid_offset = 0;
1295 static int mlxsw_sp_fid_dummy_configure(struct mlxsw_sp_fid *fid)
1297 return mlxsw_sp_fid_op(fid, true);
1300 static void mlxsw_sp_fid_dummy_deconfigure(struct mlxsw_sp_fid *fid)
1302 mlxsw_sp_fid_op(fid, false);
1305 static int mlxsw_sp_fid_dummy_index_alloc(struct mlxsw_sp_fid *fid,
1306 const void *arg, u16 *p_fid_index)
1308 *p_fid_index = fid->fid_family->start_index;
1313 static bool mlxsw_sp_fid_dummy_compare(const struct mlxsw_sp_fid *fid,
1319 static int mlxsw_sp_fid_dummy_vni_set(struct mlxsw_sp_fid *fid)
1324 static void mlxsw_sp_fid_dummy_vni_clear(struct mlxsw_sp_fid *fid)
1329 static int mlxsw_sp_fid_dummy_nve_flood_index_set(struct mlxsw_sp_fid *fid)
1334 static void mlxsw_sp_fid_dummy_nve_flood_index_clear(struct mlxsw_sp_fid *fid)
1339 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_dummy_ops = {
1340 .setup = mlxsw_sp_fid_dummy_setup,
1341 .configure = mlxsw_sp_fid_dummy_configure,
1342 .deconfigure = mlxsw_sp_fid_dummy_deconfigure,
1343 .index_alloc = mlxsw_sp_fid_dummy_index_alloc,
1344 .compare = mlxsw_sp_fid_dummy_compare,
1345 .vni_set = mlxsw_sp_fid_dummy_vni_set,
1346 .vni_clear = mlxsw_sp_fid_dummy_vni_clear,
1347 .nve_flood_index_set = mlxsw_sp_fid_dummy_nve_flood_index_set,
1348 .nve_flood_index_clear = mlxsw_sp_fid_dummy_nve_flood_index_clear,
1351 static const struct mlxsw_sp_fid_family mlxsw_sp_fid_dummy_family = {
1352 .type = MLXSW_SP_FID_TYPE_DUMMY,
1353 .fid_size = sizeof(struct mlxsw_sp_fid),
1354 .start_index = VLAN_N_VID - 1,
1355 .end_index = VLAN_N_VID - 1,
1356 .ops = &mlxsw_sp_fid_dummy_ops,
1359 const struct mlxsw_sp_fid_family *mlxsw_sp1_fid_family_arr[] = {
1360 [MLXSW_SP_FID_TYPE_8021Q] = &mlxsw_sp_fid_8021q_emu_family,
1361 [MLXSW_SP_FID_TYPE_8021D] = &mlxsw_sp_fid_8021d_family,
1362 [MLXSW_SP_FID_TYPE_RFID] = &mlxsw_sp_fid_rfid_family,
1363 [MLXSW_SP_FID_TYPE_DUMMY] = &mlxsw_sp_fid_dummy_family,
1366 const struct mlxsw_sp_fid_family *mlxsw_sp2_fid_family_arr[] = {
1367 [MLXSW_SP_FID_TYPE_8021Q] = &mlxsw_sp_fid_8021q_emu_family,
1368 [MLXSW_SP_FID_TYPE_8021D] = &mlxsw_sp_fid_8021d_family,
1369 [MLXSW_SP_FID_TYPE_RFID] = &mlxsw_sp_fid_rfid_family,
1370 [MLXSW_SP_FID_TYPE_DUMMY] = &mlxsw_sp_fid_dummy_family,
1373 static struct mlxsw_sp_fid *mlxsw_sp_fid_lookup(struct mlxsw_sp *mlxsw_sp,
1374 enum mlxsw_sp_fid_type type,
1377 struct mlxsw_sp_fid_family *fid_family;
1378 struct mlxsw_sp_fid *fid;
1380 fid_family = mlxsw_sp->fid_core->fid_family_arr[type];
1381 list_for_each_entry(fid, &fid_family->fids_list, list) {
1382 if (!fid->fid_family->ops->compare(fid, arg))
1384 refcount_inc(&fid->ref_count);
1391 static struct mlxsw_sp_fid *mlxsw_sp_fid_get(struct mlxsw_sp *mlxsw_sp,
1392 enum mlxsw_sp_fid_type type,
1395 struct mlxsw_sp_fid_family *fid_family;
1396 struct mlxsw_sp_fid *fid;
1400 fid = mlxsw_sp_fid_lookup(mlxsw_sp, type, arg);
1404 fid_family = mlxsw_sp->fid_core->fid_family_arr[type];
1405 fid = kzalloc(fid_family->fid_size, GFP_KERNEL);
1407 return ERR_PTR(-ENOMEM);
1409 INIT_LIST_HEAD(&fid->port_vid_list);
1410 fid->fid_family = fid_family;
1412 err = fid->fid_family->ops->index_alloc(fid, arg, &fid_index);
1414 goto err_index_alloc;
1415 fid->fid_index = fid_index;
1416 __set_bit(fid_index - fid_family->start_index, fid_family->fids_bitmap);
1418 fid->fid_family->ops->setup(fid, arg);
1420 err = fid->fid_family->ops->configure(fid);
1424 err = rhashtable_insert_fast(&mlxsw_sp->fid_core->fid_ht, &fid->ht_node,
1425 mlxsw_sp_fid_ht_params);
1427 goto err_rhashtable_insert;
1429 list_add(&fid->list, &fid_family->fids_list);
1430 refcount_set(&fid->ref_count, 1);
1433 err_rhashtable_insert:
1434 fid->fid_family->ops->deconfigure(fid);
1436 __clear_bit(fid_index - fid_family->start_index,
1437 fid_family->fids_bitmap);
1440 return ERR_PTR(err);
1443 void mlxsw_sp_fid_put(struct mlxsw_sp_fid *fid)
1445 struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
1446 struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
1448 if (!refcount_dec_and_test(&fid->ref_count))
1451 list_del(&fid->list);
1452 rhashtable_remove_fast(&mlxsw_sp->fid_core->fid_ht,
1453 &fid->ht_node, mlxsw_sp_fid_ht_params);
1454 fid->fid_family->ops->deconfigure(fid);
1455 __clear_bit(fid->fid_index - fid_family->start_index,
1456 fid_family->fids_bitmap);
1457 WARN_ON_ONCE(!list_empty(&fid->port_vid_list));
1461 struct mlxsw_sp_fid *mlxsw_sp_fid_8021q_get(struct mlxsw_sp *mlxsw_sp, u16 vid)
1463 return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_8021Q, &vid);
1466 struct mlxsw_sp_fid *mlxsw_sp_fid_8021d_get(struct mlxsw_sp *mlxsw_sp,
1469 return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_8021D, &br_ifindex);
1472 struct mlxsw_sp_fid *mlxsw_sp_fid_8021q_lookup(struct mlxsw_sp *mlxsw_sp,
1475 return mlxsw_sp_fid_lookup(mlxsw_sp, MLXSW_SP_FID_TYPE_8021Q, &vid);
1478 struct mlxsw_sp_fid *mlxsw_sp_fid_8021d_lookup(struct mlxsw_sp *mlxsw_sp,
1481 return mlxsw_sp_fid_lookup(mlxsw_sp, MLXSW_SP_FID_TYPE_8021D,
1485 struct mlxsw_sp_fid *mlxsw_sp_fid_rfid_get(struct mlxsw_sp *mlxsw_sp,
1488 return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_RFID, &rif_index);
1491 struct mlxsw_sp_fid *mlxsw_sp_fid_dummy_get(struct mlxsw_sp *mlxsw_sp)
1493 return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_DUMMY, NULL);
1497 mlxsw_sp_fid_flood_table_init(struct mlxsw_sp_fid_family *fid_family,
1498 const struct mlxsw_sp_flood_table *flood_table)
1500 enum mlxsw_sp_flood_type packet_type = flood_table->packet_type;
1501 struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
1502 u16 mid_base, num_fids, table_index;
1503 const int *sfgc_packet_types;
1506 mid_base = mlxsw_sp_fid_flood_table_mid(fid_family, flood_table, 0);
1507 num_fids = mlxsw_sp_fid_family_num_fids(fid_family);
1508 err = mlxsw_sp_pgt_mid_alloc_range(mlxsw_sp, mid_base, num_fids);
1512 sfgc_packet_types = mlxsw_sp_packet_type_sfgc_types[packet_type];
1513 for (i = 0; i < MLXSW_REG_SFGC_TYPE_MAX; i++) {
1514 char sfgc_pl[MLXSW_REG_SFGC_LEN];
1516 if (!sfgc_packet_types[i])
1519 mid_base = mlxsw_sp->ubridge ? mid_base : 0;
1520 table_index = mlxsw_sp->ubridge ? 0 : flood_table->table_index;
1522 mlxsw_reg_sfgc_pack(sfgc_pl, i, fid_family->bridge_type,
1523 flood_table->table_type, table_index,
1526 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfgc), sfgc_pl);
1534 mid_base = mlxsw_sp_fid_flood_table_mid(fid_family, flood_table, 0);
1535 mlxsw_sp_pgt_mid_free_range(mlxsw_sp, mid_base, num_fids);
1540 mlxsw_sp_fid_flood_table_fini(struct mlxsw_sp_fid_family *fid_family,
1541 const struct mlxsw_sp_flood_table *flood_table)
1543 struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
1544 u16 num_fids, mid_base;
1546 mid_base = mlxsw_sp_fid_flood_table_mid(fid_family, flood_table, 0);
1547 num_fids = mlxsw_sp_fid_family_num_fids(fid_family);
1548 mlxsw_sp_pgt_mid_free_range(mlxsw_sp, mid_base, num_fids);
1552 mlxsw_sp_fid_flood_tables_init(struct mlxsw_sp_fid_family *fid_family)
1556 for (i = 0; i < fid_family->nr_flood_tables; i++) {
1557 const struct mlxsw_sp_flood_table *flood_table;
1560 flood_table = &fid_family->flood_tables[i];
1561 err = mlxsw_sp_fid_flood_table_init(fid_family, flood_table);
1570 mlxsw_sp_fid_flood_tables_fini(struct mlxsw_sp_fid_family *fid_family)
1574 for (i = 0; i < fid_family->nr_flood_tables; i++) {
1575 const struct mlxsw_sp_flood_table *flood_table;
1577 flood_table = &fid_family->flood_tables[i];
1578 mlxsw_sp_fid_flood_table_fini(fid_family, flood_table);
1582 static int mlxsw_sp_fid_family_register(struct mlxsw_sp *mlxsw_sp,
1583 const struct mlxsw_sp_fid_family *tmpl)
1585 u16 nr_fids = tmpl->end_index - tmpl->start_index + 1;
1586 struct mlxsw_sp_fid_family *fid_family;
1589 fid_family = kmemdup(tmpl, sizeof(*fid_family), GFP_KERNEL);
1593 fid_family->mlxsw_sp = mlxsw_sp;
1594 INIT_LIST_HEAD(&fid_family->fids_list);
1595 fid_family->fids_bitmap = bitmap_zalloc(nr_fids, GFP_KERNEL);
1596 if (!fid_family->fids_bitmap) {
1598 goto err_alloc_fids_bitmap;
1601 if (fid_family->flood_tables) {
1602 err = mlxsw_sp_fid_flood_tables_init(fid_family);
1604 goto err_fid_flood_tables_init;
1607 mlxsw_sp->fid_core->fid_family_arr[tmpl->type] = fid_family;
1611 err_fid_flood_tables_init:
1612 bitmap_free(fid_family->fids_bitmap);
1613 err_alloc_fids_bitmap:
1619 mlxsw_sp_fid_family_unregister(struct mlxsw_sp *mlxsw_sp,
1620 struct mlxsw_sp_fid_family *fid_family)
1622 mlxsw_sp->fid_core->fid_family_arr[fid_family->type] = NULL;
1624 if (fid_family->flood_tables)
1625 mlxsw_sp_fid_flood_tables_fini(fid_family);
1627 bitmap_free(fid_family->fids_bitmap);
1628 WARN_ON_ONCE(!list_empty(&fid_family->fids_list));
1632 int mlxsw_sp_port_fids_init(struct mlxsw_sp_port *mlxsw_sp_port)
1634 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1636 /* Track number of FIDs configured on the port with mapping type
1637 * PORT_VID_TO_FID, so that we know when to transition the port
1638 * back to non-virtual (VLAN) mode.
1640 mlxsw_sp->fid_core->port_fid_mappings[mlxsw_sp_port->local_port] = 0;
1642 return mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, false);
1645 void mlxsw_sp_port_fids_fini(struct mlxsw_sp_port *mlxsw_sp_port)
1647 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1649 mlxsw_sp->fid_core->port_fid_mappings[mlxsw_sp_port->local_port] = 0;
1652 int mlxsw_sp_fids_init(struct mlxsw_sp *mlxsw_sp)
1654 unsigned int max_ports = mlxsw_core_max_ports(mlxsw_sp->core);
1655 struct mlxsw_sp_fid_core *fid_core;
1658 fid_core = kzalloc(sizeof(*mlxsw_sp->fid_core), GFP_KERNEL);
1661 mlxsw_sp->fid_core = fid_core;
1663 err = rhashtable_init(&fid_core->fid_ht, &mlxsw_sp_fid_ht_params);
1665 goto err_rhashtable_fid_init;
1667 err = rhashtable_init(&fid_core->vni_ht, &mlxsw_sp_fid_vni_ht_params);
1669 goto err_rhashtable_vni_init;
1671 fid_core->port_fid_mappings = kcalloc(max_ports, sizeof(unsigned int),
1673 if (!fid_core->port_fid_mappings) {
1675 goto err_alloc_port_fid_mappings;
1678 for (i = 0; i < MLXSW_SP_FID_TYPE_MAX; i++) {
1679 err = mlxsw_sp_fid_family_register(mlxsw_sp,
1680 mlxsw_sp->fid_family_arr[i]);
1683 goto err_fid_ops_register;
1688 err_fid_ops_register:
1689 for (i--; i >= 0; i--) {
1690 struct mlxsw_sp_fid_family *fid_family;
1692 fid_family = fid_core->fid_family_arr[i];
1693 mlxsw_sp_fid_family_unregister(mlxsw_sp, fid_family);
1695 kfree(fid_core->port_fid_mappings);
1696 err_alloc_port_fid_mappings:
1697 rhashtable_destroy(&fid_core->vni_ht);
1698 err_rhashtable_vni_init:
1699 rhashtable_destroy(&fid_core->fid_ht);
1700 err_rhashtable_fid_init:
1705 void mlxsw_sp_fids_fini(struct mlxsw_sp *mlxsw_sp)
1707 struct mlxsw_sp_fid_core *fid_core = mlxsw_sp->fid_core;
1710 for (i = 0; i < MLXSW_SP_FID_TYPE_MAX; i++)
1711 mlxsw_sp_fid_family_unregister(mlxsw_sp,
1712 fid_core->fid_family_arr[i]);
1713 kfree(fid_core->port_fid_mappings);
1714 rhashtable_destroy(&fid_core->vni_ht);
1715 rhashtable_destroy(&fid_core->fid_ht);