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