0001
0002
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;
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
0527
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
0563
0564
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
0597
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
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
1164
1165
1166
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
1361
1362
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
1419 #define MLXSW_SP_FID_8021Q_START 1
1420 #define MLXSW_SP_FID_8021Q_END (MLXSW_SP_FID_8021Q_START + \
1421 MLXSW_SP_FID_8021Q_MAX - 1)
1422
1423
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
1429 #define MLXSW_SP_FID_DUMMY (MLXSW_SP_FID_8021D_END + 1)
1430
1431
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
1796
1797
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 }