FILE
spectrum_fid.c
File preview with syntax highlighting.
linux-6.19.14/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 2/* Copyright (c) 2017-2018 Mellanox Technologies. All rights reserved */ 3 4#include <linux/kernel.h> 5#include <linux/bitops.h> 6#include <linux/if_vlan.h> 7#include <linux/if_bridge.h> 8#include <linux/netdevice.h> 9#include <linux/rhashtable.h> 10#include <linux/rtnetlink.h> 11#include <linux/refcount.h> 12 13#include "spectrum.h" 14#include "spectrum_router.h" 15#include "reg.h" 16 17struct mlxsw_sp_fid_family; 18 19struct mlxsw_sp_fid_core { 20 struct rhashtable fid_ht; 21 struct rhashtable vni_ht; 22 struct mlxsw_sp_fid_family *fid_family_arr[MLXSW_SP_FID_TYPE_MAX]; 23 unsigned int *port_fid_mappings; 24}; 25 26struct mlxsw_sp_fid_port_vid { 27 struct list_head list; 28 u16 local_port; 29 u16 vid; 30}; 31 32struct mlxsw_sp_fid { 33 struct list_head list; 34 struct mlxsw_sp_rif *rif; 35 refcount_t ref_count; 36 u16 fid_index; 37 u16 fid_offset; 38 struct mlxsw_sp_fid_family *fid_family; 39 struct rhash_head ht_node; 40 41 struct rhash_head vni_ht_node; 42 enum mlxsw_sp_nve_type nve_type; 43 __be32 vni; 44 u32 nve_flood_index; 45 int nve_ifindex; 46 u8 vni_valid:1, 47 nve_flood_index_valid:1; 48 struct list_head port_vid_list; /* Ordered by local port. */ 49}; 50 51struct mlxsw_sp_fid_8021q { 52 struct mlxsw_sp_fid common; 53 u16 vid; 54}; 55 56struct mlxsw_sp_fid_8021d { 57 struct mlxsw_sp_fid common; 58 int br_ifindex; 59}; 60 61static const struct rhashtable_params mlxsw_sp_fid_ht_params = { 62 .key_len = sizeof_field(struct mlxsw_sp_fid, fid_index), 63 .key_offset = offsetof(struct mlxsw_sp_fid, fid_index), 64 .head_offset = offsetof(struct mlxsw_sp_fid, ht_node), 65}; 66 67static const struct rhashtable_params mlxsw_sp_fid_vni_ht_params = { 68 .key_len = sizeof_field(struct mlxsw_sp_fid, vni), 69 .key_offset = offsetof(struct mlxsw_sp_fid, vni), 70 .head_offset = offsetof(struct mlxsw_sp_fid, vni_ht_node), 71}; 72 73struct mlxsw_sp_flood_table { 74 enum mlxsw_sp_flood_type packet_type; 75 enum mlxsw_flood_table_type table_type; /* For flood_mode!=CFF. */ 76 int table_index; 77}; 78 79struct mlxsw_sp_fid_ops { 80 int (*setup)(struct mlxsw_sp_fid *fid, const void *arg); 81 int (*configure)(struct mlxsw_sp_fid *fid); 82 void (*deconfigure)(struct mlxsw_sp_fid *fid); 83 int (*index_alloc)(struct mlxsw_sp_fid *fid, const void *arg, 84 u16 *p_fid_index); 85 bool (*compare)(const struct mlxsw_sp_fid *fid, 86 const void *arg); 87 int (*port_vid_map)(struct mlxsw_sp_fid *fid, 88 struct mlxsw_sp_port *port, u16 vid); 89 void (*port_vid_unmap)(struct mlxsw_sp_fid *fid, 90 struct mlxsw_sp_port *port, u16 vid); 91 int (*vni_set)(struct mlxsw_sp_fid *fid); 92 void (*vni_clear)(struct mlxsw_sp_fid *fid); 93 int (*nve_flood_index_set)(struct mlxsw_sp_fid *fid); 94 void (*nve_flood_index_clear)(struct mlxsw_sp_fid *fid); 95 void (*fdb_clear_offload)(const struct mlxsw_sp_fid *fid, 96 const struct net_device *nve_dev); 97 int (*vid_to_fid_rif_update)(const struct mlxsw_sp_fid *fid, 98 const struct mlxsw_sp_rif *rif); 99 int (*flood_table_init)(struct mlxsw_sp_fid_family *fid_family, 100 const struct mlxsw_sp_flood_table *flood_table); 101 int (*pgt_size)(const struct mlxsw_sp_fid_family *fid_family, 102 u16 *p_pgt_size); 103 u16 (*fid_mid)(const struct mlxsw_sp_fid *fid, 104 const struct mlxsw_sp_flood_table *flood_table); 105 void (*fid_pack)(char *sfmr_pl, const struct mlxsw_sp_fid *fid, 106 enum mlxsw_reg_sfmr_op op); 107 108 /* These are specific to RFID families and we assume are only 109 * implemented by RFID families, if at all. 110 */ 111 int (*fid_port_init)(const struct mlxsw_sp_fid_family *fid_family, 112 const struct mlxsw_sp_port *mlxsw_sp_port); 113 void (*fid_port_fini)(const struct mlxsw_sp_fid_family *fid_family, 114 const struct mlxsw_sp_port *mlxsw_sp_port); 115}; 116 117enum mlxsw_sp_fid_flood_profile_id { 118 MLXSW_SP_FID_FLOOD_PROFILE_ID_BRIDGE = 1, 119 MLXSW_SP_FID_FLOOD_PROFILE_ID_RSP, 120 MLXSW_SP_FID_FLOOD_PROFILE_ID_NVE, 121}; 122 123struct mlxsw_sp_fid_flood_profile { 124 const struct mlxsw_sp_flood_table *flood_tables; 125 int nr_flood_tables; 126 const enum mlxsw_sp_fid_flood_profile_id profile_id; /* For CFF mode. */ 127}; 128 129struct mlxsw_sp_fid_family { 130 enum mlxsw_sp_fid_type type; 131 size_t fid_size; 132 u16 start_index; 133 u16 end_index; 134 struct list_head fids_list; 135 unsigned long *fids_bitmap; 136 const struct mlxsw_sp_fid_flood_profile *flood_profile; 137 enum mlxsw_sp_rif_type rif_type; 138 const struct mlxsw_sp_fid_ops *ops; 139 struct mlxsw_sp *mlxsw_sp; 140 bool flood_rsp; /* For flood_mode!=CFF. */ 141 enum mlxsw_reg_bridge_type bridge_type; 142 u16 pgt_base; 143 bool smpe_index_valid; 144}; 145 146static const int mlxsw_sp_sfgc_uc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = { 147 [MLXSW_REG_SFGC_TYPE_UNKNOWN_UNICAST] = 1, 148}; 149 150static const int mlxsw_sp_sfgc_bc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = { 151 [MLXSW_REG_SFGC_TYPE_BROADCAST] = 1, 152 [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_NON_IP] = 1, 153 [MLXSW_REG_SFGC_TYPE_IPV4_LINK_LOCAL] = 1, 154 [MLXSW_REG_SFGC_TYPE_IPV6_ALL_HOST] = 1, 155 [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV6] = 1, 156}; 157 158static const int mlxsw_sp_sfgc_mc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = { 159 [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV4] = 1, 160}; 161 162static const int mlxsw_sp_sfgc_not_uc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = { 163 [MLXSW_REG_SFGC_TYPE_BROADCAST] = 1, 164 [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_NON_IP] = 1, 165 [MLXSW_REG_SFGC_TYPE_IPV4_LINK_LOCAL] = 1, 166 [MLXSW_REG_SFGC_TYPE_IPV6_ALL_HOST] = 1, 167 [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV6] = 1, 168 [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV4] = 1, 169}; 170 171static const int mlxsw_sp_sfgc_any_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = { 172 [MLXSW_REG_SFGC_TYPE_UNKNOWN_UNICAST] = 1, 173 [MLXSW_REG_SFGC_TYPE_BROADCAST] = 1, 174 [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_NON_IP] = 1, 175 [MLXSW_REG_SFGC_TYPE_IPV4_LINK_LOCAL] = 1, 176 [MLXSW_REG_SFGC_TYPE_IPV6_ALL_HOST] = 1, 177 [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV6] = 1, 178 [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV4] = 1, 179}; 180 181static const int *mlxsw_sp_packet_type_sfgc_types[] = { 182 [MLXSW_SP_FLOOD_TYPE_UC] = mlxsw_sp_sfgc_uc_packet_types, 183 [MLXSW_SP_FLOOD_TYPE_BC] = mlxsw_sp_sfgc_bc_packet_types, 184 [MLXSW_SP_FLOOD_TYPE_MC] = mlxsw_sp_sfgc_mc_packet_types, 185 [MLXSW_SP_FLOOD_TYPE_NOT_UC] = mlxsw_sp_sfgc_not_uc_packet_types, 186 [MLXSW_SP_FLOOD_TYPE_ANY] = mlxsw_sp_sfgc_any_packet_types, 187}; 188 189struct mlxsw_sp_fid *mlxsw_sp_fid_lookup_by_index(struct mlxsw_sp *mlxsw_sp, 190 u16 fid_index) 191{ 192 struct mlxsw_sp_fid *fid; 193 194 fid = rhashtable_lookup_fast(&mlxsw_sp->fid_core->fid_ht, &fid_index, 195 mlxsw_sp_fid_ht_params); 196 if (fid) 197 refcount_inc(&fid->ref_count); 198 199 return fid; 200} 201 202int mlxsw_sp_fid_nve_ifindex(const struct mlxsw_sp_fid *fid, int *nve_ifindex) 203{ 204 if (!fid->vni_valid) 205 return -EINVAL; 206 207 *nve_ifindex = fid->nve_ifindex; 208 209 return 0; 210} 211 212int mlxsw_sp_fid_nve_type(const struct mlxsw_sp_fid *fid, 213 enum mlxsw_sp_nve_type *p_type) 214{ 215 if (!fid->vni_valid) 216 return -EINVAL; 217 218 *p_type = fid->nve_type; 219 220 return 0; 221} 222 223struct mlxsw_sp_fid *mlxsw_sp_fid_lookup_by_vni(struct mlxsw_sp *mlxsw_sp, 224 __be32 vni) 225{ 226 struct mlxsw_sp_fid *fid; 227 228 fid = rhashtable_lookup_fast(&mlxsw_sp->fid_core->vni_ht, &vni, 229 mlxsw_sp_fid_vni_ht_params); 230 if (fid) 231 refcount_inc(&fid->ref_count); 232 233 return fid; 234} 235 236int mlxsw_sp_fid_vni(const struct mlxsw_sp_fid *fid, __be32 *vni) 237{ 238 if (!fid->vni_valid) 239 return -EINVAL; 240 241 *vni = fid->vni; 242 243 return 0; 244} 245 246int mlxsw_sp_fid_nve_flood_index_set(struct mlxsw_sp_fid *fid, 247 u32 nve_flood_index) 248{ 249 struct mlxsw_sp_fid_family *fid_family = fid->fid_family; 250 const struct mlxsw_sp_fid_ops *ops = fid_family->ops; 251 int err; 252 253 if (WARN_ON(fid->nve_flood_index_valid)) 254 return -EINVAL; 255 256 fid->nve_flood_index = nve_flood_index; 257 fid->nve_flood_index_valid = true; 258 err = ops->nve_flood_index_set(fid); 259 if (err) 260 goto err_nve_flood_index_set; 261 262 return 0; 263 264err_nve_flood_index_set: 265 fid->nve_flood_index_valid = false; 266 return err; 267} 268 269void mlxsw_sp_fid_nve_flood_index_clear(struct mlxsw_sp_fid *fid) 270{ 271 struct mlxsw_sp_fid_family *fid_family = fid->fid_family; 272 const struct mlxsw_sp_fid_ops *ops = fid_family->ops; 273 274 if (WARN_ON(!fid->nve_flood_index_valid)) 275 return; 276 277 fid->nve_flood_index_valid = false; 278 ops->nve_flood_index_clear(fid); 279} 280 281bool mlxsw_sp_fid_nve_flood_index_is_set(const struct mlxsw_sp_fid *fid) 282{ 283 return fid->nve_flood_index_valid; 284} 285 286int mlxsw_sp_fid_vni_set(struct mlxsw_sp_fid *fid, enum mlxsw_sp_nve_type type, 287 __be32 vni, int nve_ifindex) 288{ 289 struct mlxsw_sp_fid_family *fid_family = fid->fid_family; 290 const struct mlxsw_sp_fid_ops *ops = fid_family->ops; 291 struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp; 292 int err; 293 294 if (WARN_ON(fid->vni_valid)) 295 return -EINVAL; 296 297 fid->nve_type = type; 298 fid->nve_ifindex = nve_ifindex; 299 fid->vni = vni; 300 err = rhashtable_lookup_insert_fast(&mlxsw_sp->fid_core->vni_ht, 301 &fid->vni_ht_node, 302 mlxsw_sp_fid_vni_ht_params); 303 if (err) 304 return err; 305 306 fid->vni_valid = true; 307 err = ops->vni_set(fid); 308 if (err) 309 goto err_vni_set; 310 311 return 0; 312 313err_vni_set: 314 fid->vni_valid = false; 315 rhashtable_remove_fast(&mlxsw_sp->fid_core->vni_ht, &fid->vni_ht_node, 316 mlxsw_sp_fid_vni_ht_params); 317 return err; 318} 319 320void mlxsw_sp_fid_vni_clear(struct mlxsw_sp_fid *fid) 321{ 322 struct mlxsw_sp_fid_family *fid_family = fid->fid_family; 323 const struct mlxsw_sp_fid_ops *ops = fid_family->ops; 324 struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp; 325 326 if (WARN_ON(!fid->vni_valid)) 327 return; 328 329 fid->vni_valid = false; 330 ops->vni_clear(fid); 331 rhashtable_remove_fast(&mlxsw_sp->fid_core->vni_ht, &fid->vni_ht_node, 332 mlxsw_sp_fid_vni_ht_params); 333} 334 335bool mlxsw_sp_fid_vni_is_set(const struct mlxsw_sp_fid *fid) 336{ 337 return fid->vni_valid; 338} 339 340void mlxsw_sp_fid_fdb_clear_offload(const struct mlxsw_sp_fid *fid, 341 const struct net_device *nve_dev) 342{ 343 struct mlxsw_sp_fid_family *fid_family = fid->fid_family; 344 const struct mlxsw_sp_fid_ops *ops = fid_family->ops; 345 346 if (ops->fdb_clear_offload) 347 ops->fdb_clear_offload(fid, nve_dev); 348} 349 350static const struct mlxsw_sp_flood_table * 351mlxsw_sp_fid_flood_table_lookup(const struct mlxsw_sp_fid *fid, 352 enum mlxsw_sp_flood_type packet_type) 353{ 354 struct mlxsw_sp_fid_family *fid_family = fid->fid_family; 355 int i; 356 357 for (i = 0; i < fid_family->flood_profile->nr_flood_tables; i++) { 358 const struct mlxsw_sp_flood_table *flood_table; 359 360 flood_table = &fid_family->flood_profile->flood_tables[i]; 361 if (flood_table->packet_type != packet_type) 362 continue; 363 return flood_table; 364 } 365 366 return NULL; 367} 368 369static u16 370mlxsw_sp_fid_family_num_fids(const struct mlxsw_sp_fid_family *fid_family) 371{ 372 return fid_family->end_index - fid_family->start_index + 1; 373} 374 375static int 376mlxsw_sp_fid_8021d_pgt_size(const struct mlxsw_sp_fid_family *fid_family, 377 u16 *p_pgt_size) 378{ 379 u16 num_fids = mlxsw_sp_fid_family_num_fids(fid_family); 380 381 *p_pgt_size = num_fids * fid_family->flood_profile->nr_flood_tables; 382 return 0; 383} 384 385static unsigned int mlxsw_sp_fid_rfid_port_offset_cff(unsigned int local_port) 386{ 387 /* Port 0 is the CPU port. Since we never create RIFs based off that 388 * port, we don't need to count it. 389 */ 390 return WARN_ON_ONCE(!local_port) ? 0 : local_port - 1; 391} 392 393static int 394mlxsw_sp_fid_rfid_pgt_size_cff(const struct mlxsw_sp_fid_family *fid_family, 395 u16 *p_pgt_size) 396{ 397 struct mlxsw_core *core = fid_family->mlxsw_sp->core; 398 unsigned int max_ports; 399 u16 pgt_size; 400 u16 max_lags; 401 int err; 402 403 max_ports = mlxsw_core_max_ports(core); 404 405 err = mlxsw_core_max_lag(core, &max_lags); 406 if (err) 407 return err; 408 409 pgt_size = (mlxsw_sp_fid_rfid_port_offset_cff(max_ports) + max_lags) * 410 fid_family->flood_profile->nr_flood_tables; 411 *p_pgt_size = pgt_size; 412 return 0; 413} 414 415static u16 416mlxsw_sp_fid_pgt_base_ctl(const struct mlxsw_sp_fid_family *fid_family, 417 const struct mlxsw_sp_flood_table *flood_table) 418{ 419 u16 num_fids; 420 421 num_fids = mlxsw_sp_fid_family_num_fids(fid_family); 422 return fid_family->pgt_base + num_fids * flood_table->table_index; 423} 424 425static u16 426mlxsw_sp_fid_fid_mid_ctl(const struct mlxsw_sp_fid *fid, 427 const struct mlxsw_sp_flood_table *flood_table) 428{ 429 return mlxsw_sp_fid_pgt_base_ctl(fid->fid_family, flood_table) + 430 fid->fid_offset; 431} 432 433int mlxsw_sp_fid_flood_set(struct mlxsw_sp_fid *fid, 434 enum mlxsw_sp_flood_type packet_type, u16 local_port, 435 bool member) 436{ 437 struct mlxsw_sp_fid_family *fid_family = fid->fid_family; 438 const struct mlxsw_sp_flood_table *flood_table; 439 u16 mid_index; 440 441 if (WARN_ON(!fid_family->flood_profile)) 442 return -EINVAL; 443 444 flood_table = mlxsw_sp_fid_flood_table_lookup(fid, packet_type); 445 if (!flood_table) 446 return -ESRCH; 447 448 mid_index = fid_family->ops->fid_mid(fid, flood_table); 449 return mlxsw_sp_pgt_entry_port_set(fid_family->mlxsw_sp, mid_index, 450 fid->fid_index, local_port, member); 451} 452 453int mlxsw_sp_fid_port_vid_map(struct mlxsw_sp_fid *fid, 454 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid) 455{ 456 if (WARN_ON(!fid->fid_family->ops->port_vid_map)) 457 return -EINVAL; 458 return fid->fid_family->ops->port_vid_map(fid, mlxsw_sp_port, vid); 459} 460 461void mlxsw_sp_fid_port_vid_unmap(struct mlxsw_sp_fid *fid, 462 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid) 463{ 464 fid->fid_family->ops->port_vid_unmap(fid, mlxsw_sp_port, vid); 465} 466 467u16 mlxsw_sp_fid_index(const struct mlxsw_sp_fid *fid) 468{ 469 return fid->fid_index; 470} 471 472enum mlxsw_sp_fid_type mlxsw_sp_fid_type(const struct mlxsw_sp_fid *fid) 473{ 474 return fid->fid_family->type; 475} 476 477struct mlxsw_sp_rif *mlxsw_sp_fid_rif(const struct mlxsw_sp_fid *fid) 478{ 479 return fid->rif; 480} 481 482enum mlxsw_sp_rif_type 483mlxsw_sp_fid_type_rif_type(const struct mlxsw_sp *mlxsw_sp, 484 enum mlxsw_sp_fid_type type) 485{ 486 struct mlxsw_sp_fid_core *fid_core = mlxsw_sp->fid_core; 487 488 return fid_core->fid_family_arr[type]->rif_type; 489} 490 491static struct mlxsw_sp_fid_8021q * 492mlxsw_sp_fid_8021q_fid(const struct mlxsw_sp_fid *fid) 493{ 494 return container_of(fid, struct mlxsw_sp_fid_8021q, common); 495} 496 497u16 mlxsw_sp_fid_8021q_vid(const struct mlxsw_sp_fid *fid) 498{ 499 return mlxsw_sp_fid_8021q_fid(fid)->vid; 500} 501 502static int mlxsw_sp_fid_8021q_setup(struct mlxsw_sp_fid *fid, const void *arg) 503{ 504 u16 vid = *(u16 *) arg; 505 506 mlxsw_sp_fid_8021q_fid(fid)->vid = vid; 507 fid->fid_offset = fid->fid_index - fid->fid_family->start_index; 508 return 0; 509} 510 511static enum mlxsw_reg_sfmr_op mlxsw_sp_sfmr_op(bool valid) 512{ 513 return valid ? MLXSW_REG_SFMR_OP_CREATE_FID : 514 MLXSW_REG_SFMR_OP_DESTROY_FID; 515} 516 517static void mlxsw_sp_fid_pack(char *sfmr_pl, 518 const struct mlxsw_sp_fid *fid, 519 enum mlxsw_reg_sfmr_op op) 520{ 521 u16 smpe; 522 523 smpe = fid->fid_family->smpe_index_valid ? fid->fid_index : 0; 524 525 mlxsw_reg_sfmr_pack(sfmr_pl, op, fid->fid_index, 526 fid->fid_family->smpe_index_valid, smpe); 527} 528 529static void mlxsw_sp_fid_pack_ctl(char *sfmr_pl, 530 const struct mlxsw_sp_fid *fid, 531 enum mlxsw_reg_sfmr_op op) 532{ 533 mlxsw_sp_fid_pack(sfmr_pl, fid, op); 534 mlxsw_reg_sfmr_fid_offset_set(sfmr_pl, fid->fid_offset); 535 mlxsw_reg_sfmr_flood_rsp_set(sfmr_pl, fid->fid_family->flood_rsp); 536 mlxsw_reg_sfmr_flood_bridge_type_set(sfmr_pl, 537 fid->fid_family->bridge_type); 538} 539 540static u16 541mlxsw_sp_fid_off_pgt_base_cff(const struct mlxsw_sp_fid_family *fid_family, 542 u16 fid_offset) 543{ 544 return fid_family->pgt_base + 545 fid_offset * fid_family->flood_profile->nr_flood_tables; 546} 547 548static u16 mlxsw_sp_fid_pgt_base_cff(const struct mlxsw_sp_fid *fid) 549{ 550 return mlxsw_sp_fid_off_pgt_base_cff(fid->fid_family, fid->fid_offset); 551} 552 553static void mlxsw_sp_fid_fid_pack_cff(char *sfmr_pl, 554 const struct mlxsw_sp_fid *fid, 555 enum mlxsw_reg_sfmr_op op) 556{ 557 struct mlxsw_sp_fid_family *fid_family = fid->fid_family; 558 u16 pgt_base = mlxsw_sp_fid_pgt_base_cff(fid); 559 560 mlxsw_sp_fid_pack(sfmr_pl, fid, op); 561 mlxsw_reg_sfmr_cff_mid_base_set(sfmr_pl, pgt_base); 562 mlxsw_reg_sfmr_cff_prf_id_set(sfmr_pl, 563 fid_family->flood_profile->profile_id); 564 mlxsw_reg_sfmr_nve_flood_prf_id_set(sfmr_pl, 565 MLXSW_SP_FID_FLOOD_PROFILE_ID_NVE); 566} 567 568static u16 mlxsw_sp_fid_rfid_fid_offset_cff(struct mlxsw_sp *mlxsw_sp, 569 u16 port_lag_id, bool is_lag) 570{ 571 u16 max_ports = mlxsw_core_max_ports(mlxsw_sp->core); 572 573 if (is_lag) 574 return mlxsw_sp_fid_rfid_port_offset_cff(max_ports) + 575 port_lag_id; 576 else 577 return mlxsw_sp_fid_rfid_port_offset_cff(port_lag_id); 578} 579 580static int mlxsw_sp_fid_op(const struct mlxsw_sp_fid *fid, bool valid) 581{ 582 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; 583 char sfmr_pl[MLXSW_REG_SFMR_LEN]; 584 585 fid->fid_family->ops->fid_pack(sfmr_pl, fid, 586 mlxsw_sp_sfmr_op(valid)); 587 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl); 588} 589 590static int mlxsw_sp_fid_edit_op(const struct mlxsw_sp_fid *fid, 591 const struct mlxsw_sp_rif *rif) 592{ 593 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; 594 char sfmr_pl[MLXSW_REG_SFMR_LEN]; 595 596 fid->fid_family->ops->fid_pack(sfmr_pl, fid, 597 MLXSW_REG_SFMR_OP_CREATE_FID); 598 599 mlxsw_reg_sfmr_vv_set(sfmr_pl, fid->vni_valid); 600 mlxsw_reg_sfmr_vni_set(sfmr_pl, be32_to_cpu(fid->vni)); 601 mlxsw_reg_sfmr_vtfp_set(sfmr_pl, fid->nve_flood_index_valid); 602 mlxsw_reg_sfmr_nve_tunnel_flood_ptr_set(sfmr_pl, fid->nve_flood_index); 603 604 if (rif) { 605 mlxsw_reg_sfmr_irif_v_set(sfmr_pl, true); 606 mlxsw_reg_sfmr_irif_set(sfmr_pl, mlxsw_sp_rif_index(rif)); 607 } 608 609 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl); 610} 611 612static int mlxsw_sp_fid_vni_to_fid_map(const struct mlxsw_sp_fid *fid, 613 const struct mlxsw_sp_rif *rif, 614 bool valid) 615{ 616 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; 617 char svfa_pl[MLXSW_REG_SVFA_LEN]; 618 bool irif_valid; 619 u16 irif_index; 620 621 irif_valid = !!rif; 622 irif_index = rif ? mlxsw_sp_rif_index(rif) : 0; 623 624 mlxsw_reg_svfa_vni_pack(svfa_pl, valid, fid->fid_index, 625 be32_to_cpu(fid->vni), irif_valid, irif_index); 626 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl); 627} 628 629static int mlxsw_sp_fid_to_fid_rif_update(const struct mlxsw_sp_fid *fid, 630 const struct mlxsw_sp_rif *rif) 631{ 632 return mlxsw_sp_fid_edit_op(fid, rif); 633} 634 635static int mlxsw_sp_fid_vni_to_fid_rif_update(const struct mlxsw_sp_fid *fid, 636 const struct mlxsw_sp_rif *rif) 637{ 638 if (!fid->vni_valid) 639 return 0; 640 641 return mlxsw_sp_fid_vni_to_fid_map(fid, rif, fid->vni_valid); 642} 643 644static int 645mlxsw_sp_fid_vid_to_fid_map(const struct mlxsw_sp_fid *fid, u16 vid, bool valid, 646 const struct mlxsw_sp_rif *rif) 647{ 648 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; 649 char svfa_pl[MLXSW_REG_SVFA_LEN]; 650 bool irif_valid; 651 u16 irif_index; 652 653 irif_valid = !!rif; 654 irif_index = rif ? mlxsw_sp_rif_index(rif) : 0; 655 656 mlxsw_reg_svfa_vid_pack(svfa_pl, valid, fid->fid_index, vid, irif_valid, 657 irif_index); 658 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl); 659} 660 661static int 662mlxsw_sp_fid_8021q_vid_to_fid_rif_update(const struct mlxsw_sp_fid *fid, 663 const struct mlxsw_sp_rif *rif) 664{ 665 struct mlxsw_sp_fid_8021q *fid_8021q = mlxsw_sp_fid_8021q_fid(fid); 666 667 /* Update the global VID => FID mapping we created when the FID was 668 * configured. 669 */ 670 return mlxsw_sp_fid_vid_to_fid_map(fid, fid_8021q->vid, true, rif); 671} 672 673static int 674mlxsw_sp_fid_port_vid_to_fid_rif_update_one(const struct mlxsw_sp_fid *fid, 675 struct mlxsw_sp_fid_port_vid *pv, 676 bool irif_valid, u16 irif_index) 677{ 678 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; 679 char svfa_pl[MLXSW_REG_SVFA_LEN]; 680 681 mlxsw_reg_svfa_port_vid_pack(svfa_pl, pv->local_port, true, 682 fid->fid_index, pv->vid, irif_valid, 683 irif_index); 684 685 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl); 686} 687 688static int mlxsw_sp_fid_vid_to_fid_rif_set(const struct mlxsw_sp_fid *fid, 689 const struct mlxsw_sp_rif *rif) 690{ 691 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; 692 struct mlxsw_sp_fid_port_vid *pv; 693 u16 irif_index; 694 int err; 695 696 err = fid->fid_family->ops->vid_to_fid_rif_update(fid, rif); 697 if (err) 698 return err; 699 700 irif_index = mlxsw_sp_rif_index(rif); 701 702 list_for_each_entry(pv, &fid->port_vid_list, list) { 703 /* If port is not in virtual mode, then it does not have any 704 * {Port, VID}->FID mappings that need to be updated with the 705 * ingress RIF. 706 */ 707 if (!mlxsw_sp->fid_core->port_fid_mappings[pv->local_port]) 708 continue; 709 710 err = mlxsw_sp_fid_port_vid_to_fid_rif_update_one(fid, pv, 711 true, 712 irif_index); 713 if (err) 714 goto err_port_vid_to_fid_rif_update_one; 715 } 716 717 return 0; 718 719err_port_vid_to_fid_rif_update_one: 720 list_for_each_entry_continue_reverse(pv, &fid->port_vid_list, list) { 721 if (!mlxsw_sp->fid_core->port_fid_mappings[pv->local_port]) 722 continue; 723 724 mlxsw_sp_fid_port_vid_to_fid_rif_update_one(fid, pv, false, 0); 725 } 726 727 fid->fid_family->ops->vid_to_fid_rif_update(fid, NULL); 728 return err; 729} 730 731static void mlxsw_sp_fid_vid_to_fid_rif_unset(const struct mlxsw_sp_fid *fid) 732{ 733 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; 734 struct mlxsw_sp_fid_port_vid *pv; 735 736 list_for_each_entry(pv, &fid->port_vid_list, list) { 737 /* If port is not in virtual mode, then it does not have any 738 * {Port, VID}->FID mappings that need to be updated. 739 */ 740 if (!mlxsw_sp->fid_core->port_fid_mappings[pv->local_port]) 741 continue; 742 743 mlxsw_sp_fid_port_vid_to_fid_rif_update_one(fid, pv, false, 0); 744 } 745 746 fid->fid_family->ops->vid_to_fid_rif_update(fid, NULL); 747} 748 749static int mlxsw_sp_fid_reiv_handle(struct mlxsw_sp_fid *fid, u16 rif_index, 750 bool valid, u8 port_page) 751{ 752 u16 local_port_end = (port_page + 1) * MLXSW_REG_REIV_REC_MAX_COUNT - 1; 753 u16 local_port_start = port_page * MLXSW_REG_REIV_REC_MAX_COUNT; 754 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; 755 struct mlxsw_sp_fid_port_vid *port_vid; 756 u8 rec_num, entries_num = 0; 757 char *reiv_pl; 758 int err; 759 760 reiv_pl = kmalloc(MLXSW_REG_REIV_LEN, GFP_KERNEL); 761 if (!reiv_pl) 762 return -ENOMEM; 763 764 mlxsw_reg_reiv_pack(reiv_pl, port_page, rif_index); 765 766 list_for_each_entry(port_vid, &fid->port_vid_list, list) { 767 /* port_vid_list is sorted by local_port. */ 768 if (port_vid->local_port < local_port_start) 769 continue; 770 771 if (port_vid->local_port > local_port_end) 772 break; 773 774 rec_num = port_vid->local_port % MLXSW_REG_REIV_REC_MAX_COUNT; 775 mlxsw_reg_reiv_rec_update_set(reiv_pl, rec_num, true); 776 mlxsw_reg_reiv_rec_evid_set(reiv_pl, rec_num, 777 valid ? port_vid->vid : 0); 778 entries_num++; 779 } 780 781 if (!entries_num) { 782 kfree(reiv_pl); 783 return 0; 784 } 785 786 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(reiv), reiv_pl); 787 if (err) 788 goto err_reg_write; 789 790 kfree(reiv_pl); 791 return 0; 792 793err_reg_write: 794 kfree(reiv_pl); 795 return err; 796} 797 798static int mlxsw_sp_fid_erif_eport_to_vid_map(struct mlxsw_sp_fid *fid, 799 u16 rif_index, bool valid) 800{ 801 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; 802 u8 num_port_pages; 803 int err, i; 804 805 num_port_pages = mlxsw_core_max_ports(mlxsw_sp->core) / 806 MLXSW_REG_REIV_REC_MAX_COUNT + 1; 807 808 for (i = 0; i < num_port_pages; i++) { 809 err = mlxsw_sp_fid_reiv_handle(fid, rif_index, valid, i); 810 if (err) 811 goto err_reiv_handle; 812 } 813 814 return 0; 815 816err_reiv_handle: 817 for (; i >= 0; i--) 818 mlxsw_sp_fid_reiv_handle(fid, rif_index, !valid, i); 819 return err; 820} 821 822int mlxsw_sp_fid_rif_set(struct mlxsw_sp_fid *fid, struct mlxsw_sp_rif *rif) 823{ 824 u16 rif_index = mlxsw_sp_rif_index(rif); 825 int err; 826 827 err = mlxsw_sp_fid_to_fid_rif_update(fid, rif); 828 if (err) 829 return err; 830 831 err = mlxsw_sp_fid_vni_to_fid_rif_update(fid, rif); 832 if (err) 833 goto err_vni_to_fid_rif_update; 834 835 err = mlxsw_sp_fid_vid_to_fid_rif_set(fid, rif); 836 if (err) 837 goto err_vid_to_fid_rif_set; 838 839 err = mlxsw_sp_fid_erif_eport_to_vid_map(fid, rif_index, true); 840 if (err) 841 goto err_erif_eport_to_vid_map; 842 843 fid->rif = rif; 844 return 0; 845 846err_erif_eport_to_vid_map: 847 mlxsw_sp_fid_vid_to_fid_rif_unset(fid); 848err_vid_to_fid_rif_set: 849 mlxsw_sp_fid_vni_to_fid_rif_update(fid, NULL); 850err_vni_to_fid_rif_update: 851 mlxsw_sp_fid_to_fid_rif_update(fid, NULL); 852 return err; 853} 854 855void mlxsw_sp_fid_rif_unset(struct mlxsw_sp_fid *fid) 856{ 857 u16 rif_index; 858 859 if (!fid->rif) 860 return; 861 862 rif_index = mlxsw_sp_rif_index(fid->rif); 863 fid->rif = NULL; 864 865 mlxsw_sp_fid_erif_eport_to_vid_map(fid, rif_index, false); 866 mlxsw_sp_fid_vid_to_fid_rif_unset(fid); 867 mlxsw_sp_fid_vni_to_fid_rif_update(fid, NULL); 868 mlxsw_sp_fid_to_fid_rif_update(fid, NULL); 869} 870 871static int mlxsw_sp_fid_vni_op(const struct mlxsw_sp_fid *fid) 872{ 873 int err; 874 875 err = mlxsw_sp_fid_vni_to_fid_map(fid, fid->rif, fid->vni_valid); 876 if (err) 877 return err; 878 879 err = mlxsw_sp_fid_edit_op(fid, fid->rif); 880 if (err) 881 goto err_fid_edit_op; 882 883 return 0; 884 885err_fid_edit_op: 886 mlxsw_sp_fid_vni_to_fid_map(fid, fid->rif, !fid->vni_valid); 887 return err; 888} 889 890static int __mlxsw_sp_fid_port_vid_map(const struct mlxsw_sp_fid *fid, 891 u16 local_port, u16 vid, bool valid) 892{ 893 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; 894 char svfa_pl[MLXSW_REG_SVFA_LEN]; 895 bool irif_valid = false; 896 u16 irif_index = 0; 897 898 if (fid->rif) { 899 irif_valid = true; 900 irif_index = mlxsw_sp_rif_index(fid->rif); 901 } 902 903 mlxsw_reg_svfa_port_vid_pack(svfa_pl, local_port, valid, fid->fid_index, 904 vid, irif_valid, irif_index); 905 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl); 906} 907 908static struct mlxsw_sp_fid_8021d * 909mlxsw_sp_fid_8021d_fid(const struct mlxsw_sp_fid *fid) 910{ 911 return container_of(fid, struct mlxsw_sp_fid_8021d, common); 912} 913 914static int mlxsw_sp_fid_8021d_setup(struct mlxsw_sp_fid *fid, const void *arg) 915{ 916 int br_ifindex = *(int *) arg; 917 918 mlxsw_sp_fid_8021d_fid(fid)->br_ifindex = br_ifindex; 919 fid->fid_offset = fid->fid_index - fid->fid_family->start_index; 920 return 0; 921} 922 923static int mlxsw_sp_fid_8021d_configure(struct mlxsw_sp_fid *fid) 924{ 925 return mlxsw_sp_fid_op(fid, true); 926} 927 928static void mlxsw_sp_fid_8021d_deconfigure(struct mlxsw_sp_fid *fid) 929{ 930 if (fid->vni_valid) 931 mlxsw_sp_nve_fid_disable(fid->fid_family->mlxsw_sp, fid); 932 mlxsw_sp_fid_op(fid, false); 933} 934 935static int mlxsw_sp_fid_8021d_index_alloc(struct mlxsw_sp_fid *fid, 936 const void *arg, u16 *p_fid_index) 937{ 938 struct mlxsw_sp_fid_family *fid_family = fid->fid_family; 939 u16 nr_fids, fid_index; 940 941 nr_fids = fid_family->end_index - fid_family->start_index + 1; 942 fid_index = find_first_zero_bit(fid_family->fids_bitmap, nr_fids); 943 if (fid_index == nr_fids) 944 return -ENOBUFS; 945 *p_fid_index = fid_family->start_index + fid_index; 946 947 return 0; 948} 949 950static bool 951mlxsw_sp_fid_8021d_compare(const struct mlxsw_sp_fid *fid, const void *arg) 952{ 953 int br_ifindex = *(int *) arg; 954 955 return mlxsw_sp_fid_8021d_fid(fid)->br_ifindex == br_ifindex; 956} 957 958static int mlxsw_sp_port_vp_mode_trans(struct mlxsw_sp_port *mlxsw_sp_port) 959{ 960 struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan; 961 int err; 962 963 list_for_each_entry(mlxsw_sp_port_vlan, &mlxsw_sp_port->vlans_list, 964 list) { 965 struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid; 966 u16 vid = mlxsw_sp_port_vlan->vid; 967 968 if (!fid) 969 continue; 970 971 err = __mlxsw_sp_fid_port_vid_map(fid, 972 mlxsw_sp_port->local_port, 973 vid, true); 974 if (err) 975 goto err_fid_port_vid_map; 976 } 977 978 err = mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, true); 979 if (err) 980 goto err_port_vp_mode_set; 981 982 return 0; 983 984err_port_vp_mode_set: 985err_fid_port_vid_map: 986 list_for_each_entry_continue_reverse(mlxsw_sp_port_vlan, 987 &mlxsw_sp_port->vlans_list, list) { 988 struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid; 989 u16 vid = mlxsw_sp_port_vlan->vid; 990 991 if (!fid) 992 continue; 993 994 __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, 995 false); 996 } 997 return err; 998} 999 1000static void mlxsw_sp_port_vlan_mode_trans(struct mlxsw_sp_port *mlxsw_sp_port) 1001{ 1002 struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan; 1003 1004 mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, false); 1005 1006 list_for_each_entry_reverse(mlxsw_sp_port_vlan, 1007 &mlxsw_sp_port->vlans_list, list) { 1008 struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid; 1009 u16 vid = mlxsw_sp_port_vlan->vid; 1010 1011 if (!fid) 1012 continue; 1013 1014 __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, 1015 false); 1016 } 1017} 1018 1019static int 1020mlxsw_sp_fid_port_vid_list_add(struct mlxsw_sp_fid *fid, u16 local_port, 1021 u16 vid) 1022{ 1023 struct mlxsw_sp_fid_port_vid *port_vid, *tmp_port_vid; 1024 1025 port_vid = kzalloc(sizeof(*port_vid), GFP_KERNEL); 1026 if (!port_vid) 1027 return -ENOMEM; 1028 1029 port_vid->local_port = local_port; 1030 port_vid->vid = vid; 1031 1032 list_for_each_entry(tmp_port_vid, &fid->port_vid_list, list) { 1033 if (tmp_port_vid->local_port > local_port) 1034 break; 1035 } 1036 1037 list_add_tail(&port_vid->list, &tmp_port_vid->list); 1038 return 0; 1039} 1040 1041static void 1042mlxsw_sp_fid_port_vid_list_del(struct mlxsw_sp_fid *fid, u16 local_port, 1043 u16 vid) 1044{ 1045 struct mlxsw_sp_fid_port_vid *port_vid, *tmp; 1046 1047 list_for_each_entry_safe(port_vid, tmp, &fid->port_vid_list, list) { 1048 if (port_vid->local_port != local_port || port_vid->vid != vid) 1049 continue; 1050 1051 list_del(&port_vid->list); 1052 kfree(port_vid); 1053 return; 1054 } 1055} 1056 1057static int 1058mlxsw_sp_fid_mpe_table_map(const struct mlxsw_sp_fid *fid, u16 local_port, 1059 u16 vid, bool valid) 1060{ 1061 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; 1062 char smpe_pl[MLXSW_REG_SMPE_LEN]; 1063 1064 mlxsw_reg_smpe_pack(smpe_pl, local_port, fid->fid_index, 1065 valid ? vid : 0); 1066 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(smpe), smpe_pl); 1067} 1068 1069static int 1070mlxsw_sp_fid_erif_eport_to_vid_map_one(const struct mlxsw_sp_fid *fid, 1071 u16 local_port, u16 vid, bool valid) 1072{ 1073 u8 port_page = local_port / MLXSW_REG_REIV_REC_MAX_COUNT; 1074 u8 rec_num = local_port % MLXSW_REG_REIV_REC_MAX_COUNT; 1075 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; 1076 u16 rif_index = mlxsw_sp_rif_index(fid->rif); 1077 char *reiv_pl; 1078 int err; 1079 1080 reiv_pl = kmalloc(MLXSW_REG_REIV_LEN, GFP_KERNEL); 1081 if (!reiv_pl) 1082 return -ENOMEM; 1083 1084 mlxsw_reg_reiv_pack(reiv_pl, port_page, rif_index); 1085 mlxsw_reg_reiv_rec_update_set(reiv_pl, rec_num, true); 1086 mlxsw_reg_reiv_rec_evid_set(reiv_pl, rec_num, valid ? vid : 0); 1087 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(reiv), reiv_pl); 1088 kfree(reiv_pl); 1089 return err; 1090} 1091 1092static int mlxsw_sp_fid_evid_map(const struct mlxsw_sp_fid *fid, u16 local_port, 1093 u16 vid, bool valid) 1094{ 1095 int err; 1096 1097 err = mlxsw_sp_fid_mpe_table_map(fid, local_port, vid, valid); 1098 if (err) 1099 return err; 1100 1101 if (!fid->rif) 1102 return 0; 1103 1104 err = mlxsw_sp_fid_erif_eport_to_vid_map_one(fid, local_port, vid, 1105 valid); 1106 if (err) 1107 goto err_erif_eport_to_vid_map_one; 1108 1109 return 0; 1110 1111err_erif_eport_to_vid_map_one: 1112 mlxsw_sp_fid_mpe_table_map(fid, local_port, vid, !valid); 1113 return err; 1114} 1115 1116static int mlxsw_sp_fid_8021d_port_vid_map(struct mlxsw_sp_fid *fid, 1117 struct mlxsw_sp_port *mlxsw_sp_port, 1118 u16 vid) 1119{ 1120 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 1121 u16 local_port = mlxsw_sp_port->local_port; 1122 int err; 1123 1124 err = __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, 1125 true); 1126 if (err) 1127 return err; 1128 1129 err = mlxsw_sp_fid_evid_map(fid, local_port, vid, true); 1130 if (err) 1131 goto err_fid_evid_map; 1132 1133 err = mlxsw_sp_fid_port_vid_list_add(fid, mlxsw_sp_port->local_port, 1134 vid); 1135 if (err) 1136 goto err_port_vid_list_add; 1137 1138 if (mlxsw_sp->fid_core->port_fid_mappings[local_port]++ == 0) { 1139 err = mlxsw_sp_port_vp_mode_trans(mlxsw_sp_port); 1140 if (err) 1141 goto err_port_vp_mode_trans; 1142 } 1143 1144 return 0; 1145 1146err_port_vp_mode_trans: 1147 mlxsw_sp->fid_core->port_fid_mappings[local_port]--; 1148 mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid); 1149err_port_vid_list_add: 1150 mlxsw_sp_fid_evid_map(fid, local_port, vid, false); 1151err_fid_evid_map: 1152 __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, false); 1153 return err; 1154} 1155 1156static void 1157mlxsw_sp_fid_8021d_port_vid_unmap(struct mlxsw_sp_fid *fid, 1158 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid) 1159{ 1160 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 1161 u16 local_port = mlxsw_sp_port->local_port; 1162 1163 if (mlxsw_sp->fid_core->port_fid_mappings[local_port] == 1) 1164 mlxsw_sp_port_vlan_mode_trans(mlxsw_sp_port); 1165 mlxsw_sp->fid_core->port_fid_mappings[local_port]--; 1166 mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid); 1167 mlxsw_sp_fid_evid_map(fid, local_port, vid, false); 1168 __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, false); 1169} 1170 1171static int mlxsw_sp_fid_8021d_vni_set(struct mlxsw_sp_fid *fid) 1172{ 1173 return mlxsw_sp_fid_vni_op(fid); 1174} 1175 1176static void mlxsw_sp_fid_8021d_vni_clear(struct mlxsw_sp_fid *fid) 1177{ 1178 mlxsw_sp_fid_vni_op(fid); 1179} 1180 1181static int mlxsw_sp_fid_8021d_nve_flood_index_set(struct mlxsw_sp_fid *fid) 1182{ 1183 return mlxsw_sp_fid_edit_op(fid, fid->rif); 1184} 1185 1186static void mlxsw_sp_fid_8021d_nve_flood_index_clear(struct mlxsw_sp_fid *fid) 1187{ 1188 mlxsw_sp_fid_edit_op(fid, fid->rif); 1189} 1190 1191static void 1192mlxsw_sp_fid_8021d_fdb_clear_offload(const struct mlxsw_sp_fid *fid, 1193 const struct net_device *nve_dev) 1194{ 1195 br_fdb_clear_offload(nve_dev, 0); 1196} 1197 1198static int 1199mlxsw_sp_fid_8021d_vid_to_fid_rif_update(const struct mlxsw_sp_fid *fid, 1200 const struct mlxsw_sp_rif *rif) 1201{ 1202 return 0; 1203} 1204 1205static int 1206mlxsw_sp_fid_flood_table_init_ctl(struct mlxsw_sp_fid_family *fid_family, 1207 const struct mlxsw_sp_flood_table *flood_table) 1208{ 1209 enum mlxsw_sp_flood_type packet_type = flood_table->packet_type; 1210 struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp; 1211 const int *sfgc_packet_types; 1212 u16 mid_base; 1213 int err, i; 1214 1215 mid_base = mlxsw_sp_fid_pgt_base_ctl(fid_family, flood_table); 1216 1217 sfgc_packet_types = mlxsw_sp_packet_type_sfgc_types[packet_type]; 1218 for (i = 0; i < MLXSW_REG_SFGC_TYPE_MAX; i++) { 1219 char sfgc_pl[MLXSW_REG_SFGC_LEN]; 1220 1221 if (!sfgc_packet_types[i]) 1222 continue; 1223 1224 mlxsw_reg_sfgc_pack(sfgc_pl, i, fid_family->bridge_type, 1225 flood_table->table_type, 0, mid_base); 1226 1227 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfgc), sfgc_pl); 1228 if (err) 1229 return err; 1230 } 1231 1232 return 0; 1233} 1234 1235static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021d_ops_ctl = { 1236 .setup = mlxsw_sp_fid_8021d_setup, 1237 .configure = mlxsw_sp_fid_8021d_configure, 1238 .deconfigure = mlxsw_sp_fid_8021d_deconfigure, 1239 .index_alloc = mlxsw_sp_fid_8021d_index_alloc, 1240 .compare = mlxsw_sp_fid_8021d_compare, 1241 .port_vid_map = mlxsw_sp_fid_8021d_port_vid_map, 1242 .port_vid_unmap = mlxsw_sp_fid_8021d_port_vid_unmap, 1243 .vni_set = mlxsw_sp_fid_8021d_vni_set, 1244 .vni_clear = mlxsw_sp_fid_8021d_vni_clear, 1245 .nve_flood_index_set = mlxsw_sp_fid_8021d_nve_flood_index_set, 1246 .nve_flood_index_clear = mlxsw_sp_fid_8021d_nve_flood_index_clear, 1247 .fdb_clear_offload = mlxsw_sp_fid_8021d_fdb_clear_offload, 1248 .vid_to_fid_rif_update = mlxsw_sp_fid_8021d_vid_to_fid_rif_update, 1249 .flood_table_init = mlxsw_sp_fid_flood_table_init_ctl, 1250 .pgt_size = mlxsw_sp_fid_8021d_pgt_size, 1251 .fid_mid = mlxsw_sp_fid_fid_mid_ctl, 1252 .fid_pack = mlxsw_sp_fid_pack_ctl, 1253}; 1254 1255static u16 1256mlxsw_sp_fid_fid_mid_cff(const struct mlxsw_sp_fid *fid, 1257 const struct mlxsw_sp_flood_table *flood_table) 1258{ 1259 return mlxsw_sp_fid_pgt_base_cff(fid) + flood_table->table_index; 1260} 1261 1262static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021d_ops_cff = { 1263 .setup = mlxsw_sp_fid_8021d_setup, 1264 .configure = mlxsw_sp_fid_8021d_configure, 1265 .deconfigure = mlxsw_sp_fid_8021d_deconfigure, 1266 .index_alloc = mlxsw_sp_fid_8021d_index_alloc, 1267 .compare = mlxsw_sp_fid_8021d_compare, 1268 .port_vid_map = mlxsw_sp_fid_8021d_port_vid_map, 1269 .port_vid_unmap = mlxsw_sp_fid_8021d_port_vid_unmap, 1270 .vni_set = mlxsw_sp_fid_8021d_vni_set, 1271 .vni_clear = mlxsw_sp_fid_8021d_vni_clear, 1272 .nve_flood_index_set = mlxsw_sp_fid_8021d_nve_flood_index_set, 1273 .nve_flood_index_clear = mlxsw_sp_fid_8021d_nve_flood_index_clear, 1274 .fdb_clear_offload = mlxsw_sp_fid_8021d_fdb_clear_offload, 1275 .vid_to_fid_rif_update = mlxsw_sp_fid_8021d_vid_to_fid_rif_update, 1276 .pgt_size = mlxsw_sp_fid_8021d_pgt_size, 1277 .fid_mid = mlxsw_sp_fid_fid_mid_cff, 1278 .fid_pack = mlxsw_sp_fid_fid_pack_cff, 1279}; 1280 1281#define MLXSW_SP_FID_8021Q_MAX (VLAN_N_VID - 2) 1282#define MLXSW_SP_FID_RFID_MAX (11 * 1024) 1283 1284static const struct mlxsw_sp_flood_table mlxsw_sp_fid_8021d_flood_tables[] = { 1285 { 1286 .packet_type = MLXSW_SP_FLOOD_TYPE_UC, 1287 .table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFSET, 1288 .table_index = 0, 1289 }, 1290 { 1291 .packet_type = MLXSW_SP_FLOOD_TYPE_MC, 1292 .table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFSET, 1293 .table_index = 1, 1294 }, 1295 { 1296 .packet_type = MLXSW_SP_FLOOD_TYPE_BC, 1297 .table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFSET, 1298 .table_index = 2, 1299 }, 1300}; 1301 1302static const 1303struct mlxsw_sp_fid_flood_profile mlxsw_sp_fid_8021d_flood_profile = { 1304 .flood_tables = mlxsw_sp_fid_8021d_flood_tables, 1305 .nr_flood_tables = ARRAY_SIZE(mlxsw_sp_fid_8021d_flood_tables), 1306 .profile_id = MLXSW_SP_FID_FLOOD_PROFILE_ID_BRIDGE, 1307}; 1308 1309static const struct mlxsw_sp_flood_table mlxsw_sp_fid_rsp_flood_tables_cff[] = { 1310 { 1311 .packet_type = MLXSW_SP_FLOOD_TYPE_UC, 1312 .table_index = 0, 1313 }, 1314 { 1315 .packet_type = MLXSW_SP_FLOOD_TYPE_NOT_UC, 1316 .table_index = 1, 1317 }, 1318}; 1319 1320static const 1321struct mlxsw_sp_fid_flood_profile mlxsw_sp_fid_rsp_flood_profile_cff = { 1322 .flood_tables = mlxsw_sp_fid_rsp_flood_tables_cff, 1323 .nr_flood_tables = ARRAY_SIZE(mlxsw_sp_fid_rsp_flood_tables_cff), 1324 .profile_id = MLXSW_SP_FID_FLOOD_PROFILE_ID_RSP, 1325}; 1326 1327static const struct mlxsw_sp_flood_table mlxsw_sp_fid_nve_flood_tables_cff[] = { 1328 { 1329 .packet_type = MLXSW_SP_FLOOD_TYPE_ANY, 1330 .table_index = 0, 1331 }, 1332}; 1333 1334static const 1335struct mlxsw_sp_fid_flood_profile mlxsw_sp_fid_nve_flood_profile_cff = { 1336 .flood_tables = mlxsw_sp_fid_nve_flood_tables_cff, 1337 .nr_flood_tables = ARRAY_SIZE(mlxsw_sp_fid_nve_flood_tables_cff), 1338 .profile_id = MLXSW_SP_FID_FLOOD_PROFILE_ID_NVE, 1339}; 1340 1341static bool 1342mlxsw_sp_fid_8021q_compare(const struct mlxsw_sp_fid *fid, const void *arg) 1343{ 1344 u16 vid = *(u16 *) arg; 1345 1346 return mlxsw_sp_fid_8021q_fid(fid)->vid == vid; 1347} 1348 1349static void 1350mlxsw_sp_fid_8021q_fdb_clear_offload(const struct mlxsw_sp_fid *fid, 1351 const struct net_device *nve_dev) 1352{ 1353 br_fdb_clear_offload(nve_dev, mlxsw_sp_fid_8021q_vid(fid)); 1354} 1355 1356static int mlxsw_sp_fid_rfid_setup_ctl(struct mlxsw_sp_fid *fid, 1357 const void *arg) 1358{ 1359 /* In controlled mode, the FW takes care of FID placement. */ 1360 fid->fid_offset = 0; 1361 return 0; 1362} 1363 1364static int mlxsw_sp_fid_rfid_setup_cff(struct mlxsw_sp_fid *fid, 1365 const void *arg) 1366{ 1367 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; 1368 u16 rif_index = *(const u16 *)arg; 1369 struct mlxsw_sp_rif *rif; 1370 bool is_lag; 1371 u16 port; 1372 int err; 1373 1374 rif = mlxsw_sp_rif_by_index(mlxsw_sp, rif_index); 1375 if (!rif) 1376 return -ENOENT; 1377 1378 err = mlxsw_sp_rif_subport_port(rif, &port, &is_lag); 1379 if (err) 1380 return err; 1381 1382 fid->fid_offset = mlxsw_sp_fid_rfid_fid_offset_cff(mlxsw_sp, port, 1383 is_lag); 1384 return 0; 1385} 1386 1387static int mlxsw_sp_fid_rfid_configure(struct mlxsw_sp_fid *fid) 1388{ 1389 return mlxsw_sp_fid_op(fid, true); 1390} 1391 1392static void mlxsw_sp_fid_rfid_deconfigure(struct mlxsw_sp_fid *fid) 1393{ 1394 mlxsw_sp_fid_op(fid, false); 1395} 1396 1397static int mlxsw_sp_fid_rfid_index_alloc(struct mlxsw_sp_fid *fid, 1398 const void *arg, u16 *p_fid_index) 1399{ 1400 u16 rif_index = *(u16 *) arg; 1401 1402 *p_fid_index = fid->fid_family->start_index + rif_index; 1403 1404 return 0; 1405} 1406 1407static bool mlxsw_sp_fid_rfid_compare(const struct mlxsw_sp_fid *fid, 1408 const void *arg) 1409{ 1410 u16 rif_index = *(u16 *) arg; 1411 1412 return fid->fid_index == rif_index + fid->fid_family->start_index; 1413} 1414 1415static int mlxsw_sp_fid_rfid_port_vid_map(struct mlxsw_sp_fid *fid, 1416 struct mlxsw_sp_port *mlxsw_sp_port, 1417 u16 vid) 1418{ 1419 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 1420 u16 local_port = mlxsw_sp_port->local_port; 1421 int err; 1422 1423 err = mlxsw_sp_fid_port_vid_list_add(fid, mlxsw_sp_port->local_port, 1424 vid); 1425 if (err) 1426 return err; 1427 1428 /* Using legacy bridge model, we only need to transition the port to 1429 * virtual mode since {Port, VID} => FID is done by the firmware upon 1430 * RIF creation. Using unified bridge model, we need to map 1431 * {Port, VID} => FID and map egress VID. 1432 */ 1433 err = __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, 1434 true); 1435 if (err) 1436 goto err_port_vid_map; 1437 1438 if (fid->rif) { 1439 err = mlxsw_sp_fid_erif_eport_to_vid_map_one(fid, local_port, 1440 vid, true); 1441 if (err) 1442 goto err_erif_eport_to_vid_map_one; 1443 } 1444 1445 if (mlxsw_sp->fid_core->port_fid_mappings[local_port]++ == 0) { 1446 err = mlxsw_sp_port_vp_mode_trans(mlxsw_sp_port); 1447 if (err) 1448 goto err_port_vp_mode_trans; 1449 } 1450 1451 return 0; 1452 1453err_port_vp_mode_trans: 1454 mlxsw_sp->fid_core->port_fid_mappings[local_port]--; 1455 if (fid->rif) 1456 mlxsw_sp_fid_erif_eport_to_vid_map_one(fid, local_port, vid, 1457 false); 1458err_erif_eport_to_vid_map_one: 1459 __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, false); 1460err_port_vid_map: 1461 mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid); 1462 return err; 1463} 1464 1465static void 1466mlxsw_sp_fid_rfid_port_vid_unmap(struct mlxsw_sp_fid *fid, 1467 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid) 1468{ 1469 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 1470 u16 local_port = mlxsw_sp_port->local_port; 1471 1472 if (mlxsw_sp->fid_core->port_fid_mappings[local_port] == 1) 1473 mlxsw_sp_port_vlan_mode_trans(mlxsw_sp_port); 1474 mlxsw_sp->fid_core->port_fid_mappings[local_port]--; 1475 1476 if (fid->rif) 1477 mlxsw_sp_fid_erif_eport_to_vid_map_one(fid, local_port, vid, 1478 false); 1479 __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, false); 1480 mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid); 1481} 1482 1483static int mlxsw_sp_fid_rfid_vni_set(struct mlxsw_sp_fid *fid) 1484{ 1485 return -EOPNOTSUPP; 1486} 1487 1488static void mlxsw_sp_fid_rfid_vni_clear(struct mlxsw_sp_fid *fid) 1489{ 1490 WARN_ON_ONCE(1); 1491} 1492 1493static int mlxsw_sp_fid_rfid_nve_flood_index_set(struct mlxsw_sp_fid *fid) 1494{ 1495 return -EOPNOTSUPP; 1496} 1497 1498static void mlxsw_sp_fid_rfid_nve_flood_index_clear(struct mlxsw_sp_fid *fid) 1499{ 1500 WARN_ON_ONCE(1); 1501} 1502 1503static int 1504mlxsw_sp_fid_rfid_vid_to_fid_rif_update(const struct mlxsw_sp_fid *fid, 1505 const struct mlxsw_sp_rif *rif) 1506{ 1507 return 0; 1508} 1509 1510static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_rfid_ops_ctl = { 1511 .setup = mlxsw_sp_fid_rfid_setup_ctl, 1512 .configure = mlxsw_sp_fid_rfid_configure, 1513 .deconfigure = mlxsw_sp_fid_rfid_deconfigure, 1514 .index_alloc = mlxsw_sp_fid_rfid_index_alloc, 1515 .compare = mlxsw_sp_fid_rfid_compare, 1516 .port_vid_map = mlxsw_sp_fid_rfid_port_vid_map, 1517 .port_vid_unmap = mlxsw_sp_fid_rfid_port_vid_unmap, 1518 .vni_set = mlxsw_sp_fid_rfid_vni_set, 1519 .vni_clear = mlxsw_sp_fid_rfid_vni_clear, 1520 .nve_flood_index_set = mlxsw_sp_fid_rfid_nve_flood_index_set, 1521 .nve_flood_index_clear = mlxsw_sp_fid_rfid_nve_flood_index_clear, 1522 .vid_to_fid_rif_update = mlxsw_sp_fid_rfid_vid_to_fid_rif_update, 1523 .fid_pack = mlxsw_sp_fid_pack_ctl, 1524}; 1525 1526static int 1527mlxsw_sp_fid_rfid_port_add_cff(struct mlxsw_sp *mlxsw_sp, 1528 const struct mlxsw_sp_flood_table *flood_table, 1529 u16 pgt_addr, u16 smpe, unsigned int local_port) 1530{ 1531 int err; 1532 1533 err = mlxsw_sp_pgt_entry_port_set(mlxsw_sp, pgt_addr, smpe, 1534 local_port, true); 1535 if (err) 1536 return err; 1537 1538 if (flood_table->packet_type == MLXSW_SP_FLOOD_TYPE_NOT_UC) { 1539 u16 router_port = mlxsw_sp_router_port(mlxsw_sp); 1540 1541 err = mlxsw_sp_pgt_entry_port_set(mlxsw_sp, pgt_addr, smpe, 1542 router_port, true); 1543 if (err) 1544 goto err_entry_port_set; 1545 } 1546 1547 return 0; 1548 1549err_entry_port_set: 1550 mlxsw_sp_pgt_entry_port_set(mlxsw_sp, pgt_addr, smpe, local_port, 1551 false); 1552 return err; 1553} 1554 1555static void 1556mlxsw_sp_fid_rfid_port_del_cff(struct mlxsw_sp *mlxsw_sp, 1557 const struct mlxsw_sp_flood_table *flood_table, 1558 u16 pgt_addr, u16 smpe, u16 local_port) 1559{ 1560 if (flood_table->packet_type == MLXSW_SP_FLOOD_TYPE_NOT_UC) { 1561 u16 router_port = mlxsw_sp_router_port(mlxsw_sp); 1562 1563 mlxsw_sp_pgt_entry_port_set(mlxsw_sp, pgt_addr, smpe, 1564 router_port, false); 1565 } 1566 mlxsw_sp_pgt_entry_port_set(mlxsw_sp, pgt_addr, smpe, local_port, 1567 false); 1568} 1569 1570static int 1571mlxsw_sp_fid_rfid_port_memb_ft_cff(const struct mlxsw_sp_fid_family *fid_family, 1572 const struct mlxsw_sp_flood_table *flood_table, 1573 const struct mlxsw_sp_port *mlxsw_sp_port, 1574 bool member) 1575{ 1576 struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp; 1577 u16 local_port = mlxsw_sp_port->local_port; 1578 u16 fid_pgt_base; 1579 u16 fid_offset; 1580 u16 pgt_addr; 1581 u16 smpe; 1582 u16 port; 1583 1584 /* In-PGT SMPE is only valid on Spectrum-1, CFF only on Spectrum>1. */ 1585 smpe = 0; 1586 1587 port = mlxsw_sp_port->lagged ? mlxsw_sp_port->lag_id : local_port; 1588 fid_offset = mlxsw_sp_fid_rfid_fid_offset_cff(mlxsw_sp, port, 1589 mlxsw_sp_port->lagged); 1590 fid_pgt_base = mlxsw_sp_fid_off_pgt_base_cff(fid_family, fid_offset); 1591 pgt_addr = fid_pgt_base + flood_table->table_index; 1592 1593 if (member) 1594 return mlxsw_sp_fid_rfid_port_add_cff(mlxsw_sp, flood_table, 1595 pgt_addr, smpe, 1596 local_port); 1597 1598 mlxsw_sp_fid_rfid_port_del_cff(mlxsw_sp, flood_table, pgt_addr, smpe, 1599 local_port); 1600 return 0; 1601} 1602 1603static int 1604mlxsw_sp_fid_rfid_port_memb_cff(const struct mlxsw_sp_fid_family *fid_family, 1605 const struct mlxsw_sp_port *mlxsw_sp_port, 1606 bool member) 1607{ 1608 int i; 1609 1610 for (i = 0; i < fid_family->flood_profile->nr_flood_tables; i++) { 1611 const struct mlxsw_sp_flood_table *flood_table = 1612 &fid_family->flood_profile->flood_tables[i]; 1613 int err; 1614 1615 err = mlxsw_sp_fid_rfid_port_memb_ft_cff(fid_family, 1616 flood_table, 1617 mlxsw_sp_port, member); 1618 if (err) 1619 return err; 1620 } 1621 1622 return 0; 1623} 1624 1625static int 1626mlxsw_sp_fid_rfid_port_init_cff(const struct mlxsw_sp_fid_family *fid_family, 1627 const struct mlxsw_sp_port *mlxsw_sp_port) 1628{ 1629 return mlxsw_sp_fid_rfid_port_memb_cff(fid_family, mlxsw_sp_port, true); 1630} 1631 1632static void 1633mlxsw_sp_fid_rfid_port_fini_cff(const struct mlxsw_sp_fid_family *fid_family, 1634 const struct mlxsw_sp_port *mlxsw_sp_port) 1635{ 1636 mlxsw_sp_fid_rfid_port_memb_cff(fid_family, mlxsw_sp_port, false); 1637} 1638 1639static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_rfid_ops_cff = { 1640 .setup = mlxsw_sp_fid_rfid_setup_cff, 1641 .configure = mlxsw_sp_fid_rfid_configure, 1642 .deconfigure = mlxsw_sp_fid_rfid_deconfigure, 1643 .index_alloc = mlxsw_sp_fid_rfid_index_alloc, 1644 .compare = mlxsw_sp_fid_rfid_compare, 1645 .port_vid_map = mlxsw_sp_fid_rfid_port_vid_map, 1646 .port_vid_unmap = mlxsw_sp_fid_rfid_port_vid_unmap, 1647 .vni_set = mlxsw_sp_fid_rfid_vni_set, 1648 .vni_clear = mlxsw_sp_fid_rfid_vni_clear, 1649 .nve_flood_index_set = mlxsw_sp_fid_rfid_nve_flood_index_set, 1650 .nve_flood_index_clear = mlxsw_sp_fid_rfid_nve_flood_index_clear, 1651 .vid_to_fid_rif_update = mlxsw_sp_fid_rfid_vid_to_fid_rif_update, 1652 .pgt_size = mlxsw_sp_fid_rfid_pgt_size_cff, 1653 .fid_port_init = mlxsw_sp_fid_rfid_port_init_cff, 1654 .fid_port_fini = mlxsw_sp_fid_rfid_port_fini_cff, 1655 .fid_mid = mlxsw_sp_fid_fid_mid_cff, 1656 .fid_pack = mlxsw_sp_fid_fid_pack_cff, 1657}; 1658 1659static int mlxsw_sp_fid_dummy_setup(struct mlxsw_sp_fid *fid, const void *arg) 1660{ 1661 fid->fid_offset = 0; 1662 return 0; 1663} 1664 1665static int mlxsw_sp_fid_dummy_configure(struct mlxsw_sp_fid *fid) 1666{ 1667 return mlxsw_sp_fid_op(fid, true); 1668} 1669 1670static void mlxsw_sp_fid_dummy_deconfigure(struct mlxsw_sp_fid *fid) 1671{ 1672 mlxsw_sp_fid_op(fid, false); 1673} 1674 1675static int mlxsw_sp_fid_dummy_index_alloc(struct mlxsw_sp_fid *fid, 1676 const void *arg, u16 *p_fid_index) 1677{ 1678 *p_fid_index = fid->fid_family->start_index; 1679 1680 return 0; 1681} 1682 1683static bool mlxsw_sp_fid_dummy_compare(const struct mlxsw_sp_fid *fid, 1684 const void *arg) 1685{ 1686 return true; 1687} 1688 1689static int mlxsw_sp_fid_dummy_vni_set(struct mlxsw_sp_fid *fid) 1690{ 1691 return -EOPNOTSUPP; 1692} 1693 1694static void mlxsw_sp_fid_dummy_vni_clear(struct mlxsw_sp_fid *fid) 1695{ 1696 WARN_ON_ONCE(1); 1697} 1698 1699static int mlxsw_sp_fid_dummy_nve_flood_index_set(struct mlxsw_sp_fid *fid) 1700{ 1701 return -EOPNOTSUPP; 1702} 1703 1704static void mlxsw_sp_fid_dummy_nve_flood_index_clear(struct mlxsw_sp_fid *fid) 1705{ 1706 WARN_ON_ONCE(1); 1707} 1708 1709static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_dummy_ops = { 1710 .setup = mlxsw_sp_fid_dummy_setup, 1711 .configure = mlxsw_sp_fid_dummy_configure, 1712 .deconfigure = mlxsw_sp_fid_dummy_deconfigure, 1713 .index_alloc = mlxsw_sp_fid_dummy_index_alloc, 1714 .compare = mlxsw_sp_fid_dummy_compare, 1715 .vni_set = mlxsw_sp_fid_dummy_vni_set, 1716 .vni_clear = mlxsw_sp_fid_dummy_vni_clear, 1717 .nve_flood_index_set = mlxsw_sp_fid_dummy_nve_flood_index_set, 1718 .nve_flood_index_clear = mlxsw_sp_fid_dummy_nve_flood_index_clear, 1719 .fid_pack = mlxsw_sp_fid_pack, 1720}; 1721 1722static int mlxsw_sp_fid_8021q_configure(struct mlxsw_sp_fid *fid) 1723{ 1724 struct mlxsw_sp_fid_8021q *fid_8021q = mlxsw_sp_fid_8021q_fid(fid); 1725 int err; 1726 1727 err = mlxsw_sp_fid_op(fid, true); 1728 if (err) 1729 return err; 1730 1731 err = mlxsw_sp_fid_vid_to_fid_map(fid, fid_8021q->vid, true, fid->rif); 1732 if (err) 1733 goto err_vid_to_fid_map; 1734 1735 return 0; 1736 1737err_vid_to_fid_map: 1738 mlxsw_sp_fid_op(fid, false); 1739 return err; 1740} 1741 1742static void mlxsw_sp_fid_8021q_deconfigure(struct mlxsw_sp_fid *fid) 1743{ 1744 struct mlxsw_sp_fid_8021q *fid_8021q = mlxsw_sp_fid_8021q_fid(fid); 1745 1746 if (fid->vni_valid) 1747 mlxsw_sp_nve_fid_disable(fid->fid_family->mlxsw_sp, fid); 1748 1749 mlxsw_sp_fid_vid_to_fid_map(fid, fid_8021q->vid, false, NULL); 1750 mlxsw_sp_fid_op(fid, false); 1751} 1752 1753static int mlxsw_sp_fid_8021q_port_vid_map(struct mlxsw_sp_fid *fid, 1754 struct mlxsw_sp_port *mlxsw_sp_port, 1755 u16 vid) 1756{ 1757 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 1758 u16 local_port = mlxsw_sp_port->local_port; 1759 int err; 1760 1761 /* In case there are no {Port, VID} => FID mappings on the port, 1762 * we can use the global VID => FID mapping we created when the 1763 * FID was configured, otherwise, configure new mapping. 1764 */ 1765 if (mlxsw_sp->fid_core->port_fid_mappings[local_port]) { 1766 err = __mlxsw_sp_fid_port_vid_map(fid, local_port, vid, true); 1767 if (err) 1768 return err; 1769 } 1770 1771 err = mlxsw_sp_fid_evid_map(fid, local_port, vid, true); 1772 if (err) 1773 goto err_fid_evid_map; 1774 1775 err = mlxsw_sp_fid_port_vid_list_add(fid, mlxsw_sp_port->local_port, 1776 vid); 1777 if (err) 1778 goto err_port_vid_list_add; 1779 1780 return 0; 1781 1782err_port_vid_list_add: 1783 mlxsw_sp_fid_evid_map(fid, local_port, vid, false); 1784err_fid_evid_map: 1785 if (mlxsw_sp->fid_core->port_fid_mappings[local_port]) 1786 __mlxsw_sp_fid_port_vid_map(fid, local_port, vid, false); 1787 return err; 1788} 1789 1790static void 1791mlxsw_sp_fid_8021q_port_vid_unmap(struct mlxsw_sp_fid *fid, 1792 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid) 1793{ 1794 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 1795 u16 local_port = mlxsw_sp_port->local_port; 1796 1797 mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid); 1798 mlxsw_sp_fid_evid_map(fid, local_port, vid, false); 1799 if (mlxsw_sp->fid_core->port_fid_mappings[local_port]) 1800 __mlxsw_sp_fid_port_vid_map(fid, local_port, vid, false); 1801} 1802 1803static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021q_ops_ctl = { 1804 .setup = mlxsw_sp_fid_8021q_setup, 1805 .configure = mlxsw_sp_fid_8021q_configure, 1806 .deconfigure = mlxsw_sp_fid_8021q_deconfigure, 1807 .index_alloc = mlxsw_sp_fid_8021d_index_alloc, 1808 .compare = mlxsw_sp_fid_8021q_compare, 1809 .port_vid_map = mlxsw_sp_fid_8021q_port_vid_map, 1810 .port_vid_unmap = mlxsw_sp_fid_8021q_port_vid_unmap, 1811 .vni_set = mlxsw_sp_fid_8021d_vni_set, 1812 .vni_clear = mlxsw_sp_fid_8021d_vni_clear, 1813 .nve_flood_index_set = mlxsw_sp_fid_8021d_nve_flood_index_set, 1814 .nve_flood_index_clear = mlxsw_sp_fid_8021d_nve_flood_index_clear, 1815 .fdb_clear_offload = mlxsw_sp_fid_8021q_fdb_clear_offload, 1816 .vid_to_fid_rif_update = mlxsw_sp_fid_8021q_vid_to_fid_rif_update, 1817 .flood_table_init = mlxsw_sp_fid_flood_table_init_ctl, 1818 .pgt_size = mlxsw_sp_fid_8021d_pgt_size, 1819 .fid_mid = mlxsw_sp_fid_fid_mid_ctl, 1820 .fid_pack = mlxsw_sp_fid_pack_ctl, 1821}; 1822 1823static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021q_ops_cff = { 1824 .setup = mlxsw_sp_fid_8021q_setup, 1825 .configure = mlxsw_sp_fid_8021q_configure, 1826 .deconfigure = mlxsw_sp_fid_8021q_deconfigure, 1827 .index_alloc = mlxsw_sp_fid_8021d_index_alloc, 1828 .compare = mlxsw_sp_fid_8021q_compare, 1829 .port_vid_map = mlxsw_sp_fid_8021q_port_vid_map, 1830 .port_vid_unmap = mlxsw_sp_fid_8021q_port_vid_unmap, 1831 .vni_set = mlxsw_sp_fid_8021d_vni_set, 1832 .vni_clear = mlxsw_sp_fid_8021d_vni_clear, 1833 .nve_flood_index_set = mlxsw_sp_fid_8021d_nve_flood_index_set, 1834 .nve_flood_index_clear = mlxsw_sp_fid_8021d_nve_flood_index_clear, 1835 .fdb_clear_offload = mlxsw_sp_fid_8021q_fdb_clear_offload, 1836 .vid_to_fid_rif_update = mlxsw_sp_fid_8021q_vid_to_fid_rif_update, 1837 .pgt_size = mlxsw_sp_fid_8021d_pgt_size, 1838 .fid_mid = mlxsw_sp_fid_fid_mid_cff, 1839 .fid_pack = mlxsw_sp_fid_fid_pack_cff, 1840}; 1841 1842/* There are 4K-2 802.1Q FIDs */ 1843#define MLXSW_SP_FID_8021Q_START 1 /* FID 0 is reserved. */ 1844#define MLXSW_SP_FID_8021Q_END (MLXSW_SP_FID_8021Q_START + \ 1845 MLXSW_SP_FID_8021Q_MAX - 1) 1846 1847/* There are 1K 802.1D FIDs */ 1848#define MLXSW_SP_FID_8021D_START (MLXSW_SP_FID_8021Q_END + 1) 1849#define MLXSW_SP_FID_8021D_END (MLXSW_SP_FID_8021D_START + \ 1850 MLXSW_SP_FID_8021D_MAX - 1) 1851 1852/* There is one dummy FID */ 1853#define MLXSW_SP_FID_DUMMY (MLXSW_SP_FID_8021D_END + 1) 1854 1855/* There are 11K rFIDs */ 1856#define MLXSW_SP_RFID_START (MLXSW_SP_FID_DUMMY + 1) 1857#define MLXSW_SP_RFID_END (MLXSW_SP_RFID_START + \ 1858 MLXSW_SP_FID_RFID_MAX - 1) 1859 1860static const struct mlxsw_sp_fid_family mlxsw_sp1_fid_8021q_family = { 1861 .type = MLXSW_SP_FID_TYPE_8021Q, 1862 .fid_size = sizeof(struct mlxsw_sp_fid_8021q), 1863 .start_index = MLXSW_SP_FID_8021Q_START, 1864 .end_index = MLXSW_SP_FID_8021Q_END, 1865 .flood_profile = &mlxsw_sp_fid_8021d_flood_profile, 1866 .rif_type = MLXSW_SP_RIF_TYPE_VLAN, 1867 .ops = &mlxsw_sp_fid_8021q_ops_ctl, 1868 .flood_rsp = false, 1869 .bridge_type = MLXSW_REG_BRIDGE_TYPE_0, 1870 .smpe_index_valid = false, 1871}; 1872 1873static const struct mlxsw_sp_fid_family mlxsw_sp1_fid_8021d_family = { 1874 .type = MLXSW_SP_FID_TYPE_8021D, 1875 .fid_size = sizeof(struct mlxsw_sp_fid_8021d), 1876 .start_index = MLXSW_SP_FID_8021D_START, 1877 .end_index = MLXSW_SP_FID_8021D_END, 1878 .flood_profile = &mlxsw_sp_fid_8021d_flood_profile, 1879 .rif_type = MLXSW_SP_RIF_TYPE_FID, 1880 .ops = &mlxsw_sp_fid_8021d_ops_ctl, 1881 .bridge_type = MLXSW_REG_BRIDGE_TYPE_1, 1882 .smpe_index_valid = false, 1883}; 1884 1885static const struct mlxsw_sp_fid_family mlxsw_sp1_fid_dummy_family = { 1886 .type = MLXSW_SP_FID_TYPE_DUMMY, 1887 .fid_size = sizeof(struct mlxsw_sp_fid), 1888 .start_index = MLXSW_SP_FID_DUMMY, 1889 .end_index = MLXSW_SP_FID_DUMMY, 1890 .ops = &mlxsw_sp_fid_dummy_ops, 1891 .smpe_index_valid = false, 1892}; 1893 1894static const struct mlxsw_sp_fid_family mlxsw_sp_fid_rfid_family_ctl = { 1895 .type = MLXSW_SP_FID_TYPE_RFID, 1896 .fid_size = sizeof(struct mlxsw_sp_fid), 1897 .start_index = MLXSW_SP_RFID_START, 1898 .end_index = MLXSW_SP_RFID_END, 1899 .rif_type = MLXSW_SP_RIF_TYPE_SUBPORT, 1900 .ops = &mlxsw_sp_fid_rfid_ops_ctl, 1901 .flood_rsp = true, 1902 .smpe_index_valid = false, 1903}; 1904 1905static const struct mlxsw_sp_fid_family *mlxsw_sp1_fid_family_arr[] = { 1906 [MLXSW_SP_FID_TYPE_8021Q] = &mlxsw_sp1_fid_8021q_family, 1907 [MLXSW_SP_FID_TYPE_8021D] = &mlxsw_sp1_fid_8021d_family, 1908 [MLXSW_SP_FID_TYPE_DUMMY] = &mlxsw_sp1_fid_dummy_family, 1909 [MLXSW_SP_FID_TYPE_RFID] = &mlxsw_sp_fid_rfid_family_ctl, 1910}; 1911 1912static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_8021q_family_ctl = { 1913 .type = MLXSW_SP_FID_TYPE_8021Q, 1914 .fid_size = sizeof(struct mlxsw_sp_fid_8021q), 1915 .start_index = MLXSW_SP_FID_8021Q_START, 1916 .end_index = MLXSW_SP_FID_8021Q_END, 1917 .flood_profile = &mlxsw_sp_fid_8021d_flood_profile, 1918 .rif_type = MLXSW_SP_RIF_TYPE_VLAN, 1919 .ops = &mlxsw_sp_fid_8021q_ops_ctl, 1920 .flood_rsp = false, 1921 .bridge_type = MLXSW_REG_BRIDGE_TYPE_0, 1922 .smpe_index_valid = true, 1923}; 1924 1925static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_8021d_family_ctl = { 1926 .type = MLXSW_SP_FID_TYPE_8021D, 1927 .fid_size = sizeof(struct mlxsw_sp_fid_8021d), 1928 .start_index = MLXSW_SP_FID_8021D_START, 1929 .end_index = MLXSW_SP_FID_8021D_END, 1930 .flood_profile = &mlxsw_sp_fid_8021d_flood_profile, 1931 .rif_type = MLXSW_SP_RIF_TYPE_FID, 1932 .ops = &mlxsw_sp_fid_8021d_ops_ctl, 1933 .bridge_type = MLXSW_REG_BRIDGE_TYPE_1, 1934 .smpe_index_valid = true, 1935}; 1936 1937static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_dummy_family = { 1938 .type = MLXSW_SP_FID_TYPE_DUMMY, 1939 .fid_size = sizeof(struct mlxsw_sp_fid), 1940 .start_index = MLXSW_SP_FID_DUMMY, 1941 .end_index = MLXSW_SP_FID_DUMMY, 1942 .ops = &mlxsw_sp_fid_dummy_ops, 1943 .smpe_index_valid = false, 1944}; 1945 1946static const struct mlxsw_sp_fid_family *mlxsw_sp2_fid_family_arr_ctl[] = { 1947 [MLXSW_SP_FID_TYPE_8021Q] = &mlxsw_sp2_fid_8021q_family_ctl, 1948 [MLXSW_SP_FID_TYPE_8021D] = &mlxsw_sp2_fid_8021d_family_ctl, 1949 [MLXSW_SP_FID_TYPE_DUMMY] = &mlxsw_sp2_fid_dummy_family, 1950 [MLXSW_SP_FID_TYPE_RFID] = &mlxsw_sp_fid_rfid_family_ctl, 1951}; 1952 1953static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_8021q_family_cff = { 1954 .type = MLXSW_SP_FID_TYPE_8021Q, 1955 .fid_size = sizeof(struct mlxsw_sp_fid_8021q), 1956 .start_index = MLXSW_SP_FID_8021Q_START, 1957 .end_index = MLXSW_SP_FID_8021Q_END, 1958 .flood_profile = &mlxsw_sp_fid_8021d_flood_profile, 1959 .rif_type = MLXSW_SP_RIF_TYPE_VLAN, 1960 .ops = &mlxsw_sp_fid_8021q_ops_cff, 1961 .smpe_index_valid = true, 1962}; 1963 1964static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_8021d_family_cff = { 1965 .type = MLXSW_SP_FID_TYPE_8021D, 1966 .fid_size = sizeof(struct mlxsw_sp_fid_8021d), 1967 .start_index = MLXSW_SP_FID_8021D_START, 1968 .end_index = MLXSW_SP_FID_8021D_END, 1969 .flood_profile = &mlxsw_sp_fid_8021d_flood_profile, 1970 .rif_type = MLXSW_SP_RIF_TYPE_FID, 1971 .ops = &mlxsw_sp_fid_8021d_ops_cff, 1972 .smpe_index_valid = true, 1973}; 1974 1975static const struct mlxsw_sp_fid_family mlxsw_sp_fid_rfid_family_cff = { 1976 .type = MLXSW_SP_FID_TYPE_RFID, 1977 .fid_size = sizeof(struct mlxsw_sp_fid), 1978 .start_index = MLXSW_SP_RFID_START, 1979 .end_index = MLXSW_SP_RFID_END, 1980 .flood_profile = &mlxsw_sp_fid_rsp_flood_profile_cff, 1981 .rif_type = MLXSW_SP_RIF_TYPE_SUBPORT, 1982 .ops = &mlxsw_sp_fid_rfid_ops_cff, 1983 .smpe_index_valid = false, 1984}; 1985 1986static const struct mlxsw_sp_fid_family *mlxsw_sp2_fid_family_arr_cff[] = { 1987 [MLXSW_SP_FID_TYPE_8021Q] = &mlxsw_sp2_fid_8021q_family_cff, 1988 [MLXSW_SP_FID_TYPE_8021D] = &mlxsw_sp2_fid_8021d_family_cff, 1989 [MLXSW_SP_FID_TYPE_DUMMY] = &mlxsw_sp2_fid_dummy_family, 1990 [MLXSW_SP_FID_TYPE_RFID] = &mlxsw_sp_fid_rfid_family_cff, 1991}; 1992 1993static struct mlxsw_sp_fid *mlxsw_sp_fid_lookup(struct mlxsw_sp *mlxsw_sp, 1994 enum mlxsw_sp_fid_type type, 1995 const void *arg) 1996{ 1997 struct mlxsw_sp_fid_family *fid_family; 1998 struct mlxsw_sp_fid *fid; 1999 2000 fid_family = mlxsw_sp->fid_core->fid_family_arr[type]; 2001 list_for_each_entry(fid, &fid_family->fids_list, list) { 2002 if (!fid->fid_family->ops->compare(fid, arg)) 2003 continue; 2004 refcount_inc(&fid->ref_count); 2005 return fid; 2006 } 2007 2008 return NULL; 2009} 2010 2011static struct mlxsw_sp_fid *mlxsw_sp_fid_get(struct mlxsw_sp *mlxsw_sp, 2012 enum mlxsw_sp_fid_type type, 2013 const void *arg) 2014{ 2015 struct mlxsw_sp_fid_family *fid_family; 2016 struct mlxsw_sp_fid *fid; 2017 u16 fid_index; 2018 int err; 2019 2020 fid = mlxsw_sp_fid_lookup(mlxsw_sp, type, arg); 2021 if (fid) 2022 return fid; 2023 2024 fid_family = mlxsw_sp->fid_core->fid_family_arr[type]; 2025 fid = kzalloc(fid_family->fid_size, GFP_KERNEL); 2026 if (!fid) 2027 return ERR_PTR(-ENOMEM); 2028 2029 INIT_LIST_HEAD(&fid->port_vid_list); 2030 fid->fid_family = fid_family; 2031 2032 err = fid->fid_family->ops->index_alloc(fid, arg, &fid_index); 2033 if (err) 2034 goto err_index_alloc; 2035 fid->fid_index = fid_index; 2036 __set_bit(fid_index - fid_family->start_index, fid_family->fids_bitmap); 2037 2038 err = fid->fid_family->ops->setup(fid, arg); 2039 if (err) 2040 goto err_setup; 2041 2042 err = fid->fid_family->ops->configure(fid); 2043 if (err) 2044 goto err_configure; 2045 2046 err = rhashtable_insert_fast(&mlxsw_sp->fid_core->fid_ht, &fid->ht_node, 2047 mlxsw_sp_fid_ht_params); 2048 if (err) 2049 goto err_rhashtable_insert; 2050 2051 list_add(&fid->list, &fid_family->fids_list); 2052 refcount_set(&fid->ref_count, 1); 2053 return fid; 2054 2055err_rhashtable_insert: 2056 fid->fid_family->ops->deconfigure(fid); 2057err_configure: 2058err_setup: 2059 __clear_bit(fid_index - fid_family->start_index, 2060 fid_family->fids_bitmap); 2061err_index_alloc: 2062 kfree(fid); 2063 return ERR_PTR(err); 2064} 2065 2066void mlxsw_sp_fid_put(struct mlxsw_sp_fid *fid) 2067{ 2068 struct mlxsw_sp_fid_family *fid_family = fid->fid_family; 2069 struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp; 2070 2071 if (!refcount_dec_and_test(&fid->ref_count)) 2072 return; 2073 2074 list_del(&fid->list); 2075 rhashtable_remove_fast(&mlxsw_sp->fid_core->fid_ht, 2076 &fid->ht_node, mlxsw_sp_fid_ht_params); 2077 fid->fid_family->ops->deconfigure(fid); 2078 __clear_bit(fid->fid_index - fid_family->start_index, 2079 fid_family->fids_bitmap); 2080 WARN_ON_ONCE(!list_empty(&fid->port_vid_list)); 2081 kfree(fid); 2082} 2083 2084struct mlxsw_sp_fid *mlxsw_sp_fid_8021q_get(struct mlxsw_sp *mlxsw_sp, u16 vid) 2085{ 2086 return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_8021Q, &vid); 2087} 2088 2089struct mlxsw_sp_fid *mlxsw_sp_fid_8021d_get(struct mlxsw_sp *mlxsw_sp, 2090 int br_ifindex) 2091{ 2092 return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_8021D, &br_ifindex); 2093} 2094 2095struct mlxsw_sp_fid *mlxsw_sp_fid_8021q_lookup(struct mlxsw_sp *mlxsw_sp, 2096 u16 vid) 2097{ 2098 return mlxsw_sp_fid_lookup(mlxsw_sp, MLXSW_SP_FID_TYPE_8021Q, &vid); 2099} 2100 2101struct mlxsw_sp_fid *mlxsw_sp_fid_8021d_lookup(struct mlxsw_sp *mlxsw_sp, 2102 int br_ifindex) 2103{ 2104 return mlxsw_sp_fid_lookup(mlxsw_sp, MLXSW_SP_FID_TYPE_8021D, 2105 &br_ifindex); 2106} 2107 2108struct mlxsw_sp_fid *mlxsw_sp_fid_rfid_get(struct mlxsw_sp *mlxsw_sp, 2109 u16 rif_index) 2110{ 2111 return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_RFID, &rif_index); 2112} 2113 2114struct mlxsw_sp_fid *mlxsw_sp_fid_dummy_get(struct mlxsw_sp *mlxsw_sp) 2115{ 2116 return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_DUMMY, NULL); 2117} 2118 2119static int 2120mlxsw_sp_fid_flood_tables_init(struct mlxsw_sp_fid_family *fid_family) 2121{ 2122 struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp; 2123 u16 pgt_size; 2124 int err; 2125 int i; 2126 2127 err = fid_family->ops->pgt_size(fid_family, &pgt_size); 2128 if (err) 2129 return err; 2130 2131 err = mlxsw_sp_pgt_mid_alloc_range(mlxsw_sp, &fid_family->pgt_base, 2132 pgt_size); 2133 if (err) 2134 return err; 2135 2136 if (!fid_family->flood_profile) 2137 return 0; 2138 2139 for (i = 0; i < fid_family->flood_profile->nr_flood_tables; i++) { 2140 const struct mlxsw_sp_flood_table *flood_table; 2141 2142 flood_table = &fid_family->flood_profile->flood_tables[i]; 2143 if (fid_family->ops->flood_table_init) { 2144 err = fid_family->ops->flood_table_init(fid_family, 2145 flood_table); 2146 if (err) 2147 goto err_flood_table_init; 2148 } 2149 } 2150 2151 return 0; 2152 2153err_flood_table_init: 2154 mlxsw_sp_pgt_mid_free_range(mlxsw_sp, fid_family->pgt_base, pgt_size); 2155 return err; 2156} 2157 2158static void 2159mlxsw_sp_fid_flood_tables_fini(struct mlxsw_sp_fid_family *fid_family) 2160{ 2161 struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp; 2162 u16 pgt_size; 2163 int err; 2164 2165 err = fid_family->ops->pgt_size(fid_family, &pgt_size); 2166 if (WARN_ON_ONCE(err)) 2167 return; 2168 2169 mlxsw_sp_pgt_mid_free_range(mlxsw_sp, fid_family->pgt_base, pgt_size); 2170} 2171 2172static int mlxsw_sp_fid_family_register(struct mlxsw_sp *mlxsw_sp, 2173 const struct mlxsw_sp_fid_family *tmpl) 2174{ 2175 u16 nr_fids = tmpl->end_index - tmpl->start_index + 1; 2176 struct mlxsw_sp_fid_family *fid_family; 2177 int err; 2178 2179 fid_family = kmemdup(tmpl, sizeof(*fid_family), GFP_KERNEL); 2180 if (!fid_family) 2181 return -ENOMEM; 2182 2183 fid_family->mlxsw_sp = mlxsw_sp; 2184 INIT_LIST_HEAD(&fid_family->fids_list); 2185 fid_family->fids_bitmap = bitmap_zalloc(nr_fids, GFP_KERNEL); 2186 if (!fid_family->fids_bitmap) { 2187 err = -ENOMEM; 2188 goto err_alloc_fids_bitmap; 2189 } 2190 2191 if (fid_family->flood_profile) { 2192 err = mlxsw_sp_fid_flood_tables_init(fid_family); 2193 if (err) 2194 goto err_fid_flood_tables_init; 2195 } 2196 2197 mlxsw_sp->fid_core->fid_family_arr[tmpl->type] = fid_family; 2198 2199 return 0; 2200 2201err_fid_flood_tables_init: 2202 bitmap_free(fid_family->fids_bitmap); 2203err_alloc_fids_bitmap: 2204 kfree(fid_family); 2205 return err; 2206} 2207 2208static void 2209mlxsw_sp_fid_family_unregister(struct mlxsw_sp *mlxsw_sp, 2210 struct mlxsw_sp_fid_family *fid_family) 2211{ 2212 mlxsw_sp->fid_core->fid_family_arr[fid_family->type] = NULL; 2213 2214 if (fid_family->flood_profile) 2215 mlxsw_sp_fid_flood_tables_fini(fid_family); 2216 2217 bitmap_free(fid_family->fids_bitmap); 2218 WARN_ON_ONCE(!list_empty(&fid_family->fids_list)); 2219 kfree(fid_family); 2220} 2221 2222static int mlxsw_sp_fid_port_init(const struct mlxsw_sp_port *mlxsw_sp_port) 2223{ 2224 const enum mlxsw_sp_fid_type type_rfid = MLXSW_SP_FID_TYPE_RFID; 2225 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 2226 struct mlxsw_sp_fid_family *rfid_family; 2227 2228 rfid_family = mlxsw_sp->fid_core->fid_family_arr[type_rfid]; 2229 if (rfid_family->ops->fid_port_init) 2230 return rfid_family->ops->fid_port_init(rfid_family, 2231 mlxsw_sp_port); 2232 return 0; 2233} 2234 2235static void mlxsw_sp_fid_port_fini(const struct mlxsw_sp_port *mlxsw_sp_port) 2236{ 2237 const enum mlxsw_sp_fid_type type_rfid = MLXSW_SP_FID_TYPE_RFID; 2238 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 2239 struct mlxsw_sp_fid_family *rfid_family; 2240 2241 rfid_family = mlxsw_sp->fid_core->fid_family_arr[type_rfid]; 2242 if (rfid_family->ops->fid_port_fini) 2243 rfid_family->ops->fid_port_fini(rfid_family, mlxsw_sp_port); 2244} 2245 2246int mlxsw_sp_port_fids_init(struct mlxsw_sp_port *mlxsw_sp_port) 2247{ 2248 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 2249 int err; 2250 2251 /* Track number of FIDs configured on the port with mapping type 2252 * PORT_VID_TO_FID, so that we know when to transition the port 2253 * back to non-virtual (VLAN) mode. 2254 */ 2255 mlxsw_sp->fid_core->port_fid_mappings[mlxsw_sp_port->local_port] = 0; 2256 2257 err = mlxsw_sp_fid_port_init(mlxsw_sp_port); 2258 if (err) 2259 return err; 2260 2261 err = mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, false); 2262 if (err) 2263 goto err_vp_mode_set; 2264 2265 return 0; 2266 2267err_vp_mode_set: 2268 mlxsw_sp_fid_port_fini(mlxsw_sp_port); 2269 return err; 2270} 2271 2272void mlxsw_sp_port_fids_fini(struct mlxsw_sp_port *mlxsw_sp_port) 2273{ 2274 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 2275 2276 mlxsw_sp_fid_port_fini(mlxsw_sp_port); 2277 mlxsw_sp->fid_core->port_fid_mappings[mlxsw_sp_port->local_port] = 0; 2278} 2279 2280int mlxsw_sp_fid_port_join_lag(const struct mlxsw_sp_port *mlxsw_sp_port) 2281{ 2282 return mlxsw_sp_fid_port_init(mlxsw_sp_port); 2283} 2284 2285void mlxsw_sp_fid_port_leave_lag(const struct mlxsw_sp_port *mlxsw_sp_port) 2286{ 2287 mlxsw_sp_fid_port_fini(mlxsw_sp_port); 2288} 2289 2290static int 2291mlxsw_sp_fids_init(struct mlxsw_sp *mlxsw_sp, 2292 const struct mlxsw_sp_fid_family *fid_family_arr[]) 2293{ 2294 unsigned int max_ports = mlxsw_core_max_ports(mlxsw_sp->core); 2295 struct mlxsw_sp_fid_core *fid_core; 2296 int err, i; 2297 2298 fid_core = kzalloc(sizeof(*mlxsw_sp->fid_core), GFP_KERNEL); 2299 if (!fid_core) 2300 return -ENOMEM; 2301 mlxsw_sp->fid_core = fid_core; 2302 2303 err = rhashtable_init(&fid_core->fid_ht, &mlxsw_sp_fid_ht_params); 2304 if (err) 2305 goto err_rhashtable_fid_init; 2306 2307 err = rhashtable_init(&fid_core->vni_ht, &mlxsw_sp_fid_vni_ht_params); 2308 if (err) 2309 goto err_rhashtable_vni_init; 2310 2311 fid_core->port_fid_mappings = kcalloc(max_ports, sizeof(unsigned int), 2312 GFP_KERNEL); 2313 if (!fid_core->port_fid_mappings) { 2314 err = -ENOMEM; 2315 goto err_alloc_port_fid_mappings; 2316 } 2317 2318 for (i = 0; i < MLXSW_SP_FID_TYPE_MAX; i++) { 2319 err = mlxsw_sp_fid_family_register(mlxsw_sp, fid_family_arr[i]); 2320 2321 if (err) 2322 goto err_fid_ops_register; 2323 } 2324 2325 return 0; 2326 2327err_fid_ops_register: 2328 for (i--; i >= 0; i--) { 2329 struct mlxsw_sp_fid_family *fid_family; 2330 2331 fid_family = fid_core->fid_family_arr[i]; 2332 mlxsw_sp_fid_family_unregister(mlxsw_sp, fid_family); 2333 } 2334 kfree(fid_core->port_fid_mappings); 2335err_alloc_port_fid_mappings: 2336 rhashtable_destroy(&fid_core->vni_ht); 2337err_rhashtable_vni_init: 2338 rhashtable_destroy(&fid_core->fid_ht); 2339err_rhashtable_fid_init: 2340 kfree(fid_core); 2341 return err; 2342} 2343 2344static void mlxsw_sp_fids_fini(struct mlxsw_sp *mlxsw_sp) 2345{ 2346 struct mlxsw_sp_fid_core *fid_core = mlxsw_sp->fid_core; 2347 int i; 2348 2349 for (i = 0; i < MLXSW_SP_FID_TYPE_MAX; i++) 2350 mlxsw_sp_fid_family_unregister(mlxsw_sp, 2351 fid_core->fid_family_arr[i]); 2352 kfree(fid_core->port_fid_mappings); 2353 rhashtable_destroy(&fid_core->vni_ht); 2354 rhashtable_destroy(&fid_core->fid_ht); 2355 kfree(fid_core); 2356} 2357 2358static int mlxsw_sp1_fids_init(struct mlxsw_sp *mlxsw_sp) 2359{ 2360 return mlxsw_sp_fids_init(mlxsw_sp, mlxsw_sp1_fid_family_arr); 2361} 2362 2363const struct mlxsw_sp_fid_core_ops mlxsw_sp1_fid_core_ops = { 2364 .init = mlxsw_sp1_fids_init, 2365 .fini = mlxsw_sp_fids_fini, 2366}; 2367 2368static int mlxsw_sp_fid_check_flood_profile_id(struct mlxsw_sp *mlxsw_sp, 2369 int profile_id) 2370{ 2371 u32 max_profiles; 2372 2373 if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_NVE_FLOOD_PRF)) 2374 return -EIO; 2375 2376 max_profiles = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_NVE_FLOOD_PRF); 2377 if (WARN_ON_ONCE(!profile_id) || 2378 WARN_ON_ONCE(profile_id >= max_profiles)) 2379 return -EINVAL; 2380 2381 return 0; 2382} 2383 2384static int 2385mlxsw_sp2_fids_init_flood_table(struct mlxsw_sp *mlxsw_sp, 2386 enum mlxsw_sp_fid_flood_profile_id profile_id, 2387 const struct mlxsw_sp_flood_table *flood_table) 2388{ 2389 enum mlxsw_sp_flood_type packet_type = flood_table->packet_type; 2390 const int *sfgc_packet_types; 2391 int err; 2392 int i; 2393 2394 sfgc_packet_types = mlxsw_sp_packet_type_sfgc_types[packet_type]; 2395 for (i = 0; i < MLXSW_REG_SFGC_TYPE_MAX; i++) { 2396 char sffp_pl[MLXSW_REG_SFFP_LEN]; 2397 2398 if (!sfgc_packet_types[i]) 2399 continue; 2400 2401 mlxsw_reg_sffp_pack(sffp_pl, profile_id, i, 2402 flood_table->table_index); 2403 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sffp), sffp_pl); 2404 if (err) 2405 return err; 2406 } 2407 2408 return 0; 2409} 2410 2411static int 2412mlxsw_sp2_fids_init_flood_profile(struct mlxsw_sp *mlxsw_sp, 2413 const struct mlxsw_sp_fid_flood_profile * 2414 flood_profile) 2415{ 2416 int err; 2417 int i; 2418 2419 err = mlxsw_sp_fid_check_flood_profile_id(mlxsw_sp, 2420 flood_profile->profile_id); 2421 if (err) 2422 return err; 2423 2424 for (i = 0; i < flood_profile->nr_flood_tables; i++) { 2425 const struct mlxsw_sp_flood_table *flood_table; 2426 2427 flood_table = &flood_profile->flood_tables[i]; 2428 err = mlxsw_sp2_fids_init_flood_table(mlxsw_sp, 2429 flood_profile->profile_id, 2430 flood_table); 2431 if (err) 2432 return err; 2433 } 2434 2435 return 0; 2436} 2437 2438static const 2439struct mlxsw_sp_fid_flood_profile *mlxsw_sp_fid_flood_profiles[] = { 2440 &mlxsw_sp_fid_8021d_flood_profile, 2441 &mlxsw_sp_fid_rsp_flood_profile_cff, 2442 &mlxsw_sp_fid_nve_flood_profile_cff, 2443}; 2444 2445static int 2446mlxsw_sp2_fids_init_flood_profiles(struct mlxsw_sp *mlxsw_sp) 2447{ 2448 int err; 2449 int i; 2450 2451 for (i = 0; i < ARRAY_SIZE(mlxsw_sp_fid_flood_profiles); i++) { 2452 const struct mlxsw_sp_fid_flood_profile *flood_profile; 2453 2454 flood_profile = mlxsw_sp_fid_flood_profiles[i]; 2455 err = mlxsw_sp2_fids_init_flood_profile(mlxsw_sp, 2456 flood_profile); 2457 if (err) 2458 return err; 2459 } 2460 2461 return 0; 2462} 2463 2464static int mlxsw_sp2_fids_init_ctl(struct mlxsw_sp *mlxsw_sp) 2465{ 2466 return mlxsw_sp_fids_init(mlxsw_sp, mlxsw_sp2_fid_family_arr_ctl); 2467} 2468 2469static int mlxsw_sp2_fids_init_cff(struct mlxsw_sp *mlxsw_sp) 2470{ 2471 int err; 2472 2473 err = mlxsw_sp2_fids_init_flood_profiles(mlxsw_sp); 2474 if (err) 2475 return err; 2476 2477 return mlxsw_sp_fids_init(mlxsw_sp, mlxsw_sp2_fid_family_arr_cff); 2478} 2479 2480static int mlxsw_sp2_fids_init(struct mlxsw_sp *mlxsw_sp) 2481{ 2482 switch (mlxsw_core_flood_mode(mlxsw_sp->core)) { 2483 case MLXSW_CMD_MBOX_CONFIG_PROFILE_FLOOD_MODE_CONTROLLED: 2484 return mlxsw_sp2_fids_init_ctl(mlxsw_sp); 2485 case MLXSW_CMD_MBOX_CONFIG_PROFILE_FLOOD_MODE_CFF: 2486 return mlxsw_sp2_fids_init_cff(mlxsw_sp); 2487 default: 2488 WARN_ON_ONCE(1); 2489 return -EINVAL; 2490 } 2491} 2492 2493const struct mlxsw_sp_fid_core_ops mlxsw_sp2_fid_core_ops = { 2494 .init = mlxsw_sp2_fids_init, 2495 .fini = mlxsw_sp_fids_fini, 2496};
~/
Read-only file preview.