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 "reg.h" 15 16 struct mlxsw_sp_fid_family; 17 18 struct mlxsw_sp_fid_core { 19 struct rhashtable fid_ht; 20 struct rhashtable vni_ht; 21 struct mlxsw_sp_fid_family *fid_family_arr[MLXSW_SP_FID_TYPE_MAX]; 22 unsigned int *port_fid_mappings; 23 }; 24 25 struct mlxsw_sp_fid_port_vid { 26 struct list_head list; 27 u16 local_port; 28 u16 vid; 29 }; 30 31 struct mlxsw_sp_fid { 32 struct list_head list; 33 struct mlxsw_sp_rif *rif; 34 refcount_t ref_count; 35 u16 fid_index; 36 u16 fid_offset; 37 struct mlxsw_sp_fid_family *fid_family; 38 struct rhash_head ht_node; 39 40 struct rhash_head vni_ht_node; 41 enum mlxsw_sp_nve_type nve_type; 42 __be32 vni; 43 u32 nve_flood_index; 44 int nve_ifindex; 45 u8 vni_valid:1, 46 nve_flood_index_valid:1; 47 struct list_head port_vid_list; /* Ordered by local port. */ 48 }; 49 50 struct mlxsw_sp_fid_8021q { 51 struct mlxsw_sp_fid common; 52 u16 vid; 53 }; 54 55 struct mlxsw_sp_fid_8021d { 56 struct mlxsw_sp_fid common; 57 int br_ifindex; 58 }; 59 60 static const struct rhashtable_params mlxsw_sp_fid_ht_params = { 61 .key_len = sizeof_field(struct mlxsw_sp_fid, fid_index), 62 .key_offset = offsetof(struct mlxsw_sp_fid, fid_index), 63 .head_offset = offsetof(struct mlxsw_sp_fid, ht_node), 64 }; 65 66 static const struct rhashtable_params mlxsw_sp_fid_vni_ht_params = { 67 .key_len = sizeof_field(struct mlxsw_sp_fid, vni), 68 .key_offset = offsetof(struct mlxsw_sp_fid, vni), 69 .head_offset = offsetof(struct mlxsw_sp_fid, vni_ht_node), 70 }; 71 72 struct mlxsw_sp_flood_table { 73 enum mlxsw_sp_flood_type packet_type; 74 enum mlxsw_flood_table_type table_type; 75 int table_index; 76 }; 77 78 struct mlxsw_sp_fid_ops { 79 void (*setup)(struct mlxsw_sp_fid *fid, const void *arg); 80 int (*configure)(struct mlxsw_sp_fid *fid); 81 void (*deconfigure)(struct mlxsw_sp_fid *fid); 82 int (*index_alloc)(struct mlxsw_sp_fid *fid, const void *arg, 83 u16 *p_fid_index); 84 bool (*compare)(const struct mlxsw_sp_fid *fid, 85 const void *arg); 86 int (*port_vid_map)(struct mlxsw_sp_fid *fid, 87 struct mlxsw_sp_port *port, u16 vid); 88 void (*port_vid_unmap)(struct mlxsw_sp_fid *fid, 89 struct mlxsw_sp_port *port, u16 vid); 90 int (*vni_set)(struct mlxsw_sp_fid *fid); 91 void (*vni_clear)(struct mlxsw_sp_fid *fid); 92 int (*nve_flood_index_set)(struct mlxsw_sp_fid *fid); 93 void (*nve_flood_index_clear)(struct mlxsw_sp_fid *fid); 94 void (*fdb_clear_offload)(const struct mlxsw_sp_fid *fid, 95 const struct net_device *nve_dev); 96 int (*vid_to_fid_rif_update)(const struct mlxsw_sp_fid *fid, 97 const struct mlxsw_sp_rif *rif); 98 }; 99 100 struct mlxsw_sp_fid_family { 101 enum mlxsw_sp_fid_type type; 102 size_t fid_size; 103 u16 start_index; 104 u16 end_index; 105 struct list_head fids_list; 106 unsigned long *fids_bitmap; 107 const struct mlxsw_sp_flood_table *flood_tables; 108 int nr_flood_tables; 109 enum mlxsw_sp_rif_type rif_type; 110 const struct mlxsw_sp_fid_ops *ops; 111 struct mlxsw_sp *mlxsw_sp; 112 bool flood_rsp; 113 enum mlxsw_reg_bridge_type bridge_type; 114 u16 pgt_base; 115 bool smpe_index_valid; 116 }; 117 118 static const int mlxsw_sp_sfgc_uc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = { 119 [MLXSW_REG_SFGC_TYPE_UNKNOWN_UNICAST] = 1, 120 }; 121 122 static const int mlxsw_sp_sfgc_bc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = { 123 [MLXSW_REG_SFGC_TYPE_BROADCAST] = 1, 124 [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_NON_IP] = 1, 125 [MLXSW_REG_SFGC_TYPE_IPV4_LINK_LOCAL] = 1, 126 [MLXSW_REG_SFGC_TYPE_IPV6_ALL_HOST] = 1, 127 [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV6] = 1, 128 }; 129 130 static const int mlxsw_sp_sfgc_mc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = { 131 [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV4] = 1, 132 }; 133 134 static const int *mlxsw_sp_packet_type_sfgc_types[] = { 135 [MLXSW_SP_FLOOD_TYPE_UC] = mlxsw_sp_sfgc_uc_packet_types, 136 [MLXSW_SP_FLOOD_TYPE_BC] = mlxsw_sp_sfgc_bc_packet_types, 137 [MLXSW_SP_FLOOD_TYPE_MC] = mlxsw_sp_sfgc_mc_packet_types, 138 }; 139 140 struct mlxsw_sp_fid *mlxsw_sp_fid_lookup_by_index(struct mlxsw_sp *mlxsw_sp, 141 u16 fid_index) 142 { 143 struct mlxsw_sp_fid *fid; 144 145 fid = rhashtable_lookup_fast(&mlxsw_sp->fid_core->fid_ht, &fid_index, 146 mlxsw_sp_fid_ht_params); 147 if (fid) 148 refcount_inc(&fid->ref_count); 149 150 return fid; 151 } 152 153 int mlxsw_sp_fid_nve_ifindex(const struct mlxsw_sp_fid *fid, int *nve_ifindex) 154 { 155 if (!fid->vni_valid) 156 return -EINVAL; 157 158 *nve_ifindex = fid->nve_ifindex; 159 160 return 0; 161 } 162 163 int mlxsw_sp_fid_nve_type(const struct mlxsw_sp_fid *fid, 164 enum mlxsw_sp_nve_type *p_type) 165 { 166 if (!fid->vni_valid) 167 return -EINVAL; 168 169 *p_type = fid->nve_type; 170 171 return 0; 172 } 173 174 struct mlxsw_sp_fid *mlxsw_sp_fid_lookup_by_vni(struct mlxsw_sp *mlxsw_sp, 175 __be32 vni) 176 { 177 struct mlxsw_sp_fid *fid; 178 179 fid = rhashtable_lookup_fast(&mlxsw_sp->fid_core->vni_ht, &vni, 180 mlxsw_sp_fid_vni_ht_params); 181 if (fid) 182 refcount_inc(&fid->ref_count); 183 184 return fid; 185 } 186 187 int mlxsw_sp_fid_vni(const struct mlxsw_sp_fid *fid, __be32 *vni) 188 { 189 if (!fid->vni_valid) 190 return -EINVAL; 191 192 *vni = fid->vni; 193 194 return 0; 195 } 196 197 int mlxsw_sp_fid_nve_flood_index_set(struct mlxsw_sp_fid *fid, 198 u32 nve_flood_index) 199 { 200 struct mlxsw_sp_fid_family *fid_family = fid->fid_family; 201 const struct mlxsw_sp_fid_ops *ops = fid_family->ops; 202 int err; 203 204 if (WARN_ON(fid->nve_flood_index_valid)) 205 return -EINVAL; 206 207 fid->nve_flood_index = nve_flood_index; 208 fid->nve_flood_index_valid = true; 209 err = ops->nve_flood_index_set(fid); 210 if (err) 211 goto err_nve_flood_index_set; 212 213 return 0; 214 215 err_nve_flood_index_set: 216 fid->nve_flood_index_valid = false; 217 return err; 218 } 219 220 void mlxsw_sp_fid_nve_flood_index_clear(struct mlxsw_sp_fid *fid) 221 { 222 struct mlxsw_sp_fid_family *fid_family = fid->fid_family; 223 const struct mlxsw_sp_fid_ops *ops = fid_family->ops; 224 225 if (WARN_ON(!fid->nve_flood_index_valid)) 226 return; 227 228 fid->nve_flood_index_valid = false; 229 ops->nve_flood_index_clear(fid); 230 } 231 232 bool mlxsw_sp_fid_nve_flood_index_is_set(const struct mlxsw_sp_fid *fid) 233 { 234 return fid->nve_flood_index_valid; 235 } 236 237 int mlxsw_sp_fid_vni_set(struct mlxsw_sp_fid *fid, enum mlxsw_sp_nve_type type, 238 __be32 vni, int nve_ifindex) 239 { 240 struct mlxsw_sp_fid_family *fid_family = fid->fid_family; 241 const struct mlxsw_sp_fid_ops *ops = fid_family->ops; 242 struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp; 243 int err; 244 245 if (WARN_ON(fid->vni_valid)) 246 return -EINVAL; 247 248 fid->nve_type = type; 249 fid->nve_ifindex = nve_ifindex; 250 fid->vni = vni; 251 err = rhashtable_lookup_insert_fast(&mlxsw_sp->fid_core->vni_ht, 252 &fid->vni_ht_node, 253 mlxsw_sp_fid_vni_ht_params); 254 if (err) 255 return err; 256 257 fid->vni_valid = true; 258 err = ops->vni_set(fid); 259 if (err) 260 goto err_vni_set; 261 262 return 0; 263 264 err_vni_set: 265 fid->vni_valid = false; 266 rhashtable_remove_fast(&mlxsw_sp->fid_core->vni_ht, &fid->vni_ht_node, 267 mlxsw_sp_fid_vni_ht_params); 268 return err; 269 } 270 271 void mlxsw_sp_fid_vni_clear(struct mlxsw_sp_fid *fid) 272 { 273 struct mlxsw_sp_fid_family *fid_family = fid->fid_family; 274 const struct mlxsw_sp_fid_ops *ops = fid_family->ops; 275 struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp; 276 277 if (WARN_ON(!fid->vni_valid)) 278 return; 279 280 fid->vni_valid = false; 281 ops->vni_clear(fid); 282 rhashtable_remove_fast(&mlxsw_sp->fid_core->vni_ht, &fid->vni_ht_node, 283 mlxsw_sp_fid_vni_ht_params); 284 } 285 286 bool mlxsw_sp_fid_vni_is_set(const struct mlxsw_sp_fid *fid) 287 { 288 return fid->vni_valid; 289 } 290 291 void mlxsw_sp_fid_fdb_clear_offload(const struct mlxsw_sp_fid *fid, 292 const struct net_device *nve_dev) 293 { 294 struct mlxsw_sp_fid_family *fid_family = fid->fid_family; 295 const struct mlxsw_sp_fid_ops *ops = fid_family->ops; 296 297 if (ops->fdb_clear_offload) 298 ops->fdb_clear_offload(fid, nve_dev); 299 } 300 301 static const struct mlxsw_sp_flood_table * 302 mlxsw_sp_fid_flood_table_lookup(const struct mlxsw_sp_fid *fid, 303 enum mlxsw_sp_flood_type packet_type) 304 { 305 struct mlxsw_sp_fid_family *fid_family = fid->fid_family; 306 int i; 307 308 for (i = 0; i < fid_family->nr_flood_tables; i++) { 309 if (fid_family->flood_tables[i].packet_type != packet_type) 310 continue; 311 return &fid_family->flood_tables[i]; 312 } 313 314 return NULL; 315 } 316 317 static u16 318 mlxsw_sp_fid_family_num_fids(const struct mlxsw_sp_fid_family *fid_family) 319 { 320 return fid_family->end_index - fid_family->start_index + 1; 321 } 322 323 static u16 324 mlxsw_sp_fid_family_pgt_size(const struct mlxsw_sp_fid_family *fid_family) 325 { 326 u16 num_fids = mlxsw_sp_fid_family_num_fids(fid_family); 327 328 return num_fids * fid_family->nr_flood_tables; 329 } 330 331 static u16 332 mlxsw_sp_fid_flood_table_mid(const struct mlxsw_sp_fid_family *fid_family, 333 const struct mlxsw_sp_flood_table *flood_table, 334 u16 fid_offset) 335 { 336 u16 num_fids; 337 338 num_fids = mlxsw_sp_fid_family_num_fids(fid_family); 339 return fid_family->pgt_base + num_fids * flood_table->table_index + 340 fid_offset; 341 } 342 343 int mlxsw_sp_fid_flood_set(struct mlxsw_sp_fid *fid, 344 enum mlxsw_sp_flood_type packet_type, u16 local_port, 345 bool member) 346 { 347 struct mlxsw_sp_fid_family *fid_family = fid->fid_family; 348 const struct mlxsw_sp_flood_table *flood_table; 349 u16 mid_index; 350 351 if (WARN_ON(!fid_family->flood_tables)) 352 return -EINVAL; 353 354 flood_table = mlxsw_sp_fid_flood_table_lookup(fid, packet_type); 355 if (!flood_table) 356 return -ESRCH; 357 358 mid_index = mlxsw_sp_fid_flood_table_mid(fid_family, flood_table, 359 fid->fid_offset); 360 return mlxsw_sp_pgt_entry_port_set(fid_family->mlxsw_sp, mid_index, 361 fid->fid_index, local_port, member); 362 } 363 364 int mlxsw_sp_fid_port_vid_map(struct mlxsw_sp_fid *fid, 365 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid) 366 { 367 if (WARN_ON(!fid->fid_family->ops->port_vid_map)) 368 return -EINVAL; 369 return fid->fid_family->ops->port_vid_map(fid, mlxsw_sp_port, vid); 370 } 371 372 void mlxsw_sp_fid_port_vid_unmap(struct mlxsw_sp_fid *fid, 373 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid) 374 { 375 fid->fid_family->ops->port_vid_unmap(fid, mlxsw_sp_port, vid); 376 } 377 378 u16 mlxsw_sp_fid_index(const struct mlxsw_sp_fid *fid) 379 { 380 return fid->fid_index; 381 } 382 383 enum mlxsw_sp_fid_type mlxsw_sp_fid_type(const struct mlxsw_sp_fid *fid) 384 { 385 return fid->fid_family->type; 386 } 387 388 struct mlxsw_sp_rif *mlxsw_sp_fid_rif(const struct mlxsw_sp_fid *fid) 389 { 390 return fid->rif; 391 } 392 393 enum mlxsw_sp_rif_type 394 mlxsw_sp_fid_type_rif_type(const struct mlxsw_sp *mlxsw_sp, 395 enum mlxsw_sp_fid_type type) 396 { 397 struct mlxsw_sp_fid_core *fid_core = mlxsw_sp->fid_core; 398 399 return fid_core->fid_family_arr[type]->rif_type; 400 } 401 402 static struct mlxsw_sp_fid_8021q * 403 mlxsw_sp_fid_8021q_fid(const struct mlxsw_sp_fid *fid) 404 { 405 return container_of(fid, struct mlxsw_sp_fid_8021q, common); 406 } 407 408 u16 mlxsw_sp_fid_8021q_vid(const struct mlxsw_sp_fid *fid) 409 { 410 return mlxsw_sp_fid_8021q_fid(fid)->vid; 411 } 412 413 static void mlxsw_sp_fid_8021q_setup(struct mlxsw_sp_fid *fid, const void *arg) 414 { 415 u16 vid = *(u16 *) arg; 416 417 mlxsw_sp_fid_8021q_fid(fid)->vid = vid; 418 fid->fid_offset = fid->fid_index - fid->fid_family->start_index; 419 } 420 421 static enum mlxsw_reg_sfmr_op mlxsw_sp_sfmr_op(bool valid) 422 { 423 return valid ? MLXSW_REG_SFMR_OP_CREATE_FID : 424 MLXSW_REG_SFMR_OP_DESTROY_FID; 425 } 426 427 static int mlxsw_sp_fid_op(const struct mlxsw_sp_fid *fid, bool valid) 428 { 429 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; 430 char sfmr_pl[MLXSW_REG_SFMR_LEN]; 431 u16 smpe; 432 433 smpe = fid->fid_family->smpe_index_valid ? fid->fid_index : 0; 434 435 mlxsw_reg_sfmr_pack(sfmr_pl, mlxsw_sp_sfmr_op(valid), fid->fid_index, 436 fid->fid_offset, fid->fid_family->flood_rsp, 437 fid->fid_family->bridge_type, 438 fid->fid_family->smpe_index_valid, smpe); 439 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl); 440 } 441 442 static int mlxsw_sp_fid_edit_op(const struct mlxsw_sp_fid *fid, 443 const struct mlxsw_sp_rif *rif) 444 { 445 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; 446 char sfmr_pl[MLXSW_REG_SFMR_LEN]; 447 u16 smpe; 448 449 smpe = fid->fid_family->smpe_index_valid ? fid->fid_index : 0; 450 451 mlxsw_reg_sfmr_pack(sfmr_pl, MLXSW_REG_SFMR_OP_CREATE_FID, 452 fid->fid_index, fid->fid_offset, 453 fid->fid_family->flood_rsp, 454 fid->fid_family->bridge_type, 455 fid->fid_family->smpe_index_valid, smpe); 456 mlxsw_reg_sfmr_vv_set(sfmr_pl, fid->vni_valid); 457 mlxsw_reg_sfmr_vni_set(sfmr_pl, be32_to_cpu(fid->vni)); 458 mlxsw_reg_sfmr_vtfp_set(sfmr_pl, fid->nve_flood_index_valid); 459 mlxsw_reg_sfmr_nve_tunnel_flood_ptr_set(sfmr_pl, fid->nve_flood_index); 460 461 if (rif) { 462 mlxsw_reg_sfmr_irif_v_set(sfmr_pl, true); 463 mlxsw_reg_sfmr_irif_set(sfmr_pl, mlxsw_sp_rif_index(rif)); 464 } 465 466 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl); 467 } 468 469 static int mlxsw_sp_fid_vni_to_fid_map(const struct mlxsw_sp_fid *fid, 470 const struct mlxsw_sp_rif *rif, 471 bool valid) 472 { 473 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; 474 char svfa_pl[MLXSW_REG_SVFA_LEN]; 475 bool irif_valid; 476 u16 irif_index; 477 478 irif_valid = !!rif; 479 irif_index = rif ? mlxsw_sp_rif_index(rif) : 0; 480 481 mlxsw_reg_svfa_vni_pack(svfa_pl, valid, fid->fid_index, 482 be32_to_cpu(fid->vni), irif_valid, irif_index); 483 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl); 484 } 485 486 static int mlxsw_sp_fid_to_fid_rif_update(const struct mlxsw_sp_fid *fid, 487 const struct mlxsw_sp_rif *rif) 488 { 489 return mlxsw_sp_fid_edit_op(fid, rif); 490 } 491 492 static int mlxsw_sp_fid_vni_to_fid_rif_update(const struct mlxsw_sp_fid *fid, 493 const struct mlxsw_sp_rif *rif) 494 { 495 if (!fid->vni_valid) 496 return 0; 497 498 return mlxsw_sp_fid_vni_to_fid_map(fid, rif, fid->vni_valid); 499 } 500 501 static int 502 mlxsw_sp_fid_vid_to_fid_map(const struct mlxsw_sp_fid *fid, u16 vid, bool valid, 503 const struct mlxsw_sp_rif *rif) 504 { 505 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; 506 char svfa_pl[MLXSW_REG_SVFA_LEN]; 507 bool irif_valid; 508 u16 irif_index; 509 510 irif_valid = !!rif; 511 irif_index = rif ? mlxsw_sp_rif_index(rif) : 0; 512 513 mlxsw_reg_svfa_vid_pack(svfa_pl, valid, fid->fid_index, vid, irif_valid, 514 irif_index); 515 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl); 516 } 517 518 static int 519 mlxsw_sp_fid_8021q_vid_to_fid_rif_update(const struct mlxsw_sp_fid *fid, 520 const struct mlxsw_sp_rif *rif) 521 { 522 struct mlxsw_sp_fid_8021q *fid_8021q = mlxsw_sp_fid_8021q_fid(fid); 523 524 /* Update the global VID => FID mapping we created when the FID was 525 * configured. 526 */ 527 return mlxsw_sp_fid_vid_to_fid_map(fid, fid_8021q->vid, true, rif); 528 } 529 530 static int 531 mlxsw_sp_fid_port_vid_to_fid_rif_update_one(const struct mlxsw_sp_fid *fid, 532 struct mlxsw_sp_fid_port_vid *pv, 533 bool irif_valid, u16 irif_index) 534 { 535 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; 536 char svfa_pl[MLXSW_REG_SVFA_LEN]; 537 538 mlxsw_reg_svfa_port_vid_pack(svfa_pl, pv->local_port, true, 539 fid->fid_index, pv->vid, irif_valid, 540 irif_index); 541 542 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl); 543 } 544 545 static int mlxsw_sp_fid_vid_to_fid_rif_set(const struct mlxsw_sp_fid *fid, 546 const struct mlxsw_sp_rif *rif) 547 { 548 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; 549 struct mlxsw_sp_fid_port_vid *pv; 550 u16 irif_index; 551 int err; 552 553 err = fid->fid_family->ops->vid_to_fid_rif_update(fid, rif); 554 if (err) 555 return err; 556 557 irif_index = mlxsw_sp_rif_index(rif); 558 559 list_for_each_entry(pv, &fid->port_vid_list, list) { 560 /* If port is not in virtual mode, then it does not have any 561 * {Port, VID}->FID mappings that need to be updated with the 562 * ingress RIF. 563 */ 564 if (!mlxsw_sp->fid_core->port_fid_mappings[pv->local_port]) 565 continue; 566 567 err = mlxsw_sp_fid_port_vid_to_fid_rif_update_one(fid, pv, 568 true, 569 irif_index); 570 if (err) 571 goto err_port_vid_to_fid_rif_update_one; 572 } 573 574 return 0; 575 576 err_port_vid_to_fid_rif_update_one: 577 list_for_each_entry_continue_reverse(pv, &fid->port_vid_list, list) { 578 if (!mlxsw_sp->fid_core->port_fid_mappings[pv->local_port]) 579 continue; 580 581 mlxsw_sp_fid_port_vid_to_fid_rif_update_one(fid, pv, false, 0); 582 } 583 584 fid->fid_family->ops->vid_to_fid_rif_update(fid, NULL); 585 return err; 586 } 587 588 static void mlxsw_sp_fid_vid_to_fid_rif_unset(const struct mlxsw_sp_fid *fid) 589 { 590 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; 591 struct mlxsw_sp_fid_port_vid *pv; 592 593 list_for_each_entry(pv, &fid->port_vid_list, list) { 594 /* If port is not in virtual mode, then it does not have any 595 * {Port, VID}->FID mappings that need to be updated. 596 */ 597 if (!mlxsw_sp->fid_core->port_fid_mappings[pv->local_port]) 598 continue; 599 600 mlxsw_sp_fid_port_vid_to_fid_rif_update_one(fid, pv, false, 0); 601 } 602 603 fid->fid_family->ops->vid_to_fid_rif_update(fid, NULL); 604 } 605 606 static int mlxsw_sp_fid_reiv_handle(struct mlxsw_sp_fid *fid, u16 rif_index, 607 bool valid, u8 port_page) 608 { 609 u16 local_port_end = (port_page + 1) * MLXSW_REG_REIV_REC_MAX_COUNT - 1; 610 u16 local_port_start = port_page * MLXSW_REG_REIV_REC_MAX_COUNT; 611 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; 612 struct mlxsw_sp_fid_port_vid *port_vid; 613 u8 rec_num, entries_num = 0; 614 char *reiv_pl; 615 int err; 616 617 reiv_pl = kmalloc(MLXSW_REG_REIV_LEN, GFP_KERNEL); 618 if (!reiv_pl) 619 return -ENOMEM; 620 621 mlxsw_reg_reiv_pack(reiv_pl, port_page, rif_index); 622 623 list_for_each_entry(port_vid, &fid->port_vid_list, list) { 624 /* port_vid_list is sorted by local_port. */ 625 if (port_vid->local_port < local_port_start) 626 continue; 627 628 if (port_vid->local_port > local_port_end) 629 break; 630 631 rec_num = port_vid->local_port % MLXSW_REG_REIV_REC_MAX_COUNT; 632 mlxsw_reg_reiv_rec_update_set(reiv_pl, rec_num, true); 633 mlxsw_reg_reiv_rec_evid_set(reiv_pl, rec_num, 634 valid ? port_vid->vid : 0); 635 entries_num++; 636 } 637 638 if (!entries_num) { 639 kfree(reiv_pl); 640 return 0; 641 } 642 643 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(reiv), reiv_pl); 644 if (err) 645 goto err_reg_write; 646 647 kfree(reiv_pl); 648 return 0; 649 650 err_reg_write: 651 kfree(reiv_pl); 652 return err; 653 } 654 655 static int mlxsw_sp_fid_erif_eport_to_vid_map(struct mlxsw_sp_fid *fid, 656 u16 rif_index, bool valid) 657 { 658 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; 659 u8 num_port_pages; 660 int err, i; 661 662 num_port_pages = mlxsw_core_max_ports(mlxsw_sp->core) / 663 MLXSW_REG_REIV_REC_MAX_COUNT + 1; 664 665 for (i = 0; i < num_port_pages; i++) { 666 err = mlxsw_sp_fid_reiv_handle(fid, rif_index, valid, i); 667 if (err) 668 goto err_reiv_handle; 669 } 670 671 return 0; 672 673 err_reiv_handle: 674 for (; i >= 0; i--) 675 mlxsw_sp_fid_reiv_handle(fid, rif_index, !valid, i); 676 return err; 677 } 678 679 int mlxsw_sp_fid_rif_set(struct mlxsw_sp_fid *fid, struct mlxsw_sp_rif *rif) 680 { 681 u16 rif_index = mlxsw_sp_rif_index(rif); 682 int err; 683 684 err = mlxsw_sp_fid_to_fid_rif_update(fid, rif); 685 if (err) 686 return err; 687 688 err = mlxsw_sp_fid_vni_to_fid_rif_update(fid, rif); 689 if (err) 690 goto err_vni_to_fid_rif_update; 691 692 err = mlxsw_sp_fid_vid_to_fid_rif_set(fid, rif); 693 if (err) 694 goto err_vid_to_fid_rif_set; 695 696 err = mlxsw_sp_fid_erif_eport_to_vid_map(fid, rif_index, true); 697 if (err) 698 goto err_erif_eport_to_vid_map; 699 700 fid->rif = rif; 701 return 0; 702 703 err_erif_eport_to_vid_map: 704 mlxsw_sp_fid_vid_to_fid_rif_unset(fid); 705 err_vid_to_fid_rif_set: 706 mlxsw_sp_fid_vni_to_fid_rif_update(fid, NULL); 707 err_vni_to_fid_rif_update: 708 mlxsw_sp_fid_to_fid_rif_update(fid, NULL); 709 return err; 710 } 711 712 void mlxsw_sp_fid_rif_unset(struct mlxsw_sp_fid *fid) 713 { 714 u16 rif_index; 715 716 if (!fid->rif) 717 return; 718 719 rif_index = mlxsw_sp_rif_index(fid->rif); 720 fid->rif = NULL; 721 722 mlxsw_sp_fid_erif_eport_to_vid_map(fid, rif_index, false); 723 mlxsw_sp_fid_vid_to_fid_rif_unset(fid); 724 mlxsw_sp_fid_vni_to_fid_rif_update(fid, NULL); 725 mlxsw_sp_fid_to_fid_rif_update(fid, NULL); 726 } 727 728 static int mlxsw_sp_fid_vni_op(const struct mlxsw_sp_fid *fid) 729 { 730 int err; 731 732 err = mlxsw_sp_fid_vni_to_fid_map(fid, fid->rif, fid->vni_valid); 733 if (err) 734 return err; 735 736 err = mlxsw_sp_fid_edit_op(fid, fid->rif); 737 if (err) 738 goto err_fid_edit_op; 739 740 return 0; 741 742 err_fid_edit_op: 743 mlxsw_sp_fid_vni_to_fid_map(fid, fid->rif, !fid->vni_valid); 744 return err; 745 } 746 747 static int __mlxsw_sp_fid_port_vid_map(const struct mlxsw_sp_fid *fid, 748 u16 local_port, u16 vid, bool valid) 749 { 750 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; 751 char svfa_pl[MLXSW_REG_SVFA_LEN]; 752 bool irif_valid = false; 753 u16 irif_index = 0; 754 755 if (fid->rif) { 756 irif_valid = true; 757 irif_index = mlxsw_sp_rif_index(fid->rif); 758 } 759 760 mlxsw_reg_svfa_port_vid_pack(svfa_pl, local_port, valid, fid->fid_index, 761 vid, irif_valid, irif_index); 762 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl); 763 } 764 765 static struct mlxsw_sp_fid_8021d * 766 mlxsw_sp_fid_8021d_fid(const struct mlxsw_sp_fid *fid) 767 { 768 return container_of(fid, struct mlxsw_sp_fid_8021d, common); 769 } 770 771 static void mlxsw_sp_fid_8021d_setup(struct mlxsw_sp_fid *fid, const void *arg) 772 { 773 int br_ifindex = *(int *) arg; 774 775 mlxsw_sp_fid_8021d_fid(fid)->br_ifindex = br_ifindex; 776 fid->fid_offset = fid->fid_index - fid->fid_family->start_index; 777 } 778 779 static int mlxsw_sp_fid_8021d_configure(struct mlxsw_sp_fid *fid) 780 { 781 return mlxsw_sp_fid_op(fid, true); 782 } 783 784 static void mlxsw_sp_fid_8021d_deconfigure(struct mlxsw_sp_fid *fid) 785 { 786 if (fid->vni_valid) 787 mlxsw_sp_nve_fid_disable(fid->fid_family->mlxsw_sp, fid); 788 mlxsw_sp_fid_op(fid, false); 789 } 790 791 static int mlxsw_sp_fid_8021d_index_alloc(struct mlxsw_sp_fid *fid, 792 const void *arg, u16 *p_fid_index) 793 { 794 struct mlxsw_sp_fid_family *fid_family = fid->fid_family; 795 u16 nr_fids, fid_index; 796 797 nr_fids = fid_family->end_index - fid_family->start_index + 1; 798 fid_index = find_first_zero_bit(fid_family->fids_bitmap, nr_fids); 799 if (fid_index == nr_fids) 800 return -ENOBUFS; 801 *p_fid_index = fid_family->start_index + fid_index; 802 803 return 0; 804 } 805 806 static bool 807 mlxsw_sp_fid_8021d_compare(const struct mlxsw_sp_fid *fid, const void *arg) 808 { 809 int br_ifindex = *(int *) arg; 810 811 return mlxsw_sp_fid_8021d_fid(fid)->br_ifindex == br_ifindex; 812 } 813 814 static int mlxsw_sp_port_vp_mode_trans(struct mlxsw_sp_port *mlxsw_sp_port) 815 { 816 struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan; 817 int err; 818 819 list_for_each_entry(mlxsw_sp_port_vlan, &mlxsw_sp_port->vlans_list, 820 list) { 821 struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid; 822 u16 vid = mlxsw_sp_port_vlan->vid; 823 824 if (!fid) 825 continue; 826 827 err = __mlxsw_sp_fid_port_vid_map(fid, 828 mlxsw_sp_port->local_port, 829 vid, true); 830 if (err) 831 goto err_fid_port_vid_map; 832 } 833 834 err = mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, true); 835 if (err) 836 goto err_port_vp_mode_set; 837 838 return 0; 839 840 err_port_vp_mode_set: 841 err_fid_port_vid_map: 842 list_for_each_entry_continue_reverse(mlxsw_sp_port_vlan, 843 &mlxsw_sp_port->vlans_list, list) { 844 struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid; 845 u16 vid = mlxsw_sp_port_vlan->vid; 846 847 if (!fid) 848 continue; 849 850 __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, 851 false); 852 } 853 return err; 854 } 855 856 static void mlxsw_sp_port_vlan_mode_trans(struct mlxsw_sp_port *mlxsw_sp_port) 857 { 858 struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan; 859 860 mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, false); 861 862 list_for_each_entry_reverse(mlxsw_sp_port_vlan, 863 &mlxsw_sp_port->vlans_list, list) { 864 struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid; 865 u16 vid = mlxsw_sp_port_vlan->vid; 866 867 if (!fid) 868 continue; 869 870 __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, 871 false); 872 } 873 } 874 875 static int 876 mlxsw_sp_fid_port_vid_list_add(struct mlxsw_sp_fid *fid, u16 local_port, 877 u16 vid) 878 { 879 struct mlxsw_sp_fid_port_vid *port_vid, *tmp_port_vid; 880 881 port_vid = kzalloc(sizeof(*port_vid), GFP_KERNEL); 882 if (!port_vid) 883 return -ENOMEM; 884 885 port_vid->local_port = local_port; 886 port_vid->vid = vid; 887 888 list_for_each_entry(tmp_port_vid, &fid->port_vid_list, list) { 889 if (tmp_port_vid->local_port > local_port) 890 break; 891 } 892 893 list_add_tail(&port_vid->list, &tmp_port_vid->list); 894 return 0; 895 } 896 897 static void 898 mlxsw_sp_fid_port_vid_list_del(struct mlxsw_sp_fid *fid, u16 local_port, 899 u16 vid) 900 { 901 struct mlxsw_sp_fid_port_vid *port_vid, *tmp; 902 903 list_for_each_entry_safe(port_vid, tmp, &fid->port_vid_list, list) { 904 if (port_vid->local_port != local_port || port_vid->vid != vid) 905 continue; 906 907 list_del(&port_vid->list); 908 kfree(port_vid); 909 return; 910 } 911 } 912 913 static int 914 mlxsw_sp_fid_mpe_table_map(const struct mlxsw_sp_fid *fid, u16 local_port, 915 u16 vid, bool valid) 916 { 917 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; 918 char smpe_pl[MLXSW_REG_SMPE_LEN]; 919 920 mlxsw_reg_smpe_pack(smpe_pl, local_port, fid->fid_index, 921 valid ? vid : 0); 922 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(smpe), smpe_pl); 923 } 924 925 static int 926 mlxsw_sp_fid_erif_eport_to_vid_map_one(const struct mlxsw_sp_fid *fid, 927 u16 local_port, u16 vid, bool valid) 928 { 929 u8 port_page = local_port / MLXSW_REG_REIV_REC_MAX_COUNT; 930 u8 rec_num = local_port % MLXSW_REG_REIV_REC_MAX_COUNT; 931 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; 932 u16 rif_index = mlxsw_sp_rif_index(fid->rif); 933 char *reiv_pl; 934 int err; 935 936 reiv_pl = kmalloc(MLXSW_REG_REIV_LEN, GFP_KERNEL); 937 if (!reiv_pl) 938 return -ENOMEM; 939 940 mlxsw_reg_reiv_pack(reiv_pl, port_page, rif_index); 941 mlxsw_reg_reiv_rec_update_set(reiv_pl, rec_num, true); 942 mlxsw_reg_reiv_rec_evid_set(reiv_pl, rec_num, valid ? vid : 0); 943 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(reiv), reiv_pl); 944 kfree(reiv_pl); 945 return err; 946 } 947 948 static int mlxsw_sp_fid_evid_map(const struct mlxsw_sp_fid *fid, u16 local_port, 949 u16 vid, bool valid) 950 { 951 int err; 952 953 err = mlxsw_sp_fid_mpe_table_map(fid, local_port, vid, valid); 954 if (err) 955 return err; 956 957 if (!fid->rif) 958 return 0; 959 960 err = mlxsw_sp_fid_erif_eport_to_vid_map_one(fid, local_port, vid, 961 valid); 962 if (err) 963 goto err_erif_eport_to_vid_map_one; 964 965 return 0; 966 967 err_erif_eport_to_vid_map_one: 968 mlxsw_sp_fid_mpe_table_map(fid, local_port, vid, !valid); 969 return err; 970 } 971 972 static int mlxsw_sp_fid_8021d_port_vid_map(struct mlxsw_sp_fid *fid, 973 struct mlxsw_sp_port *mlxsw_sp_port, 974 u16 vid) 975 { 976 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 977 u16 local_port = mlxsw_sp_port->local_port; 978 int err; 979 980 err = __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, 981 true); 982 if (err) 983 return err; 984 985 err = mlxsw_sp_fid_evid_map(fid, local_port, vid, true); 986 if (err) 987 goto err_fid_evid_map; 988 989 err = mlxsw_sp_fid_port_vid_list_add(fid, mlxsw_sp_port->local_port, 990 vid); 991 if (err) 992 goto err_port_vid_list_add; 993 994 if (mlxsw_sp->fid_core->port_fid_mappings[local_port]++ == 0) { 995 err = mlxsw_sp_port_vp_mode_trans(mlxsw_sp_port); 996 if (err) 997 goto err_port_vp_mode_trans; 998 } 999 1000 return 0; 1001 1002 err_port_vp_mode_trans: 1003 mlxsw_sp->fid_core->port_fid_mappings[local_port]--; 1004 mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid); 1005 err_port_vid_list_add: 1006 mlxsw_sp_fid_evid_map(fid, local_port, vid, false); 1007 err_fid_evid_map: 1008 __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, false); 1009 return err; 1010 } 1011 1012 static void 1013 mlxsw_sp_fid_8021d_port_vid_unmap(struct mlxsw_sp_fid *fid, 1014 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid) 1015 { 1016 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 1017 u16 local_port = mlxsw_sp_port->local_port; 1018 1019 if (mlxsw_sp->fid_core->port_fid_mappings[local_port] == 1) 1020 mlxsw_sp_port_vlan_mode_trans(mlxsw_sp_port); 1021 mlxsw_sp->fid_core->port_fid_mappings[local_port]--; 1022 mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid); 1023 mlxsw_sp_fid_evid_map(fid, local_port, vid, false); 1024 __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, false); 1025 } 1026 1027 static int mlxsw_sp_fid_8021d_vni_set(struct mlxsw_sp_fid *fid) 1028 { 1029 return mlxsw_sp_fid_vni_op(fid); 1030 } 1031 1032 static void mlxsw_sp_fid_8021d_vni_clear(struct mlxsw_sp_fid *fid) 1033 { 1034 mlxsw_sp_fid_vni_op(fid); 1035 } 1036 1037 static int mlxsw_sp_fid_8021d_nve_flood_index_set(struct mlxsw_sp_fid *fid) 1038 { 1039 return mlxsw_sp_fid_edit_op(fid, fid->rif); 1040 } 1041 1042 static void mlxsw_sp_fid_8021d_nve_flood_index_clear(struct mlxsw_sp_fid *fid) 1043 { 1044 mlxsw_sp_fid_edit_op(fid, fid->rif); 1045 } 1046 1047 static void 1048 mlxsw_sp_fid_8021d_fdb_clear_offload(const struct mlxsw_sp_fid *fid, 1049 const struct net_device *nve_dev) 1050 { 1051 br_fdb_clear_offload(nve_dev, 0); 1052 } 1053 1054 static int 1055 mlxsw_sp_fid_8021d_vid_to_fid_rif_update(const struct mlxsw_sp_fid *fid, 1056 const struct mlxsw_sp_rif *rif) 1057 { 1058 return 0; 1059 } 1060 1061 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021d_ops = { 1062 .setup = mlxsw_sp_fid_8021d_setup, 1063 .configure = mlxsw_sp_fid_8021d_configure, 1064 .deconfigure = mlxsw_sp_fid_8021d_deconfigure, 1065 .index_alloc = mlxsw_sp_fid_8021d_index_alloc, 1066 .compare = mlxsw_sp_fid_8021d_compare, 1067 .port_vid_map = mlxsw_sp_fid_8021d_port_vid_map, 1068 .port_vid_unmap = mlxsw_sp_fid_8021d_port_vid_unmap, 1069 .vni_set = mlxsw_sp_fid_8021d_vni_set, 1070 .vni_clear = mlxsw_sp_fid_8021d_vni_clear, 1071 .nve_flood_index_set = mlxsw_sp_fid_8021d_nve_flood_index_set, 1072 .nve_flood_index_clear = mlxsw_sp_fid_8021d_nve_flood_index_clear, 1073 .fdb_clear_offload = mlxsw_sp_fid_8021d_fdb_clear_offload, 1074 .vid_to_fid_rif_update = mlxsw_sp_fid_8021d_vid_to_fid_rif_update, 1075 }; 1076 1077 #define MLXSW_SP_FID_8021Q_MAX (VLAN_N_VID - 2) 1078 #define MLXSW_SP_FID_RFID_MAX (11 * 1024) 1079 1080 static const struct mlxsw_sp_flood_table mlxsw_sp_fid_8021d_flood_tables[] = { 1081 { 1082 .packet_type = MLXSW_SP_FLOOD_TYPE_UC, 1083 .table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFSET, 1084 .table_index = 0, 1085 }, 1086 { 1087 .packet_type = MLXSW_SP_FLOOD_TYPE_MC, 1088 .table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFSET, 1089 .table_index = 1, 1090 }, 1091 { 1092 .packet_type = MLXSW_SP_FLOOD_TYPE_BC, 1093 .table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFSET, 1094 .table_index = 2, 1095 }, 1096 }; 1097 1098 static bool 1099 mlxsw_sp_fid_8021q_compare(const struct mlxsw_sp_fid *fid, const void *arg) 1100 { 1101 u16 vid = *(u16 *) arg; 1102 1103 return mlxsw_sp_fid_8021q_fid(fid)->vid == vid; 1104 } 1105 1106 static void 1107 mlxsw_sp_fid_8021q_fdb_clear_offload(const struct mlxsw_sp_fid *fid, 1108 const struct net_device *nve_dev) 1109 { 1110 br_fdb_clear_offload(nve_dev, mlxsw_sp_fid_8021q_vid(fid)); 1111 } 1112 1113 static void mlxsw_sp_fid_rfid_setup(struct mlxsw_sp_fid *fid, const void *arg) 1114 { 1115 fid->fid_offset = 0; 1116 } 1117 1118 static int mlxsw_sp_fid_rfid_configure(struct mlxsw_sp_fid *fid) 1119 { 1120 return mlxsw_sp_fid_op(fid, true); 1121 } 1122 1123 static void mlxsw_sp_fid_rfid_deconfigure(struct mlxsw_sp_fid *fid) 1124 { 1125 mlxsw_sp_fid_op(fid, false); 1126 } 1127 1128 static int mlxsw_sp_fid_rfid_index_alloc(struct mlxsw_sp_fid *fid, 1129 const void *arg, u16 *p_fid_index) 1130 { 1131 u16 rif_index = *(u16 *) arg; 1132 1133 *p_fid_index = fid->fid_family->start_index + rif_index; 1134 1135 return 0; 1136 } 1137 1138 static bool mlxsw_sp_fid_rfid_compare(const struct mlxsw_sp_fid *fid, 1139 const void *arg) 1140 { 1141 u16 rif_index = *(u16 *) arg; 1142 1143 return fid->fid_index == rif_index + fid->fid_family->start_index; 1144 } 1145 1146 static int mlxsw_sp_fid_rfid_port_vid_map(struct mlxsw_sp_fid *fid, 1147 struct mlxsw_sp_port *mlxsw_sp_port, 1148 u16 vid) 1149 { 1150 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 1151 u16 local_port = mlxsw_sp_port->local_port; 1152 int err; 1153 1154 err = mlxsw_sp_fid_port_vid_list_add(fid, mlxsw_sp_port->local_port, 1155 vid); 1156 if (err) 1157 return err; 1158 1159 /* Using legacy bridge model, we only need to transition the port to 1160 * virtual mode since {Port, VID} => FID is done by the firmware upon 1161 * RIF creation. Using unified bridge model, we need to map 1162 * {Port, VID} => FID and map egress VID. 1163 */ 1164 err = __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, 1165 true); 1166 if (err) 1167 goto err_port_vid_map; 1168 1169 if (fid->rif) { 1170 err = mlxsw_sp_fid_erif_eport_to_vid_map_one(fid, local_port, 1171 vid, true); 1172 if (err) 1173 goto err_erif_eport_to_vid_map_one; 1174 } 1175 1176 if (mlxsw_sp->fid_core->port_fid_mappings[local_port]++ == 0) { 1177 err = mlxsw_sp_port_vp_mode_trans(mlxsw_sp_port); 1178 if (err) 1179 goto err_port_vp_mode_trans; 1180 } 1181 1182 return 0; 1183 1184 err_port_vp_mode_trans: 1185 mlxsw_sp->fid_core->port_fid_mappings[local_port]--; 1186 if (fid->rif) 1187 mlxsw_sp_fid_erif_eport_to_vid_map_one(fid, local_port, vid, 1188 false); 1189 err_erif_eport_to_vid_map_one: 1190 __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, false); 1191 err_port_vid_map: 1192 mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid); 1193 return err; 1194 } 1195 1196 static void 1197 mlxsw_sp_fid_rfid_port_vid_unmap(struct mlxsw_sp_fid *fid, 1198 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid) 1199 { 1200 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 1201 u16 local_port = mlxsw_sp_port->local_port; 1202 1203 if (mlxsw_sp->fid_core->port_fid_mappings[local_port] == 1) 1204 mlxsw_sp_port_vlan_mode_trans(mlxsw_sp_port); 1205 mlxsw_sp->fid_core->port_fid_mappings[local_port]--; 1206 1207 if (fid->rif) 1208 mlxsw_sp_fid_erif_eport_to_vid_map_one(fid, local_port, vid, 1209 false); 1210 __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, false); 1211 mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid); 1212 } 1213 1214 static int mlxsw_sp_fid_rfid_vni_set(struct mlxsw_sp_fid *fid) 1215 { 1216 return -EOPNOTSUPP; 1217 } 1218 1219 static void mlxsw_sp_fid_rfid_vni_clear(struct mlxsw_sp_fid *fid) 1220 { 1221 WARN_ON_ONCE(1); 1222 } 1223 1224 static int mlxsw_sp_fid_rfid_nve_flood_index_set(struct mlxsw_sp_fid *fid) 1225 { 1226 return -EOPNOTSUPP; 1227 } 1228 1229 static void mlxsw_sp_fid_rfid_nve_flood_index_clear(struct mlxsw_sp_fid *fid) 1230 { 1231 WARN_ON_ONCE(1); 1232 } 1233 1234 static int 1235 mlxsw_sp_fid_rfid_vid_to_fid_rif_update(const struct mlxsw_sp_fid *fid, 1236 const struct mlxsw_sp_rif *rif) 1237 { 1238 return 0; 1239 } 1240 1241 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_rfid_ops = { 1242 .setup = mlxsw_sp_fid_rfid_setup, 1243 .configure = mlxsw_sp_fid_rfid_configure, 1244 .deconfigure = mlxsw_sp_fid_rfid_deconfigure, 1245 .index_alloc = mlxsw_sp_fid_rfid_index_alloc, 1246 .compare = mlxsw_sp_fid_rfid_compare, 1247 .port_vid_map = mlxsw_sp_fid_rfid_port_vid_map, 1248 .port_vid_unmap = mlxsw_sp_fid_rfid_port_vid_unmap, 1249 .vni_set = mlxsw_sp_fid_rfid_vni_set, 1250 .vni_clear = mlxsw_sp_fid_rfid_vni_clear, 1251 .nve_flood_index_set = mlxsw_sp_fid_rfid_nve_flood_index_set, 1252 .nve_flood_index_clear = mlxsw_sp_fid_rfid_nve_flood_index_clear, 1253 .vid_to_fid_rif_update = mlxsw_sp_fid_rfid_vid_to_fid_rif_update, 1254 }; 1255 1256 static void mlxsw_sp_fid_dummy_setup(struct mlxsw_sp_fid *fid, const void *arg) 1257 { 1258 fid->fid_offset = 0; 1259 } 1260 1261 static int mlxsw_sp_fid_dummy_configure(struct mlxsw_sp_fid *fid) 1262 { 1263 return mlxsw_sp_fid_op(fid, true); 1264 } 1265 1266 static void mlxsw_sp_fid_dummy_deconfigure(struct mlxsw_sp_fid *fid) 1267 { 1268 mlxsw_sp_fid_op(fid, false); 1269 } 1270 1271 static int mlxsw_sp_fid_dummy_index_alloc(struct mlxsw_sp_fid *fid, 1272 const void *arg, u16 *p_fid_index) 1273 { 1274 *p_fid_index = fid->fid_family->start_index; 1275 1276 return 0; 1277 } 1278 1279 static bool mlxsw_sp_fid_dummy_compare(const struct mlxsw_sp_fid *fid, 1280 const void *arg) 1281 { 1282 return true; 1283 } 1284 1285 static int mlxsw_sp_fid_dummy_vni_set(struct mlxsw_sp_fid *fid) 1286 { 1287 return -EOPNOTSUPP; 1288 } 1289 1290 static void mlxsw_sp_fid_dummy_vni_clear(struct mlxsw_sp_fid *fid) 1291 { 1292 WARN_ON_ONCE(1); 1293 } 1294 1295 static int mlxsw_sp_fid_dummy_nve_flood_index_set(struct mlxsw_sp_fid *fid) 1296 { 1297 return -EOPNOTSUPP; 1298 } 1299 1300 static void mlxsw_sp_fid_dummy_nve_flood_index_clear(struct mlxsw_sp_fid *fid) 1301 { 1302 WARN_ON_ONCE(1); 1303 } 1304 1305 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_dummy_ops = { 1306 .setup = mlxsw_sp_fid_dummy_setup, 1307 .configure = mlxsw_sp_fid_dummy_configure, 1308 .deconfigure = mlxsw_sp_fid_dummy_deconfigure, 1309 .index_alloc = mlxsw_sp_fid_dummy_index_alloc, 1310 .compare = mlxsw_sp_fid_dummy_compare, 1311 .vni_set = mlxsw_sp_fid_dummy_vni_set, 1312 .vni_clear = mlxsw_sp_fid_dummy_vni_clear, 1313 .nve_flood_index_set = mlxsw_sp_fid_dummy_nve_flood_index_set, 1314 .nve_flood_index_clear = mlxsw_sp_fid_dummy_nve_flood_index_clear, 1315 }; 1316 1317 static int mlxsw_sp_fid_8021q_configure(struct mlxsw_sp_fid *fid) 1318 { 1319 struct mlxsw_sp_fid_8021q *fid_8021q = mlxsw_sp_fid_8021q_fid(fid); 1320 int err; 1321 1322 err = mlxsw_sp_fid_op(fid, true); 1323 if (err) 1324 return err; 1325 1326 err = mlxsw_sp_fid_vid_to_fid_map(fid, fid_8021q->vid, true, fid->rif); 1327 if (err) 1328 goto err_vid_to_fid_map; 1329 1330 return 0; 1331 1332 err_vid_to_fid_map: 1333 mlxsw_sp_fid_op(fid, false); 1334 return err; 1335 } 1336 1337 static void mlxsw_sp_fid_8021q_deconfigure(struct mlxsw_sp_fid *fid) 1338 { 1339 struct mlxsw_sp_fid_8021q *fid_8021q = mlxsw_sp_fid_8021q_fid(fid); 1340 1341 if (fid->vni_valid) 1342 mlxsw_sp_nve_fid_disable(fid->fid_family->mlxsw_sp, fid); 1343 1344 mlxsw_sp_fid_vid_to_fid_map(fid, fid_8021q->vid, false, NULL); 1345 mlxsw_sp_fid_op(fid, false); 1346 } 1347 1348 static int mlxsw_sp_fid_8021q_port_vid_map(struct mlxsw_sp_fid *fid, 1349 struct mlxsw_sp_port *mlxsw_sp_port, 1350 u16 vid) 1351 { 1352 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 1353 u16 local_port = mlxsw_sp_port->local_port; 1354 int err; 1355 1356 /* In case there are no {Port, VID} => FID mappings on the port, 1357 * we can use the global VID => FID mapping we created when the 1358 * FID was configured, otherwise, configure new mapping. 1359 */ 1360 if (mlxsw_sp->fid_core->port_fid_mappings[local_port]) { 1361 err = __mlxsw_sp_fid_port_vid_map(fid, local_port, vid, true); 1362 if (err) 1363 return err; 1364 } 1365 1366 err = mlxsw_sp_fid_evid_map(fid, local_port, vid, true); 1367 if (err) 1368 goto err_fid_evid_map; 1369 1370 err = mlxsw_sp_fid_port_vid_list_add(fid, mlxsw_sp_port->local_port, 1371 vid); 1372 if (err) 1373 goto err_port_vid_list_add; 1374 1375 return 0; 1376 1377 err_port_vid_list_add: 1378 mlxsw_sp_fid_evid_map(fid, local_port, vid, false); 1379 err_fid_evid_map: 1380 if (mlxsw_sp->fid_core->port_fid_mappings[local_port]) 1381 __mlxsw_sp_fid_port_vid_map(fid, local_port, vid, false); 1382 return err; 1383 } 1384 1385 static void 1386 mlxsw_sp_fid_8021q_port_vid_unmap(struct mlxsw_sp_fid *fid, 1387 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid) 1388 { 1389 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 1390 u16 local_port = mlxsw_sp_port->local_port; 1391 1392 mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid); 1393 mlxsw_sp_fid_evid_map(fid, local_port, vid, false); 1394 if (mlxsw_sp->fid_core->port_fid_mappings[local_port]) 1395 __mlxsw_sp_fid_port_vid_map(fid, local_port, vid, false); 1396 } 1397 1398 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021q_ops = { 1399 .setup = mlxsw_sp_fid_8021q_setup, 1400 .configure = mlxsw_sp_fid_8021q_configure, 1401 .deconfigure = mlxsw_sp_fid_8021q_deconfigure, 1402 .index_alloc = mlxsw_sp_fid_8021d_index_alloc, 1403 .compare = mlxsw_sp_fid_8021q_compare, 1404 .port_vid_map = mlxsw_sp_fid_8021q_port_vid_map, 1405 .port_vid_unmap = mlxsw_sp_fid_8021q_port_vid_unmap, 1406 .vni_set = mlxsw_sp_fid_8021d_vni_set, 1407 .vni_clear = mlxsw_sp_fid_8021d_vni_clear, 1408 .nve_flood_index_set = mlxsw_sp_fid_8021d_nve_flood_index_set, 1409 .nve_flood_index_clear = mlxsw_sp_fid_8021d_nve_flood_index_clear, 1410 .fdb_clear_offload = mlxsw_sp_fid_8021q_fdb_clear_offload, 1411 .vid_to_fid_rif_update = mlxsw_sp_fid_8021q_vid_to_fid_rif_update, 1412 }; 1413 1414 /* There are 4K-2 802.1Q FIDs */ 1415 #define MLXSW_SP_FID_8021Q_START 1 /* FID 0 is reserved. */ 1416 #define MLXSW_SP_FID_8021Q_END (MLXSW_SP_FID_8021Q_START + \ 1417 MLXSW_SP_FID_8021Q_MAX - 1) 1418 1419 /* There are 1K 802.1D FIDs */ 1420 #define MLXSW_SP_FID_8021D_START (MLXSW_SP_FID_8021Q_END + 1) 1421 #define MLXSW_SP_FID_8021D_END (MLXSW_SP_FID_8021D_START + \ 1422 MLXSW_SP_FID_8021D_MAX - 1) 1423 1424 /* There is one dummy FID */ 1425 #define MLXSW_SP_FID_DUMMY (MLXSW_SP_FID_8021D_END + 1) 1426 1427 /* There are 11K rFIDs */ 1428 #define MLXSW_SP_RFID_START (MLXSW_SP_FID_DUMMY + 1) 1429 #define MLXSW_SP_RFID_END (MLXSW_SP_RFID_START + \ 1430 MLXSW_SP_FID_RFID_MAX - 1) 1431 1432 static const struct mlxsw_sp_fid_family mlxsw_sp1_fid_8021q_family = { 1433 .type = MLXSW_SP_FID_TYPE_8021Q, 1434 .fid_size = sizeof(struct mlxsw_sp_fid_8021q), 1435 .start_index = MLXSW_SP_FID_8021Q_START, 1436 .end_index = MLXSW_SP_FID_8021Q_END, 1437 .flood_tables = mlxsw_sp_fid_8021d_flood_tables, 1438 .nr_flood_tables = ARRAY_SIZE(mlxsw_sp_fid_8021d_flood_tables), 1439 .rif_type = MLXSW_SP_RIF_TYPE_VLAN, 1440 .ops = &mlxsw_sp_fid_8021q_ops, 1441 .flood_rsp = false, 1442 .bridge_type = MLXSW_REG_BRIDGE_TYPE_0, 1443 .smpe_index_valid = false, 1444 }; 1445 1446 static const struct mlxsw_sp_fid_family mlxsw_sp1_fid_8021d_family = { 1447 .type = MLXSW_SP_FID_TYPE_8021D, 1448 .fid_size = sizeof(struct mlxsw_sp_fid_8021d), 1449 .start_index = MLXSW_SP_FID_8021D_START, 1450 .end_index = MLXSW_SP_FID_8021D_END, 1451 .flood_tables = mlxsw_sp_fid_8021d_flood_tables, 1452 .nr_flood_tables = ARRAY_SIZE(mlxsw_sp_fid_8021d_flood_tables), 1453 .rif_type = MLXSW_SP_RIF_TYPE_FID, 1454 .ops = &mlxsw_sp_fid_8021d_ops, 1455 .bridge_type = MLXSW_REG_BRIDGE_TYPE_1, 1456 .smpe_index_valid = false, 1457 }; 1458 1459 static const struct mlxsw_sp_fid_family mlxsw_sp1_fid_dummy_family = { 1460 .type = MLXSW_SP_FID_TYPE_DUMMY, 1461 .fid_size = sizeof(struct mlxsw_sp_fid), 1462 .start_index = MLXSW_SP_FID_DUMMY, 1463 .end_index = MLXSW_SP_FID_DUMMY, 1464 .ops = &mlxsw_sp_fid_dummy_ops, 1465 .smpe_index_valid = false, 1466 }; 1467 1468 static const struct mlxsw_sp_fid_family mlxsw_sp_fid_rfid_family = { 1469 .type = MLXSW_SP_FID_TYPE_RFID, 1470 .fid_size = sizeof(struct mlxsw_sp_fid), 1471 .start_index = MLXSW_SP_RFID_START, 1472 .end_index = MLXSW_SP_RFID_END, 1473 .rif_type = MLXSW_SP_RIF_TYPE_SUBPORT, 1474 .ops = &mlxsw_sp_fid_rfid_ops, 1475 .flood_rsp = true, 1476 .smpe_index_valid = false, 1477 }; 1478 1479 const struct mlxsw_sp_fid_family *mlxsw_sp1_fid_family_arr[] = { 1480 [MLXSW_SP_FID_TYPE_8021Q] = &mlxsw_sp1_fid_8021q_family, 1481 [MLXSW_SP_FID_TYPE_8021D] = &mlxsw_sp1_fid_8021d_family, 1482 [MLXSW_SP_FID_TYPE_DUMMY] = &mlxsw_sp1_fid_dummy_family, 1483 [MLXSW_SP_FID_TYPE_RFID] = &mlxsw_sp_fid_rfid_family, 1484 }; 1485 1486 static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_8021q_family = { 1487 .type = MLXSW_SP_FID_TYPE_8021Q, 1488 .fid_size = sizeof(struct mlxsw_sp_fid_8021q), 1489 .start_index = MLXSW_SP_FID_8021Q_START, 1490 .end_index = MLXSW_SP_FID_8021Q_END, 1491 .flood_tables = mlxsw_sp_fid_8021d_flood_tables, 1492 .nr_flood_tables = ARRAY_SIZE(mlxsw_sp_fid_8021d_flood_tables), 1493 .rif_type = MLXSW_SP_RIF_TYPE_VLAN, 1494 .ops = &mlxsw_sp_fid_8021q_ops, 1495 .flood_rsp = false, 1496 .bridge_type = MLXSW_REG_BRIDGE_TYPE_0, 1497 .smpe_index_valid = true, 1498 }; 1499 1500 static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_8021d_family = { 1501 .type = MLXSW_SP_FID_TYPE_8021D, 1502 .fid_size = sizeof(struct mlxsw_sp_fid_8021d), 1503 .start_index = MLXSW_SP_FID_8021D_START, 1504 .end_index = MLXSW_SP_FID_8021D_END, 1505 .flood_tables = mlxsw_sp_fid_8021d_flood_tables, 1506 .nr_flood_tables = ARRAY_SIZE(mlxsw_sp_fid_8021d_flood_tables), 1507 .rif_type = MLXSW_SP_RIF_TYPE_FID, 1508 .ops = &mlxsw_sp_fid_8021d_ops, 1509 .bridge_type = MLXSW_REG_BRIDGE_TYPE_1, 1510 .smpe_index_valid = true, 1511 }; 1512 1513 static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_dummy_family = { 1514 .type = MLXSW_SP_FID_TYPE_DUMMY, 1515 .fid_size = sizeof(struct mlxsw_sp_fid), 1516 .start_index = MLXSW_SP_FID_DUMMY, 1517 .end_index = MLXSW_SP_FID_DUMMY, 1518 .ops = &mlxsw_sp_fid_dummy_ops, 1519 .smpe_index_valid = false, 1520 }; 1521 1522 const struct mlxsw_sp_fid_family *mlxsw_sp2_fid_family_arr[] = { 1523 [MLXSW_SP_FID_TYPE_8021Q] = &mlxsw_sp2_fid_8021q_family, 1524 [MLXSW_SP_FID_TYPE_8021D] = &mlxsw_sp2_fid_8021d_family, 1525 [MLXSW_SP_FID_TYPE_DUMMY] = &mlxsw_sp2_fid_dummy_family, 1526 [MLXSW_SP_FID_TYPE_RFID] = &mlxsw_sp_fid_rfid_family, 1527 }; 1528 1529 static struct mlxsw_sp_fid *mlxsw_sp_fid_lookup(struct mlxsw_sp *mlxsw_sp, 1530 enum mlxsw_sp_fid_type type, 1531 const void *arg) 1532 { 1533 struct mlxsw_sp_fid_family *fid_family; 1534 struct mlxsw_sp_fid *fid; 1535 1536 fid_family = mlxsw_sp->fid_core->fid_family_arr[type]; 1537 list_for_each_entry(fid, &fid_family->fids_list, list) { 1538 if (!fid->fid_family->ops->compare(fid, arg)) 1539 continue; 1540 refcount_inc(&fid->ref_count); 1541 return fid; 1542 } 1543 1544 return NULL; 1545 } 1546 1547 static struct mlxsw_sp_fid *mlxsw_sp_fid_get(struct mlxsw_sp *mlxsw_sp, 1548 enum mlxsw_sp_fid_type type, 1549 const void *arg) 1550 { 1551 struct mlxsw_sp_fid_family *fid_family; 1552 struct mlxsw_sp_fid *fid; 1553 u16 fid_index; 1554 int err; 1555 1556 fid = mlxsw_sp_fid_lookup(mlxsw_sp, type, arg); 1557 if (fid) 1558 return fid; 1559 1560 fid_family = mlxsw_sp->fid_core->fid_family_arr[type]; 1561 fid = kzalloc(fid_family->fid_size, GFP_KERNEL); 1562 if (!fid) 1563 return ERR_PTR(-ENOMEM); 1564 1565 INIT_LIST_HEAD(&fid->port_vid_list); 1566 fid->fid_family = fid_family; 1567 1568 err = fid->fid_family->ops->index_alloc(fid, arg, &fid_index); 1569 if (err) 1570 goto err_index_alloc; 1571 fid->fid_index = fid_index; 1572 __set_bit(fid_index - fid_family->start_index, fid_family->fids_bitmap); 1573 1574 fid->fid_family->ops->setup(fid, arg); 1575 1576 err = fid->fid_family->ops->configure(fid); 1577 if (err) 1578 goto err_configure; 1579 1580 err = rhashtable_insert_fast(&mlxsw_sp->fid_core->fid_ht, &fid->ht_node, 1581 mlxsw_sp_fid_ht_params); 1582 if (err) 1583 goto err_rhashtable_insert; 1584 1585 list_add(&fid->list, &fid_family->fids_list); 1586 refcount_set(&fid->ref_count, 1); 1587 return fid; 1588 1589 err_rhashtable_insert: 1590 fid->fid_family->ops->deconfigure(fid); 1591 err_configure: 1592 __clear_bit(fid_index - fid_family->start_index, 1593 fid_family->fids_bitmap); 1594 err_index_alloc: 1595 kfree(fid); 1596 return ERR_PTR(err); 1597 } 1598 1599 void mlxsw_sp_fid_put(struct mlxsw_sp_fid *fid) 1600 { 1601 struct mlxsw_sp_fid_family *fid_family = fid->fid_family; 1602 struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp; 1603 1604 if (!refcount_dec_and_test(&fid->ref_count)) 1605 return; 1606 1607 list_del(&fid->list); 1608 rhashtable_remove_fast(&mlxsw_sp->fid_core->fid_ht, 1609 &fid->ht_node, mlxsw_sp_fid_ht_params); 1610 fid->fid_family->ops->deconfigure(fid); 1611 __clear_bit(fid->fid_index - fid_family->start_index, 1612 fid_family->fids_bitmap); 1613 WARN_ON_ONCE(!list_empty(&fid->port_vid_list)); 1614 kfree(fid); 1615 } 1616 1617 struct mlxsw_sp_fid *mlxsw_sp_fid_8021q_get(struct mlxsw_sp *mlxsw_sp, u16 vid) 1618 { 1619 return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_8021Q, &vid); 1620 } 1621 1622 struct mlxsw_sp_fid *mlxsw_sp_fid_8021d_get(struct mlxsw_sp *mlxsw_sp, 1623 int br_ifindex) 1624 { 1625 return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_8021D, &br_ifindex); 1626 } 1627 1628 struct mlxsw_sp_fid *mlxsw_sp_fid_8021q_lookup(struct mlxsw_sp *mlxsw_sp, 1629 u16 vid) 1630 { 1631 return mlxsw_sp_fid_lookup(mlxsw_sp, MLXSW_SP_FID_TYPE_8021Q, &vid); 1632 } 1633 1634 struct mlxsw_sp_fid *mlxsw_sp_fid_8021d_lookup(struct mlxsw_sp *mlxsw_sp, 1635 int br_ifindex) 1636 { 1637 return mlxsw_sp_fid_lookup(mlxsw_sp, MLXSW_SP_FID_TYPE_8021D, 1638 &br_ifindex); 1639 } 1640 1641 struct mlxsw_sp_fid *mlxsw_sp_fid_rfid_get(struct mlxsw_sp *mlxsw_sp, 1642 u16 rif_index) 1643 { 1644 return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_RFID, &rif_index); 1645 } 1646 1647 struct mlxsw_sp_fid *mlxsw_sp_fid_dummy_get(struct mlxsw_sp *mlxsw_sp) 1648 { 1649 return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_DUMMY, NULL); 1650 } 1651 1652 static int 1653 mlxsw_sp_fid_flood_table_init(struct mlxsw_sp_fid_family *fid_family, 1654 const struct mlxsw_sp_flood_table *flood_table) 1655 { 1656 enum mlxsw_sp_flood_type packet_type = flood_table->packet_type; 1657 struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp; 1658 const int *sfgc_packet_types; 1659 u16 mid_base; 1660 int err, i; 1661 1662 mid_base = mlxsw_sp_fid_flood_table_mid(fid_family, flood_table, 0); 1663 1664 sfgc_packet_types = mlxsw_sp_packet_type_sfgc_types[packet_type]; 1665 for (i = 0; i < MLXSW_REG_SFGC_TYPE_MAX; i++) { 1666 char sfgc_pl[MLXSW_REG_SFGC_LEN]; 1667 1668 if (!sfgc_packet_types[i]) 1669 continue; 1670 1671 mlxsw_reg_sfgc_pack(sfgc_pl, i, fid_family->bridge_type, 1672 flood_table->table_type, 0, mid_base); 1673 1674 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfgc), sfgc_pl); 1675 if (err) 1676 return err; 1677 } 1678 1679 return 0; 1680 } 1681 1682 static int 1683 mlxsw_sp_fid_flood_tables_init(struct mlxsw_sp_fid_family *fid_family) 1684 { 1685 struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp; 1686 u16 pgt_size; 1687 int err; 1688 int i; 1689 1690 if (!fid_family->nr_flood_tables) 1691 return 0; 1692 1693 pgt_size = mlxsw_sp_fid_family_pgt_size(fid_family); 1694 err = mlxsw_sp_pgt_mid_alloc_range(mlxsw_sp, &fid_family->pgt_base, 1695 pgt_size); 1696 if (err) 1697 return err; 1698 1699 for (i = 0; i < fid_family->nr_flood_tables; i++) { 1700 const struct mlxsw_sp_flood_table *flood_table; 1701 1702 flood_table = &fid_family->flood_tables[i]; 1703 err = mlxsw_sp_fid_flood_table_init(fid_family, flood_table); 1704 if (err) 1705 goto err_flood_table_init; 1706 } 1707 1708 return 0; 1709 1710 err_flood_table_init: 1711 mlxsw_sp_pgt_mid_free_range(mlxsw_sp, fid_family->pgt_base, pgt_size); 1712 return err; 1713 } 1714 1715 static void 1716 mlxsw_sp_fid_flood_tables_fini(struct mlxsw_sp_fid_family *fid_family) 1717 { 1718 struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp; 1719 u16 pgt_size; 1720 1721 if (!fid_family->nr_flood_tables) 1722 return; 1723 1724 pgt_size = mlxsw_sp_fid_family_pgt_size(fid_family); 1725 mlxsw_sp_pgt_mid_free_range(mlxsw_sp, fid_family->pgt_base, pgt_size); 1726 } 1727 1728 static int mlxsw_sp_fid_family_register(struct mlxsw_sp *mlxsw_sp, 1729 const struct mlxsw_sp_fid_family *tmpl) 1730 { 1731 u16 nr_fids = tmpl->end_index - tmpl->start_index + 1; 1732 struct mlxsw_sp_fid_family *fid_family; 1733 int err; 1734 1735 fid_family = kmemdup(tmpl, sizeof(*fid_family), GFP_KERNEL); 1736 if (!fid_family) 1737 return -ENOMEM; 1738 1739 fid_family->mlxsw_sp = mlxsw_sp; 1740 INIT_LIST_HEAD(&fid_family->fids_list); 1741 fid_family->fids_bitmap = bitmap_zalloc(nr_fids, GFP_KERNEL); 1742 if (!fid_family->fids_bitmap) { 1743 err = -ENOMEM; 1744 goto err_alloc_fids_bitmap; 1745 } 1746 1747 if (fid_family->flood_tables) { 1748 err = mlxsw_sp_fid_flood_tables_init(fid_family); 1749 if (err) 1750 goto err_fid_flood_tables_init; 1751 } 1752 1753 mlxsw_sp->fid_core->fid_family_arr[tmpl->type] = fid_family; 1754 1755 return 0; 1756 1757 err_fid_flood_tables_init: 1758 bitmap_free(fid_family->fids_bitmap); 1759 err_alloc_fids_bitmap: 1760 kfree(fid_family); 1761 return err; 1762 } 1763 1764 static void 1765 mlxsw_sp_fid_family_unregister(struct mlxsw_sp *mlxsw_sp, 1766 struct mlxsw_sp_fid_family *fid_family) 1767 { 1768 mlxsw_sp->fid_core->fid_family_arr[fid_family->type] = NULL; 1769 1770 if (fid_family->flood_tables) 1771 mlxsw_sp_fid_flood_tables_fini(fid_family); 1772 1773 bitmap_free(fid_family->fids_bitmap); 1774 WARN_ON_ONCE(!list_empty(&fid_family->fids_list)); 1775 kfree(fid_family); 1776 } 1777 1778 int mlxsw_sp_port_fids_init(struct mlxsw_sp_port *mlxsw_sp_port) 1779 { 1780 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 1781 1782 /* Track number of FIDs configured on the port with mapping type 1783 * PORT_VID_TO_FID, so that we know when to transition the port 1784 * back to non-virtual (VLAN) mode. 1785 */ 1786 mlxsw_sp->fid_core->port_fid_mappings[mlxsw_sp_port->local_port] = 0; 1787 1788 return mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, false); 1789 } 1790 1791 void mlxsw_sp_port_fids_fini(struct mlxsw_sp_port *mlxsw_sp_port) 1792 { 1793 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 1794 1795 mlxsw_sp->fid_core->port_fid_mappings[mlxsw_sp_port->local_port] = 0; 1796 } 1797 1798 int mlxsw_sp_fids_init(struct mlxsw_sp *mlxsw_sp) 1799 { 1800 unsigned int max_ports = mlxsw_core_max_ports(mlxsw_sp->core); 1801 struct mlxsw_sp_fid_core *fid_core; 1802 int err, i; 1803 1804 fid_core = kzalloc(sizeof(*mlxsw_sp->fid_core), GFP_KERNEL); 1805 if (!fid_core) 1806 return -ENOMEM; 1807 mlxsw_sp->fid_core = fid_core; 1808 1809 err = rhashtable_init(&fid_core->fid_ht, &mlxsw_sp_fid_ht_params); 1810 if (err) 1811 goto err_rhashtable_fid_init; 1812 1813 err = rhashtable_init(&fid_core->vni_ht, &mlxsw_sp_fid_vni_ht_params); 1814 if (err) 1815 goto err_rhashtable_vni_init; 1816 1817 fid_core->port_fid_mappings = kcalloc(max_ports, sizeof(unsigned int), 1818 GFP_KERNEL); 1819 if (!fid_core->port_fid_mappings) { 1820 err = -ENOMEM; 1821 goto err_alloc_port_fid_mappings; 1822 } 1823 1824 for (i = 0; i < MLXSW_SP_FID_TYPE_MAX; i++) { 1825 err = mlxsw_sp_fid_family_register(mlxsw_sp, 1826 mlxsw_sp->fid_family_arr[i]); 1827 1828 if (err) 1829 goto err_fid_ops_register; 1830 } 1831 1832 return 0; 1833 1834 err_fid_ops_register: 1835 for (i--; i >= 0; i--) { 1836 struct mlxsw_sp_fid_family *fid_family; 1837 1838 fid_family = fid_core->fid_family_arr[i]; 1839 mlxsw_sp_fid_family_unregister(mlxsw_sp, fid_family); 1840 } 1841 kfree(fid_core->port_fid_mappings); 1842 err_alloc_port_fid_mappings: 1843 rhashtable_destroy(&fid_core->vni_ht); 1844 err_rhashtable_vni_init: 1845 rhashtable_destroy(&fid_core->fid_ht); 1846 err_rhashtable_fid_init: 1847 kfree(fid_core); 1848 return err; 1849 } 1850 1851 void mlxsw_sp_fids_fini(struct mlxsw_sp *mlxsw_sp) 1852 { 1853 struct mlxsw_sp_fid_core *fid_core = mlxsw_sp->fid_core; 1854 int i; 1855 1856 for (i = 0; i < MLXSW_SP_FID_TYPE_MAX; i++) 1857 mlxsw_sp_fid_family_unregister(mlxsw_sp, 1858 fid_core->fid_family_arr[i]); 1859 kfree(fid_core->port_fid_mappings); 1860 rhashtable_destroy(&fid_core->vni_ht); 1861 rhashtable_destroy(&fid_core->fid_ht); 1862 kfree(fid_core); 1863 } 1864