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