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>
14 #include "spectrum_router.h"
17 struct mlxsw_sp_fid_family;
19 struct mlxsw_sp_fid_core {
20 struct rhashtable fid_ht;
21 struct rhashtable vni_ht;
22 struct mlxsw_sp_fid_family *fid_family_arr[MLXSW_SP_FID_TYPE_MAX];
23 unsigned int *port_fid_mappings;
26 struct mlxsw_sp_fid_port_vid {
27 struct list_head list;
33 struct list_head list;
34 struct mlxsw_sp_rif *rif;
38 struct mlxsw_sp_fid_family *fid_family;
39 struct rhash_head ht_node;
41 struct rhash_head vni_ht_node;
42 enum mlxsw_sp_nve_type nve_type;
47 nve_flood_index_valid:1;
48 struct list_head port_vid_list; /* Ordered by local port. */
51 struct mlxsw_sp_fid_8021q {
52 struct mlxsw_sp_fid common;
56 struct mlxsw_sp_fid_8021d {
57 struct mlxsw_sp_fid common;
61 static const struct rhashtable_params mlxsw_sp_fid_ht_params = {
62 .key_len = sizeof_field(struct mlxsw_sp_fid, fid_index),
63 .key_offset = offsetof(struct mlxsw_sp_fid, fid_index),
64 .head_offset = offsetof(struct mlxsw_sp_fid, ht_node),
67 static const struct rhashtable_params mlxsw_sp_fid_vni_ht_params = {
68 .key_len = sizeof_field(struct mlxsw_sp_fid, vni),
69 .key_offset = offsetof(struct mlxsw_sp_fid, vni),
70 .head_offset = offsetof(struct mlxsw_sp_fid, vni_ht_node),
73 struct mlxsw_sp_flood_table {
74 enum mlxsw_sp_flood_type packet_type;
75 enum mlxsw_flood_table_type table_type; /* For flood_mode!=CFF. */
79 struct mlxsw_sp_fid_ops {
80 int (*setup)(struct mlxsw_sp_fid *fid, const void *arg);
81 int (*configure)(struct mlxsw_sp_fid *fid);
82 void (*deconfigure)(struct mlxsw_sp_fid *fid);
83 int (*index_alloc)(struct mlxsw_sp_fid *fid, const void *arg,
85 bool (*compare)(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);
97 int (*vid_to_fid_rif_update)(const struct mlxsw_sp_fid *fid,
98 const struct mlxsw_sp_rif *rif);
99 int (*flood_table_init)(struct mlxsw_sp_fid_family *fid_family,
100 const struct mlxsw_sp_flood_table *flood_table);
101 int (*pgt_size)(const struct mlxsw_sp_fid_family *fid_family,
103 u16 (*fid_mid)(const struct mlxsw_sp_fid *fid,
104 const struct mlxsw_sp_flood_table *flood_table);
105 void (*fid_pack)(char *sfmr_pl, const struct mlxsw_sp_fid *fid,
106 enum mlxsw_reg_sfmr_op op);
108 /* These are specific to RFID families and we assume are only
109 * implemented by RFID families, if at all.
111 int (*fid_port_init)(const struct mlxsw_sp_fid_family *fid_family,
112 const struct mlxsw_sp_port *mlxsw_sp_port);
113 void (*fid_port_fini)(const struct mlxsw_sp_fid_family *fid_family,
114 const struct mlxsw_sp_port *mlxsw_sp_port);
117 enum mlxsw_sp_fid_flood_profile_id {
118 MLXSW_SP_FID_FLOOD_PROFILE_ID_BRIDGE = 1,
119 MLXSW_SP_FID_FLOOD_PROFILE_ID_RSP,
120 MLXSW_SP_FID_FLOOD_PROFILE_ID_NVE,
123 struct mlxsw_sp_fid_flood_profile {
124 const struct mlxsw_sp_flood_table *flood_tables;
126 const enum mlxsw_sp_fid_flood_profile_id profile_id; /* For CFF mode. */
129 struct mlxsw_sp_fid_family {
130 enum mlxsw_sp_fid_type type;
134 struct list_head fids_list;
135 unsigned long *fids_bitmap;
136 const struct mlxsw_sp_fid_flood_profile *flood_profile;
137 enum mlxsw_sp_rif_type rif_type;
138 const struct mlxsw_sp_fid_ops *ops;
139 struct mlxsw_sp *mlxsw_sp;
140 bool flood_rsp; /* For flood_mode!=CFF. */
141 enum mlxsw_reg_bridge_type bridge_type;
143 bool smpe_index_valid;
146 static const int mlxsw_sp_sfgc_uc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = {
147 [MLXSW_REG_SFGC_TYPE_UNKNOWN_UNICAST] = 1,
150 static const int mlxsw_sp_sfgc_bc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = {
151 [MLXSW_REG_SFGC_TYPE_BROADCAST] = 1,
152 [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_NON_IP] = 1,
153 [MLXSW_REG_SFGC_TYPE_IPV4_LINK_LOCAL] = 1,
154 [MLXSW_REG_SFGC_TYPE_IPV6_ALL_HOST] = 1,
155 [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV6] = 1,
158 static const int mlxsw_sp_sfgc_mc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = {
159 [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV4] = 1,
162 static const int mlxsw_sp_sfgc_not_uc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = {
163 [MLXSW_REG_SFGC_TYPE_BROADCAST] = 1,
164 [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_NON_IP] = 1,
165 [MLXSW_REG_SFGC_TYPE_IPV4_LINK_LOCAL] = 1,
166 [MLXSW_REG_SFGC_TYPE_IPV6_ALL_HOST] = 1,
167 [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV6] = 1,
168 [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV4] = 1,
171 static const int mlxsw_sp_sfgc_any_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = {
172 [MLXSW_REG_SFGC_TYPE_UNKNOWN_UNICAST] = 1,
173 [MLXSW_REG_SFGC_TYPE_BROADCAST] = 1,
174 [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_NON_IP] = 1,
175 [MLXSW_REG_SFGC_TYPE_IPV4_LINK_LOCAL] = 1,
176 [MLXSW_REG_SFGC_TYPE_IPV6_ALL_HOST] = 1,
177 [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV6] = 1,
178 [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV4] = 1,
181 static const int *mlxsw_sp_packet_type_sfgc_types[] = {
182 [MLXSW_SP_FLOOD_TYPE_UC] = mlxsw_sp_sfgc_uc_packet_types,
183 [MLXSW_SP_FLOOD_TYPE_BC] = mlxsw_sp_sfgc_bc_packet_types,
184 [MLXSW_SP_FLOOD_TYPE_MC] = mlxsw_sp_sfgc_mc_packet_types,
185 [MLXSW_SP_FLOOD_TYPE_NOT_UC] = mlxsw_sp_sfgc_not_uc_packet_types,
186 [MLXSW_SP_FLOOD_TYPE_ANY] = mlxsw_sp_sfgc_any_packet_types,
189 struct mlxsw_sp_fid *mlxsw_sp_fid_lookup_by_index(struct mlxsw_sp *mlxsw_sp,
192 struct mlxsw_sp_fid *fid;
194 fid = rhashtable_lookup_fast(&mlxsw_sp->fid_core->fid_ht, &fid_index,
195 mlxsw_sp_fid_ht_params);
197 refcount_inc(&fid->ref_count);
202 int mlxsw_sp_fid_nve_ifindex(const struct mlxsw_sp_fid *fid, int *nve_ifindex)
207 *nve_ifindex = fid->nve_ifindex;
212 int mlxsw_sp_fid_nve_type(const struct mlxsw_sp_fid *fid,
213 enum mlxsw_sp_nve_type *p_type)
218 *p_type = fid->nve_type;
223 struct mlxsw_sp_fid *mlxsw_sp_fid_lookup_by_vni(struct mlxsw_sp *mlxsw_sp,
226 struct mlxsw_sp_fid *fid;
228 fid = rhashtable_lookup_fast(&mlxsw_sp->fid_core->vni_ht, &vni,
229 mlxsw_sp_fid_vni_ht_params);
231 refcount_inc(&fid->ref_count);
236 int mlxsw_sp_fid_vni(const struct mlxsw_sp_fid *fid, __be32 *vni)
246 int mlxsw_sp_fid_nve_flood_index_set(struct mlxsw_sp_fid *fid,
249 struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
250 const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
253 if (WARN_ON(fid->nve_flood_index_valid))
256 fid->nve_flood_index = nve_flood_index;
257 fid->nve_flood_index_valid = true;
258 err = ops->nve_flood_index_set(fid);
260 goto err_nve_flood_index_set;
264 err_nve_flood_index_set:
265 fid->nve_flood_index_valid = false;
269 void mlxsw_sp_fid_nve_flood_index_clear(struct mlxsw_sp_fid *fid)
271 struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
272 const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
274 if (WARN_ON(!fid->nve_flood_index_valid))
277 fid->nve_flood_index_valid = false;
278 ops->nve_flood_index_clear(fid);
281 bool mlxsw_sp_fid_nve_flood_index_is_set(const struct mlxsw_sp_fid *fid)
283 return fid->nve_flood_index_valid;
286 int mlxsw_sp_fid_vni_set(struct mlxsw_sp_fid *fid, enum mlxsw_sp_nve_type type,
287 __be32 vni, int nve_ifindex)
289 struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
290 const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
291 struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
294 if (WARN_ON(fid->vni_valid))
297 fid->nve_type = type;
298 fid->nve_ifindex = nve_ifindex;
300 err = rhashtable_lookup_insert_fast(&mlxsw_sp->fid_core->vni_ht,
302 mlxsw_sp_fid_vni_ht_params);
306 fid->vni_valid = true;
307 err = ops->vni_set(fid);
314 fid->vni_valid = false;
315 rhashtable_remove_fast(&mlxsw_sp->fid_core->vni_ht, &fid->vni_ht_node,
316 mlxsw_sp_fid_vni_ht_params);
320 void mlxsw_sp_fid_vni_clear(struct mlxsw_sp_fid *fid)
322 struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
323 const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
324 struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
326 if (WARN_ON(!fid->vni_valid))
329 fid->vni_valid = false;
331 rhashtable_remove_fast(&mlxsw_sp->fid_core->vni_ht, &fid->vni_ht_node,
332 mlxsw_sp_fid_vni_ht_params);
335 bool mlxsw_sp_fid_vni_is_set(const struct mlxsw_sp_fid *fid)
337 return fid->vni_valid;
340 void mlxsw_sp_fid_fdb_clear_offload(const struct mlxsw_sp_fid *fid,
341 const struct net_device *nve_dev)
343 struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
344 const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
346 if (ops->fdb_clear_offload)
347 ops->fdb_clear_offload(fid, nve_dev);
350 static const struct mlxsw_sp_flood_table *
351 mlxsw_sp_fid_flood_table_lookup(const struct mlxsw_sp_fid *fid,
352 enum mlxsw_sp_flood_type packet_type)
354 struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
357 for (i = 0; i < fid_family->flood_profile->nr_flood_tables; i++) {
358 const struct mlxsw_sp_flood_table *flood_table;
360 flood_table = &fid_family->flood_profile->flood_tables[i];
361 if (flood_table->packet_type != packet_type)
370 mlxsw_sp_fid_family_num_fids(const struct mlxsw_sp_fid_family *fid_family)
372 return fid_family->end_index - fid_family->start_index + 1;
376 mlxsw_sp_fid_8021d_pgt_size(const struct mlxsw_sp_fid_family *fid_family,
379 u16 num_fids = mlxsw_sp_fid_family_num_fids(fid_family);
381 *p_pgt_size = num_fids * fid_family->flood_profile->nr_flood_tables;
385 static unsigned int mlxsw_sp_fid_rfid_port_offset_cff(unsigned int local_port)
387 /* Port 0 is the CPU port. Since we never create RIFs based off that
388 * port, we don't need to count it.
390 return WARN_ON_ONCE(!local_port) ? 0 : local_port - 1;
394 mlxsw_sp_fid_rfid_pgt_size_cff(const struct mlxsw_sp_fid_family *fid_family,
397 struct mlxsw_core *core = fid_family->mlxsw_sp->core;
398 unsigned int max_ports;
403 max_ports = mlxsw_core_max_ports(core);
405 err = mlxsw_core_max_lag(core, &max_lags);
409 pgt_size = (mlxsw_sp_fid_rfid_port_offset_cff(max_ports) + max_lags) *
410 fid_family->flood_profile->nr_flood_tables;
411 *p_pgt_size = pgt_size;
416 mlxsw_sp_fid_pgt_base_ctl(const struct mlxsw_sp_fid_family *fid_family,
417 const struct mlxsw_sp_flood_table *flood_table)
421 num_fids = mlxsw_sp_fid_family_num_fids(fid_family);
422 return fid_family->pgt_base + num_fids * flood_table->table_index;
426 mlxsw_sp_fid_fid_mid_ctl(const struct mlxsw_sp_fid *fid,
427 const struct mlxsw_sp_flood_table *flood_table)
429 return mlxsw_sp_fid_pgt_base_ctl(fid->fid_family, flood_table) +
433 int mlxsw_sp_fid_flood_set(struct mlxsw_sp_fid *fid,
434 enum mlxsw_sp_flood_type packet_type, u16 local_port,
437 struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
438 const struct mlxsw_sp_flood_table *flood_table;
441 if (WARN_ON(!fid_family->flood_profile))
444 flood_table = mlxsw_sp_fid_flood_table_lookup(fid, packet_type);
448 mid_index = fid_family->ops->fid_mid(fid, flood_table);
449 return mlxsw_sp_pgt_entry_port_set(fid_family->mlxsw_sp, mid_index,
450 fid->fid_index, local_port, member);
453 int mlxsw_sp_fid_port_vid_map(struct mlxsw_sp_fid *fid,
454 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
456 if (WARN_ON(!fid->fid_family->ops->port_vid_map))
458 return fid->fid_family->ops->port_vid_map(fid, mlxsw_sp_port, vid);
461 void mlxsw_sp_fid_port_vid_unmap(struct mlxsw_sp_fid *fid,
462 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
464 fid->fid_family->ops->port_vid_unmap(fid, mlxsw_sp_port, vid);
467 u16 mlxsw_sp_fid_index(const struct mlxsw_sp_fid *fid)
469 return fid->fid_index;
472 enum mlxsw_sp_fid_type mlxsw_sp_fid_type(const struct mlxsw_sp_fid *fid)
474 return fid->fid_family->type;
477 struct mlxsw_sp_rif *mlxsw_sp_fid_rif(const struct mlxsw_sp_fid *fid)
482 enum mlxsw_sp_rif_type
483 mlxsw_sp_fid_type_rif_type(const struct mlxsw_sp *mlxsw_sp,
484 enum mlxsw_sp_fid_type type)
486 struct mlxsw_sp_fid_core *fid_core = mlxsw_sp->fid_core;
488 return fid_core->fid_family_arr[type]->rif_type;
491 static struct mlxsw_sp_fid_8021q *
492 mlxsw_sp_fid_8021q_fid(const struct mlxsw_sp_fid *fid)
494 return container_of(fid, struct mlxsw_sp_fid_8021q, common);
497 u16 mlxsw_sp_fid_8021q_vid(const struct mlxsw_sp_fid *fid)
499 return mlxsw_sp_fid_8021q_fid(fid)->vid;
502 static int mlxsw_sp_fid_8021q_setup(struct mlxsw_sp_fid *fid, const void *arg)
504 u16 vid = *(u16 *) arg;
506 mlxsw_sp_fid_8021q_fid(fid)->vid = vid;
507 fid->fid_offset = fid->fid_index - fid->fid_family->start_index;
511 static enum mlxsw_reg_sfmr_op mlxsw_sp_sfmr_op(bool valid)
513 return valid ? MLXSW_REG_SFMR_OP_CREATE_FID :
514 MLXSW_REG_SFMR_OP_DESTROY_FID;
517 static void mlxsw_sp_fid_pack(char *sfmr_pl,
518 const struct mlxsw_sp_fid *fid,
519 enum mlxsw_reg_sfmr_op op)
523 smpe = fid->fid_family->smpe_index_valid ? fid->fid_index : 0;
525 mlxsw_reg_sfmr_pack(sfmr_pl, op, fid->fid_index,
526 fid->fid_family->smpe_index_valid, smpe);
529 static void mlxsw_sp_fid_pack_ctl(char *sfmr_pl,
530 const struct mlxsw_sp_fid *fid,
531 enum mlxsw_reg_sfmr_op op)
533 mlxsw_sp_fid_pack(sfmr_pl, fid, op);
534 mlxsw_reg_sfmr_fid_offset_set(sfmr_pl, fid->fid_offset);
535 mlxsw_reg_sfmr_flood_rsp_set(sfmr_pl, fid->fid_family->flood_rsp);
536 mlxsw_reg_sfmr_flood_bridge_type_set(sfmr_pl,
537 fid->fid_family->bridge_type);
541 mlxsw_sp_fid_off_pgt_base_cff(const struct mlxsw_sp_fid_family *fid_family,
544 return fid_family->pgt_base +
545 fid_offset * fid_family->flood_profile->nr_flood_tables;
548 static u16 mlxsw_sp_fid_pgt_base_cff(const struct mlxsw_sp_fid *fid)
550 return mlxsw_sp_fid_off_pgt_base_cff(fid->fid_family, fid->fid_offset);
553 static void mlxsw_sp_fid_fid_pack_cff(char *sfmr_pl,
554 const struct mlxsw_sp_fid *fid,
555 enum mlxsw_reg_sfmr_op op)
557 struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
558 u16 pgt_base = mlxsw_sp_fid_pgt_base_cff(fid);
560 mlxsw_sp_fid_pack(sfmr_pl, fid, op);
561 mlxsw_reg_sfmr_cff_mid_base_set(sfmr_pl, pgt_base);
562 mlxsw_reg_sfmr_cff_prf_id_set(sfmr_pl,
563 fid_family->flood_profile->profile_id);
564 mlxsw_reg_sfmr_nve_flood_prf_id_set(sfmr_pl,
565 MLXSW_SP_FID_FLOOD_PROFILE_ID_NVE);
568 static u16 mlxsw_sp_fid_rfid_fid_offset_cff(struct mlxsw_sp *mlxsw_sp,
569 u16 port_lag_id, bool is_lag)
571 u16 max_ports = mlxsw_core_max_ports(mlxsw_sp->core);
574 return mlxsw_sp_fid_rfid_port_offset_cff(max_ports) +
577 return mlxsw_sp_fid_rfid_port_offset_cff(port_lag_id);
580 static int mlxsw_sp_fid_op(const struct mlxsw_sp_fid *fid, bool valid)
582 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
583 char sfmr_pl[MLXSW_REG_SFMR_LEN];
585 fid->fid_family->ops->fid_pack(sfmr_pl, fid,
586 mlxsw_sp_sfmr_op(valid));
587 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl);
590 static int mlxsw_sp_fid_edit_op(const struct mlxsw_sp_fid *fid,
591 const struct mlxsw_sp_rif *rif)
593 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
594 char sfmr_pl[MLXSW_REG_SFMR_LEN];
596 fid->fid_family->ops->fid_pack(sfmr_pl, fid,
597 MLXSW_REG_SFMR_OP_CREATE_FID);
599 mlxsw_reg_sfmr_vv_set(sfmr_pl, fid->vni_valid);
600 mlxsw_reg_sfmr_vni_set(sfmr_pl, be32_to_cpu(fid->vni));
601 mlxsw_reg_sfmr_vtfp_set(sfmr_pl, fid->nve_flood_index_valid);
602 mlxsw_reg_sfmr_nve_tunnel_flood_ptr_set(sfmr_pl, fid->nve_flood_index);
605 mlxsw_reg_sfmr_irif_v_set(sfmr_pl, true);
606 mlxsw_reg_sfmr_irif_set(sfmr_pl, mlxsw_sp_rif_index(rif));
609 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl);
612 static int mlxsw_sp_fid_vni_to_fid_map(const struct mlxsw_sp_fid *fid,
613 const struct mlxsw_sp_rif *rif,
616 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
617 char svfa_pl[MLXSW_REG_SVFA_LEN];
622 irif_index = rif ? mlxsw_sp_rif_index(rif) : 0;
624 mlxsw_reg_svfa_vni_pack(svfa_pl, valid, fid->fid_index,
625 be32_to_cpu(fid->vni), irif_valid, irif_index);
626 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl);
629 static int mlxsw_sp_fid_to_fid_rif_update(const struct mlxsw_sp_fid *fid,
630 const struct mlxsw_sp_rif *rif)
632 return mlxsw_sp_fid_edit_op(fid, rif);
635 static int mlxsw_sp_fid_vni_to_fid_rif_update(const struct mlxsw_sp_fid *fid,
636 const struct mlxsw_sp_rif *rif)
641 return mlxsw_sp_fid_vni_to_fid_map(fid, rif, fid->vni_valid);
645 mlxsw_sp_fid_vid_to_fid_map(const struct mlxsw_sp_fid *fid, u16 vid, bool valid,
646 const struct mlxsw_sp_rif *rif)
648 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
649 char svfa_pl[MLXSW_REG_SVFA_LEN];
654 irif_index = rif ? mlxsw_sp_rif_index(rif) : 0;
656 mlxsw_reg_svfa_vid_pack(svfa_pl, valid, fid->fid_index, vid, irif_valid,
658 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl);
662 mlxsw_sp_fid_8021q_vid_to_fid_rif_update(const struct mlxsw_sp_fid *fid,
663 const struct mlxsw_sp_rif *rif)
665 struct mlxsw_sp_fid_8021q *fid_8021q = mlxsw_sp_fid_8021q_fid(fid);
667 /* Update the global VID => FID mapping we created when the FID was
670 return mlxsw_sp_fid_vid_to_fid_map(fid, fid_8021q->vid, true, rif);
674 mlxsw_sp_fid_port_vid_to_fid_rif_update_one(const struct mlxsw_sp_fid *fid,
675 struct mlxsw_sp_fid_port_vid *pv,
676 bool irif_valid, u16 irif_index)
678 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
679 char svfa_pl[MLXSW_REG_SVFA_LEN];
681 mlxsw_reg_svfa_port_vid_pack(svfa_pl, pv->local_port, true,
682 fid->fid_index, pv->vid, irif_valid,
685 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl);
688 static int mlxsw_sp_fid_vid_to_fid_rif_set(const struct mlxsw_sp_fid *fid,
689 const struct mlxsw_sp_rif *rif)
691 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
692 struct mlxsw_sp_fid_port_vid *pv;
696 err = fid->fid_family->ops->vid_to_fid_rif_update(fid, rif);
700 irif_index = mlxsw_sp_rif_index(rif);
702 list_for_each_entry(pv, &fid->port_vid_list, list) {
703 /* If port is not in virtual mode, then it does not have any
704 * {Port, VID}->FID mappings that need to be updated with the
707 if (!mlxsw_sp->fid_core->port_fid_mappings[pv->local_port])
710 err = mlxsw_sp_fid_port_vid_to_fid_rif_update_one(fid, pv,
714 goto err_port_vid_to_fid_rif_update_one;
719 err_port_vid_to_fid_rif_update_one:
720 list_for_each_entry_continue_reverse(pv, &fid->port_vid_list, list) {
721 if (!mlxsw_sp->fid_core->port_fid_mappings[pv->local_port])
724 mlxsw_sp_fid_port_vid_to_fid_rif_update_one(fid, pv, false, 0);
727 fid->fid_family->ops->vid_to_fid_rif_update(fid, NULL);
731 static void mlxsw_sp_fid_vid_to_fid_rif_unset(const struct mlxsw_sp_fid *fid)
733 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
734 struct mlxsw_sp_fid_port_vid *pv;
736 list_for_each_entry(pv, &fid->port_vid_list, list) {
737 /* If port is not in virtual mode, then it does not have any
738 * {Port, VID}->FID mappings that need to be updated.
740 if (!mlxsw_sp->fid_core->port_fid_mappings[pv->local_port])
743 mlxsw_sp_fid_port_vid_to_fid_rif_update_one(fid, pv, false, 0);
746 fid->fid_family->ops->vid_to_fid_rif_update(fid, NULL);
749 static int mlxsw_sp_fid_reiv_handle(struct mlxsw_sp_fid *fid, u16 rif_index,
750 bool valid, u8 port_page)
752 u16 local_port_end = (port_page + 1) * MLXSW_REG_REIV_REC_MAX_COUNT - 1;
753 u16 local_port_start = port_page * MLXSW_REG_REIV_REC_MAX_COUNT;
754 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
755 struct mlxsw_sp_fid_port_vid *port_vid;
756 u8 rec_num, entries_num = 0;
760 reiv_pl = kmalloc(MLXSW_REG_REIV_LEN, GFP_KERNEL);
764 mlxsw_reg_reiv_pack(reiv_pl, port_page, rif_index);
766 list_for_each_entry(port_vid, &fid->port_vid_list, list) {
767 /* port_vid_list is sorted by local_port. */
768 if (port_vid->local_port < local_port_start)
771 if (port_vid->local_port > local_port_end)
774 rec_num = port_vid->local_port % MLXSW_REG_REIV_REC_MAX_COUNT;
775 mlxsw_reg_reiv_rec_update_set(reiv_pl, rec_num, true);
776 mlxsw_reg_reiv_rec_evid_set(reiv_pl, rec_num,
777 valid ? port_vid->vid : 0);
786 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(reiv), reiv_pl);
798 static int mlxsw_sp_fid_erif_eport_to_vid_map(struct mlxsw_sp_fid *fid,
799 u16 rif_index, bool valid)
801 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
805 num_port_pages = mlxsw_core_max_ports(mlxsw_sp->core) /
806 MLXSW_REG_REIV_REC_MAX_COUNT + 1;
808 for (i = 0; i < num_port_pages; i++) {
809 err = mlxsw_sp_fid_reiv_handle(fid, rif_index, valid, i);
811 goto err_reiv_handle;
818 mlxsw_sp_fid_reiv_handle(fid, rif_index, !valid, i);
822 int mlxsw_sp_fid_rif_set(struct mlxsw_sp_fid *fid, struct mlxsw_sp_rif *rif)
824 u16 rif_index = mlxsw_sp_rif_index(rif);
827 err = mlxsw_sp_fid_to_fid_rif_update(fid, rif);
831 err = mlxsw_sp_fid_vni_to_fid_rif_update(fid, rif);
833 goto err_vni_to_fid_rif_update;
835 err = mlxsw_sp_fid_vid_to_fid_rif_set(fid, rif);
837 goto err_vid_to_fid_rif_set;
839 err = mlxsw_sp_fid_erif_eport_to_vid_map(fid, rif_index, true);
841 goto err_erif_eport_to_vid_map;
846 err_erif_eport_to_vid_map:
847 mlxsw_sp_fid_vid_to_fid_rif_unset(fid);
848 err_vid_to_fid_rif_set:
849 mlxsw_sp_fid_vni_to_fid_rif_update(fid, NULL);
850 err_vni_to_fid_rif_update:
851 mlxsw_sp_fid_to_fid_rif_update(fid, NULL);
855 void mlxsw_sp_fid_rif_unset(struct mlxsw_sp_fid *fid)
862 rif_index = mlxsw_sp_rif_index(fid->rif);
865 mlxsw_sp_fid_erif_eport_to_vid_map(fid, rif_index, false);
866 mlxsw_sp_fid_vid_to_fid_rif_unset(fid);
867 mlxsw_sp_fid_vni_to_fid_rif_update(fid, NULL);
868 mlxsw_sp_fid_to_fid_rif_update(fid, NULL);
871 static int mlxsw_sp_fid_vni_op(const struct mlxsw_sp_fid *fid)
875 err = mlxsw_sp_fid_vni_to_fid_map(fid, fid->rif, fid->vni_valid);
879 err = mlxsw_sp_fid_edit_op(fid, fid->rif);
881 goto err_fid_edit_op;
886 mlxsw_sp_fid_vni_to_fid_map(fid, fid->rif, !fid->vni_valid);
890 static int __mlxsw_sp_fid_port_vid_map(const struct mlxsw_sp_fid *fid,
891 u16 local_port, u16 vid, bool valid)
893 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
894 char svfa_pl[MLXSW_REG_SVFA_LEN];
895 bool irif_valid = false;
900 irif_index = mlxsw_sp_rif_index(fid->rif);
903 mlxsw_reg_svfa_port_vid_pack(svfa_pl, local_port, valid, fid->fid_index,
904 vid, irif_valid, irif_index);
905 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl);
908 static struct mlxsw_sp_fid_8021d *
909 mlxsw_sp_fid_8021d_fid(const struct mlxsw_sp_fid *fid)
911 return container_of(fid, struct mlxsw_sp_fid_8021d, common);
914 static int mlxsw_sp_fid_8021d_setup(struct mlxsw_sp_fid *fid, const void *arg)
916 int br_ifindex = *(int *) arg;
918 mlxsw_sp_fid_8021d_fid(fid)->br_ifindex = br_ifindex;
919 fid->fid_offset = fid->fid_index - fid->fid_family->start_index;
923 static int mlxsw_sp_fid_8021d_configure(struct mlxsw_sp_fid *fid)
925 return mlxsw_sp_fid_op(fid, true);
928 static void mlxsw_sp_fid_8021d_deconfigure(struct mlxsw_sp_fid *fid)
931 mlxsw_sp_nve_fid_disable(fid->fid_family->mlxsw_sp, fid);
932 mlxsw_sp_fid_op(fid, false);
935 static int mlxsw_sp_fid_8021d_index_alloc(struct mlxsw_sp_fid *fid,
936 const void *arg, u16 *p_fid_index)
938 struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
939 u16 nr_fids, fid_index;
941 nr_fids = fid_family->end_index - fid_family->start_index + 1;
942 fid_index = find_first_zero_bit(fid_family->fids_bitmap, nr_fids);
943 if (fid_index == nr_fids)
945 *p_fid_index = fid_family->start_index + fid_index;
951 mlxsw_sp_fid_8021d_compare(const struct mlxsw_sp_fid *fid, const void *arg)
953 int br_ifindex = *(int *) arg;
955 return mlxsw_sp_fid_8021d_fid(fid)->br_ifindex == br_ifindex;
958 static int mlxsw_sp_port_vp_mode_trans(struct mlxsw_sp_port *mlxsw_sp_port)
960 struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
963 list_for_each_entry(mlxsw_sp_port_vlan, &mlxsw_sp_port->vlans_list,
965 struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid;
966 u16 vid = mlxsw_sp_port_vlan->vid;
971 err = __mlxsw_sp_fid_port_vid_map(fid,
972 mlxsw_sp_port->local_port,
975 goto err_fid_port_vid_map;
978 err = mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, true);
980 goto err_port_vp_mode_set;
984 err_port_vp_mode_set:
985 err_fid_port_vid_map:
986 list_for_each_entry_continue_reverse(mlxsw_sp_port_vlan,
987 &mlxsw_sp_port->vlans_list, list) {
988 struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid;
989 u16 vid = mlxsw_sp_port_vlan->vid;
994 __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid,
1000 static void mlxsw_sp_port_vlan_mode_trans(struct mlxsw_sp_port *mlxsw_sp_port)
1002 struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
1004 mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, false);
1006 list_for_each_entry_reverse(mlxsw_sp_port_vlan,
1007 &mlxsw_sp_port->vlans_list, list) {
1008 struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid;
1009 u16 vid = mlxsw_sp_port_vlan->vid;
1014 __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid,
1020 mlxsw_sp_fid_port_vid_list_add(struct mlxsw_sp_fid *fid, u16 local_port,
1023 struct mlxsw_sp_fid_port_vid *port_vid, *tmp_port_vid;
1025 port_vid = kzalloc(sizeof(*port_vid), GFP_KERNEL);
1029 port_vid->local_port = local_port;
1030 port_vid->vid = vid;
1032 list_for_each_entry(tmp_port_vid, &fid->port_vid_list, list) {
1033 if (tmp_port_vid->local_port > local_port)
1037 list_add_tail(&port_vid->list, &tmp_port_vid->list);
1042 mlxsw_sp_fid_port_vid_list_del(struct mlxsw_sp_fid *fid, u16 local_port,
1045 struct mlxsw_sp_fid_port_vid *port_vid, *tmp;
1047 list_for_each_entry_safe(port_vid, tmp, &fid->port_vid_list, list) {
1048 if (port_vid->local_port != local_port || port_vid->vid != vid)
1051 list_del(&port_vid->list);
1058 mlxsw_sp_fid_mpe_table_map(const struct mlxsw_sp_fid *fid, u16 local_port,
1059 u16 vid, bool valid)
1061 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
1062 char smpe_pl[MLXSW_REG_SMPE_LEN];
1064 mlxsw_reg_smpe_pack(smpe_pl, local_port, fid->fid_index,
1066 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(smpe), smpe_pl);
1070 mlxsw_sp_fid_erif_eport_to_vid_map_one(const struct mlxsw_sp_fid *fid,
1071 u16 local_port, u16 vid, bool valid)
1073 u8 port_page = local_port / MLXSW_REG_REIV_REC_MAX_COUNT;
1074 u8 rec_num = local_port % MLXSW_REG_REIV_REC_MAX_COUNT;
1075 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
1076 u16 rif_index = mlxsw_sp_rif_index(fid->rif);
1080 reiv_pl = kmalloc(MLXSW_REG_REIV_LEN, GFP_KERNEL);
1084 mlxsw_reg_reiv_pack(reiv_pl, port_page, rif_index);
1085 mlxsw_reg_reiv_rec_update_set(reiv_pl, rec_num, true);
1086 mlxsw_reg_reiv_rec_evid_set(reiv_pl, rec_num, valid ? vid : 0);
1087 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(reiv), reiv_pl);
1092 static int mlxsw_sp_fid_evid_map(const struct mlxsw_sp_fid *fid, u16 local_port,
1093 u16 vid, bool valid)
1097 err = mlxsw_sp_fid_mpe_table_map(fid, local_port, vid, valid);
1104 err = mlxsw_sp_fid_erif_eport_to_vid_map_one(fid, local_port, vid,
1107 goto err_erif_eport_to_vid_map_one;
1111 err_erif_eport_to_vid_map_one:
1112 mlxsw_sp_fid_mpe_table_map(fid, local_port, vid, !valid);
1116 static int mlxsw_sp_fid_8021d_port_vid_map(struct mlxsw_sp_fid *fid,
1117 struct mlxsw_sp_port *mlxsw_sp_port,
1120 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1121 u16 local_port = mlxsw_sp_port->local_port;
1124 err = __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid,
1129 err = mlxsw_sp_fid_evid_map(fid, local_port, vid, true);
1131 goto err_fid_evid_map;
1133 err = mlxsw_sp_fid_port_vid_list_add(fid, mlxsw_sp_port->local_port,
1136 goto err_port_vid_list_add;
1138 if (mlxsw_sp->fid_core->port_fid_mappings[local_port]++ == 0) {
1139 err = mlxsw_sp_port_vp_mode_trans(mlxsw_sp_port);
1141 goto err_port_vp_mode_trans;
1146 err_port_vp_mode_trans:
1147 mlxsw_sp->fid_core->port_fid_mappings[local_port]--;
1148 mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid);
1149 err_port_vid_list_add:
1150 mlxsw_sp_fid_evid_map(fid, local_port, vid, false);
1152 __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, false);
1157 mlxsw_sp_fid_8021d_port_vid_unmap(struct mlxsw_sp_fid *fid,
1158 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
1160 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1161 u16 local_port = mlxsw_sp_port->local_port;
1163 if (mlxsw_sp->fid_core->port_fid_mappings[local_port] == 1)
1164 mlxsw_sp_port_vlan_mode_trans(mlxsw_sp_port);
1165 mlxsw_sp->fid_core->port_fid_mappings[local_port]--;
1166 mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid);
1167 mlxsw_sp_fid_evid_map(fid, local_port, vid, false);
1168 __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, false);
1171 static int mlxsw_sp_fid_8021d_vni_set(struct mlxsw_sp_fid *fid)
1173 return mlxsw_sp_fid_vni_op(fid);
1176 static void mlxsw_sp_fid_8021d_vni_clear(struct mlxsw_sp_fid *fid)
1178 mlxsw_sp_fid_vni_op(fid);
1181 static int mlxsw_sp_fid_8021d_nve_flood_index_set(struct mlxsw_sp_fid *fid)
1183 return mlxsw_sp_fid_edit_op(fid, fid->rif);
1186 static void mlxsw_sp_fid_8021d_nve_flood_index_clear(struct mlxsw_sp_fid *fid)
1188 mlxsw_sp_fid_edit_op(fid, fid->rif);
1192 mlxsw_sp_fid_8021d_fdb_clear_offload(const struct mlxsw_sp_fid *fid,
1193 const struct net_device *nve_dev)
1195 br_fdb_clear_offload(nve_dev, 0);
1199 mlxsw_sp_fid_8021d_vid_to_fid_rif_update(const struct mlxsw_sp_fid *fid,
1200 const struct mlxsw_sp_rif *rif)
1206 mlxsw_sp_fid_flood_table_init_ctl(struct mlxsw_sp_fid_family *fid_family,
1207 const struct mlxsw_sp_flood_table *flood_table)
1209 enum mlxsw_sp_flood_type packet_type = flood_table->packet_type;
1210 struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
1211 const int *sfgc_packet_types;
1215 mid_base = mlxsw_sp_fid_pgt_base_ctl(fid_family, flood_table);
1217 sfgc_packet_types = mlxsw_sp_packet_type_sfgc_types[packet_type];
1218 for (i = 0; i < MLXSW_REG_SFGC_TYPE_MAX; i++) {
1219 char sfgc_pl[MLXSW_REG_SFGC_LEN];
1221 if (!sfgc_packet_types[i])
1224 mlxsw_reg_sfgc_pack(sfgc_pl, i, fid_family->bridge_type,
1225 flood_table->table_type, 0, mid_base);
1227 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfgc), sfgc_pl);
1235 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021d_ops_ctl = {
1236 .setup = mlxsw_sp_fid_8021d_setup,
1237 .configure = mlxsw_sp_fid_8021d_configure,
1238 .deconfigure = mlxsw_sp_fid_8021d_deconfigure,
1239 .index_alloc = mlxsw_sp_fid_8021d_index_alloc,
1240 .compare = mlxsw_sp_fid_8021d_compare,
1241 .port_vid_map = mlxsw_sp_fid_8021d_port_vid_map,
1242 .port_vid_unmap = mlxsw_sp_fid_8021d_port_vid_unmap,
1243 .vni_set = mlxsw_sp_fid_8021d_vni_set,
1244 .vni_clear = mlxsw_sp_fid_8021d_vni_clear,
1245 .nve_flood_index_set = mlxsw_sp_fid_8021d_nve_flood_index_set,
1246 .nve_flood_index_clear = mlxsw_sp_fid_8021d_nve_flood_index_clear,
1247 .fdb_clear_offload = mlxsw_sp_fid_8021d_fdb_clear_offload,
1248 .vid_to_fid_rif_update = mlxsw_sp_fid_8021d_vid_to_fid_rif_update,
1249 .flood_table_init = mlxsw_sp_fid_flood_table_init_ctl,
1250 .pgt_size = mlxsw_sp_fid_8021d_pgt_size,
1251 .fid_mid = mlxsw_sp_fid_fid_mid_ctl,
1252 .fid_pack = mlxsw_sp_fid_pack_ctl,
1256 mlxsw_sp_fid_fid_mid_cff(const struct mlxsw_sp_fid *fid,
1257 const struct mlxsw_sp_flood_table *flood_table)
1259 return mlxsw_sp_fid_pgt_base_cff(fid) + flood_table->table_index;
1262 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021d_ops_cff = {
1263 .setup = mlxsw_sp_fid_8021d_setup,
1264 .configure = mlxsw_sp_fid_8021d_configure,
1265 .deconfigure = mlxsw_sp_fid_8021d_deconfigure,
1266 .index_alloc = mlxsw_sp_fid_8021d_index_alloc,
1267 .compare = mlxsw_sp_fid_8021d_compare,
1268 .port_vid_map = mlxsw_sp_fid_8021d_port_vid_map,
1269 .port_vid_unmap = mlxsw_sp_fid_8021d_port_vid_unmap,
1270 .vni_set = mlxsw_sp_fid_8021d_vni_set,
1271 .vni_clear = mlxsw_sp_fid_8021d_vni_clear,
1272 .nve_flood_index_set = mlxsw_sp_fid_8021d_nve_flood_index_set,
1273 .nve_flood_index_clear = mlxsw_sp_fid_8021d_nve_flood_index_clear,
1274 .fdb_clear_offload = mlxsw_sp_fid_8021d_fdb_clear_offload,
1275 .vid_to_fid_rif_update = mlxsw_sp_fid_8021d_vid_to_fid_rif_update,
1276 .pgt_size = mlxsw_sp_fid_8021d_pgt_size,
1277 .fid_mid = mlxsw_sp_fid_fid_mid_cff,
1278 .fid_pack = mlxsw_sp_fid_fid_pack_cff,
1281 #define MLXSW_SP_FID_8021Q_MAX (VLAN_N_VID - 2)
1282 #define MLXSW_SP_FID_RFID_MAX (11 * 1024)
1284 static const struct mlxsw_sp_flood_table mlxsw_sp_fid_8021d_flood_tables[] = {
1286 .packet_type = MLXSW_SP_FLOOD_TYPE_UC,
1287 .table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFSET,
1291 .packet_type = MLXSW_SP_FLOOD_TYPE_MC,
1292 .table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFSET,
1296 .packet_type = MLXSW_SP_FLOOD_TYPE_BC,
1297 .table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFSET,
1303 struct mlxsw_sp_fid_flood_profile mlxsw_sp_fid_8021d_flood_profile = {
1304 .flood_tables = mlxsw_sp_fid_8021d_flood_tables,
1305 .nr_flood_tables = ARRAY_SIZE(mlxsw_sp_fid_8021d_flood_tables),
1306 .profile_id = MLXSW_SP_FID_FLOOD_PROFILE_ID_BRIDGE,
1309 static const struct mlxsw_sp_flood_table mlxsw_sp_fid_rsp_flood_tables_cff[] = {
1311 .packet_type = MLXSW_SP_FLOOD_TYPE_UC,
1315 .packet_type = MLXSW_SP_FLOOD_TYPE_NOT_UC,
1321 struct mlxsw_sp_fid_flood_profile mlxsw_sp_fid_rsp_flood_profile_cff = {
1322 .flood_tables = mlxsw_sp_fid_rsp_flood_tables_cff,
1323 .nr_flood_tables = ARRAY_SIZE(mlxsw_sp_fid_rsp_flood_tables_cff),
1324 .profile_id = MLXSW_SP_FID_FLOOD_PROFILE_ID_RSP,
1327 static const struct mlxsw_sp_flood_table mlxsw_sp_fid_nve_flood_tables_cff[] = {
1329 .packet_type = MLXSW_SP_FLOOD_TYPE_ANY,
1335 struct mlxsw_sp_fid_flood_profile mlxsw_sp_fid_nve_flood_profile_cff = {
1336 .flood_tables = mlxsw_sp_fid_nve_flood_tables_cff,
1337 .nr_flood_tables = ARRAY_SIZE(mlxsw_sp_fid_nve_flood_tables_cff),
1338 .profile_id = MLXSW_SP_FID_FLOOD_PROFILE_ID_NVE,
1342 mlxsw_sp_fid_8021q_compare(const struct mlxsw_sp_fid *fid, const void *arg)
1344 u16 vid = *(u16 *) arg;
1346 return mlxsw_sp_fid_8021q_fid(fid)->vid == vid;
1350 mlxsw_sp_fid_8021q_fdb_clear_offload(const struct mlxsw_sp_fid *fid,
1351 const struct net_device *nve_dev)
1353 br_fdb_clear_offload(nve_dev, mlxsw_sp_fid_8021q_vid(fid));
1356 static int mlxsw_sp_fid_rfid_setup_ctl(struct mlxsw_sp_fid *fid,
1359 /* In controlled mode, the FW takes care of FID placement. */
1360 fid->fid_offset = 0;
1364 static int mlxsw_sp_fid_rfid_setup_cff(struct mlxsw_sp_fid *fid,
1367 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
1368 u16 rif_index = *(const u16 *)arg;
1369 struct mlxsw_sp_rif *rif;
1374 rif = mlxsw_sp_rif_by_index(mlxsw_sp, rif_index);
1378 err = mlxsw_sp_rif_subport_port(rif, &port, &is_lag);
1382 fid->fid_offset = mlxsw_sp_fid_rfid_fid_offset_cff(mlxsw_sp, port,
1387 static int mlxsw_sp_fid_rfid_configure(struct mlxsw_sp_fid *fid)
1389 return mlxsw_sp_fid_op(fid, true);
1392 static void mlxsw_sp_fid_rfid_deconfigure(struct mlxsw_sp_fid *fid)
1394 mlxsw_sp_fid_op(fid, false);
1397 static int mlxsw_sp_fid_rfid_index_alloc(struct mlxsw_sp_fid *fid,
1398 const void *arg, u16 *p_fid_index)
1400 u16 rif_index = *(u16 *) arg;
1402 *p_fid_index = fid->fid_family->start_index + rif_index;
1407 static bool mlxsw_sp_fid_rfid_compare(const struct mlxsw_sp_fid *fid,
1410 u16 rif_index = *(u16 *) arg;
1412 return fid->fid_index == rif_index + fid->fid_family->start_index;
1415 static int mlxsw_sp_fid_rfid_port_vid_map(struct mlxsw_sp_fid *fid,
1416 struct mlxsw_sp_port *mlxsw_sp_port,
1419 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1420 u16 local_port = mlxsw_sp_port->local_port;
1423 err = mlxsw_sp_fid_port_vid_list_add(fid, mlxsw_sp_port->local_port,
1428 /* Using legacy bridge model, we only need to transition the port to
1429 * virtual mode since {Port, VID} => FID is done by the firmware upon
1430 * RIF creation. Using unified bridge model, we need to map
1431 * {Port, VID} => FID and map egress VID.
1433 err = __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid,
1436 goto err_port_vid_map;
1439 err = mlxsw_sp_fid_erif_eport_to_vid_map_one(fid, local_port,
1442 goto err_erif_eport_to_vid_map_one;
1445 if (mlxsw_sp->fid_core->port_fid_mappings[local_port]++ == 0) {
1446 err = mlxsw_sp_port_vp_mode_trans(mlxsw_sp_port);
1448 goto err_port_vp_mode_trans;
1453 err_port_vp_mode_trans:
1454 mlxsw_sp->fid_core->port_fid_mappings[local_port]--;
1456 mlxsw_sp_fid_erif_eport_to_vid_map_one(fid, local_port, vid,
1458 err_erif_eport_to_vid_map_one:
1459 __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, false);
1461 mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid);
1466 mlxsw_sp_fid_rfid_port_vid_unmap(struct mlxsw_sp_fid *fid,
1467 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
1469 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1470 u16 local_port = mlxsw_sp_port->local_port;
1472 if (mlxsw_sp->fid_core->port_fid_mappings[local_port] == 1)
1473 mlxsw_sp_port_vlan_mode_trans(mlxsw_sp_port);
1474 mlxsw_sp->fid_core->port_fid_mappings[local_port]--;
1477 mlxsw_sp_fid_erif_eport_to_vid_map_one(fid, local_port, vid,
1479 __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, false);
1480 mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid);
1483 static int mlxsw_sp_fid_rfid_vni_set(struct mlxsw_sp_fid *fid)
1488 static void mlxsw_sp_fid_rfid_vni_clear(struct mlxsw_sp_fid *fid)
1493 static int mlxsw_sp_fid_rfid_nve_flood_index_set(struct mlxsw_sp_fid *fid)
1498 static void mlxsw_sp_fid_rfid_nve_flood_index_clear(struct mlxsw_sp_fid *fid)
1504 mlxsw_sp_fid_rfid_vid_to_fid_rif_update(const struct mlxsw_sp_fid *fid,
1505 const struct mlxsw_sp_rif *rif)
1510 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_rfid_ops_ctl = {
1511 .setup = mlxsw_sp_fid_rfid_setup_ctl,
1512 .configure = mlxsw_sp_fid_rfid_configure,
1513 .deconfigure = mlxsw_sp_fid_rfid_deconfigure,
1514 .index_alloc = mlxsw_sp_fid_rfid_index_alloc,
1515 .compare = mlxsw_sp_fid_rfid_compare,
1516 .port_vid_map = mlxsw_sp_fid_rfid_port_vid_map,
1517 .port_vid_unmap = mlxsw_sp_fid_rfid_port_vid_unmap,
1518 .vni_set = mlxsw_sp_fid_rfid_vni_set,
1519 .vni_clear = mlxsw_sp_fid_rfid_vni_clear,
1520 .nve_flood_index_set = mlxsw_sp_fid_rfid_nve_flood_index_set,
1521 .nve_flood_index_clear = mlxsw_sp_fid_rfid_nve_flood_index_clear,
1522 .vid_to_fid_rif_update = mlxsw_sp_fid_rfid_vid_to_fid_rif_update,
1523 .fid_pack = mlxsw_sp_fid_pack_ctl,
1527 mlxsw_sp_fid_rfid_port_add_cff(struct mlxsw_sp *mlxsw_sp,
1528 const struct mlxsw_sp_flood_table *flood_table,
1529 u16 pgt_addr, u16 smpe, unsigned int local_port)
1533 err = mlxsw_sp_pgt_entry_port_set(mlxsw_sp, pgt_addr, smpe,
1538 if (flood_table->packet_type == MLXSW_SP_FLOOD_TYPE_NOT_UC) {
1539 u16 router_port = mlxsw_sp_router_port(mlxsw_sp);
1541 err = mlxsw_sp_pgt_entry_port_set(mlxsw_sp, pgt_addr, smpe,
1544 goto err_entry_port_set;
1550 mlxsw_sp_pgt_entry_port_set(mlxsw_sp, pgt_addr, smpe, local_port,
1556 mlxsw_sp_fid_rfid_port_del_cff(struct mlxsw_sp *mlxsw_sp,
1557 const struct mlxsw_sp_flood_table *flood_table,
1558 u16 pgt_addr, u16 smpe, u16 local_port)
1560 if (flood_table->packet_type == MLXSW_SP_FLOOD_TYPE_NOT_UC) {
1561 u16 router_port = mlxsw_sp_router_port(mlxsw_sp);
1563 mlxsw_sp_pgt_entry_port_set(mlxsw_sp, pgt_addr, smpe,
1564 router_port, false);
1566 mlxsw_sp_pgt_entry_port_set(mlxsw_sp, pgt_addr, smpe, local_port,
1571 mlxsw_sp_fid_rfid_port_memb_ft_cff(const struct mlxsw_sp_fid_family *fid_family,
1572 const struct mlxsw_sp_flood_table *flood_table,
1573 const struct mlxsw_sp_port *mlxsw_sp_port,
1576 struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
1577 u16 local_port = mlxsw_sp_port->local_port;
1584 /* In-PGT SMPE is only valid on Spectrum-1, CFF only on Spectrum>1. */
1587 port = mlxsw_sp_port->lagged ? mlxsw_sp_port->lag_id : local_port;
1588 fid_offset = mlxsw_sp_fid_rfid_fid_offset_cff(mlxsw_sp, port,
1589 mlxsw_sp_port->lagged);
1590 fid_pgt_base = mlxsw_sp_fid_off_pgt_base_cff(fid_family, fid_offset);
1591 pgt_addr = fid_pgt_base + flood_table->table_index;
1594 return mlxsw_sp_fid_rfid_port_add_cff(mlxsw_sp, flood_table,
1598 mlxsw_sp_fid_rfid_port_del_cff(mlxsw_sp, flood_table, pgt_addr, smpe,
1604 mlxsw_sp_fid_rfid_port_memb_cff(const struct mlxsw_sp_fid_family *fid_family,
1605 const struct mlxsw_sp_port *mlxsw_sp_port,
1610 for (i = 0; i < fid_family->flood_profile->nr_flood_tables; i++) {
1611 const struct mlxsw_sp_flood_table *flood_table =
1612 &fid_family->flood_profile->flood_tables[i];
1615 err = mlxsw_sp_fid_rfid_port_memb_ft_cff(fid_family,
1617 mlxsw_sp_port, member);
1626 mlxsw_sp_fid_rfid_port_init_cff(const struct mlxsw_sp_fid_family *fid_family,
1627 const struct mlxsw_sp_port *mlxsw_sp_port)
1629 return mlxsw_sp_fid_rfid_port_memb_cff(fid_family, mlxsw_sp_port, true);
1633 mlxsw_sp_fid_rfid_port_fini_cff(const struct mlxsw_sp_fid_family *fid_family,
1634 const struct mlxsw_sp_port *mlxsw_sp_port)
1636 mlxsw_sp_fid_rfid_port_memb_cff(fid_family, mlxsw_sp_port, false);
1639 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_rfid_ops_cff = {
1640 .setup = mlxsw_sp_fid_rfid_setup_cff,
1641 .configure = mlxsw_sp_fid_rfid_configure,
1642 .deconfigure = mlxsw_sp_fid_rfid_deconfigure,
1643 .index_alloc = mlxsw_sp_fid_rfid_index_alloc,
1644 .compare = mlxsw_sp_fid_rfid_compare,
1645 .port_vid_map = mlxsw_sp_fid_rfid_port_vid_map,
1646 .port_vid_unmap = mlxsw_sp_fid_rfid_port_vid_unmap,
1647 .vni_set = mlxsw_sp_fid_rfid_vni_set,
1648 .vni_clear = mlxsw_sp_fid_rfid_vni_clear,
1649 .nve_flood_index_set = mlxsw_sp_fid_rfid_nve_flood_index_set,
1650 .nve_flood_index_clear = mlxsw_sp_fid_rfid_nve_flood_index_clear,
1651 .vid_to_fid_rif_update = mlxsw_sp_fid_rfid_vid_to_fid_rif_update,
1652 .pgt_size = mlxsw_sp_fid_rfid_pgt_size_cff,
1653 .fid_port_init = mlxsw_sp_fid_rfid_port_init_cff,
1654 .fid_port_fini = mlxsw_sp_fid_rfid_port_fini_cff,
1655 .fid_mid = mlxsw_sp_fid_fid_mid_cff,
1656 .fid_pack = mlxsw_sp_fid_fid_pack_cff,
1659 static int mlxsw_sp_fid_dummy_setup(struct mlxsw_sp_fid *fid, const void *arg)
1661 fid->fid_offset = 0;
1665 static int mlxsw_sp_fid_dummy_configure(struct mlxsw_sp_fid *fid)
1667 return mlxsw_sp_fid_op(fid, true);
1670 static void mlxsw_sp_fid_dummy_deconfigure(struct mlxsw_sp_fid *fid)
1672 mlxsw_sp_fid_op(fid, false);
1675 static int mlxsw_sp_fid_dummy_index_alloc(struct mlxsw_sp_fid *fid,
1676 const void *arg, u16 *p_fid_index)
1678 *p_fid_index = fid->fid_family->start_index;
1683 static bool mlxsw_sp_fid_dummy_compare(const struct mlxsw_sp_fid *fid,
1689 static int mlxsw_sp_fid_dummy_vni_set(struct mlxsw_sp_fid *fid)
1694 static void mlxsw_sp_fid_dummy_vni_clear(struct mlxsw_sp_fid *fid)
1699 static int mlxsw_sp_fid_dummy_nve_flood_index_set(struct mlxsw_sp_fid *fid)
1704 static void mlxsw_sp_fid_dummy_nve_flood_index_clear(struct mlxsw_sp_fid *fid)
1709 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_dummy_ops = {
1710 .setup = mlxsw_sp_fid_dummy_setup,
1711 .configure = mlxsw_sp_fid_dummy_configure,
1712 .deconfigure = mlxsw_sp_fid_dummy_deconfigure,
1713 .index_alloc = mlxsw_sp_fid_dummy_index_alloc,
1714 .compare = mlxsw_sp_fid_dummy_compare,
1715 .vni_set = mlxsw_sp_fid_dummy_vni_set,
1716 .vni_clear = mlxsw_sp_fid_dummy_vni_clear,
1717 .nve_flood_index_set = mlxsw_sp_fid_dummy_nve_flood_index_set,
1718 .nve_flood_index_clear = mlxsw_sp_fid_dummy_nve_flood_index_clear,
1719 .fid_pack = mlxsw_sp_fid_pack,
1722 static int mlxsw_sp_fid_8021q_configure(struct mlxsw_sp_fid *fid)
1724 struct mlxsw_sp_fid_8021q *fid_8021q = mlxsw_sp_fid_8021q_fid(fid);
1727 err = mlxsw_sp_fid_op(fid, true);
1731 err = mlxsw_sp_fid_vid_to_fid_map(fid, fid_8021q->vid, true, fid->rif);
1733 goto err_vid_to_fid_map;
1738 mlxsw_sp_fid_op(fid, false);
1742 static void mlxsw_sp_fid_8021q_deconfigure(struct mlxsw_sp_fid *fid)
1744 struct mlxsw_sp_fid_8021q *fid_8021q = mlxsw_sp_fid_8021q_fid(fid);
1747 mlxsw_sp_nve_fid_disable(fid->fid_family->mlxsw_sp, fid);
1749 mlxsw_sp_fid_vid_to_fid_map(fid, fid_8021q->vid, false, NULL);
1750 mlxsw_sp_fid_op(fid, false);
1753 static int mlxsw_sp_fid_8021q_port_vid_map(struct mlxsw_sp_fid *fid,
1754 struct mlxsw_sp_port *mlxsw_sp_port,
1757 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1758 u16 local_port = mlxsw_sp_port->local_port;
1761 /* In case there are no {Port, VID} => FID mappings on the port,
1762 * we can use the global VID => FID mapping we created when the
1763 * FID was configured, otherwise, configure new mapping.
1765 if (mlxsw_sp->fid_core->port_fid_mappings[local_port]) {
1766 err = __mlxsw_sp_fid_port_vid_map(fid, local_port, vid, true);
1771 err = mlxsw_sp_fid_evid_map(fid, local_port, vid, true);
1773 goto err_fid_evid_map;
1775 err = mlxsw_sp_fid_port_vid_list_add(fid, mlxsw_sp_port->local_port,
1778 goto err_port_vid_list_add;
1782 err_port_vid_list_add:
1783 mlxsw_sp_fid_evid_map(fid, local_port, vid, false);
1785 if (mlxsw_sp->fid_core->port_fid_mappings[local_port])
1786 __mlxsw_sp_fid_port_vid_map(fid, local_port, vid, false);
1791 mlxsw_sp_fid_8021q_port_vid_unmap(struct mlxsw_sp_fid *fid,
1792 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
1794 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1795 u16 local_port = mlxsw_sp_port->local_port;
1797 mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid);
1798 mlxsw_sp_fid_evid_map(fid, local_port, vid, false);
1799 if (mlxsw_sp->fid_core->port_fid_mappings[local_port])
1800 __mlxsw_sp_fid_port_vid_map(fid, local_port, vid, false);
1803 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021q_ops_ctl = {
1804 .setup = mlxsw_sp_fid_8021q_setup,
1805 .configure = mlxsw_sp_fid_8021q_configure,
1806 .deconfigure = mlxsw_sp_fid_8021q_deconfigure,
1807 .index_alloc = mlxsw_sp_fid_8021d_index_alloc,
1808 .compare = mlxsw_sp_fid_8021q_compare,
1809 .port_vid_map = mlxsw_sp_fid_8021q_port_vid_map,
1810 .port_vid_unmap = mlxsw_sp_fid_8021q_port_vid_unmap,
1811 .vni_set = mlxsw_sp_fid_8021d_vni_set,
1812 .vni_clear = mlxsw_sp_fid_8021d_vni_clear,
1813 .nve_flood_index_set = mlxsw_sp_fid_8021d_nve_flood_index_set,
1814 .nve_flood_index_clear = mlxsw_sp_fid_8021d_nve_flood_index_clear,
1815 .fdb_clear_offload = mlxsw_sp_fid_8021q_fdb_clear_offload,
1816 .vid_to_fid_rif_update = mlxsw_sp_fid_8021q_vid_to_fid_rif_update,
1817 .flood_table_init = mlxsw_sp_fid_flood_table_init_ctl,
1818 .pgt_size = mlxsw_sp_fid_8021d_pgt_size,
1819 .fid_mid = mlxsw_sp_fid_fid_mid_ctl,
1820 .fid_pack = mlxsw_sp_fid_pack_ctl,
1823 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021q_ops_cff = {
1824 .setup = mlxsw_sp_fid_8021q_setup,
1825 .configure = mlxsw_sp_fid_8021q_configure,
1826 .deconfigure = mlxsw_sp_fid_8021q_deconfigure,
1827 .index_alloc = mlxsw_sp_fid_8021d_index_alloc,
1828 .compare = mlxsw_sp_fid_8021q_compare,
1829 .port_vid_map = mlxsw_sp_fid_8021q_port_vid_map,
1830 .port_vid_unmap = mlxsw_sp_fid_8021q_port_vid_unmap,
1831 .vni_set = mlxsw_sp_fid_8021d_vni_set,
1832 .vni_clear = mlxsw_sp_fid_8021d_vni_clear,
1833 .nve_flood_index_set = mlxsw_sp_fid_8021d_nve_flood_index_set,
1834 .nve_flood_index_clear = mlxsw_sp_fid_8021d_nve_flood_index_clear,
1835 .fdb_clear_offload = mlxsw_sp_fid_8021q_fdb_clear_offload,
1836 .vid_to_fid_rif_update = mlxsw_sp_fid_8021q_vid_to_fid_rif_update,
1837 .pgt_size = mlxsw_sp_fid_8021d_pgt_size,
1838 .fid_mid = mlxsw_sp_fid_fid_mid_cff,
1839 .fid_pack = mlxsw_sp_fid_fid_pack_cff,
1842 /* There are 4K-2 802.1Q FIDs */
1843 #define MLXSW_SP_FID_8021Q_START 1 /* FID 0 is reserved. */
1844 #define MLXSW_SP_FID_8021Q_END (MLXSW_SP_FID_8021Q_START + \
1845 MLXSW_SP_FID_8021Q_MAX - 1)
1847 /* There are 1K 802.1D FIDs */
1848 #define MLXSW_SP_FID_8021D_START (MLXSW_SP_FID_8021Q_END + 1)
1849 #define MLXSW_SP_FID_8021D_END (MLXSW_SP_FID_8021D_START + \
1850 MLXSW_SP_FID_8021D_MAX - 1)
1852 /* There is one dummy FID */
1853 #define MLXSW_SP_FID_DUMMY (MLXSW_SP_FID_8021D_END + 1)
1855 /* There are 11K rFIDs */
1856 #define MLXSW_SP_RFID_START (MLXSW_SP_FID_DUMMY + 1)
1857 #define MLXSW_SP_RFID_END (MLXSW_SP_RFID_START + \
1858 MLXSW_SP_FID_RFID_MAX - 1)
1860 static const struct mlxsw_sp_fid_family mlxsw_sp1_fid_8021q_family = {
1861 .type = MLXSW_SP_FID_TYPE_8021Q,
1862 .fid_size = sizeof(struct mlxsw_sp_fid_8021q),
1863 .start_index = MLXSW_SP_FID_8021Q_START,
1864 .end_index = MLXSW_SP_FID_8021Q_END,
1865 .flood_profile = &mlxsw_sp_fid_8021d_flood_profile,
1866 .rif_type = MLXSW_SP_RIF_TYPE_VLAN,
1867 .ops = &mlxsw_sp_fid_8021q_ops_ctl,
1869 .bridge_type = MLXSW_REG_BRIDGE_TYPE_0,
1870 .smpe_index_valid = false,
1873 static const struct mlxsw_sp_fid_family mlxsw_sp1_fid_8021d_family = {
1874 .type = MLXSW_SP_FID_TYPE_8021D,
1875 .fid_size = sizeof(struct mlxsw_sp_fid_8021d),
1876 .start_index = MLXSW_SP_FID_8021D_START,
1877 .end_index = MLXSW_SP_FID_8021D_END,
1878 .flood_profile = &mlxsw_sp_fid_8021d_flood_profile,
1879 .rif_type = MLXSW_SP_RIF_TYPE_FID,
1880 .ops = &mlxsw_sp_fid_8021d_ops_ctl,
1881 .bridge_type = MLXSW_REG_BRIDGE_TYPE_1,
1882 .smpe_index_valid = false,
1885 static const struct mlxsw_sp_fid_family mlxsw_sp1_fid_dummy_family = {
1886 .type = MLXSW_SP_FID_TYPE_DUMMY,
1887 .fid_size = sizeof(struct mlxsw_sp_fid),
1888 .start_index = MLXSW_SP_FID_DUMMY,
1889 .end_index = MLXSW_SP_FID_DUMMY,
1890 .ops = &mlxsw_sp_fid_dummy_ops,
1891 .smpe_index_valid = false,
1894 static const struct mlxsw_sp_fid_family mlxsw_sp_fid_rfid_family_ctl = {
1895 .type = MLXSW_SP_FID_TYPE_RFID,
1896 .fid_size = sizeof(struct mlxsw_sp_fid),
1897 .start_index = MLXSW_SP_RFID_START,
1898 .end_index = MLXSW_SP_RFID_END,
1899 .rif_type = MLXSW_SP_RIF_TYPE_SUBPORT,
1900 .ops = &mlxsw_sp_fid_rfid_ops_ctl,
1902 .smpe_index_valid = false,
1905 static const struct mlxsw_sp_fid_family *mlxsw_sp1_fid_family_arr[] = {
1906 [MLXSW_SP_FID_TYPE_8021Q] = &mlxsw_sp1_fid_8021q_family,
1907 [MLXSW_SP_FID_TYPE_8021D] = &mlxsw_sp1_fid_8021d_family,
1908 [MLXSW_SP_FID_TYPE_DUMMY] = &mlxsw_sp1_fid_dummy_family,
1909 [MLXSW_SP_FID_TYPE_RFID] = &mlxsw_sp_fid_rfid_family_ctl,
1912 static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_8021q_family_ctl = {
1913 .type = MLXSW_SP_FID_TYPE_8021Q,
1914 .fid_size = sizeof(struct mlxsw_sp_fid_8021q),
1915 .start_index = MLXSW_SP_FID_8021Q_START,
1916 .end_index = MLXSW_SP_FID_8021Q_END,
1917 .flood_profile = &mlxsw_sp_fid_8021d_flood_profile,
1918 .rif_type = MLXSW_SP_RIF_TYPE_VLAN,
1919 .ops = &mlxsw_sp_fid_8021q_ops_ctl,
1921 .bridge_type = MLXSW_REG_BRIDGE_TYPE_0,
1922 .smpe_index_valid = true,
1925 static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_8021d_family_ctl = {
1926 .type = MLXSW_SP_FID_TYPE_8021D,
1927 .fid_size = sizeof(struct mlxsw_sp_fid_8021d),
1928 .start_index = MLXSW_SP_FID_8021D_START,
1929 .end_index = MLXSW_SP_FID_8021D_END,
1930 .flood_profile = &mlxsw_sp_fid_8021d_flood_profile,
1931 .rif_type = MLXSW_SP_RIF_TYPE_FID,
1932 .ops = &mlxsw_sp_fid_8021d_ops_ctl,
1933 .bridge_type = MLXSW_REG_BRIDGE_TYPE_1,
1934 .smpe_index_valid = true,
1937 static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_dummy_family = {
1938 .type = MLXSW_SP_FID_TYPE_DUMMY,
1939 .fid_size = sizeof(struct mlxsw_sp_fid),
1940 .start_index = MLXSW_SP_FID_DUMMY,
1941 .end_index = MLXSW_SP_FID_DUMMY,
1942 .ops = &mlxsw_sp_fid_dummy_ops,
1943 .smpe_index_valid = false,
1946 static const struct mlxsw_sp_fid_family *mlxsw_sp2_fid_family_arr_ctl[] = {
1947 [MLXSW_SP_FID_TYPE_8021Q] = &mlxsw_sp2_fid_8021q_family_ctl,
1948 [MLXSW_SP_FID_TYPE_8021D] = &mlxsw_sp2_fid_8021d_family_ctl,
1949 [MLXSW_SP_FID_TYPE_DUMMY] = &mlxsw_sp2_fid_dummy_family,
1950 [MLXSW_SP_FID_TYPE_RFID] = &mlxsw_sp_fid_rfid_family_ctl,
1953 static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_8021q_family_cff = {
1954 .type = MLXSW_SP_FID_TYPE_8021Q,
1955 .fid_size = sizeof(struct mlxsw_sp_fid_8021q),
1956 .start_index = MLXSW_SP_FID_8021Q_START,
1957 .end_index = MLXSW_SP_FID_8021Q_END,
1958 .flood_profile = &mlxsw_sp_fid_8021d_flood_profile,
1959 .rif_type = MLXSW_SP_RIF_TYPE_VLAN,
1960 .ops = &mlxsw_sp_fid_8021q_ops_cff,
1961 .smpe_index_valid = true,
1964 static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_8021d_family_cff = {
1965 .type = MLXSW_SP_FID_TYPE_8021D,
1966 .fid_size = sizeof(struct mlxsw_sp_fid_8021d),
1967 .start_index = MLXSW_SP_FID_8021D_START,
1968 .end_index = MLXSW_SP_FID_8021D_END,
1969 .flood_profile = &mlxsw_sp_fid_8021d_flood_profile,
1970 .rif_type = MLXSW_SP_RIF_TYPE_FID,
1971 .ops = &mlxsw_sp_fid_8021d_ops_cff,
1972 .smpe_index_valid = true,
1975 static const struct mlxsw_sp_fid_family mlxsw_sp_fid_rfid_family_cff = {
1976 .type = MLXSW_SP_FID_TYPE_RFID,
1977 .fid_size = sizeof(struct mlxsw_sp_fid),
1978 .start_index = MLXSW_SP_RFID_START,
1979 .end_index = MLXSW_SP_RFID_END,
1980 .flood_profile = &mlxsw_sp_fid_rsp_flood_profile_cff,
1981 .rif_type = MLXSW_SP_RIF_TYPE_SUBPORT,
1982 .ops = &mlxsw_sp_fid_rfid_ops_cff,
1983 .smpe_index_valid = false,
1986 static const struct mlxsw_sp_fid_family *mlxsw_sp2_fid_family_arr_cff[] = {
1987 [MLXSW_SP_FID_TYPE_8021Q] = &mlxsw_sp2_fid_8021q_family_cff,
1988 [MLXSW_SP_FID_TYPE_8021D] = &mlxsw_sp2_fid_8021d_family_cff,
1989 [MLXSW_SP_FID_TYPE_DUMMY] = &mlxsw_sp2_fid_dummy_family,
1990 [MLXSW_SP_FID_TYPE_RFID] = &mlxsw_sp_fid_rfid_family_cff,
1993 static struct mlxsw_sp_fid *mlxsw_sp_fid_lookup(struct mlxsw_sp *mlxsw_sp,
1994 enum mlxsw_sp_fid_type type,
1997 struct mlxsw_sp_fid_family *fid_family;
1998 struct mlxsw_sp_fid *fid;
2000 fid_family = mlxsw_sp->fid_core->fid_family_arr[type];
2001 list_for_each_entry(fid, &fid_family->fids_list, list) {
2002 if (!fid->fid_family->ops->compare(fid, arg))
2004 refcount_inc(&fid->ref_count);
2011 static struct mlxsw_sp_fid *mlxsw_sp_fid_get(struct mlxsw_sp *mlxsw_sp,
2012 enum mlxsw_sp_fid_type type,
2015 struct mlxsw_sp_fid_family *fid_family;
2016 struct mlxsw_sp_fid *fid;
2020 fid = mlxsw_sp_fid_lookup(mlxsw_sp, type, arg);
2024 fid_family = mlxsw_sp->fid_core->fid_family_arr[type];
2025 fid = kzalloc(fid_family->fid_size, GFP_KERNEL);
2027 return ERR_PTR(-ENOMEM);
2029 INIT_LIST_HEAD(&fid->port_vid_list);
2030 fid->fid_family = fid_family;
2032 err = fid->fid_family->ops->index_alloc(fid, arg, &fid_index);
2034 goto err_index_alloc;
2035 fid->fid_index = fid_index;
2036 __set_bit(fid_index - fid_family->start_index, fid_family->fids_bitmap);
2038 err = fid->fid_family->ops->setup(fid, arg);
2042 err = fid->fid_family->ops->configure(fid);
2046 err = rhashtable_insert_fast(&mlxsw_sp->fid_core->fid_ht, &fid->ht_node,
2047 mlxsw_sp_fid_ht_params);
2049 goto err_rhashtable_insert;
2051 list_add(&fid->list, &fid_family->fids_list);
2052 refcount_set(&fid->ref_count, 1);
2055 err_rhashtable_insert:
2056 fid->fid_family->ops->deconfigure(fid);
2059 __clear_bit(fid_index - fid_family->start_index,
2060 fid_family->fids_bitmap);
2063 return ERR_PTR(err);
2066 void mlxsw_sp_fid_put(struct mlxsw_sp_fid *fid)
2068 struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
2069 struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
2071 if (!refcount_dec_and_test(&fid->ref_count))
2074 list_del(&fid->list);
2075 rhashtable_remove_fast(&mlxsw_sp->fid_core->fid_ht,
2076 &fid->ht_node, mlxsw_sp_fid_ht_params);
2077 fid->fid_family->ops->deconfigure(fid);
2078 __clear_bit(fid->fid_index - fid_family->start_index,
2079 fid_family->fids_bitmap);
2080 WARN_ON_ONCE(!list_empty(&fid->port_vid_list));
2084 struct mlxsw_sp_fid *mlxsw_sp_fid_8021q_get(struct mlxsw_sp *mlxsw_sp, u16 vid)
2086 return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_8021Q, &vid);
2089 struct mlxsw_sp_fid *mlxsw_sp_fid_8021d_get(struct mlxsw_sp *mlxsw_sp,
2092 return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_8021D, &br_ifindex);
2095 struct mlxsw_sp_fid *mlxsw_sp_fid_8021q_lookup(struct mlxsw_sp *mlxsw_sp,
2098 return mlxsw_sp_fid_lookup(mlxsw_sp, MLXSW_SP_FID_TYPE_8021Q, &vid);
2101 struct mlxsw_sp_fid *mlxsw_sp_fid_8021d_lookup(struct mlxsw_sp *mlxsw_sp,
2104 return mlxsw_sp_fid_lookup(mlxsw_sp, MLXSW_SP_FID_TYPE_8021D,
2108 struct mlxsw_sp_fid *mlxsw_sp_fid_rfid_get(struct mlxsw_sp *mlxsw_sp,
2111 return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_RFID, &rif_index);
2114 struct mlxsw_sp_fid *mlxsw_sp_fid_dummy_get(struct mlxsw_sp *mlxsw_sp)
2116 return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_DUMMY, NULL);
2120 mlxsw_sp_fid_flood_tables_init(struct mlxsw_sp_fid_family *fid_family)
2122 struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
2127 err = fid_family->ops->pgt_size(fid_family, &pgt_size);
2131 err = mlxsw_sp_pgt_mid_alloc_range(mlxsw_sp, &fid_family->pgt_base,
2136 if (!fid_family->flood_profile)
2139 for (i = 0; i < fid_family->flood_profile->nr_flood_tables; i++) {
2140 const struct mlxsw_sp_flood_table *flood_table;
2142 flood_table = &fid_family->flood_profile->flood_tables[i];
2143 if (fid_family->ops->flood_table_init) {
2144 err = fid_family->ops->flood_table_init(fid_family,
2147 goto err_flood_table_init;
2153 err_flood_table_init:
2154 mlxsw_sp_pgt_mid_free_range(mlxsw_sp, fid_family->pgt_base, pgt_size);
2159 mlxsw_sp_fid_flood_tables_fini(struct mlxsw_sp_fid_family *fid_family)
2161 struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
2165 err = fid_family->ops->pgt_size(fid_family, &pgt_size);
2166 if (WARN_ON_ONCE(err))
2169 mlxsw_sp_pgt_mid_free_range(mlxsw_sp, fid_family->pgt_base, pgt_size);
2172 static int mlxsw_sp_fid_family_register(struct mlxsw_sp *mlxsw_sp,
2173 const struct mlxsw_sp_fid_family *tmpl)
2175 u16 nr_fids = tmpl->end_index - tmpl->start_index + 1;
2176 struct mlxsw_sp_fid_family *fid_family;
2179 fid_family = kmemdup(tmpl, sizeof(*fid_family), GFP_KERNEL);
2183 fid_family->mlxsw_sp = mlxsw_sp;
2184 INIT_LIST_HEAD(&fid_family->fids_list);
2185 fid_family->fids_bitmap = bitmap_zalloc(nr_fids, GFP_KERNEL);
2186 if (!fid_family->fids_bitmap) {
2188 goto err_alloc_fids_bitmap;
2191 if (fid_family->flood_profile) {
2192 err = mlxsw_sp_fid_flood_tables_init(fid_family);
2194 goto err_fid_flood_tables_init;
2197 mlxsw_sp->fid_core->fid_family_arr[tmpl->type] = fid_family;
2201 err_fid_flood_tables_init:
2202 bitmap_free(fid_family->fids_bitmap);
2203 err_alloc_fids_bitmap:
2209 mlxsw_sp_fid_family_unregister(struct mlxsw_sp *mlxsw_sp,
2210 struct mlxsw_sp_fid_family *fid_family)
2212 mlxsw_sp->fid_core->fid_family_arr[fid_family->type] = NULL;
2214 if (fid_family->flood_profile)
2215 mlxsw_sp_fid_flood_tables_fini(fid_family);
2217 bitmap_free(fid_family->fids_bitmap);
2218 WARN_ON_ONCE(!list_empty(&fid_family->fids_list));
2222 static int mlxsw_sp_fid_port_init(const struct mlxsw_sp_port *mlxsw_sp_port)
2224 const enum mlxsw_sp_fid_type type_rfid = MLXSW_SP_FID_TYPE_RFID;
2225 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
2226 struct mlxsw_sp_fid_family *rfid_family;
2228 rfid_family = mlxsw_sp->fid_core->fid_family_arr[type_rfid];
2229 if (rfid_family->ops->fid_port_init)
2230 return rfid_family->ops->fid_port_init(rfid_family,
2235 static void mlxsw_sp_fid_port_fini(const struct mlxsw_sp_port *mlxsw_sp_port)
2237 const enum mlxsw_sp_fid_type type_rfid = MLXSW_SP_FID_TYPE_RFID;
2238 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
2239 struct mlxsw_sp_fid_family *rfid_family;
2241 rfid_family = mlxsw_sp->fid_core->fid_family_arr[type_rfid];
2242 if (rfid_family->ops->fid_port_fini)
2243 rfid_family->ops->fid_port_fini(rfid_family, mlxsw_sp_port);
2246 int mlxsw_sp_port_fids_init(struct mlxsw_sp_port *mlxsw_sp_port)
2248 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
2251 /* Track number of FIDs configured on the port with mapping type
2252 * PORT_VID_TO_FID, so that we know when to transition the port
2253 * back to non-virtual (VLAN) mode.
2255 mlxsw_sp->fid_core->port_fid_mappings[mlxsw_sp_port->local_port] = 0;
2257 err = mlxsw_sp_fid_port_init(mlxsw_sp_port);
2261 err = mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, false);
2263 goto err_vp_mode_set;
2268 mlxsw_sp_fid_port_fini(mlxsw_sp_port);
2272 void mlxsw_sp_port_fids_fini(struct mlxsw_sp_port *mlxsw_sp_port)
2274 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
2276 mlxsw_sp_fid_port_fini(mlxsw_sp_port);
2277 mlxsw_sp->fid_core->port_fid_mappings[mlxsw_sp_port->local_port] = 0;
2280 int mlxsw_sp_fid_port_join_lag(const struct mlxsw_sp_port *mlxsw_sp_port)
2282 return mlxsw_sp_fid_port_init(mlxsw_sp_port);
2285 void mlxsw_sp_fid_port_leave_lag(const struct mlxsw_sp_port *mlxsw_sp_port)
2287 mlxsw_sp_fid_port_fini(mlxsw_sp_port);
2291 mlxsw_sp_fids_init(struct mlxsw_sp *mlxsw_sp,
2292 const struct mlxsw_sp_fid_family *fid_family_arr[])
2294 unsigned int max_ports = mlxsw_core_max_ports(mlxsw_sp->core);
2295 struct mlxsw_sp_fid_core *fid_core;
2298 fid_core = kzalloc(sizeof(*mlxsw_sp->fid_core), GFP_KERNEL);
2301 mlxsw_sp->fid_core = fid_core;
2303 err = rhashtable_init(&fid_core->fid_ht, &mlxsw_sp_fid_ht_params);
2305 goto err_rhashtable_fid_init;
2307 err = rhashtable_init(&fid_core->vni_ht, &mlxsw_sp_fid_vni_ht_params);
2309 goto err_rhashtable_vni_init;
2311 fid_core->port_fid_mappings = kcalloc(max_ports, sizeof(unsigned int),
2313 if (!fid_core->port_fid_mappings) {
2315 goto err_alloc_port_fid_mappings;
2318 for (i = 0; i < MLXSW_SP_FID_TYPE_MAX; i++) {
2319 err = mlxsw_sp_fid_family_register(mlxsw_sp, fid_family_arr[i]);
2322 goto err_fid_ops_register;
2327 err_fid_ops_register:
2328 for (i--; i >= 0; i--) {
2329 struct mlxsw_sp_fid_family *fid_family;
2331 fid_family = fid_core->fid_family_arr[i];
2332 mlxsw_sp_fid_family_unregister(mlxsw_sp, fid_family);
2334 kfree(fid_core->port_fid_mappings);
2335 err_alloc_port_fid_mappings:
2336 rhashtable_destroy(&fid_core->vni_ht);
2337 err_rhashtable_vni_init:
2338 rhashtable_destroy(&fid_core->fid_ht);
2339 err_rhashtable_fid_init:
2344 static void mlxsw_sp_fids_fini(struct mlxsw_sp *mlxsw_sp)
2346 struct mlxsw_sp_fid_core *fid_core = mlxsw_sp->fid_core;
2349 for (i = 0; i < MLXSW_SP_FID_TYPE_MAX; i++)
2350 mlxsw_sp_fid_family_unregister(mlxsw_sp,
2351 fid_core->fid_family_arr[i]);
2352 kfree(fid_core->port_fid_mappings);
2353 rhashtable_destroy(&fid_core->vni_ht);
2354 rhashtable_destroy(&fid_core->fid_ht);
2358 static int mlxsw_sp1_fids_init(struct mlxsw_sp *mlxsw_sp)
2360 return mlxsw_sp_fids_init(mlxsw_sp, mlxsw_sp1_fid_family_arr);
2363 const struct mlxsw_sp_fid_core_ops mlxsw_sp1_fid_core_ops = {
2364 .init = mlxsw_sp1_fids_init,
2365 .fini = mlxsw_sp_fids_fini,
2368 static int mlxsw_sp_fid_check_flood_profile_id(struct mlxsw_sp *mlxsw_sp,
2373 if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_NVE_FLOOD_PRF))
2376 max_profiles = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_NVE_FLOOD_PRF);
2377 if (WARN_ON_ONCE(!profile_id) ||
2378 WARN_ON_ONCE(profile_id >= max_profiles))
2385 mlxsw_sp2_fids_init_flood_table(struct mlxsw_sp *mlxsw_sp,
2386 enum mlxsw_sp_fid_flood_profile_id profile_id,
2387 const struct mlxsw_sp_flood_table *flood_table)
2389 enum mlxsw_sp_flood_type packet_type = flood_table->packet_type;
2390 const int *sfgc_packet_types;
2394 sfgc_packet_types = mlxsw_sp_packet_type_sfgc_types[packet_type];
2395 for (i = 0; i < MLXSW_REG_SFGC_TYPE_MAX; i++) {
2396 char sffp_pl[MLXSW_REG_SFFP_LEN];
2398 if (!sfgc_packet_types[i])
2401 mlxsw_reg_sffp_pack(sffp_pl, profile_id, i,
2402 flood_table->table_index);
2403 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sffp), sffp_pl);
2412 mlxsw_sp2_fids_init_flood_profile(struct mlxsw_sp *mlxsw_sp,
2413 const struct mlxsw_sp_fid_flood_profile *
2419 err = mlxsw_sp_fid_check_flood_profile_id(mlxsw_sp,
2420 flood_profile->profile_id);
2424 for (i = 0; i < flood_profile->nr_flood_tables; i++) {
2425 const struct mlxsw_sp_flood_table *flood_table;
2427 flood_table = &flood_profile->flood_tables[i];
2428 err = mlxsw_sp2_fids_init_flood_table(mlxsw_sp,
2429 flood_profile->profile_id,
2439 struct mlxsw_sp_fid_flood_profile *mlxsw_sp_fid_flood_profiles[] = {
2440 &mlxsw_sp_fid_8021d_flood_profile,
2441 &mlxsw_sp_fid_rsp_flood_profile_cff,
2442 &mlxsw_sp_fid_nve_flood_profile_cff,
2446 mlxsw_sp2_fids_init_flood_profiles(struct mlxsw_sp *mlxsw_sp)
2451 for (i = 0; i < ARRAY_SIZE(mlxsw_sp_fid_flood_profiles); i++) {
2452 const struct mlxsw_sp_fid_flood_profile *flood_profile;
2454 flood_profile = mlxsw_sp_fid_flood_profiles[i];
2455 err = mlxsw_sp2_fids_init_flood_profile(mlxsw_sp,
2464 static int mlxsw_sp2_fids_init_ctl(struct mlxsw_sp *mlxsw_sp)
2466 return mlxsw_sp_fids_init(mlxsw_sp, mlxsw_sp2_fid_family_arr_ctl);
2469 static int mlxsw_sp2_fids_init_cff(struct mlxsw_sp *mlxsw_sp)
2473 err = mlxsw_sp2_fids_init_flood_profiles(mlxsw_sp);
2477 return mlxsw_sp_fids_init(mlxsw_sp, mlxsw_sp2_fid_family_arr_cff);
2480 static int mlxsw_sp2_fids_init(struct mlxsw_sp *mlxsw_sp)
2482 switch (mlxsw_core_flood_mode(mlxsw_sp->core)) {
2483 case MLXSW_CMD_MBOX_CONFIG_PROFILE_FLOOD_MODE_CONTROLLED:
2484 return mlxsw_sp2_fids_init_ctl(mlxsw_sp);
2485 case MLXSW_CMD_MBOX_CONFIG_PROFILE_FLOOD_MODE_CFF:
2486 return mlxsw_sp2_fids_init_cff(mlxsw_sp);
2493 const struct mlxsw_sp_fid_core_ops mlxsw_sp2_fid_core_ops = {
2494 .init = mlxsw_sp2_fids_init,
2495 .fini = mlxsw_sp_fids_fini,