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 17 struct mlxsw_sp_fid_family; 18 19 struct mlxsw_sp_fid_core { 20 struct rhashtable fid_ht; 21 struct rhashtable vni_ht; 22 struct mlxsw_sp_fid_family *fid_family_arr[MLXSW_SP_FID_TYPE_MAX]; 23 unsigned int *port_fid_mappings; 24 }; 25 26 struct mlxsw_sp_fid_port_vid { 27 struct list_head list; 28 u16 local_port; 29 u16 vid; 30 }; 31 32 struct 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 51 struct mlxsw_sp_fid_8021q { 52 struct mlxsw_sp_fid common; 53 u16 vid; 54 }; 55 56 struct mlxsw_sp_fid_8021d { 57 struct mlxsw_sp_fid common; 58 int br_ifindex; 59 }; 60 61 static const struct rhashtable_params mlxsw_sp_fid_ht_params = { 62 .key_len = sizeof_field(struct mlxsw_sp_fid, fid_index), 63 .key_offset = offsetof(struct mlxsw_sp_fid, fid_index), 64 .head_offset = offsetof(struct mlxsw_sp_fid, ht_node), 65 }; 66 67 static const struct rhashtable_params mlxsw_sp_fid_vni_ht_params = { 68 .key_len = sizeof_field(struct mlxsw_sp_fid, vni), 69 .key_offset = offsetof(struct mlxsw_sp_fid, vni), 70 .head_offset = offsetof(struct mlxsw_sp_fid, vni_ht_node), 71 }; 72 73 struct mlxsw_sp_flood_table { 74 enum mlxsw_sp_flood_type packet_type; 75 enum mlxsw_flood_table_type table_type; /* For flood_mode!=CFF. */ 76 int table_index; 77 }; 78 79 struct mlxsw_sp_fid_ops { 80 int (*setup)(struct mlxsw_sp_fid *fid, const void *arg); 81 int (*configure)(struct mlxsw_sp_fid *fid); 82 void (*deconfigure)(struct mlxsw_sp_fid *fid); 83 int (*index_alloc)(struct mlxsw_sp_fid *fid, const void *arg, 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 117 enum mlxsw_sp_fid_flood_profile_id { 118 MLXSW_SP_FID_FLOOD_PROFILE_ID_BRIDGE = 1, 119 MLXSW_SP_FID_FLOOD_PROFILE_ID_RSP, 120 MLXSW_SP_FID_FLOOD_PROFILE_ID_NVE, 121 }; 122 123 struct 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 129 struct 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 146 static const int mlxsw_sp_sfgc_uc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = { 147 [MLXSW_REG_SFGC_TYPE_UNKNOWN_UNICAST] = 1, 148 }; 149 150 static const int mlxsw_sp_sfgc_bc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = { 151 [MLXSW_REG_SFGC_TYPE_BROADCAST] = 1, 152 [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_NON_IP] = 1, 153 [MLXSW_REG_SFGC_TYPE_IPV4_LINK_LOCAL] = 1, 154 [MLXSW_REG_SFGC_TYPE_IPV6_ALL_HOST] = 1, 155 [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV6] = 1, 156 }; 157 158 static const int mlxsw_sp_sfgc_mc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = { 159 [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV4] = 1, 160 }; 161 162 static const int mlxsw_sp_sfgc_not_uc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = { 163 [MLXSW_REG_SFGC_TYPE_BROADCAST] = 1, 164 [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_NON_IP] = 1, 165 [MLXSW_REG_SFGC_TYPE_IPV4_LINK_LOCAL] = 1, 166 [MLXSW_REG_SFGC_TYPE_IPV6_ALL_HOST] = 1, 167 [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV6] = 1, 168 [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV4] = 1, 169 }; 170 171 static const int mlxsw_sp_sfgc_any_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = { 172 [MLXSW_REG_SFGC_TYPE_UNKNOWN_UNICAST] = 1, 173 [MLXSW_REG_SFGC_TYPE_BROADCAST] = 1, 174 [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_NON_IP] = 1, 175 [MLXSW_REG_SFGC_TYPE_IPV4_LINK_LOCAL] = 1, 176 [MLXSW_REG_SFGC_TYPE_IPV6_ALL_HOST] = 1, 177 [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV6] = 1, 178 [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV4] = 1, 179 }; 180 181 static const int *mlxsw_sp_packet_type_sfgc_types[] = { 182 [MLXSW_SP_FLOOD_TYPE_UC] = mlxsw_sp_sfgc_uc_packet_types, 183 [MLXSW_SP_FLOOD_TYPE_BC] = mlxsw_sp_sfgc_bc_packet_types, 184 [MLXSW_SP_FLOOD_TYPE_MC] = mlxsw_sp_sfgc_mc_packet_types, 185 [MLXSW_SP_FLOOD_TYPE_NOT_UC] = mlxsw_sp_sfgc_not_uc_packet_types, 186 [MLXSW_SP_FLOOD_TYPE_ANY] = mlxsw_sp_sfgc_any_packet_types, 187 }; 188 189 struct 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 202 int 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 212 int 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 223 struct 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 236 int 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 246 int 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 264 err_nve_flood_index_set: 265 fid->nve_flood_index_valid = false; 266 return err; 267 } 268 269 void 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 281 bool mlxsw_sp_fid_nve_flood_index_is_set(const struct mlxsw_sp_fid *fid) 282 { 283 return fid->nve_flood_index_valid; 284 } 285 286 int 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 313 err_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 320 void 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 335 bool mlxsw_sp_fid_vni_is_set(const struct mlxsw_sp_fid *fid) 336 { 337 return fid->vni_valid; 338 } 339 340 void 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 350 static const struct mlxsw_sp_flood_table * 351 mlxsw_sp_fid_flood_table_lookup(const struct mlxsw_sp_fid *fid, 352 enum mlxsw_sp_flood_type packet_type) 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 369 static u16 370 mlxsw_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 375 static int 376 mlxsw_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 385 static 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 393 static int 394 mlxsw_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 415 static u16 416 mlxsw_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 425 static u16 426 mlxsw_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 433 int 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 453 int 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 461 void 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 467 u16 mlxsw_sp_fid_index(const struct mlxsw_sp_fid *fid) 468 { 469 return fid->fid_index; 470 } 471 472 enum mlxsw_sp_fid_type mlxsw_sp_fid_type(const struct mlxsw_sp_fid *fid) 473 { 474 return fid->fid_family->type; 475 } 476 477 struct mlxsw_sp_rif *mlxsw_sp_fid_rif(const struct mlxsw_sp_fid *fid) 478 { 479 return fid->rif; 480 } 481 482 enum mlxsw_sp_rif_type 483 mlxsw_sp_fid_type_rif_type(const struct mlxsw_sp *mlxsw_sp, 484 enum mlxsw_sp_fid_type type) 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 491 static struct mlxsw_sp_fid_8021q * 492 mlxsw_sp_fid_8021q_fid(const struct mlxsw_sp_fid *fid) 493 { 494 return container_of(fid, struct mlxsw_sp_fid_8021q, common); 495 } 496 497 u16 mlxsw_sp_fid_8021q_vid(const struct mlxsw_sp_fid *fid) 498 { 499 return mlxsw_sp_fid_8021q_fid(fid)->vid; 500 } 501 502 static 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 511 static 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 517 static 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 529 static void mlxsw_sp_fid_pack_ctl(char *sfmr_pl, 530 const struct mlxsw_sp_fid *fid, 531 enum mlxsw_reg_sfmr_op op) 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 540 static u16 541 mlxsw_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 548 static 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 553 static void mlxsw_sp_fid_fid_pack_cff(char *sfmr_pl, 554 const struct mlxsw_sp_fid *fid, 555 enum mlxsw_reg_sfmr_op op) 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 568 static 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 580 static 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 590 static 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 612 static 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 629 static 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 635 static 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 644 static int 645 mlxsw_sp_fid_vid_to_fid_map(const struct mlxsw_sp_fid *fid, u16 vid, bool valid, 646 const struct mlxsw_sp_rif *rif) 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 661 static int 662 mlxsw_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 673 static int 674 mlxsw_sp_fid_port_vid_to_fid_rif_update_one(const struct mlxsw_sp_fid *fid, 675 struct mlxsw_sp_fid_port_vid *pv, 676 bool irif_valid, u16 irif_index) 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 688 static 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 719 err_port_vid_to_fid_rif_update_one: 720 list_for_each_entry_continue_reverse(pv, &fid->port_vid_list, list) { 721 if (!mlxsw_sp->fid_core->port_fid_mappings[pv->local_port]) 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 731 static 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 749 static 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 793 err_reg_write: 794 kfree(reiv_pl); 795 return err; 796 } 797 798 static 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 816 err_reiv_handle: 817 for (; i >= 0; i--) 818 mlxsw_sp_fid_reiv_handle(fid, rif_index, !valid, i); 819 return err; 820 } 821 822 int 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 846 err_erif_eport_to_vid_map: 847 mlxsw_sp_fid_vid_to_fid_rif_unset(fid); 848 err_vid_to_fid_rif_set: 849 mlxsw_sp_fid_vni_to_fid_rif_update(fid, NULL); 850 err_vni_to_fid_rif_update: 851 mlxsw_sp_fid_to_fid_rif_update(fid, NULL); 852 return err; 853 } 854 855 void 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 871 static 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 885 err_fid_edit_op: 886 mlxsw_sp_fid_vni_to_fid_map(fid, fid->rif, !fid->vni_valid); 887 return err; 888 } 889 890 static 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 908 static struct mlxsw_sp_fid_8021d * 909 mlxsw_sp_fid_8021d_fid(const struct mlxsw_sp_fid *fid) 910 { 911 return container_of(fid, struct mlxsw_sp_fid_8021d, common); 912 } 913 914 static 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 923 static int mlxsw_sp_fid_8021d_configure(struct mlxsw_sp_fid *fid) 924 { 925 return mlxsw_sp_fid_op(fid, true); 926 } 927 928 static 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 935 static 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 950 static bool 951 mlxsw_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 958 static 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 984 err_port_vp_mode_set: 985 err_fid_port_vid_map: 986 list_for_each_entry_continue_reverse(mlxsw_sp_port_vlan, 987 &mlxsw_sp_port->vlans_list, list) { 988 struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid; 989 u16 vid = mlxsw_sp_port_vlan->vid; 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 1000 static 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 1019 static int 1020 mlxsw_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 1041 static void 1042 mlxsw_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 1057 static int 1058 mlxsw_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 1069 static int 1070 mlxsw_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 1092 static 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 1111 err_erif_eport_to_vid_map_one: 1112 mlxsw_sp_fid_mpe_table_map(fid, local_port, vid, !valid); 1113 return err; 1114 } 1115 1116 static 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 1146 err_port_vp_mode_trans: 1147 mlxsw_sp->fid_core->port_fid_mappings[local_port]--; 1148 mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid); 1149 err_port_vid_list_add: 1150 mlxsw_sp_fid_evid_map(fid, local_port, vid, false); 1151 err_fid_evid_map: 1152 __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, false); 1153 return err; 1154 } 1155 1156 static void 1157 mlxsw_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 1171 static int mlxsw_sp_fid_8021d_vni_set(struct mlxsw_sp_fid *fid) 1172 { 1173 return mlxsw_sp_fid_vni_op(fid); 1174 } 1175 1176 static void mlxsw_sp_fid_8021d_vni_clear(struct mlxsw_sp_fid *fid) 1177 { 1178 mlxsw_sp_fid_vni_op(fid); 1179 } 1180 1181 static 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 1186 static 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 1191 static void 1192 mlxsw_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 1198 static int 1199 mlxsw_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 1205 static int 1206 mlxsw_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 1235 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021d_ops_ctl = { 1236 .setup = mlxsw_sp_fid_8021d_setup, 1237 .configure = mlxsw_sp_fid_8021d_configure, 1238 .deconfigure = mlxsw_sp_fid_8021d_deconfigure, 1239 .index_alloc = mlxsw_sp_fid_8021d_index_alloc, 1240 .compare = mlxsw_sp_fid_8021d_compare, 1241 .port_vid_map = mlxsw_sp_fid_8021d_port_vid_map, 1242 .port_vid_unmap = mlxsw_sp_fid_8021d_port_vid_unmap, 1243 .vni_set = mlxsw_sp_fid_8021d_vni_set, 1244 .vni_clear = mlxsw_sp_fid_8021d_vni_clear, 1245 .nve_flood_index_set = mlxsw_sp_fid_8021d_nve_flood_index_set, 1246 .nve_flood_index_clear = mlxsw_sp_fid_8021d_nve_flood_index_clear, 1247 .fdb_clear_offload = mlxsw_sp_fid_8021d_fdb_clear_offload, 1248 .vid_to_fid_rif_update = mlxsw_sp_fid_8021d_vid_to_fid_rif_update, 1249 .flood_table_init = mlxsw_sp_fid_flood_table_init_ctl, 1250 .pgt_size = mlxsw_sp_fid_8021d_pgt_size, 1251 .fid_mid = mlxsw_sp_fid_fid_mid_ctl, 1252 .fid_pack = mlxsw_sp_fid_pack_ctl, 1253 }; 1254 1255 static u16 1256 mlxsw_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 1262 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021d_ops_cff = { 1263 .setup = mlxsw_sp_fid_8021d_setup, 1264 .configure = mlxsw_sp_fid_8021d_configure, 1265 .deconfigure = mlxsw_sp_fid_8021d_deconfigure, 1266 .index_alloc = mlxsw_sp_fid_8021d_index_alloc, 1267 .compare = mlxsw_sp_fid_8021d_compare, 1268 .port_vid_map = mlxsw_sp_fid_8021d_port_vid_map, 1269 .port_vid_unmap = mlxsw_sp_fid_8021d_port_vid_unmap, 1270 .vni_set = mlxsw_sp_fid_8021d_vni_set, 1271 .vni_clear = mlxsw_sp_fid_8021d_vni_clear, 1272 .nve_flood_index_set = mlxsw_sp_fid_8021d_nve_flood_index_set, 1273 .nve_flood_index_clear = mlxsw_sp_fid_8021d_nve_flood_index_clear, 1274 .fdb_clear_offload = mlxsw_sp_fid_8021d_fdb_clear_offload, 1275 .vid_to_fid_rif_update = mlxsw_sp_fid_8021d_vid_to_fid_rif_update, 1276 .pgt_size = mlxsw_sp_fid_8021d_pgt_size, 1277 .fid_mid = mlxsw_sp_fid_fid_mid_cff, 1278 .fid_pack = mlxsw_sp_fid_fid_pack_cff, 1279 }; 1280 1281 #define MLXSW_SP_FID_8021Q_MAX (VLAN_N_VID - 2) 1282 #define MLXSW_SP_FID_RFID_MAX (11 * 1024) 1283 1284 static 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 1302 static const 1303 struct mlxsw_sp_fid_flood_profile mlxsw_sp_fid_8021d_flood_profile = { 1304 .flood_tables = mlxsw_sp_fid_8021d_flood_tables, 1305 .nr_flood_tables = ARRAY_SIZE(mlxsw_sp_fid_8021d_flood_tables), 1306 .profile_id = MLXSW_SP_FID_FLOOD_PROFILE_ID_BRIDGE, 1307 }; 1308 1309 static 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 1320 static const 1321 struct mlxsw_sp_fid_flood_profile mlxsw_sp_fid_rsp_flood_profile_cff = { 1322 .flood_tables = mlxsw_sp_fid_rsp_flood_tables_cff, 1323 .nr_flood_tables = ARRAY_SIZE(mlxsw_sp_fid_rsp_flood_tables_cff), 1324 .profile_id = MLXSW_SP_FID_FLOOD_PROFILE_ID_RSP, 1325 }; 1326 1327 static 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 1334 static const 1335 struct mlxsw_sp_fid_flood_profile mlxsw_sp_fid_nve_flood_profile_cff = { 1336 .flood_tables = mlxsw_sp_fid_nve_flood_tables_cff, 1337 .nr_flood_tables = ARRAY_SIZE(mlxsw_sp_fid_nve_flood_tables_cff), 1338 .profile_id = MLXSW_SP_FID_FLOOD_PROFILE_ID_NVE, 1339 }; 1340 1341 static bool 1342 mlxsw_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 1349 static void 1350 mlxsw_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 1356 static 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 1364 static 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 1387 static int mlxsw_sp_fid_rfid_configure(struct mlxsw_sp_fid *fid) 1388 { 1389 return mlxsw_sp_fid_op(fid, true); 1390 } 1391 1392 static void mlxsw_sp_fid_rfid_deconfigure(struct mlxsw_sp_fid *fid) 1393 { 1394 mlxsw_sp_fid_op(fid, false); 1395 } 1396 1397 static 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 1407 static 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 1415 static 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 1453 err_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); 1458 err_erif_eport_to_vid_map_one: 1459 __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, false); 1460 err_port_vid_map: 1461 mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid); 1462 return err; 1463 } 1464 1465 static void 1466 mlxsw_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 1483 static int mlxsw_sp_fid_rfid_vni_set(struct mlxsw_sp_fid *fid) 1484 { 1485 return -EOPNOTSUPP; 1486 } 1487 1488 static void mlxsw_sp_fid_rfid_vni_clear(struct mlxsw_sp_fid *fid) 1489 { 1490 WARN_ON_ONCE(1); 1491 } 1492 1493 static int mlxsw_sp_fid_rfid_nve_flood_index_set(struct mlxsw_sp_fid *fid) 1494 { 1495 return -EOPNOTSUPP; 1496 } 1497 1498 static void mlxsw_sp_fid_rfid_nve_flood_index_clear(struct mlxsw_sp_fid *fid) 1499 { 1500 WARN_ON_ONCE(1); 1501 } 1502 1503 static int 1504 mlxsw_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 1510 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_rfid_ops_ctl = { 1511 .setup = mlxsw_sp_fid_rfid_setup_ctl, 1512 .configure = mlxsw_sp_fid_rfid_configure, 1513 .deconfigure = mlxsw_sp_fid_rfid_deconfigure, 1514 .index_alloc = mlxsw_sp_fid_rfid_index_alloc, 1515 .compare = mlxsw_sp_fid_rfid_compare, 1516 .port_vid_map = mlxsw_sp_fid_rfid_port_vid_map, 1517 .port_vid_unmap = mlxsw_sp_fid_rfid_port_vid_unmap, 1518 .vni_set = mlxsw_sp_fid_rfid_vni_set, 1519 .vni_clear = mlxsw_sp_fid_rfid_vni_clear, 1520 .nve_flood_index_set = mlxsw_sp_fid_rfid_nve_flood_index_set, 1521 .nve_flood_index_clear = mlxsw_sp_fid_rfid_nve_flood_index_clear, 1522 .vid_to_fid_rif_update = mlxsw_sp_fid_rfid_vid_to_fid_rif_update, 1523 .fid_pack = mlxsw_sp_fid_pack_ctl, 1524 }; 1525 1526 static int 1527 mlxsw_sp_fid_rfid_port_add_cff(struct mlxsw_sp *mlxsw_sp, 1528 const struct mlxsw_sp_flood_table *flood_table, 1529 u16 pgt_addr, u16 smpe, unsigned int local_port) 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 1549 err_entry_port_set: 1550 mlxsw_sp_pgt_entry_port_set(mlxsw_sp, pgt_addr, smpe, local_port, 1551 false); 1552 return err; 1553 } 1554 1555 static void 1556 mlxsw_sp_fid_rfid_port_del_cff(struct mlxsw_sp *mlxsw_sp, 1557 const struct mlxsw_sp_flood_table *flood_table, 1558 u16 pgt_addr, u16 smpe, u16 local_port) 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 1570 static int 1571 mlxsw_sp_fid_rfid_port_memb_ft_cff(const struct mlxsw_sp_fid_family *fid_family, 1572 const struct mlxsw_sp_flood_table *flood_table, 1573 const struct mlxsw_sp_port *mlxsw_sp_port, 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 1603 static int 1604 mlxsw_sp_fid_rfid_port_memb_cff(const struct mlxsw_sp_fid_family *fid_family, 1605 const struct mlxsw_sp_port *mlxsw_sp_port, 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 1625 static int 1626 mlxsw_sp_fid_rfid_port_init_cff(const struct mlxsw_sp_fid_family *fid_family, 1627 const struct mlxsw_sp_port *mlxsw_sp_port) 1628 { 1629 return mlxsw_sp_fid_rfid_port_memb_cff(fid_family, mlxsw_sp_port, true); 1630 } 1631 1632 static void 1633 mlxsw_sp_fid_rfid_port_fini_cff(const struct mlxsw_sp_fid_family *fid_family, 1634 const struct mlxsw_sp_port *mlxsw_sp_port) 1635 { 1636 mlxsw_sp_fid_rfid_port_memb_cff(fid_family, mlxsw_sp_port, false); 1637 } 1638 1639 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_rfid_ops_cff = { 1640 .setup = mlxsw_sp_fid_rfid_setup_cff, 1641 .configure = mlxsw_sp_fid_rfid_configure, 1642 .deconfigure = mlxsw_sp_fid_rfid_deconfigure, 1643 .index_alloc = mlxsw_sp_fid_rfid_index_alloc, 1644 .compare = mlxsw_sp_fid_rfid_compare, 1645 .port_vid_map = mlxsw_sp_fid_rfid_port_vid_map, 1646 .port_vid_unmap = mlxsw_sp_fid_rfid_port_vid_unmap, 1647 .vni_set = mlxsw_sp_fid_rfid_vni_set, 1648 .vni_clear = mlxsw_sp_fid_rfid_vni_clear, 1649 .nve_flood_index_set = mlxsw_sp_fid_rfid_nve_flood_index_set, 1650 .nve_flood_index_clear = mlxsw_sp_fid_rfid_nve_flood_index_clear, 1651 .vid_to_fid_rif_update = mlxsw_sp_fid_rfid_vid_to_fid_rif_update, 1652 .pgt_size = mlxsw_sp_fid_rfid_pgt_size_cff, 1653 .fid_port_init = mlxsw_sp_fid_rfid_port_init_cff, 1654 .fid_port_fini = mlxsw_sp_fid_rfid_port_fini_cff, 1655 .fid_mid = mlxsw_sp_fid_fid_mid_cff, 1656 .fid_pack = mlxsw_sp_fid_fid_pack_cff, 1657 }; 1658 1659 static 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 1665 static int mlxsw_sp_fid_dummy_configure(struct mlxsw_sp_fid *fid) 1666 { 1667 return mlxsw_sp_fid_op(fid, true); 1668 } 1669 1670 static void mlxsw_sp_fid_dummy_deconfigure(struct mlxsw_sp_fid *fid) 1671 { 1672 mlxsw_sp_fid_op(fid, false); 1673 } 1674 1675 static 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 1683 static bool mlxsw_sp_fid_dummy_compare(const struct mlxsw_sp_fid *fid, 1684 const void *arg) 1685 { 1686 return true; 1687 } 1688 1689 static int mlxsw_sp_fid_dummy_vni_set(struct mlxsw_sp_fid *fid) 1690 { 1691 return -EOPNOTSUPP; 1692 } 1693 1694 static void mlxsw_sp_fid_dummy_vni_clear(struct mlxsw_sp_fid *fid) 1695 { 1696 WARN_ON_ONCE(1); 1697 } 1698 1699 static int mlxsw_sp_fid_dummy_nve_flood_index_set(struct mlxsw_sp_fid *fid) 1700 { 1701 return -EOPNOTSUPP; 1702 } 1703 1704 static void mlxsw_sp_fid_dummy_nve_flood_index_clear(struct mlxsw_sp_fid *fid) 1705 { 1706 WARN_ON_ONCE(1); 1707 } 1708 1709 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_dummy_ops = { 1710 .setup = mlxsw_sp_fid_dummy_setup, 1711 .configure = mlxsw_sp_fid_dummy_configure, 1712 .deconfigure = mlxsw_sp_fid_dummy_deconfigure, 1713 .index_alloc = mlxsw_sp_fid_dummy_index_alloc, 1714 .compare = mlxsw_sp_fid_dummy_compare, 1715 .vni_set = mlxsw_sp_fid_dummy_vni_set, 1716 .vni_clear = mlxsw_sp_fid_dummy_vni_clear, 1717 .nve_flood_index_set = mlxsw_sp_fid_dummy_nve_flood_index_set, 1718 .nve_flood_index_clear = mlxsw_sp_fid_dummy_nve_flood_index_clear, 1719 .fid_pack = mlxsw_sp_fid_pack, 1720 }; 1721 1722 static 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 1737 err_vid_to_fid_map: 1738 mlxsw_sp_fid_op(fid, false); 1739 return err; 1740 } 1741 1742 static 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 1753 static 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 1782 err_port_vid_list_add: 1783 mlxsw_sp_fid_evid_map(fid, local_port, vid, false); 1784 err_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 1790 static void 1791 mlxsw_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 1803 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021q_ops_ctl = { 1804 .setup = mlxsw_sp_fid_8021q_setup, 1805 .configure = mlxsw_sp_fid_8021q_configure, 1806 .deconfigure = mlxsw_sp_fid_8021q_deconfigure, 1807 .index_alloc = mlxsw_sp_fid_8021d_index_alloc, 1808 .compare = mlxsw_sp_fid_8021q_compare, 1809 .port_vid_map = mlxsw_sp_fid_8021q_port_vid_map, 1810 .port_vid_unmap = mlxsw_sp_fid_8021q_port_vid_unmap, 1811 .vni_set = mlxsw_sp_fid_8021d_vni_set, 1812 .vni_clear = mlxsw_sp_fid_8021d_vni_clear, 1813 .nve_flood_index_set = mlxsw_sp_fid_8021d_nve_flood_index_set, 1814 .nve_flood_index_clear = mlxsw_sp_fid_8021d_nve_flood_index_clear, 1815 .fdb_clear_offload = mlxsw_sp_fid_8021q_fdb_clear_offload, 1816 .vid_to_fid_rif_update = mlxsw_sp_fid_8021q_vid_to_fid_rif_update, 1817 .flood_table_init = mlxsw_sp_fid_flood_table_init_ctl, 1818 .pgt_size = mlxsw_sp_fid_8021d_pgt_size, 1819 .fid_mid = mlxsw_sp_fid_fid_mid_ctl, 1820 .fid_pack = mlxsw_sp_fid_pack_ctl, 1821 }; 1822 1823 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021q_ops_cff = { 1824 .setup = mlxsw_sp_fid_8021q_setup, 1825 .configure = mlxsw_sp_fid_8021q_configure, 1826 .deconfigure = mlxsw_sp_fid_8021q_deconfigure, 1827 .index_alloc = mlxsw_sp_fid_8021d_index_alloc, 1828 .compare = mlxsw_sp_fid_8021q_compare, 1829 .port_vid_map = mlxsw_sp_fid_8021q_port_vid_map, 1830 .port_vid_unmap = mlxsw_sp_fid_8021q_port_vid_unmap, 1831 .vni_set = mlxsw_sp_fid_8021d_vni_set, 1832 .vni_clear = mlxsw_sp_fid_8021d_vni_clear, 1833 .nve_flood_index_set = mlxsw_sp_fid_8021d_nve_flood_index_set, 1834 .nve_flood_index_clear = mlxsw_sp_fid_8021d_nve_flood_index_clear, 1835 .fdb_clear_offload = mlxsw_sp_fid_8021q_fdb_clear_offload, 1836 .vid_to_fid_rif_update = mlxsw_sp_fid_8021q_vid_to_fid_rif_update, 1837 .pgt_size = mlxsw_sp_fid_8021d_pgt_size, 1838 .fid_mid = mlxsw_sp_fid_fid_mid_cff, 1839 .fid_pack = mlxsw_sp_fid_fid_pack_cff, 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 1860 static const struct mlxsw_sp_fid_family mlxsw_sp1_fid_8021q_family = { 1861 .type = MLXSW_SP_FID_TYPE_8021Q, 1862 .fid_size = sizeof(struct mlxsw_sp_fid_8021q), 1863 .start_index = MLXSW_SP_FID_8021Q_START, 1864 .end_index = MLXSW_SP_FID_8021Q_END, 1865 .flood_profile = &mlxsw_sp_fid_8021d_flood_profile, 1866 .rif_type = MLXSW_SP_RIF_TYPE_VLAN, 1867 .ops = &mlxsw_sp_fid_8021q_ops_ctl, 1868 .flood_rsp = false, 1869 .bridge_type = MLXSW_REG_BRIDGE_TYPE_0, 1870 .smpe_index_valid = false, 1871 }; 1872 1873 static const struct mlxsw_sp_fid_family mlxsw_sp1_fid_8021d_family = { 1874 .type = MLXSW_SP_FID_TYPE_8021D, 1875 .fid_size = sizeof(struct mlxsw_sp_fid_8021d), 1876 .start_index = MLXSW_SP_FID_8021D_START, 1877 .end_index = MLXSW_SP_FID_8021D_END, 1878 .flood_profile = &mlxsw_sp_fid_8021d_flood_profile, 1879 .rif_type = MLXSW_SP_RIF_TYPE_FID, 1880 .ops = &mlxsw_sp_fid_8021d_ops_ctl, 1881 .bridge_type = MLXSW_REG_BRIDGE_TYPE_1, 1882 .smpe_index_valid = false, 1883 }; 1884 1885 static const struct mlxsw_sp_fid_family mlxsw_sp1_fid_dummy_family = { 1886 .type = MLXSW_SP_FID_TYPE_DUMMY, 1887 .fid_size = sizeof(struct mlxsw_sp_fid), 1888 .start_index = MLXSW_SP_FID_DUMMY, 1889 .end_index = MLXSW_SP_FID_DUMMY, 1890 .ops = &mlxsw_sp_fid_dummy_ops, 1891 .smpe_index_valid = false, 1892 }; 1893 1894 static const struct mlxsw_sp_fid_family mlxsw_sp_fid_rfid_family_ctl = { 1895 .type = MLXSW_SP_FID_TYPE_RFID, 1896 .fid_size = sizeof(struct mlxsw_sp_fid), 1897 .start_index = MLXSW_SP_RFID_START, 1898 .end_index = MLXSW_SP_RFID_END, 1899 .rif_type = MLXSW_SP_RIF_TYPE_SUBPORT, 1900 .ops = &mlxsw_sp_fid_rfid_ops_ctl, 1901 .flood_rsp = true, 1902 .smpe_index_valid = false, 1903 }; 1904 1905 static const struct mlxsw_sp_fid_family *mlxsw_sp1_fid_family_arr[] = { 1906 [MLXSW_SP_FID_TYPE_8021Q] = &mlxsw_sp1_fid_8021q_family, 1907 [MLXSW_SP_FID_TYPE_8021D] = &mlxsw_sp1_fid_8021d_family, 1908 [MLXSW_SP_FID_TYPE_DUMMY] = &mlxsw_sp1_fid_dummy_family, 1909 [MLXSW_SP_FID_TYPE_RFID] = &mlxsw_sp_fid_rfid_family_ctl, 1910 }; 1911 1912 static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_8021q_family_ctl = { 1913 .type = MLXSW_SP_FID_TYPE_8021Q, 1914 .fid_size = sizeof(struct mlxsw_sp_fid_8021q), 1915 .start_index = MLXSW_SP_FID_8021Q_START, 1916 .end_index = MLXSW_SP_FID_8021Q_END, 1917 .flood_profile = &mlxsw_sp_fid_8021d_flood_profile, 1918 .rif_type = MLXSW_SP_RIF_TYPE_VLAN, 1919 .ops = &mlxsw_sp_fid_8021q_ops_ctl, 1920 .flood_rsp = false, 1921 .bridge_type = MLXSW_REG_BRIDGE_TYPE_0, 1922 .smpe_index_valid = true, 1923 }; 1924 1925 static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_8021d_family_ctl = { 1926 .type = MLXSW_SP_FID_TYPE_8021D, 1927 .fid_size = sizeof(struct mlxsw_sp_fid_8021d), 1928 .start_index = MLXSW_SP_FID_8021D_START, 1929 .end_index = MLXSW_SP_FID_8021D_END, 1930 .flood_profile = &mlxsw_sp_fid_8021d_flood_profile, 1931 .rif_type = MLXSW_SP_RIF_TYPE_FID, 1932 .ops = &mlxsw_sp_fid_8021d_ops_ctl, 1933 .bridge_type = MLXSW_REG_BRIDGE_TYPE_1, 1934 .smpe_index_valid = true, 1935 }; 1936 1937 static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_dummy_family = { 1938 .type = MLXSW_SP_FID_TYPE_DUMMY, 1939 .fid_size = sizeof(struct mlxsw_sp_fid), 1940 .start_index = MLXSW_SP_FID_DUMMY, 1941 .end_index = MLXSW_SP_FID_DUMMY, 1942 .ops = &mlxsw_sp_fid_dummy_ops, 1943 .smpe_index_valid = false, 1944 }; 1945 1946 static const struct mlxsw_sp_fid_family *mlxsw_sp2_fid_family_arr_ctl[] = { 1947 [MLXSW_SP_FID_TYPE_8021Q] = &mlxsw_sp2_fid_8021q_family_ctl, 1948 [MLXSW_SP_FID_TYPE_8021D] = &mlxsw_sp2_fid_8021d_family_ctl, 1949 [MLXSW_SP_FID_TYPE_DUMMY] = &mlxsw_sp2_fid_dummy_family, 1950 [MLXSW_SP_FID_TYPE_RFID] = &mlxsw_sp_fid_rfid_family_ctl, 1951 }; 1952 1953 static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_8021q_family_cff = { 1954 .type = MLXSW_SP_FID_TYPE_8021Q, 1955 .fid_size = sizeof(struct mlxsw_sp_fid_8021q), 1956 .start_index = MLXSW_SP_FID_8021Q_START, 1957 .end_index = MLXSW_SP_FID_8021Q_END, 1958 .flood_profile = &mlxsw_sp_fid_8021d_flood_profile, 1959 .rif_type = MLXSW_SP_RIF_TYPE_VLAN, 1960 .ops = &mlxsw_sp_fid_8021q_ops_cff, 1961 .smpe_index_valid = true, 1962 }; 1963 1964 static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_8021d_family_cff = { 1965 .type = MLXSW_SP_FID_TYPE_8021D, 1966 .fid_size = sizeof(struct mlxsw_sp_fid_8021d), 1967 .start_index = MLXSW_SP_FID_8021D_START, 1968 .end_index = MLXSW_SP_FID_8021D_END, 1969 .flood_profile = &mlxsw_sp_fid_8021d_flood_profile, 1970 .rif_type = MLXSW_SP_RIF_TYPE_FID, 1971 .ops = &mlxsw_sp_fid_8021d_ops_cff, 1972 .smpe_index_valid = true, 1973 }; 1974 1975 static const struct mlxsw_sp_fid_family mlxsw_sp_fid_rfid_family_cff = { 1976 .type = MLXSW_SP_FID_TYPE_RFID, 1977 .fid_size = sizeof(struct mlxsw_sp_fid), 1978 .start_index = MLXSW_SP_RFID_START, 1979 .end_index = MLXSW_SP_RFID_END, 1980 .flood_profile = &mlxsw_sp_fid_rsp_flood_profile_cff, 1981 .rif_type = MLXSW_SP_RIF_TYPE_SUBPORT, 1982 .ops = &mlxsw_sp_fid_rfid_ops_cff, 1983 .smpe_index_valid = false, 1984 }; 1985 1986 static const struct mlxsw_sp_fid_family *mlxsw_sp2_fid_family_arr_cff[] = { 1987 [MLXSW_SP_FID_TYPE_8021Q] = &mlxsw_sp2_fid_8021q_family_cff, 1988 [MLXSW_SP_FID_TYPE_8021D] = &mlxsw_sp2_fid_8021d_family_cff, 1989 [MLXSW_SP_FID_TYPE_DUMMY] = &mlxsw_sp2_fid_dummy_family, 1990 [MLXSW_SP_FID_TYPE_RFID] = &mlxsw_sp_fid_rfid_family_cff, 1991 }; 1992 1993 static 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 2011 static 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 2055 err_rhashtable_insert: 2056 fid->fid_family->ops->deconfigure(fid); 2057 err_configure: 2058 err_setup: 2059 __clear_bit(fid_index - fid_family->start_index, 2060 fid_family->fids_bitmap); 2061 err_index_alloc: 2062 kfree(fid); 2063 return ERR_PTR(err); 2064 } 2065 2066 void 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 2084 struct 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 2089 struct 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 2095 struct 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 2101 struct 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 2108 struct 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 2114 struct 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 2119 static int 2120 mlxsw_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 2153 err_flood_table_init: 2154 mlxsw_sp_pgt_mid_free_range(mlxsw_sp, fid_family->pgt_base, pgt_size); 2155 return err; 2156 } 2157 2158 static void 2159 mlxsw_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 2172 static 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 2201 err_fid_flood_tables_init: 2202 bitmap_free(fid_family->fids_bitmap); 2203 err_alloc_fids_bitmap: 2204 kfree(fid_family); 2205 return err; 2206 } 2207 2208 static void 2209 mlxsw_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 2222 static 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 2235 static 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 2246 int 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 2267 err_vp_mode_set: 2268 mlxsw_sp_fid_port_fini(mlxsw_sp_port); 2269 return err; 2270 } 2271 2272 void 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 2280 int 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 2285 void 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 2290 static int 2291 mlxsw_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 2327 err_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); 2335 err_alloc_port_fid_mappings: 2336 rhashtable_destroy(&fid_core->vni_ht); 2337 err_rhashtable_vni_init: 2338 rhashtable_destroy(&fid_core->fid_ht); 2339 err_rhashtable_fid_init: 2340 kfree(fid_core); 2341 return err; 2342 } 2343 2344 static 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 2358 static 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 2363 const struct mlxsw_sp_fid_core_ops mlxsw_sp1_fid_core_ops = { 2364 .init = mlxsw_sp1_fids_init, 2365 .fini = mlxsw_sp_fids_fini, 2366 }; 2367 2368 static 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 2384 static int 2385 mlxsw_sp2_fids_init_flood_table(struct mlxsw_sp *mlxsw_sp, 2386 enum mlxsw_sp_fid_flood_profile_id profile_id, 2387 const struct mlxsw_sp_flood_table *flood_table) 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 2411 static int 2412 mlxsw_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 2438 static const 2439 struct mlxsw_sp_fid_flood_profile *mlxsw_sp_fid_flood_profiles[] = { 2440 &mlxsw_sp_fid_8021d_flood_profile, 2441 &mlxsw_sp_fid_rsp_flood_profile_cff, 2442 &mlxsw_sp_fid_nve_flood_profile_cff, 2443 }; 2444 2445 static int 2446 mlxsw_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 2464 static 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 2469 static 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 2480 static 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 2493 const struct mlxsw_sp_fid_core_ops mlxsw_sp2_fid_core_ops = { 2494 .init = mlxsw_sp2_fids_init, 2495 .fini = mlxsw_sp_fids_fini, 2496 }; 2497