Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
0002 /* Copyright (c) 2017-2018 Mellanox Technologies. All rights reserved */
0003 
0004 #include <linux/kernel.h>
0005 #include <linux/bitops.h>
0006 #include <linux/if_vlan.h>
0007 #include <linux/if_bridge.h>
0008 #include <linux/netdevice.h>
0009 #include <linux/rhashtable.h>
0010 #include <linux/rtnetlink.h>
0011 #include <linux/refcount.h>
0012 
0013 #include "spectrum.h"
0014 #include "reg.h"
0015 
0016 struct mlxsw_sp_fid_family;
0017 
0018 struct mlxsw_sp_fid_core {
0019     struct rhashtable fid_ht;
0020     struct rhashtable vni_ht;
0021     struct mlxsw_sp_fid_family *fid_family_arr[MLXSW_SP_FID_TYPE_MAX];
0022     unsigned int *port_fid_mappings;
0023 };
0024 
0025 struct mlxsw_sp_fid_port_vid {
0026     struct list_head list;
0027     u16 local_port;
0028     u16 vid;
0029 };
0030 
0031 struct mlxsw_sp_fid {
0032     struct list_head list;
0033     struct mlxsw_sp_rif *rif;
0034     refcount_t ref_count;
0035     u16 fid_index;
0036     u16 fid_offset;
0037     struct mlxsw_sp_fid_family *fid_family;
0038     struct rhash_head ht_node;
0039 
0040     struct rhash_head vni_ht_node;
0041     enum mlxsw_sp_nve_type nve_type;
0042     __be32 vni;
0043     u32 nve_flood_index;
0044     int nve_ifindex;
0045     u8 vni_valid:1,
0046        nve_flood_index_valid:1;
0047     struct list_head port_vid_list; /* Ordered by local port. */
0048 };
0049 
0050 struct mlxsw_sp_fid_8021q {
0051     struct mlxsw_sp_fid common;
0052     u16 vid;
0053 };
0054 
0055 struct mlxsw_sp_fid_8021d {
0056     struct mlxsw_sp_fid common;
0057     int br_ifindex;
0058 };
0059 
0060 static const struct rhashtable_params mlxsw_sp_fid_ht_params = {
0061     .key_len = sizeof_field(struct mlxsw_sp_fid, fid_index),
0062     .key_offset = offsetof(struct mlxsw_sp_fid, fid_index),
0063     .head_offset = offsetof(struct mlxsw_sp_fid, ht_node),
0064 };
0065 
0066 static const struct rhashtable_params mlxsw_sp_fid_vni_ht_params = {
0067     .key_len = sizeof_field(struct mlxsw_sp_fid, vni),
0068     .key_offset = offsetof(struct mlxsw_sp_fid, vni),
0069     .head_offset = offsetof(struct mlxsw_sp_fid, vni_ht_node),
0070 };
0071 
0072 struct mlxsw_sp_flood_table {
0073     enum mlxsw_sp_flood_type packet_type;
0074     enum mlxsw_flood_table_type table_type;
0075     int table_index;
0076 };
0077 
0078 struct mlxsw_sp_fid_ops {
0079     void (*setup)(struct mlxsw_sp_fid *fid, const void *arg);
0080     int (*configure)(struct mlxsw_sp_fid *fid);
0081     void (*deconfigure)(struct mlxsw_sp_fid *fid);
0082     int (*index_alloc)(struct mlxsw_sp_fid *fid, const void *arg,
0083                u16 *p_fid_index);
0084     bool (*compare)(const struct mlxsw_sp_fid *fid,
0085             const void *arg);
0086     int (*port_vid_map)(struct mlxsw_sp_fid *fid,
0087                 struct mlxsw_sp_port *port, u16 vid);
0088     void (*port_vid_unmap)(struct mlxsw_sp_fid *fid,
0089                    struct mlxsw_sp_port *port, u16 vid);
0090     int (*vni_set)(struct mlxsw_sp_fid *fid);
0091     void (*vni_clear)(struct mlxsw_sp_fid *fid);
0092     int (*nve_flood_index_set)(struct mlxsw_sp_fid *fid);
0093     void (*nve_flood_index_clear)(struct mlxsw_sp_fid *fid);
0094     void (*fdb_clear_offload)(const struct mlxsw_sp_fid *fid,
0095                   const struct net_device *nve_dev);
0096     int (*vid_to_fid_rif_update)(const struct mlxsw_sp_fid *fid,
0097                      const struct mlxsw_sp_rif *rif);
0098 };
0099 
0100 struct mlxsw_sp_fid_family {
0101     enum mlxsw_sp_fid_type type;
0102     size_t fid_size;
0103     u16 start_index;
0104     u16 end_index;
0105     struct list_head fids_list;
0106     unsigned long *fids_bitmap;
0107     const struct mlxsw_sp_flood_table *flood_tables;
0108     int nr_flood_tables;
0109     enum mlxsw_sp_rif_type rif_type;
0110     const struct mlxsw_sp_fid_ops *ops;
0111     struct mlxsw_sp *mlxsw_sp;
0112     bool flood_rsp;
0113     enum mlxsw_reg_bridge_type bridge_type;
0114     u16 pgt_base;
0115     bool smpe_index_valid;
0116 };
0117 
0118 static const int mlxsw_sp_sfgc_uc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = {
0119     [MLXSW_REG_SFGC_TYPE_UNKNOWN_UNICAST]           = 1,
0120 };
0121 
0122 static const int mlxsw_sp_sfgc_bc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = {
0123     [MLXSW_REG_SFGC_TYPE_BROADCAST]             = 1,
0124     [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_NON_IP] = 1,
0125     [MLXSW_REG_SFGC_TYPE_IPV4_LINK_LOCAL]           = 1,
0126     [MLXSW_REG_SFGC_TYPE_IPV6_ALL_HOST]         = 1,
0127     [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV6]   = 1,
0128 };
0129 
0130 static const int mlxsw_sp_sfgc_mc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = {
0131     [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV4]   = 1,
0132 };
0133 
0134 static const int *mlxsw_sp_packet_type_sfgc_types[] = {
0135     [MLXSW_SP_FLOOD_TYPE_UC]    = mlxsw_sp_sfgc_uc_packet_types,
0136     [MLXSW_SP_FLOOD_TYPE_BC]    = mlxsw_sp_sfgc_bc_packet_types,
0137     [MLXSW_SP_FLOOD_TYPE_MC]    = mlxsw_sp_sfgc_mc_packet_types,
0138 };
0139 
0140 bool mlxsw_sp_fid_is_dummy(struct mlxsw_sp *mlxsw_sp, u16 fid_index)
0141 {
0142     enum mlxsw_sp_fid_type fid_type = MLXSW_SP_FID_TYPE_DUMMY;
0143     struct mlxsw_sp_fid_family *fid_family;
0144 
0145     fid_family = mlxsw_sp->fid_core->fid_family_arr[fid_type];
0146 
0147     return fid_family->start_index == fid_index;
0148 }
0149 
0150 struct mlxsw_sp_fid *mlxsw_sp_fid_lookup_by_index(struct mlxsw_sp *mlxsw_sp,
0151                           u16 fid_index)
0152 {
0153     struct mlxsw_sp_fid *fid;
0154 
0155     fid = rhashtable_lookup_fast(&mlxsw_sp->fid_core->fid_ht, &fid_index,
0156                      mlxsw_sp_fid_ht_params);
0157     if (fid)
0158         refcount_inc(&fid->ref_count);
0159 
0160     return fid;
0161 }
0162 
0163 int mlxsw_sp_fid_nve_ifindex(const struct mlxsw_sp_fid *fid, int *nve_ifindex)
0164 {
0165     if (!fid->vni_valid)
0166         return -EINVAL;
0167 
0168     *nve_ifindex = fid->nve_ifindex;
0169 
0170     return 0;
0171 }
0172 
0173 int mlxsw_sp_fid_nve_type(const struct mlxsw_sp_fid *fid,
0174               enum mlxsw_sp_nve_type *p_type)
0175 {
0176     if (!fid->vni_valid)
0177         return -EINVAL;
0178 
0179     *p_type = fid->nve_type;
0180 
0181     return 0;
0182 }
0183 
0184 struct mlxsw_sp_fid *mlxsw_sp_fid_lookup_by_vni(struct mlxsw_sp *mlxsw_sp,
0185                         __be32 vni)
0186 {
0187     struct mlxsw_sp_fid *fid;
0188 
0189     fid = rhashtable_lookup_fast(&mlxsw_sp->fid_core->vni_ht, &vni,
0190                      mlxsw_sp_fid_vni_ht_params);
0191     if (fid)
0192         refcount_inc(&fid->ref_count);
0193 
0194     return fid;
0195 }
0196 
0197 int mlxsw_sp_fid_vni(const struct mlxsw_sp_fid *fid, __be32 *vni)
0198 {
0199     if (!fid->vni_valid)
0200         return -EINVAL;
0201 
0202     *vni = fid->vni;
0203 
0204     return 0;
0205 }
0206 
0207 int mlxsw_sp_fid_nve_flood_index_set(struct mlxsw_sp_fid *fid,
0208                      u32 nve_flood_index)
0209 {
0210     struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
0211     const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
0212     int err;
0213 
0214     if (WARN_ON(fid->nve_flood_index_valid))
0215         return -EINVAL;
0216 
0217     fid->nve_flood_index = nve_flood_index;
0218     fid->nve_flood_index_valid = true;
0219     err = ops->nve_flood_index_set(fid);
0220     if (err)
0221         goto err_nve_flood_index_set;
0222 
0223     return 0;
0224 
0225 err_nve_flood_index_set:
0226     fid->nve_flood_index_valid = false;
0227     return err;
0228 }
0229 
0230 void mlxsw_sp_fid_nve_flood_index_clear(struct mlxsw_sp_fid *fid)
0231 {
0232     struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
0233     const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
0234 
0235     if (WARN_ON(!fid->nve_flood_index_valid))
0236         return;
0237 
0238     fid->nve_flood_index_valid = false;
0239     ops->nve_flood_index_clear(fid);
0240 }
0241 
0242 bool mlxsw_sp_fid_nve_flood_index_is_set(const struct mlxsw_sp_fid *fid)
0243 {
0244     return fid->nve_flood_index_valid;
0245 }
0246 
0247 int mlxsw_sp_fid_vni_set(struct mlxsw_sp_fid *fid, enum mlxsw_sp_nve_type type,
0248              __be32 vni, int nve_ifindex)
0249 {
0250     struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
0251     const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
0252     struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
0253     int err;
0254 
0255     if (WARN_ON(fid->vni_valid))
0256         return -EINVAL;
0257 
0258     fid->nve_type = type;
0259     fid->nve_ifindex = nve_ifindex;
0260     fid->vni = vni;
0261     err = rhashtable_lookup_insert_fast(&mlxsw_sp->fid_core->vni_ht,
0262                         &fid->vni_ht_node,
0263                         mlxsw_sp_fid_vni_ht_params);
0264     if (err)
0265         return err;
0266 
0267     fid->vni_valid = true;
0268     err = ops->vni_set(fid);
0269     if (err)
0270         goto err_vni_set;
0271 
0272     return 0;
0273 
0274 err_vni_set:
0275     fid->vni_valid = false;
0276     rhashtable_remove_fast(&mlxsw_sp->fid_core->vni_ht, &fid->vni_ht_node,
0277                    mlxsw_sp_fid_vni_ht_params);
0278     return err;
0279 }
0280 
0281 void mlxsw_sp_fid_vni_clear(struct mlxsw_sp_fid *fid)
0282 {
0283     struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
0284     const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
0285     struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
0286 
0287     if (WARN_ON(!fid->vni_valid))
0288         return;
0289 
0290     fid->vni_valid = false;
0291     ops->vni_clear(fid);
0292     rhashtable_remove_fast(&mlxsw_sp->fid_core->vni_ht, &fid->vni_ht_node,
0293                    mlxsw_sp_fid_vni_ht_params);
0294 }
0295 
0296 bool mlxsw_sp_fid_vni_is_set(const struct mlxsw_sp_fid *fid)
0297 {
0298     return fid->vni_valid;
0299 }
0300 
0301 void mlxsw_sp_fid_fdb_clear_offload(const struct mlxsw_sp_fid *fid,
0302                     const struct net_device *nve_dev)
0303 {
0304     struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
0305     const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
0306 
0307     if (ops->fdb_clear_offload)
0308         ops->fdb_clear_offload(fid, nve_dev);
0309 }
0310 
0311 static const struct mlxsw_sp_flood_table *
0312 mlxsw_sp_fid_flood_table_lookup(const struct mlxsw_sp_fid *fid,
0313                 enum mlxsw_sp_flood_type packet_type)
0314 {
0315     struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
0316     int i;
0317 
0318     for (i = 0; i < fid_family->nr_flood_tables; i++) {
0319         if (fid_family->flood_tables[i].packet_type != packet_type)
0320             continue;
0321         return &fid_family->flood_tables[i];
0322     }
0323 
0324     return NULL;
0325 }
0326 
0327 static u16
0328 mlxsw_sp_fid_family_num_fids(const struct mlxsw_sp_fid_family *fid_family)
0329 {
0330     return fid_family->end_index - fid_family->start_index + 1;
0331 }
0332 
0333 static u16
0334 mlxsw_sp_fid_flood_table_mid(const struct mlxsw_sp_fid_family *fid_family,
0335                  const struct mlxsw_sp_flood_table *flood_table,
0336                  u16 fid_offset)
0337 {
0338     u16 num_fids;
0339 
0340     num_fids = mlxsw_sp_fid_family_num_fids(fid_family);
0341     return fid_family->pgt_base + num_fids * flood_table->table_index +
0342            fid_offset;
0343 }
0344 
0345 int mlxsw_sp_fid_flood_set(struct mlxsw_sp_fid *fid,
0346                enum mlxsw_sp_flood_type packet_type, u16 local_port,
0347                bool member)
0348 {
0349     struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
0350     const struct mlxsw_sp_flood_table *flood_table;
0351     u16 mid_index;
0352 
0353     if (WARN_ON(!fid_family->flood_tables))
0354         return -EINVAL;
0355 
0356     flood_table = mlxsw_sp_fid_flood_table_lookup(fid, packet_type);
0357     if (!flood_table)
0358         return -ESRCH;
0359 
0360     mid_index = mlxsw_sp_fid_flood_table_mid(fid_family, flood_table,
0361                          fid->fid_offset);
0362     return mlxsw_sp_pgt_entry_port_set(fid_family->mlxsw_sp, mid_index,
0363                        fid->fid_index, local_port, member);
0364 }
0365 
0366 int mlxsw_sp_fid_port_vid_map(struct mlxsw_sp_fid *fid,
0367                   struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
0368 {
0369     if (WARN_ON(!fid->fid_family->ops->port_vid_map))
0370         return -EINVAL;
0371     return fid->fid_family->ops->port_vid_map(fid, mlxsw_sp_port, vid);
0372 }
0373 
0374 void mlxsw_sp_fid_port_vid_unmap(struct mlxsw_sp_fid *fid,
0375                  struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
0376 {
0377     fid->fid_family->ops->port_vid_unmap(fid, mlxsw_sp_port, vid);
0378 }
0379 
0380 u16 mlxsw_sp_fid_index(const struct mlxsw_sp_fid *fid)
0381 {
0382     return fid->fid_index;
0383 }
0384 
0385 enum mlxsw_sp_fid_type mlxsw_sp_fid_type(const struct mlxsw_sp_fid *fid)
0386 {
0387     return fid->fid_family->type;
0388 }
0389 
0390 struct mlxsw_sp_rif *mlxsw_sp_fid_rif(const struct mlxsw_sp_fid *fid)
0391 {
0392     return fid->rif;
0393 }
0394 
0395 enum mlxsw_sp_rif_type
0396 mlxsw_sp_fid_type_rif_type(const struct mlxsw_sp *mlxsw_sp,
0397                enum mlxsw_sp_fid_type type)
0398 {
0399     struct mlxsw_sp_fid_core *fid_core = mlxsw_sp->fid_core;
0400 
0401     return fid_core->fid_family_arr[type]->rif_type;
0402 }
0403 
0404 static struct mlxsw_sp_fid_8021q *
0405 mlxsw_sp_fid_8021q_fid(const struct mlxsw_sp_fid *fid)
0406 {
0407     return container_of(fid, struct mlxsw_sp_fid_8021q, common);
0408 }
0409 
0410 u16 mlxsw_sp_fid_8021q_vid(const struct mlxsw_sp_fid *fid)
0411 {
0412     return mlxsw_sp_fid_8021q_fid(fid)->vid;
0413 }
0414 
0415 static void mlxsw_sp_fid_8021q_setup(struct mlxsw_sp_fid *fid, const void *arg)
0416 {
0417     u16 vid = *(u16 *) arg;
0418 
0419     mlxsw_sp_fid_8021q_fid(fid)->vid = vid;
0420     fid->fid_offset = fid->fid_index - fid->fid_family->start_index;
0421 }
0422 
0423 static enum mlxsw_reg_sfmr_op mlxsw_sp_sfmr_op(bool valid)
0424 {
0425     return valid ? MLXSW_REG_SFMR_OP_CREATE_FID :
0426                MLXSW_REG_SFMR_OP_DESTROY_FID;
0427 }
0428 
0429 static int mlxsw_sp_fid_op(const struct mlxsw_sp_fid *fid, bool valid)
0430 {
0431     struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
0432     char sfmr_pl[MLXSW_REG_SFMR_LEN];
0433     u16 smpe;
0434 
0435     smpe = fid->fid_family->smpe_index_valid ? fid->fid_index : 0;
0436 
0437     mlxsw_reg_sfmr_pack(sfmr_pl, mlxsw_sp_sfmr_op(valid), fid->fid_index,
0438                 fid->fid_offset, fid->fid_family->flood_rsp,
0439                 fid->fid_family->bridge_type,
0440                 fid->fid_family->smpe_index_valid, smpe);
0441     return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl);
0442 }
0443 
0444 static int mlxsw_sp_fid_edit_op(const struct mlxsw_sp_fid *fid,
0445                 const struct mlxsw_sp_rif *rif)
0446 {
0447     struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
0448     char sfmr_pl[MLXSW_REG_SFMR_LEN];
0449     u16 smpe;
0450 
0451     smpe = fid->fid_family->smpe_index_valid ? fid->fid_index : 0;
0452 
0453     mlxsw_reg_sfmr_pack(sfmr_pl, MLXSW_REG_SFMR_OP_CREATE_FID,
0454                 fid->fid_index, fid->fid_offset,
0455                 fid->fid_family->flood_rsp,
0456                 fid->fid_family->bridge_type,
0457                 fid->fid_family->smpe_index_valid, smpe);
0458     mlxsw_reg_sfmr_vv_set(sfmr_pl, fid->vni_valid);
0459     mlxsw_reg_sfmr_vni_set(sfmr_pl, be32_to_cpu(fid->vni));
0460     mlxsw_reg_sfmr_vtfp_set(sfmr_pl, fid->nve_flood_index_valid);
0461     mlxsw_reg_sfmr_nve_tunnel_flood_ptr_set(sfmr_pl, fid->nve_flood_index);
0462 
0463     if (rif) {
0464         mlxsw_reg_sfmr_irif_v_set(sfmr_pl, true);
0465         mlxsw_reg_sfmr_irif_set(sfmr_pl, mlxsw_sp_rif_index(rif));
0466     }
0467 
0468     return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl);
0469 }
0470 
0471 static int mlxsw_sp_fid_vni_to_fid_map(const struct mlxsw_sp_fid *fid,
0472                        const struct mlxsw_sp_rif *rif,
0473                        bool valid)
0474 {
0475     struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
0476     char svfa_pl[MLXSW_REG_SVFA_LEN];
0477     bool irif_valid;
0478     u16 irif_index;
0479 
0480     irif_valid = !!rif;
0481     irif_index = rif ? mlxsw_sp_rif_index(rif) : 0;
0482 
0483     mlxsw_reg_svfa_vni_pack(svfa_pl, valid, fid->fid_index,
0484                 be32_to_cpu(fid->vni), irif_valid, irif_index);
0485     return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl);
0486 }
0487 
0488 static int mlxsw_sp_fid_to_fid_rif_update(const struct mlxsw_sp_fid *fid,
0489                       const struct mlxsw_sp_rif *rif)
0490 {
0491     return mlxsw_sp_fid_edit_op(fid, rif);
0492 }
0493 
0494 static int mlxsw_sp_fid_vni_to_fid_rif_update(const struct mlxsw_sp_fid *fid,
0495                           const struct mlxsw_sp_rif *rif)
0496 {
0497     if (!fid->vni_valid)
0498         return 0;
0499 
0500     return mlxsw_sp_fid_vni_to_fid_map(fid, rif, fid->vni_valid);
0501 }
0502 
0503 static int
0504 mlxsw_sp_fid_vid_to_fid_map(const struct mlxsw_sp_fid *fid, u16 vid, bool valid,
0505                 const struct mlxsw_sp_rif *rif)
0506 {
0507     struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
0508     char svfa_pl[MLXSW_REG_SVFA_LEN];
0509     bool irif_valid;
0510     u16 irif_index;
0511 
0512     irif_valid = !!rif;
0513     irif_index = rif ? mlxsw_sp_rif_index(rif) : 0;
0514 
0515     mlxsw_reg_svfa_vid_pack(svfa_pl, valid, fid->fid_index, vid, irif_valid,
0516                 irif_index);
0517     return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl);
0518 }
0519 
0520 static int
0521 mlxsw_sp_fid_8021q_vid_to_fid_rif_update(const struct mlxsw_sp_fid *fid,
0522                      const struct mlxsw_sp_rif *rif)
0523 {
0524     struct mlxsw_sp_fid_8021q *fid_8021q = mlxsw_sp_fid_8021q_fid(fid);
0525 
0526     /* Update the global VID => FID mapping we created when the FID was
0527      * configured.
0528      */
0529     return mlxsw_sp_fid_vid_to_fid_map(fid, fid_8021q->vid, true, rif);
0530 }
0531 
0532 static int
0533 mlxsw_sp_fid_port_vid_to_fid_rif_update_one(const struct mlxsw_sp_fid *fid,
0534                         struct mlxsw_sp_fid_port_vid *pv,
0535                         bool irif_valid, u16 irif_index)
0536 {
0537     struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
0538     char svfa_pl[MLXSW_REG_SVFA_LEN];
0539 
0540     mlxsw_reg_svfa_port_vid_pack(svfa_pl, pv->local_port, true,
0541                      fid->fid_index, pv->vid, irif_valid,
0542                      irif_index);
0543 
0544     return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl);
0545 }
0546 
0547 static int mlxsw_sp_fid_vid_to_fid_rif_set(const struct mlxsw_sp_fid *fid,
0548                        const struct mlxsw_sp_rif *rif)
0549 {
0550     struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
0551     struct mlxsw_sp_fid_port_vid *pv;
0552     u16 irif_index;
0553     int err;
0554 
0555     err = fid->fid_family->ops->vid_to_fid_rif_update(fid, rif);
0556     if (err)
0557         return err;
0558 
0559     irif_index = mlxsw_sp_rif_index(rif);
0560 
0561     list_for_each_entry(pv, &fid->port_vid_list, list) {
0562         /* If port is not in virtual mode, then it does not have any
0563          * {Port, VID}->FID mappings that need to be updated with the
0564          * ingress RIF.
0565          */
0566         if (!mlxsw_sp->fid_core->port_fid_mappings[pv->local_port])
0567             continue;
0568 
0569         err = mlxsw_sp_fid_port_vid_to_fid_rif_update_one(fid, pv,
0570                                   true,
0571                                   irif_index);
0572         if (err)
0573             goto err_port_vid_to_fid_rif_update_one;
0574     }
0575 
0576     return 0;
0577 
0578 err_port_vid_to_fid_rif_update_one:
0579     list_for_each_entry_continue_reverse(pv, &fid->port_vid_list, list) {
0580         if (!mlxsw_sp->fid_core->port_fid_mappings[pv->local_port])
0581             continue;
0582 
0583         mlxsw_sp_fid_port_vid_to_fid_rif_update_one(fid, pv, false, 0);
0584     }
0585 
0586     fid->fid_family->ops->vid_to_fid_rif_update(fid, NULL);
0587     return err;
0588 }
0589 
0590 static void mlxsw_sp_fid_vid_to_fid_rif_unset(const struct mlxsw_sp_fid *fid)
0591 {
0592     struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
0593     struct mlxsw_sp_fid_port_vid *pv;
0594 
0595     list_for_each_entry(pv, &fid->port_vid_list, list) {
0596         /* If port is not in virtual mode, then it does not have any
0597          * {Port, VID}->FID mappings that need to be updated.
0598          */
0599         if (!mlxsw_sp->fid_core->port_fid_mappings[pv->local_port])
0600             continue;
0601 
0602         mlxsw_sp_fid_port_vid_to_fid_rif_update_one(fid, pv, false, 0);
0603     }
0604 
0605     fid->fid_family->ops->vid_to_fid_rif_update(fid, NULL);
0606 }
0607 
0608 static int mlxsw_sp_fid_reiv_handle(struct mlxsw_sp_fid *fid, u16 rif_index,
0609                     bool valid, u8 port_page)
0610 {
0611     u16 local_port_end = (port_page + 1) * MLXSW_REG_REIV_REC_MAX_COUNT - 1;
0612     u16 local_port_start = port_page * MLXSW_REG_REIV_REC_MAX_COUNT;
0613     struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
0614     struct mlxsw_sp_fid_port_vid *port_vid;
0615     u8 rec_num, entries_num = 0;
0616     char *reiv_pl;
0617     int err;
0618 
0619     reiv_pl = kmalloc(MLXSW_REG_REIV_LEN, GFP_KERNEL);
0620     if (!reiv_pl)
0621         return -ENOMEM;
0622 
0623     mlxsw_reg_reiv_pack(reiv_pl, port_page, rif_index);
0624 
0625     list_for_each_entry(port_vid, &fid->port_vid_list, list) {
0626         /* port_vid_list is sorted by local_port. */
0627         if (port_vid->local_port < local_port_start)
0628             continue;
0629 
0630         if (port_vid->local_port > local_port_end)
0631             break;
0632 
0633         rec_num = port_vid->local_port % MLXSW_REG_REIV_REC_MAX_COUNT;
0634         mlxsw_reg_reiv_rec_update_set(reiv_pl, rec_num, true);
0635         mlxsw_reg_reiv_rec_evid_set(reiv_pl, rec_num,
0636                         valid ? port_vid->vid : 0);
0637         entries_num++;
0638     }
0639 
0640     if (!entries_num) {
0641         kfree(reiv_pl);
0642         return 0;
0643     }
0644 
0645     err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(reiv), reiv_pl);
0646     if (err)
0647         goto err_reg_write;
0648 
0649     kfree(reiv_pl);
0650     return 0;
0651 
0652 err_reg_write:
0653     kfree(reiv_pl);
0654     return err;
0655 }
0656 
0657 static int mlxsw_sp_fid_erif_eport_to_vid_map(struct mlxsw_sp_fid *fid,
0658                           u16 rif_index, bool valid)
0659 {
0660     struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
0661     u8 num_port_pages;
0662     int err, i;
0663 
0664     num_port_pages = mlxsw_core_max_ports(mlxsw_sp->core) /
0665              MLXSW_REG_REIV_REC_MAX_COUNT + 1;
0666 
0667     for (i = 0; i < num_port_pages; i++) {
0668         err = mlxsw_sp_fid_reiv_handle(fid, rif_index, valid, i);
0669         if (err)
0670             goto err_reiv_handle;
0671     }
0672 
0673     return 0;
0674 
0675 err_reiv_handle:
0676     for (; i >= 0; i--)
0677         mlxsw_sp_fid_reiv_handle(fid, rif_index, !valid, i);
0678     return err;
0679 }
0680 
0681 int mlxsw_sp_fid_rif_set(struct mlxsw_sp_fid *fid, struct mlxsw_sp_rif *rif)
0682 {
0683     u16 rif_index = mlxsw_sp_rif_index(rif);
0684     int err;
0685 
0686     err = mlxsw_sp_fid_to_fid_rif_update(fid, rif);
0687     if (err)
0688         return err;
0689 
0690     err = mlxsw_sp_fid_vni_to_fid_rif_update(fid, rif);
0691     if (err)
0692         goto err_vni_to_fid_rif_update;
0693 
0694     err = mlxsw_sp_fid_vid_to_fid_rif_set(fid, rif);
0695     if (err)
0696         goto err_vid_to_fid_rif_set;
0697 
0698     err = mlxsw_sp_fid_erif_eport_to_vid_map(fid, rif_index, true);
0699     if (err)
0700         goto err_erif_eport_to_vid_map;
0701 
0702     fid->rif = rif;
0703     return 0;
0704 
0705 err_erif_eport_to_vid_map:
0706     mlxsw_sp_fid_vid_to_fid_rif_unset(fid);
0707 err_vid_to_fid_rif_set:
0708     mlxsw_sp_fid_vni_to_fid_rif_update(fid, NULL);
0709 err_vni_to_fid_rif_update:
0710     mlxsw_sp_fid_to_fid_rif_update(fid, NULL);
0711     return err;
0712 }
0713 
0714 void mlxsw_sp_fid_rif_unset(struct mlxsw_sp_fid *fid)
0715 {
0716     u16 rif_index;
0717 
0718     if (!fid->rif)
0719         return;
0720 
0721     rif_index = mlxsw_sp_rif_index(fid->rif);
0722     fid->rif = NULL;
0723 
0724     mlxsw_sp_fid_erif_eport_to_vid_map(fid, rif_index, false);
0725     mlxsw_sp_fid_vid_to_fid_rif_unset(fid);
0726     mlxsw_sp_fid_vni_to_fid_rif_update(fid, NULL);
0727     mlxsw_sp_fid_to_fid_rif_update(fid, NULL);
0728 }
0729 
0730 static int mlxsw_sp_fid_vni_op(const struct mlxsw_sp_fid *fid)
0731 {
0732     int err;
0733 
0734     err = mlxsw_sp_fid_vni_to_fid_map(fid, fid->rif, fid->vni_valid);
0735     if (err)
0736         return err;
0737 
0738     err = mlxsw_sp_fid_edit_op(fid, fid->rif);
0739     if (err)
0740         goto err_fid_edit_op;
0741 
0742     return 0;
0743 
0744 err_fid_edit_op:
0745     mlxsw_sp_fid_vni_to_fid_map(fid, fid->rif, !fid->vni_valid);
0746     return err;
0747 }
0748 
0749 static int __mlxsw_sp_fid_port_vid_map(const struct mlxsw_sp_fid *fid,
0750                        u16 local_port, u16 vid, bool valid)
0751 {
0752     struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
0753     char svfa_pl[MLXSW_REG_SVFA_LEN];
0754     bool irif_valid = false;
0755     u16 irif_index = 0;
0756 
0757     if (fid->rif) {
0758         irif_valid = true;
0759         irif_index = mlxsw_sp_rif_index(fid->rif);
0760     }
0761 
0762     mlxsw_reg_svfa_port_vid_pack(svfa_pl, local_port, valid, fid->fid_index,
0763                      vid, irif_valid, irif_index);
0764     return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl);
0765 }
0766 
0767 static struct mlxsw_sp_fid_8021d *
0768 mlxsw_sp_fid_8021d_fid(const struct mlxsw_sp_fid *fid)
0769 {
0770     return container_of(fid, struct mlxsw_sp_fid_8021d, common);
0771 }
0772 
0773 static void mlxsw_sp_fid_8021d_setup(struct mlxsw_sp_fid *fid, const void *arg)
0774 {
0775     int br_ifindex = *(int *) arg;
0776 
0777     mlxsw_sp_fid_8021d_fid(fid)->br_ifindex = br_ifindex;
0778     fid->fid_offset = fid->fid_index - fid->fid_family->start_index;
0779 }
0780 
0781 static int mlxsw_sp_fid_8021d_configure(struct mlxsw_sp_fid *fid)
0782 {
0783     return mlxsw_sp_fid_op(fid, true);
0784 }
0785 
0786 static void mlxsw_sp_fid_8021d_deconfigure(struct mlxsw_sp_fid *fid)
0787 {
0788     if (fid->vni_valid)
0789         mlxsw_sp_nve_fid_disable(fid->fid_family->mlxsw_sp, fid);
0790     mlxsw_sp_fid_op(fid, false);
0791 }
0792 
0793 static int mlxsw_sp_fid_8021d_index_alloc(struct mlxsw_sp_fid *fid,
0794                       const void *arg, u16 *p_fid_index)
0795 {
0796     struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
0797     u16 nr_fids, fid_index;
0798 
0799     nr_fids = fid_family->end_index - fid_family->start_index + 1;
0800     fid_index = find_first_zero_bit(fid_family->fids_bitmap, nr_fids);
0801     if (fid_index == nr_fids)
0802         return -ENOBUFS;
0803     *p_fid_index = fid_family->start_index + fid_index;
0804 
0805     return 0;
0806 }
0807 
0808 static bool
0809 mlxsw_sp_fid_8021d_compare(const struct mlxsw_sp_fid *fid, const void *arg)
0810 {
0811     int br_ifindex = *(int *) arg;
0812 
0813     return mlxsw_sp_fid_8021d_fid(fid)->br_ifindex == br_ifindex;
0814 }
0815 
0816 static int mlxsw_sp_port_vp_mode_trans(struct mlxsw_sp_port *mlxsw_sp_port)
0817 {
0818     struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
0819     int err;
0820 
0821     list_for_each_entry(mlxsw_sp_port_vlan, &mlxsw_sp_port->vlans_list,
0822                 list) {
0823         struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid;
0824         u16 vid = mlxsw_sp_port_vlan->vid;
0825 
0826         if (!fid)
0827             continue;
0828 
0829         err = __mlxsw_sp_fid_port_vid_map(fid,
0830                           mlxsw_sp_port->local_port,
0831                           vid, true);
0832         if (err)
0833             goto err_fid_port_vid_map;
0834     }
0835 
0836     err = mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, true);
0837     if (err)
0838         goto err_port_vp_mode_set;
0839 
0840     return 0;
0841 
0842 err_port_vp_mode_set:
0843 err_fid_port_vid_map:
0844     list_for_each_entry_continue_reverse(mlxsw_sp_port_vlan,
0845                          &mlxsw_sp_port->vlans_list, list) {
0846         struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid;
0847         u16 vid = mlxsw_sp_port_vlan->vid;
0848 
0849         if (!fid)
0850             continue;
0851 
0852         __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid,
0853                         false);
0854     }
0855     return err;
0856 }
0857 
0858 static void mlxsw_sp_port_vlan_mode_trans(struct mlxsw_sp_port *mlxsw_sp_port)
0859 {
0860     struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
0861 
0862     mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, false);
0863 
0864     list_for_each_entry_reverse(mlxsw_sp_port_vlan,
0865                     &mlxsw_sp_port->vlans_list, list) {
0866         struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid;
0867         u16 vid = mlxsw_sp_port_vlan->vid;
0868 
0869         if (!fid)
0870             continue;
0871 
0872         __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid,
0873                         false);
0874     }
0875 }
0876 
0877 static int
0878 mlxsw_sp_fid_port_vid_list_add(struct mlxsw_sp_fid *fid, u16 local_port,
0879                    u16 vid)
0880 {
0881     struct mlxsw_sp_fid_port_vid *port_vid, *tmp_port_vid;
0882 
0883     port_vid = kzalloc(sizeof(*port_vid), GFP_KERNEL);
0884     if (!port_vid)
0885         return -ENOMEM;
0886 
0887     port_vid->local_port = local_port;
0888     port_vid->vid = vid;
0889 
0890     list_for_each_entry(tmp_port_vid, &fid->port_vid_list, list) {
0891         if (tmp_port_vid->local_port > local_port)
0892             break;
0893     }
0894 
0895     list_add_tail(&port_vid->list, &tmp_port_vid->list);
0896     return 0;
0897 }
0898 
0899 static void
0900 mlxsw_sp_fid_port_vid_list_del(struct mlxsw_sp_fid *fid, u16 local_port,
0901                    u16 vid)
0902 {
0903     struct mlxsw_sp_fid_port_vid *port_vid, *tmp;
0904 
0905     list_for_each_entry_safe(port_vid, tmp, &fid->port_vid_list, list) {
0906         if (port_vid->local_port != local_port || port_vid->vid != vid)
0907             continue;
0908 
0909         list_del(&port_vid->list);
0910         kfree(port_vid);
0911         return;
0912     }
0913 }
0914 
0915 static int
0916 mlxsw_sp_fid_mpe_table_map(const struct mlxsw_sp_fid *fid, u16 local_port,
0917                u16 vid, bool valid)
0918 {
0919     struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
0920     char smpe_pl[MLXSW_REG_SMPE_LEN];
0921 
0922     mlxsw_reg_smpe_pack(smpe_pl, local_port, fid->fid_index,
0923                 valid ? vid : 0);
0924     return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(smpe), smpe_pl);
0925 }
0926 
0927 static int
0928 mlxsw_sp_fid_erif_eport_to_vid_map_one(const struct mlxsw_sp_fid *fid,
0929                        u16 local_port, u16 vid, bool valid)
0930 {
0931     u8 port_page = local_port / MLXSW_REG_REIV_REC_MAX_COUNT;
0932     u8 rec_num = local_port % MLXSW_REG_REIV_REC_MAX_COUNT;
0933     struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
0934     u16 rif_index = mlxsw_sp_rif_index(fid->rif);
0935     char *reiv_pl;
0936     int err;
0937 
0938     reiv_pl = kmalloc(MLXSW_REG_REIV_LEN, GFP_KERNEL);
0939     if (!reiv_pl)
0940         return -ENOMEM;
0941 
0942     mlxsw_reg_reiv_pack(reiv_pl, port_page, rif_index);
0943     mlxsw_reg_reiv_rec_update_set(reiv_pl, rec_num, true);
0944     mlxsw_reg_reiv_rec_evid_set(reiv_pl, rec_num, valid ? vid : 0);
0945     err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(reiv), reiv_pl);
0946     kfree(reiv_pl);
0947     return err;
0948 }
0949 
0950 static int mlxsw_sp_fid_evid_map(const struct mlxsw_sp_fid *fid, u16 local_port,
0951                  u16 vid, bool valid)
0952 {
0953     int err;
0954 
0955     err = mlxsw_sp_fid_mpe_table_map(fid, local_port, vid, valid);
0956     if (err)
0957         return err;
0958 
0959     if (!fid->rif)
0960         return 0;
0961 
0962     err = mlxsw_sp_fid_erif_eport_to_vid_map_one(fid, local_port, vid,
0963                              valid);
0964     if (err)
0965         goto err_erif_eport_to_vid_map_one;
0966 
0967     return 0;
0968 
0969 err_erif_eport_to_vid_map_one:
0970     mlxsw_sp_fid_mpe_table_map(fid, local_port, vid, !valid);
0971     return err;
0972 }
0973 
0974 static int mlxsw_sp_fid_8021d_port_vid_map(struct mlxsw_sp_fid *fid,
0975                        struct mlxsw_sp_port *mlxsw_sp_port,
0976                        u16 vid)
0977 {
0978     struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
0979     u16 local_port = mlxsw_sp_port->local_port;
0980     int err;
0981 
0982     err = __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid,
0983                       true);
0984     if (err)
0985         return err;
0986 
0987     err = mlxsw_sp_fid_evid_map(fid, local_port, vid, true);
0988     if (err)
0989         goto err_fid_evid_map;
0990 
0991     err = mlxsw_sp_fid_port_vid_list_add(fid, mlxsw_sp_port->local_port,
0992                          vid);
0993     if (err)
0994         goto err_port_vid_list_add;
0995 
0996     if (mlxsw_sp->fid_core->port_fid_mappings[local_port]++ == 0) {
0997         err = mlxsw_sp_port_vp_mode_trans(mlxsw_sp_port);
0998         if (err)
0999             goto err_port_vp_mode_trans;
1000     }
1001 
1002     return 0;
1003 
1004 err_port_vp_mode_trans:
1005     mlxsw_sp->fid_core->port_fid_mappings[local_port]--;
1006     mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid);
1007 err_port_vid_list_add:
1008     mlxsw_sp_fid_evid_map(fid, local_port, vid, false);
1009 err_fid_evid_map:
1010     __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, false);
1011     return err;
1012 }
1013 
1014 static void
1015 mlxsw_sp_fid_8021d_port_vid_unmap(struct mlxsw_sp_fid *fid,
1016                   struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
1017 {
1018     struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1019     u16 local_port = mlxsw_sp_port->local_port;
1020 
1021     if (mlxsw_sp->fid_core->port_fid_mappings[local_port] == 1)
1022         mlxsw_sp_port_vlan_mode_trans(mlxsw_sp_port);
1023     mlxsw_sp->fid_core->port_fid_mappings[local_port]--;
1024     mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid);
1025     mlxsw_sp_fid_evid_map(fid, local_port, vid, false);
1026     __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, false);
1027 }
1028 
1029 static int mlxsw_sp_fid_8021d_vni_set(struct mlxsw_sp_fid *fid)
1030 {
1031     return mlxsw_sp_fid_vni_op(fid);
1032 }
1033 
1034 static void mlxsw_sp_fid_8021d_vni_clear(struct mlxsw_sp_fid *fid)
1035 {
1036     mlxsw_sp_fid_vni_op(fid);
1037 }
1038 
1039 static int mlxsw_sp_fid_8021d_nve_flood_index_set(struct mlxsw_sp_fid *fid)
1040 {
1041     return mlxsw_sp_fid_edit_op(fid, fid->rif);
1042 }
1043 
1044 static void mlxsw_sp_fid_8021d_nve_flood_index_clear(struct mlxsw_sp_fid *fid)
1045 {
1046     mlxsw_sp_fid_edit_op(fid, fid->rif);
1047 }
1048 
1049 static void
1050 mlxsw_sp_fid_8021d_fdb_clear_offload(const struct mlxsw_sp_fid *fid,
1051                      const struct net_device *nve_dev)
1052 {
1053     br_fdb_clear_offload(nve_dev, 0);
1054 }
1055 
1056 static int
1057 mlxsw_sp_fid_8021d_vid_to_fid_rif_update(const struct mlxsw_sp_fid *fid,
1058                      const struct mlxsw_sp_rif *rif)
1059 {
1060     return 0;
1061 }
1062 
1063 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021d_ops = {
1064     .setup          = mlxsw_sp_fid_8021d_setup,
1065     .configure      = mlxsw_sp_fid_8021d_configure,
1066     .deconfigure        = mlxsw_sp_fid_8021d_deconfigure,
1067     .index_alloc        = mlxsw_sp_fid_8021d_index_alloc,
1068     .compare        = mlxsw_sp_fid_8021d_compare,
1069     .port_vid_map       = mlxsw_sp_fid_8021d_port_vid_map,
1070     .port_vid_unmap     = mlxsw_sp_fid_8021d_port_vid_unmap,
1071     .vni_set        = mlxsw_sp_fid_8021d_vni_set,
1072     .vni_clear      = mlxsw_sp_fid_8021d_vni_clear,
1073     .nve_flood_index_set    = mlxsw_sp_fid_8021d_nve_flood_index_set,
1074     .nve_flood_index_clear  = mlxsw_sp_fid_8021d_nve_flood_index_clear,
1075     .fdb_clear_offload  = mlxsw_sp_fid_8021d_fdb_clear_offload,
1076     .vid_to_fid_rif_update  = mlxsw_sp_fid_8021d_vid_to_fid_rif_update,
1077 };
1078 
1079 #define MLXSW_SP_FID_8021Q_MAX (VLAN_N_VID - 2)
1080 #define MLXSW_SP_FID_RFID_MAX (11 * 1024)
1081 #define MLXSW_SP_FID_8021Q_PGT_BASE 0
1082 #define MLXSW_SP_FID_8021D_PGT_BASE (3 * MLXSW_SP_FID_8021Q_MAX)
1083 
1084 static const struct mlxsw_sp_flood_table mlxsw_sp_fid_8021d_flood_tables[] = {
1085     {
1086         .packet_type    = MLXSW_SP_FLOOD_TYPE_UC,
1087         .table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFSET,
1088         .table_index    = 0,
1089     },
1090     {
1091         .packet_type    = MLXSW_SP_FLOOD_TYPE_MC,
1092         .table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFSET,
1093         .table_index    = 1,
1094     },
1095     {
1096         .packet_type    = MLXSW_SP_FLOOD_TYPE_BC,
1097         .table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFSET,
1098         .table_index    = 2,
1099     },
1100 };
1101 
1102 static bool
1103 mlxsw_sp_fid_8021q_compare(const struct mlxsw_sp_fid *fid, const void *arg)
1104 {
1105     u16 vid = *(u16 *) arg;
1106 
1107     return mlxsw_sp_fid_8021q_fid(fid)->vid == vid;
1108 }
1109 
1110 static void
1111 mlxsw_sp_fid_8021q_fdb_clear_offload(const struct mlxsw_sp_fid *fid,
1112                      const struct net_device *nve_dev)
1113 {
1114     br_fdb_clear_offload(nve_dev, mlxsw_sp_fid_8021q_vid(fid));
1115 }
1116 
1117 static void mlxsw_sp_fid_rfid_setup(struct mlxsw_sp_fid *fid, const void *arg)
1118 {
1119     fid->fid_offset = 0;
1120 }
1121 
1122 static int mlxsw_sp_fid_rfid_configure(struct mlxsw_sp_fid *fid)
1123 {
1124     return mlxsw_sp_fid_op(fid, true);
1125 }
1126 
1127 static void mlxsw_sp_fid_rfid_deconfigure(struct mlxsw_sp_fid *fid)
1128 {
1129     mlxsw_sp_fid_op(fid, false);
1130 }
1131 
1132 static int mlxsw_sp_fid_rfid_index_alloc(struct mlxsw_sp_fid *fid,
1133                      const void *arg, u16 *p_fid_index)
1134 {
1135     u16 rif_index = *(u16 *) arg;
1136 
1137     *p_fid_index = fid->fid_family->start_index + rif_index;
1138 
1139     return 0;
1140 }
1141 
1142 static bool mlxsw_sp_fid_rfid_compare(const struct mlxsw_sp_fid *fid,
1143                       const void *arg)
1144 {
1145     u16 rif_index = *(u16 *) arg;
1146 
1147     return fid->fid_index == rif_index + fid->fid_family->start_index;
1148 }
1149 
1150 static int mlxsw_sp_fid_rfid_port_vid_map(struct mlxsw_sp_fid *fid,
1151                       struct mlxsw_sp_port *mlxsw_sp_port,
1152                       u16 vid)
1153 {
1154     struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1155     u16 local_port = mlxsw_sp_port->local_port;
1156     int err;
1157 
1158     err = mlxsw_sp_fid_port_vid_list_add(fid, mlxsw_sp_port->local_port,
1159                          vid);
1160     if (err)
1161         return err;
1162 
1163     /* Using legacy bridge model, we only need to transition the port to
1164      * virtual mode since {Port, VID} => FID is done by the firmware upon
1165      * RIF creation. Using unified bridge model, we need to map
1166      * {Port, VID} => FID and map egress VID.
1167      */
1168     err = __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid,
1169                       true);
1170     if (err)
1171         goto err_port_vid_map;
1172 
1173     if (fid->rif) {
1174         err = mlxsw_sp_fid_erif_eport_to_vid_map_one(fid, local_port,
1175                                  vid, true);
1176         if (err)
1177             goto err_erif_eport_to_vid_map_one;
1178     }
1179 
1180     if (mlxsw_sp->fid_core->port_fid_mappings[local_port]++ == 0) {
1181         err = mlxsw_sp_port_vp_mode_trans(mlxsw_sp_port);
1182         if (err)
1183             goto err_port_vp_mode_trans;
1184     }
1185 
1186     return 0;
1187 
1188 err_port_vp_mode_trans:
1189     mlxsw_sp->fid_core->port_fid_mappings[local_port]--;
1190     if (fid->rif)
1191         mlxsw_sp_fid_erif_eport_to_vid_map_one(fid, local_port, vid,
1192                                false);
1193 err_erif_eport_to_vid_map_one:
1194     __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, false);
1195 err_port_vid_map:
1196     mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid);
1197     return err;
1198 }
1199 
1200 static void
1201 mlxsw_sp_fid_rfid_port_vid_unmap(struct mlxsw_sp_fid *fid,
1202                  struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
1203 {
1204     struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1205     u16 local_port = mlxsw_sp_port->local_port;
1206 
1207     if (mlxsw_sp->fid_core->port_fid_mappings[local_port] == 1)
1208         mlxsw_sp_port_vlan_mode_trans(mlxsw_sp_port);
1209     mlxsw_sp->fid_core->port_fid_mappings[local_port]--;
1210 
1211     if (fid->rif)
1212         mlxsw_sp_fid_erif_eport_to_vid_map_one(fid, local_port, vid,
1213                                false);
1214     __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, false);
1215     mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid);
1216 }
1217 
1218 static int mlxsw_sp_fid_rfid_vni_set(struct mlxsw_sp_fid *fid)
1219 {
1220     return -EOPNOTSUPP;
1221 }
1222 
1223 static void mlxsw_sp_fid_rfid_vni_clear(struct mlxsw_sp_fid *fid)
1224 {
1225     WARN_ON_ONCE(1);
1226 }
1227 
1228 static int mlxsw_sp_fid_rfid_nve_flood_index_set(struct mlxsw_sp_fid *fid)
1229 {
1230     return -EOPNOTSUPP;
1231 }
1232 
1233 static void mlxsw_sp_fid_rfid_nve_flood_index_clear(struct mlxsw_sp_fid *fid)
1234 {
1235     WARN_ON_ONCE(1);
1236 }
1237 
1238 static int
1239 mlxsw_sp_fid_rfid_vid_to_fid_rif_update(const struct mlxsw_sp_fid *fid,
1240                     const struct mlxsw_sp_rif *rif)
1241 {
1242     return 0;
1243 }
1244 
1245 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_rfid_ops = {
1246     .setup          = mlxsw_sp_fid_rfid_setup,
1247     .configure      = mlxsw_sp_fid_rfid_configure,
1248     .deconfigure        = mlxsw_sp_fid_rfid_deconfigure,
1249     .index_alloc        = mlxsw_sp_fid_rfid_index_alloc,
1250     .compare        = mlxsw_sp_fid_rfid_compare,
1251     .port_vid_map       = mlxsw_sp_fid_rfid_port_vid_map,
1252     .port_vid_unmap     = mlxsw_sp_fid_rfid_port_vid_unmap,
1253     .vni_set                = mlxsw_sp_fid_rfid_vni_set,
1254     .vni_clear      = mlxsw_sp_fid_rfid_vni_clear,
1255     .nve_flood_index_set    = mlxsw_sp_fid_rfid_nve_flood_index_set,
1256     .nve_flood_index_clear  = mlxsw_sp_fid_rfid_nve_flood_index_clear,
1257     .vid_to_fid_rif_update  = mlxsw_sp_fid_rfid_vid_to_fid_rif_update,
1258 };
1259 
1260 static void mlxsw_sp_fid_dummy_setup(struct mlxsw_sp_fid *fid, const void *arg)
1261 {
1262     fid->fid_offset = 0;
1263 }
1264 
1265 static int mlxsw_sp_fid_dummy_configure(struct mlxsw_sp_fid *fid)
1266 {
1267     return mlxsw_sp_fid_op(fid, true);
1268 }
1269 
1270 static void mlxsw_sp_fid_dummy_deconfigure(struct mlxsw_sp_fid *fid)
1271 {
1272     mlxsw_sp_fid_op(fid, false);
1273 }
1274 
1275 static int mlxsw_sp_fid_dummy_index_alloc(struct mlxsw_sp_fid *fid,
1276                       const void *arg, u16 *p_fid_index)
1277 {
1278     *p_fid_index = fid->fid_family->start_index;
1279 
1280     return 0;
1281 }
1282 
1283 static bool mlxsw_sp_fid_dummy_compare(const struct mlxsw_sp_fid *fid,
1284                        const void *arg)
1285 {
1286     return true;
1287 }
1288 
1289 static int mlxsw_sp_fid_dummy_vni_set(struct mlxsw_sp_fid *fid)
1290 {
1291     return -EOPNOTSUPP;
1292 }
1293 
1294 static void mlxsw_sp_fid_dummy_vni_clear(struct mlxsw_sp_fid *fid)
1295 {
1296     WARN_ON_ONCE(1);
1297 }
1298 
1299 static int mlxsw_sp_fid_dummy_nve_flood_index_set(struct mlxsw_sp_fid *fid)
1300 {
1301     return -EOPNOTSUPP;
1302 }
1303 
1304 static void mlxsw_sp_fid_dummy_nve_flood_index_clear(struct mlxsw_sp_fid *fid)
1305 {
1306     WARN_ON_ONCE(1);
1307 }
1308 
1309 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_dummy_ops = {
1310     .setup          = mlxsw_sp_fid_dummy_setup,
1311     .configure      = mlxsw_sp_fid_dummy_configure,
1312     .deconfigure        = mlxsw_sp_fid_dummy_deconfigure,
1313     .index_alloc        = mlxsw_sp_fid_dummy_index_alloc,
1314     .compare        = mlxsw_sp_fid_dummy_compare,
1315     .vni_set                = mlxsw_sp_fid_dummy_vni_set,
1316     .vni_clear      = mlxsw_sp_fid_dummy_vni_clear,
1317     .nve_flood_index_set    = mlxsw_sp_fid_dummy_nve_flood_index_set,
1318     .nve_flood_index_clear  = mlxsw_sp_fid_dummy_nve_flood_index_clear,
1319 };
1320 
1321 static int mlxsw_sp_fid_8021q_configure(struct mlxsw_sp_fid *fid)
1322 {
1323     struct mlxsw_sp_fid_8021q *fid_8021q = mlxsw_sp_fid_8021q_fid(fid);
1324     int err;
1325 
1326     err = mlxsw_sp_fid_op(fid, true);
1327     if (err)
1328         return err;
1329 
1330     err = mlxsw_sp_fid_vid_to_fid_map(fid, fid_8021q->vid, true, fid->rif);
1331     if (err)
1332         goto err_vid_to_fid_map;
1333 
1334     return 0;
1335 
1336 err_vid_to_fid_map:
1337     mlxsw_sp_fid_op(fid, false);
1338     return err;
1339 }
1340 
1341 static void mlxsw_sp_fid_8021q_deconfigure(struct mlxsw_sp_fid *fid)
1342 {
1343     struct mlxsw_sp_fid_8021q *fid_8021q = mlxsw_sp_fid_8021q_fid(fid);
1344 
1345     if (fid->vni_valid)
1346         mlxsw_sp_nve_fid_disable(fid->fid_family->mlxsw_sp, fid);
1347 
1348     mlxsw_sp_fid_vid_to_fid_map(fid, fid_8021q->vid, false, NULL);
1349     mlxsw_sp_fid_op(fid, false);
1350 }
1351 
1352 static int mlxsw_sp_fid_8021q_port_vid_map(struct mlxsw_sp_fid *fid,
1353                        struct mlxsw_sp_port *mlxsw_sp_port,
1354                        u16 vid)
1355 {
1356     struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1357     u8 local_port = mlxsw_sp_port->local_port;
1358     int err;
1359 
1360     /* In case there are no {Port, VID} => FID mappings on the port,
1361      * we can use the global VID => FID mapping we created when the
1362      * FID was configured, otherwise, configure new mapping.
1363      */
1364     if (mlxsw_sp->fid_core->port_fid_mappings[local_port]) {
1365         err =  __mlxsw_sp_fid_port_vid_map(fid, local_port, vid, true);
1366         if (err)
1367             return err;
1368     }
1369 
1370     err = mlxsw_sp_fid_evid_map(fid, local_port, vid, true);
1371     if (err)
1372         goto err_fid_evid_map;
1373 
1374     err = mlxsw_sp_fid_port_vid_list_add(fid, mlxsw_sp_port->local_port,
1375                          vid);
1376     if (err)
1377         goto err_port_vid_list_add;
1378 
1379     return 0;
1380 
1381 err_port_vid_list_add:
1382      mlxsw_sp_fid_evid_map(fid, local_port, vid, false);
1383 err_fid_evid_map:
1384     if (mlxsw_sp->fid_core->port_fid_mappings[local_port])
1385         __mlxsw_sp_fid_port_vid_map(fid, local_port, vid, false);
1386     return err;
1387 }
1388 
1389 static void
1390 mlxsw_sp_fid_8021q_port_vid_unmap(struct mlxsw_sp_fid *fid,
1391                   struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
1392 {
1393     struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1394     u8 local_port = mlxsw_sp_port->local_port;
1395 
1396     mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid);
1397     mlxsw_sp_fid_evid_map(fid, local_port, vid, false);
1398     if (mlxsw_sp->fid_core->port_fid_mappings[local_port])
1399         __mlxsw_sp_fid_port_vid_map(fid, local_port, vid, false);
1400 }
1401 
1402 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021q_ops = {
1403     .setup          = mlxsw_sp_fid_8021q_setup,
1404     .configure      = mlxsw_sp_fid_8021q_configure,
1405     .deconfigure        = mlxsw_sp_fid_8021q_deconfigure,
1406     .index_alloc        = mlxsw_sp_fid_8021d_index_alloc,
1407     .compare        = mlxsw_sp_fid_8021q_compare,
1408     .port_vid_map       = mlxsw_sp_fid_8021q_port_vid_map,
1409     .port_vid_unmap     = mlxsw_sp_fid_8021q_port_vid_unmap,
1410     .vni_set        = mlxsw_sp_fid_8021d_vni_set,
1411     .vni_clear      = mlxsw_sp_fid_8021d_vni_clear,
1412     .nve_flood_index_set    = mlxsw_sp_fid_8021d_nve_flood_index_set,
1413     .nve_flood_index_clear  = mlxsw_sp_fid_8021d_nve_flood_index_clear,
1414     .fdb_clear_offload  = mlxsw_sp_fid_8021q_fdb_clear_offload,
1415     .vid_to_fid_rif_update  = mlxsw_sp_fid_8021q_vid_to_fid_rif_update,
1416 };
1417 
1418 /* There are 4K-2 802.1Q FIDs */
1419 #define MLXSW_SP_FID_8021Q_START    1 /* FID 0 is reserved. */
1420 #define MLXSW_SP_FID_8021Q_END      (MLXSW_SP_FID_8021Q_START + \
1421                      MLXSW_SP_FID_8021Q_MAX - 1)
1422 
1423 /* There are 1K 802.1D FIDs */
1424 #define MLXSW_SP_FID_8021D_START    (MLXSW_SP_FID_8021Q_END + 1)
1425 #define MLXSW_SP_FID_8021D_END      (MLXSW_SP_FID_8021D_START + \
1426                      MLXSW_SP_FID_8021D_MAX - 1)
1427 
1428 /* There is one dummy FID */
1429 #define MLXSW_SP_FID_DUMMY      (MLXSW_SP_FID_8021D_END + 1)
1430 
1431 /* There are 11K rFIDs */
1432 #define MLXSW_SP_RFID_START     (MLXSW_SP_FID_DUMMY + 1)
1433 #define MLXSW_SP_RFID_END       (MLXSW_SP_RFID_START + \
1434                      MLXSW_SP_FID_RFID_MAX - 1)
1435 
1436 static const struct mlxsw_sp_fid_family mlxsw_sp1_fid_8021q_family = {
1437     .type           = MLXSW_SP_FID_TYPE_8021Q,
1438     .fid_size       = sizeof(struct mlxsw_sp_fid_8021q),
1439     .start_index        = MLXSW_SP_FID_8021Q_START,
1440     .end_index      = MLXSW_SP_FID_8021Q_END,
1441     .flood_tables       = mlxsw_sp_fid_8021d_flood_tables,
1442     .nr_flood_tables    = ARRAY_SIZE(mlxsw_sp_fid_8021d_flood_tables),
1443     .rif_type       = MLXSW_SP_RIF_TYPE_VLAN,
1444     .ops            = &mlxsw_sp_fid_8021q_ops,
1445     .flood_rsp              = false,
1446     .bridge_type            = MLXSW_REG_BRIDGE_TYPE_0,
1447     .pgt_base       = MLXSW_SP_FID_8021Q_PGT_BASE,
1448     .smpe_index_valid   = false,
1449 };
1450 
1451 static const struct mlxsw_sp_fid_family mlxsw_sp1_fid_8021d_family = {
1452     .type           = MLXSW_SP_FID_TYPE_8021D,
1453     .fid_size       = sizeof(struct mlxsw_sp_fid_8021d),
1454     .start_index        = MLXSW_SP_FID_8021D_START,
1455     .end_index      = MLXSW_SP_FID_8021D_END,
1456     .flood_tables       = mlxsw_sp_fid_8021d_flood_tables,
1457     .nr_flood_tables    = ARRAY_SIZE(mlxsw_sp_fid_8021d_flood_tables),
1458     .rif_type       = MLXSW_SP_RIF_TYPE_FID,
1459     .ops            = &mlxsw_sp_fid_8021d_ops,
1460     .bridge_type            = MLXSW_REG_BRIDGE_TYPE_1,
1461     .pgt_base       = MLXSW_SP_FID_8021D_PGT_BASE,
1462     .smpe_index_valid       = false,
1463 };
1464 
1465 static const struct mlxsw_sp_fid_family mlxsw_sp1_fid_dummy_family = {
1466     .type           = MLXSW_SP_FID_TYPE_DUMMY,
1467     .fid_size       = sizeof(struct mlxsw_sp_fid),
1468     .start_index        = MLXSW_SP_FID_DUMMY,
1469     .end_index      = MLXSW_SP_FID_DUMMY,
1470     .ops            = &mlxsw_sp_fid_dummy_ops,
1471     .smpe_index_valid       = false,
1472 };
1473 
1474 static const struct mlxsw_sp_fid_family mlxsw_sp_fid_rfid_family = {
1475     .type           = MLXSW_SP_FID_TYPE_RFID,
1476     .fid_size       = sizeof(struct mlxsw_sp_fid),
1477     .start_index        = MLXSW_SP_RFID_START,
1478     .end_index      = MLXSW_SP_RFID_END,
1479     .rif_type       = MLXSW_SP_RIF_TYPE_SUBPORT,
1480     .ops            = &mlxsw_sp_fid_rfid_ops,
1481     .flood_rsp              = true,
1482     .smpe_index_valid       = false,
1483 };
1484 
1485 const struct mlxsw_sp_fid_family *mlxsw_sp1_fid_family_arr[] = {
1486     [MLXSW_SP_FID_TYPE_8021Q]   = &mlxsw_sp1_fid_8021q_family,
1487     [MLXSW_SP_FID_TYPE_8021D]   = &mlxsw_sp1_fid_8021d_family,
1488     [MLXSW_SP_FID_TYPE_DUMMY]   = &mlxsw_sp1_fid_dummy_family,
1489     [MLXSW_SP_FID_TYPE_RFID]    = &mlxsw_sp_fid_rfid_family,
1490 };
1491 
1492 static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_8021q_family = {
1493     .type           = MLXSW_SP_FID_TYPE_8021Q,
1494     .fid_size       = sizeof(struct mlxsw_sp_fid_8021q),
1495     .start_index        = MLXSW_SP_FID_8021Q_START,
1496     .end_index      = MLXSW_SP_FID_8021Q_END,
1497     .flood_tables       = mlxsw_sp_fid_8021d_flood_tables,
1498     .nr_flood_tables    = ARRAY_SIZE(mlxsw_sp_fid_8021d_flood_tables),
1499     .rif_type       = MLXSW_SP_RIF_TYPE_VLAN,
1500     .ops            = &mlxsw_sp_fid_8021q_ops,
1501     .flood_rsp              = false,
1502     .bridge_type            = MLXSW_REG_BRIDGE_TYPE_0,
1503     .pgt_base       = MLXSW_SP_FID_8021Q_PGT_BASE,
1504     .smpe_index_valid   = true,
1505 };
1506 
1507 static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_8021d_family = {
1508     .type           = MLXSW_SP_FID_TYPE_8021D,
1509     .fid_size       = sizeof(struct mlxsw_sp_fid_8021d),
1510     .start_index        = MLXSW_SP_FID_8021D_START,
1511     .end_index      = MLXSW_SP_FID_8021D_END,
1512     .flood_tables       = mlxsw_sp_fid_8021d_flood_tables,
1513     .nr_flood_tables    = ARRAY_SIZE(mlxsw_sp_fid_8021d_flood_tables),
1514     .rif_type       = MLXSW_SP_RIF_TYPE_FID,
1515     .ops            = &mlxsw_sp_fid_8021d_ops,
1516     .bridge_type            = MLXSW_REG_BRIDGE_TYPE_1,
1517     .pgt_base       = MLXSW_SP_FID_8021D_PGT_BASE,
1518     .smpe_index_valid       = true,
1519 };
1520 
1521 static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_dummy_family = {
1522     .type           = MLXSW_SP_FID_TYPE_DUMMY,
1523     .fid_size       = sizeof(struct mlxsw_sp_fid),
1524     .start_index        = MLXSW_SP_FID_DUMMY,
1525     .end_index      = MLXSW_SP_FID_DUMMY,
1526     .ops            = &mlxsw_sp_fid_dummy_ops,
1527     .smpe_index_valid       = false,
1528 };
1529 
1530 const struct mlxsw_sp_fid_family *mlxsw_sp2_fid_family_arr[] = {
1531     [MLXSW_SP_FID_TYPE_8021Q]   = &mlxsw_sp2_fid_8021q_family,
1532     [MLXSW_SP_FID_TYPE_8021D]   = &mlxsw_sp2_fid_8021d_family,
1533     [MLXSW_SP_FID_TYPE_DUMMY]   = &mlxsw_sp2_fid_dummy_family,
1534     [MLXSW_SP_FID_TYPE_RFID]    = &mlxsw_sp_fid_rfid_family,
1535 };
1536 
1537 static struct mlxsw_sp_fid *mlxsw_sp_fid_lookup(struct mlxsw_sp *mlxsw_sp,
1538                         enum mlxsw_sp_fid_type type,
1539                         const void *arg)
1540 {
1541     struct mlxsw_sp_fid_family *fid_family;
1542     struct mlxsw_sp_fid *fid;
1543 
1544     fid_family = mlxsw_sp->fid_core->fid_family_arr[type];
1545     list_for_each_entry(fid, &fid_family->fids_list, list) {
1546         if (!fid->fid_family->ops->compare(fid, arg))
1547             continue;
1548         refcount_inc(&fid->ref_count);
1549         return fid;
1550     }
1551 
1552     return NULL;
1553 }
1554 
1555 static struct mlxsw_sp_fid *mlxsw_sp_fid_get(struct mlxsw_sp *mlxsw_sp,
1556                          enum mlxsw_sp_fid_type type,
1557                          const void *arg)
1558 {
1559     struct mlxsw_sp_fid_family *fid_family;
1560     struct mlxsw_sp_fid *fid;
1561     u16 fid_index;
1562     int err;
1563 
1564     fid = mlxsw_sp_fid_lookup(mlxsw_sp, type, arg);
1565     if (fid)
1566         return fid;
1567 
1568     fid_family = mlxsw_sp->fid_core->fid_family_arr[type];
1569     fid = kzalloc(fid_family->fid_size, GFP_KERNEL);
1570     if (!fid)
1571         return ERR_PTR(-ENOMEM);
1572 
1573     INIT_LIST_HEAD(&fid->port_vid_list);
1574     fid->fid_family = fid_family;
1575 
1576     err = fid->fid_family->ops->index_alloc(fid, arg, &fid_index);
1577     if (err)
1578         goto err_index_alloc;
1579     fid->fid_index = fid_index;
1580     __set_bit(fid_index - fid_family->start_index, fid_family->fids_bitmap);
1581 
1582     fid->fid_family->ops->setup(fid, arg);
1583 
1584     err = fid->fid_family->ops->configure(fid);
1585     if (err)
1586         goto err_configure;
1587 
1588     err = rhashtable_insert_fast(&mlxsw_sp->fid_core->fid_ht, &fid->ht_node,
1589                      mlxsw_sp_fid_ht_params);
1590     if (err)
1591         goto err_rhashtable_insert;
1592 
1593     list_add(&fid->list, &fid_family->fids_list);
1594     refcount_set(&fid->ref_count, 1);
1595     return fid;
1596 
1597 err_rhashtable_insert:
1598     fid->fid_family->ops->deconfigure(fid);
1599 err_configure:
1600     __clear_bit(fid_index - fid_family->start_index,
1601             fid_family->fids_bitmap);
1602 err_index_alloc:
1603     kfree(fid);
1604     return ERR_PTR(err);
1605 }
1606 
1607 void mlxsw_sp_fid_put(struct mlxsw_sp_fid *fid)
1608 {
1609     struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
1610     struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
1611 
1612     if (!refcount_dec_and_test(&fid->ref_count))
1613         return;
1614 
1615     list_del(&fid->list);
1616     rhashtable_remove_fast(&mlxsw_sp->fid_core->fid_ht,
1617                    &fid->ht_node, mlxsw_sp_fid_ht_params);
1618     fid->fid_family->ops->deconfigure(fid);
1619     __clear_bit(fid->fid_index - fid_family->start_index,
1620             fid_family->fids_bitmap);
1621     WARN_ON_ONCE(!list_empty(&fid->port_vid_list));
1622     kfree(fid);
1623 }
1624 
1625 struct mlxsw_sp_fid *mlxsw_sp_fid_8021q_get(struct mlxsw_sp *mlxsw_sp, u16 vid)
1626 {
1627     return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_8021Q, &vid);
1628 }
1629 
1630 struct mlxsw_sp_fid *mlxsw_sp_fid_8021d_get(struct mlxsw_sp *mlxsw_sp,
1631                         int br_ifindex)
1632 {
1633     return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_8021D, &br_ifindex);
1634 }
1635 
1636 struct mlxsw_sp_fid *mlxsw_sp_fid_8021q_lookup(struct mlxsw_sp *mlxsw_sp,
1637                            u16 vid)
1638 {
1639     return mlxsw_sp_fid_lookup(mlxsw_sp, MLXSW_SP_FID_TYPE_8021Q, &vid);
1640 }
1641 
1642 struct mlxsw_sp_fid *mlxsw_sp_fid_8021d_lookup(struct mlxsw_sp *mlxsw_sp,
1643                            int br_ifindex)
1644 {
1645     return mlxsw_sp_fid_lookup(mlxsw_sp, MLXSW_SP_FID_TYPE_8021D,
1646                    &br_ifindex);
1647 }
1648 
1649 struct mlxsw_sp_fid *mlxsw_sp_fid_rfid_get(struct mlxsw_sp *mlxsw_sp,
1650                        u16 rif_index)
1651 {
1652     return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_RFID, &rif_index);
1653 }
1654 
1655 struct mlxsw_sp_fid *mlxsw_sp_fid_dummy_get(struct mlxsw_sp *mlxsw_sp)
1656 {
1657     return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_DUMMY, NULL);
1658 }
1659 
1660 static int
1661 mlxsw_sp_fid_flood_table_init(struct mlxsw_sp_fid_family *fid_family,
1662                   const struct mlxsw_sp_flood_table *flood_table)
1663 {
1664     enum mlxsw_sp_flood_type packet_type = flood_table->packet_type;
1665     struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
1666     const int *sfgc_packet_types;
1667     u16 num_fids, mid_base;
1668     int err, i;
1669 
1670     mid_base = mlxsw_sp_fid_flood_table_mid(fid_family, flood_table, 0);
1671     num_fids = mlxsw_sp_fid_family_num_fids(fid_family);
1672     err = mlxsw_sp_pgt_mid_alloc_range(mlxsw_sp, mid_base, num_fids);
1673     if (err)
1674         return err;
1675 
1676     sfgc_packet_types = mlxsw_sp_packet_type_sfgc_types[packet_type];
1677     for (i = 0; i < MLXSW_REG_SFGC_TYPE_MAX; i++) {
1678         char sfgc_pl[MLXSW_REG_SFGC_LEN];
1679 
1680         if (!sfgc_packet_types[i])
1681             continue;
1682 
1683         mlxsw_reg_sfgc_pack(sfgc_pl, i, fid_family->bridge_type,
1684                     flood_table->table_type, 0, mid_base);
1685 
1686         err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfgc), sfgc_pl);
1687         if (err)
1688             goto err_reg_write;
1689     }
1690 
1691     return 0;
1692 
1693 err_reg_write:
1694     mlxsw_sp_pgt_mid_free_range(mlxsw_sp, mid_base, num_fids);
1695     return err;
1696 }
1697 
1698 static void
1699 mlxsw_sp_fid_flood_table_fini(struct mlxsw_sp_fid_family *fid_family,
1700                   const struct mlxsw_sp_flood_table *flood_table)
1701 {
1702     struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
1703     u16 num_fids, mid_base;
1704 
1705     mid_base = mlxsw_sp_fid_flood_table_mid(fid_family, flood_table, 0);
1706     num_fids = mlxsw_sp_fid_family_num_fids(fid_family);
1707     mlxsw_sp_pgt_mid_free_range(mlxsw_sp, mid_base, num_fids);
1708 }
1709 
1710 static int
1711 mlxsw_sp_fid_flood_tables_init(struct mlxsw_sp_fid_family *fid_family)
1712 {
1713     int i;
1714 
1715     for (i = 0; i < fid_family->nr_flood_tables; i++) {
1716         const struct mlxsw_sp_flood_table *flood_table;
1717         int err;
1718 
1719         flood_table = &fid_family->flood_tables[i];
1720         err = mlxsw_sp_fid_flood_table_init(fid_family, flood_table);
1721         if (err)
1722             return err;
1723     }
1724 
1725     return 0;
1726 }
1727 
1728 static void
1729 mlxsw_sp_fid_flood_tables_fini(struct mlxsw_sp_fid_family *fid_family)
1730 {
1731     int i;
1732 
1733     for (i = 0; i < fid_family->nr_flood_tables; i++) {
1734         const struct mlxsw_sp_flood_table *flood_table;
1735 
1736         flood_table = &fid_family->flood_tables[i];
1737         mlxsw_sp_fid_flood_table_fini(fid_family, flood_table);
1738     }
1739 }
1740 
1741 static int mlxsw_sp_fid_family_register(struct mlxsw_sp *mlxsw_sp,
1742                     const struct mlxsw_sp_fid_family *tmpl)
1743 {
1744     u16 nr_fids = tmpl->end_index - tmpl->start_index + 1;
1745     struct mlxsw_sp_fid_family *fid_family;
1746     int err;
1747 
1748     fid_family = kmemdup(tmpl, sizeof(*fid_family), GFP_KERNEL);
1749     if (!fid_family)
1750         return -ENOMEM;
1751 
1752     fid_family->mlxsw_sp = mlxsw_sp;
1753     INIT_LIST_HEAD(&fid_family->fids_list);
1754     fid_family->fids_bitmap = bitmap_zalloc(nr_fids, GFP_KERNEL);
1755     if (!fid_family->fids_bitmap) {
1756         err = -ENOMEM;
1757         goto err_alloc_fids_bitmap;
1758     }
1759 
1760     if (fid_family->flood_tables) {
1761         err = mlxsw_sp_fid_flood_tables_init(fid_family);
1762         if (err)
1763             goto err_fid_flood_tables_init;
1764     }
1765 
1766     mlxsw_sp->fid_core->fid_family_arr[tmpl->type] = fid_family;
1767 
1768     return 0;
1769 
1770 err_fid_flood_tables_init:
1771     bitmap_free(fid_family->fids_bitmap);
1772 err_alloc_fids_bitmap:
1773     kfree(fid_family);
1774     return err;
1775 }
1776 
1777 static void
1778 mlxsw_sp_fid_family_unregister(struct mlxsw_sp *mlxsw_sp,
1779                    struct mlxsw_sp_fid_family *fid_family)
1780 {
1781     mlxsw_sp->fid_core->fid_family_arr[fid_family->type] = NULL;
1782 
1783     if (fid_family->flood_tables)
1784         mlxsw_sp_fid_flood_tables_fini(fid_family);
1785 
1786     bitmap_free(fid_family->fids_bitmap);
1787     WARN_ON_ONCE(!list_empty(&fid_family->fids_list));
1788     kfree(fid_family);
1789 }
1790 
1791 int mlxsw_sp_port_fids_init(struct mlxsw_sp_port *mlxsw_sp_port)
1792 {
1793     struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1794 
1795     /* Track number of FIDs configured on the port with mapping type
1796      * PORT_VID_TO_FID, so that we know when to transition the port
1797      * back to non-virtual (VLAN) mode.
1798      */
1799     mlxsw_sp->fid_core->port_fid_mappings[mlxsw_sp_port->local_port] = 0;
1800 
1801     return mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, false);
1802 }
1803 
1804 void mlxsw_sp_port_fids_fini(struct mlxsw_sp_port *mlxsw_sp_port)
1805 {
1806     struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1807 
1808     mlxsw_sp->fid_core->port_fid_mappings[mlxsw_sp_port->local_port] = 0;
1809 }
1810 
1811 int mlxsw_sp_fids_init(struct mlxsw_sp *mlxsw_sp)
1812 {
1813     unsigned int max_ports = mlxsw_core_max_ports(mlxsw_sp->core);
1814     struct mlxsw_sp_fid_core *fid_core;
1815     int err, i;
1816 
1817     fid_core = kzalloc(sizeof(*mlxsw_sp->fid_core), GFP_KERNEL);
1818     if (!fid_core)
1819         return -ENOMEM;
1820     mlxsw_sp->fid_core = fid_core;
1821 
1822     err = rhashtable_init(&fid_core->fid_ht, &mlxsw_sp_fid_ht_params);
1823     if (err)
1824         goto err_rhashtable_fid_init;
1825 
1826     err = rhashtable_init(&fid_core->vni_ht, &mlxsw_sp_fid_vni_ht_params);
1827     if (err)
1828         goto err_rhashtable_vni_init;
1829 
1830     fid_core->port_fid_mappings = kcalloc(max_ports, sizeof(unsigned int),
1831                           GFP_KERNEL);
1832     if (!fid_core->port_fid_mappings) {
1833         err = -ENOMEM;
1834         goto err_alloc_port_fid_mappings;
1835     }
1836 
1837     for (i = 0; i < MLXSW_SP_FID_TYPE_MAX; i++) {
1838         err = mlxsw_sp_fid_family_register(mlxsw_sp,
1839                            mlxsw_sp->fid_family_arr[i]);
1840 
1841         if (err)
1842             goto err_fid_ops_register;
1843     }
1844 
1845     return 0;
1846 
1847 err_fid_ops_register:
1848     for (i--; i >= 0; i--) {
1849         struct mlxsw_sp_fid_family *fid_family;
1850 
1851         fid_family = fid_core->fid_family_arr[i];
1852         mlxsw_sp_fid_family_unregister(mlxsw_sp, fid_family);
1853     }
1854     kfree(fid_core->port_fid_mappings);
1855 err_alloc_port_fid_mappings:
1856     rhashtable_destroy(&fid_core->vni_ht);
1857 err_rhashtable_vni_init:
1858     rhashtable_destroy(&fid_core->fid_ht);
1859 err_rhashtable_fid_init:
1860     kfree(fid_core);
1861     return err;
1862 }
1863 
1864 void mlxsw_sp_fids_fini(struct mlxsw_sp *mlxsw_sp)
1865 {
1866     struct mlxsw_sp_fid_core *fid_core = mlxsw_sp->fid_core;
1867     int i;
1868 
1869     for (i = 0; i < MLXSW_SP_FID_TYPE_MAX; i++)
1870         mlxsw_sp_fid_family_unregister(mlxsw_sp,
1871                            fid_core->fid_family_arr[i]);
1872     kfree(fid_core->port_fid_mappings);
1873     rhashtable_destroy(&fid_core->vni_ht);
1874     rhashtable_destroy(&fid_core->fid_ht);
1875     kfree(fid_core);
1876 }