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 u16 (*flood_index)(const struct mlxsw_sp_fid *fid); 87 int (*port_vid_map)(struct mlxsw_sp_fid *fid, 88 struct mlxsw_sp_port *port, u16 vid); 89 void (*port_vid_unmap)(struct mlxsw_sp_fid *fid, 90 struct mlxsw_sp_port *port, u16 vid); 91 int (*vni_set)(struct mlxsw_sp_fid *fid); 92 void (*vni_clear)(struct mlxsw_sp_fid *fid); 93 int (*nve_flood_index_set)(struct mlxsw_sp_fid *fid); 94 void (*nve_flood_index_clear)(struct mlxsw_sp_fid *fid); 95 void (*fdb_clear_offload)(const struct mlxsw_sp_fid *fid, 96 const struct net_device *nve_dev); 97 }; 98 99 struct mlxsw_sp_fid_family { 100 enum mlxsw_sp_fid_type type; 101 size_t fid_size; 102 u16 start_index; 103 u16 end_index; 104 struct list_head fids_list; 105 unsigned long *fids_bitmap; 106 const struct mlxsw_sp_flood_table *flood_tables; 107 int nr_flood_tables; 108 enum mlxsw_sp_rif_type rif_type; 109 const struct mlxsw_sp_fid_ops *ops; 110 struct mlxsw_sp *mlxsw_sp; 111 bool flood_rsp; 112 enum mlxsw_reg_bridge_type bridge_type; 113 u16 pgt_base; 114 }; 115 116 static const int mlxsw_sp_sfgc_uc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = { 117 [MLXSW_REG_SFGC_TYPE_UNKNOWN_UNICAST] = 1, 118 }; 119 120 static const int mlxsw_sp_sfgc_bc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = { 121 [MLXSW_REG_SFGC_TYPE_BROADCAST] = 1, 122 [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_NON_IP] = 1, 123 [MLXSW_REG_SFGC_TYPE_IPV4_LINK_LOCAL] = 1, 124 [MLXSW_REG_SFGC_TYPE_IPV6_ALL_HOST] = 1, 125 [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV6] = 1, 126 }; 127 128 static const int mlxsw_sp_sfgc_mc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = { 129 [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV4] = 1, 130 }; 131 132 static const int *mlxsw_sp_packet_type_sfgc_types[] = { 133 [MLXSW_SP_FLOOD_TYPE_UC] = mlxsw_sp_sfgc_uc_packet_types, 134 [MLXSW_SP_FLOOD_TYPE_BC] = mlxsw_sp_sfgc_bc_packet_types, 135 [MLXSW_SP_FLOOD_TYPE_MC] = mlxsw_sp_sfgc_mc_packet_types, 136 }; 137 138 bool mlxsw_sp_fid_is_dummy(struct mlxsw_sp *mlxsw_sp, u16 fid_index) 139 { 140 enum mlxsw_sp_fid_type fid_type = MLXSW_SP_FID_TYPE_DUMMY; 141 struct mlxsw_sp_fid_family *fid_family; 142 143 fid_family = mlxsw_sp->fid_core->fid_family_arr[fid_type]; 144 145 return fid_family->start_index == fid_index; 146 } 147 148 struct mlxsw_sp_fid *mlxsw_sp_fid_lookup_by_index(struct mlxsw_sp *mlxsw_sp, 149 u16 fid_index) 150 { 151 struct mlxsw_sp_fid *fid; 152 153 fid = rhashtable_lookup_fast(&mlxsw_sp->fid_core->fid_ht, &fid_index, 154 mlxsw_sp_fid_ht_params); 155 if (fid) 156 refcount_inc(&fid->ref_count); 157 158 return fid; 159 } 160 161 int mlxsw_sp_fid_nve_ifindex(const struct mlxsw_sp_fid *fid, int *nve_ifindex) 162 { 163 if (!fid->vni_valid) 164 return -EINVAL; 165 166 *nve_ifindex = fid->nve_ifindex; 167 168 return 0; 169 } 170 171 int mlxsw_sp_fid_nve_type(const struct mlxsw_sp_fid *fid, 172 enum mlxsw_sp_nve_type *p_type) 173 { 174 if (!fid->vni_valid) 175 return -EINVAL; 176 177 *p_type = fid->nve_type; 178 179 return 0; 180 } 181 182 struct mlxsw_sp_fid *mlxsw_sp_fid_lookup_by_vni(struct mlxsw_sp *mlxsw_sp, 183 __be32 vni) 184 { 185 struct mlxsw_sp_fid *fid; 186 187 fid = rhashtable_lookup_fast(&mlxsw_sp->fid_core->vni_ht, &vni, 188 mlxsw_sp_fid_vni_ht_params); 189 if (fid) 190 refcount_inc(&fid->ref_count); 191 192 return fid; 193 } 194 195 int mlxsw_sp_fid_vni(const struct mlxsw_sp_fid *fid, __be32 *vni) 196 { 197 if (!fid->vni_valid) 198 return -EINVAL; 199 200 *vni = fid->vni; 201 202 return 0; 203 } 204 205 int mlxsw_sp_fid_nve_flood_index_set(struct mlxsw_sp_fid *fid, 206 u32 nve_flood_index) 207 { 208 struct mlxsw_sp_fid_family *fid_family = fid->fid_family; 209 const struct mlxsw_sp_fid_ops *ops = fid_family->ops; 210 int err; 211 212 if (WARN_ON(fid->nve_flood_index_valid)) 213 return -EINVAL; 214 215 fid->nve_flood_index = nve_flood_index; 216 fid->nve_flood_index_valid = true; 217 err = ops->nve_flood_index_set(fid); 218 if (err) 219 goto err_nve_flood_index_set; 220 221 return 0; 222 223 err_nve_flood_index_set: 224 fid->nve_flood_index_valid = false; 225 return err; 226 } 227 228 void mlxsw_sp_fid_nve_flood_index_clear(struct mlxsw_sp_fid *fid) 229 { 230 struct mlxsw_sp_fid_family *fid_family = fid->fid_family; 231 const struct mlxsw_sp_fid_ops *ops = fid_family->ops; 232 233 if (WARN_ON(!fid->nve_flood_index_valid)) 234 return; 235 236 fid->nve_flood_index_valid = false; 237 ops->nve_flood_index_clear(fid); 238 } 239 240 bool mlxsw_sp_fid_nve_flood_index_is_set(const struct mlxsw_sp_fid *fid) 241 { 242 return fid->nve_flood_index_valid; 243 } 244 245 int mlxsw_sp_fid_vni_set(struct mlxsw_sp_fid *fid, enum mlxsw_sp_nve_type type, 246 __be32 vni, int nve_ifindex) 247 { 248 struct mlxsw_sp_fid_family *fid_family = fid->fid_family; 249 const struct mlxsw_sp_fid_ops *ops = fid_family->ops; 250 struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp; 251 int err; 252 253 if (WARN_ON(fid->vni_valid)) 254 return -EINVAL; 255 256 fid->nve_type = type; 257 fid->nve_ifindex = nve_ifindex; 258 fid->vni = vni; 259 err = rhashtable_lookup_insert_fast(&mlxsw_sp->fid_core->vni_ht, 260 &fid->vni_ht_node, 261 mlxsw_sp_fid_vni_ht_params); 262 if (err) 263 return err; 264 265 fid->vni_valid = true; 266 err = ops->vni_set(fid); 267 if (err) 268 goto err_vni_set; 269 270 return 0; 271 272 err_vni_set: 273 fid->vni_valid = false; 274 rhashtable_remove_fast(&mlxsw_sp->fid_core->vni_ht, &fid->vni_ht_node, 275 mlxsw_sp_fid_vni_ht_params); 276 return err; 277 } 278 279 void mlxsw_sp_fid_vni_clear(struct mlxsw_sp_fid *fid) 280 { 281 struct mlxsw_sp_fid_family *fid_family = fid->fid_family; 282 const struct mlxsw_sp_fid_ops *ops = fid_family->ops; 283 struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp; 284 285 if (WARN_ON(!fid->vni_valid)) 286 return; 287 288 fid->vni_valid = false; 289 ops->vni_clear(fid); 290 rhashtable_remove_fast(&mlxsw_sp->fid_core->vni_ht, &fid->vni_ht_node, 291 mlxsw_sp_fid_vni_ht_params); 292 } 293 294 bool mlxsw_sp_fid_vni_is_set(const struct mlxsw_sp_fid *fid) 295 { 296 return fid->vni_valid; 297 } 298 299 void mlxsw_sp_fid_fdb_clear_offload(const struct mlxsw_sp_fid *fid, 300 const struct net_device *nve_dev) 301 { 302 struct mlxsw_sp_fid_family *fid_family = fid->fid_family; 303 const struct mlxsw_sp_fid_ops *ops = fid_family->ops; 304 305 if (ops->fdb_clear_offload) 306 ops->fdb_clear_offload(fid, nve_dev); 307 } 308 309 static const struct mlxsw_sp_flood_table * 310 mlxsw_sp_fid_flood_table_lookup(const struct mlxsw_sp_fid *fid, 311 enum mlxsw_sp_flood_type packet_type) 312 { 313 struct mlxsw_sp_fid_family *fid_family = fid->fid_family; 314 int i; 315 316 for (i = 0; i < fid_family->nr_flood_tables; i++) { 317 if (fid_family->flood_tables[i].packet_type != packet_type) 318 continue; 319 return &fid_family->flood_tables[i]; 320 } 321 322 return NULL; 323 } 324 325 static u16 326 mlxsw_sp_fid_family_num_fids(const struct mlxsw_sp_fid_family *fid_family) 327 { 328 return fid_family->end_index - fid_family->start_index + 1; 329 } 330 331 static u16 332 mlxsw_sp_fid_flood_table_mid(const struct mlxsw_sp_fid_family *fid_family, 333 const struct mlxsw_sp_flood_table *flood_table, 334 u16 fid_offset) 335 { 336 u16 num_fids; 337 338 num_fids = mlxsw_sp_fid_family_num_fids(fid_family); 339 return fid_family->pgt_base + num_fids * flood_table->table_index + 340 fid_offset; 341 } 342 343 int mlxsw_sp_fid_flood_set(struct mlxsw_sp_fid *fid, 344 enum mlxsw_sp_flood_type packet_type, u16 local_port, 345 bool member) 346 { 347 struct mlxsw_sp_fid_family *fid_family = fid->fid_family; 348 const struct mlxsw_sp_fid_ops *ops = fid_family->ops; 349 const struct mlxsw_sp_flood_table *flood_table; 350 char *sftr2_pl; 351 u16 mid_index; 352 int err; 353 354 if (WARN_ON(!fid_family->flood_tables || !ops->flood_index)) 355 return -EINVAL; 356 357 flood_table = mlxsw_sp_fid_flood_table_lookup(fid, packet_type); 358 if (!flood_table) 359 return -ESRCH; 360 361 if (fid_family->mlxsw_sp->ubridge) { 362 mid_index = mlxsw_sp_fid_flood_table_mid(fid_family, 363 flood_table, 364 fid->fid_offset); 365 return mlxsw_sp_pgt_entry_port_set(fid_family->mlxsw_sp, 366 mid_index, fid->fid_index, 367 local_port, member); 368 } 369 370 sftr2_pl = kmalloc(MLXSW_REG_SFTR2_LEN, GFP_KERNEL); 371 if (!sftr2_pl) 372 return -ENOMEM; 373 374 mlxsw_reg_sftr2_pack(sftr2_pl, flood_table->table_index, 375 ops->flood_index(fid), flood_table->table_type, 1, 376 local_port, member); 377 err = mlxsw_reg_write(fid_family->mlxsw_sp->core, MLXSW_REG(sftr2), 378 sftr2_pl); 379 kfree(sftr2_pl); 380 return err; 381 } 382 383 int mlxsw_sp_fid_port_vid_map(struct mlxsw_sp_fid *fid, 384 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid) 385 { 386 if (WARN_ON(!fid->fid_family->ops->port_vid_map)) 387 return -EINVAL; 388 return fid->fid_family->ops->port_vid_map(fid, mlxsw_sp_port, vid); 389 } 390 391 void mlxsw_sp_fid_port_vid_unmap(struct mlxsw_sp_fid *fid, 392 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid) 393 { 394 fid->fid_family->ops->port_vid_unmap(fid, mlxsw_sp_port, vid); 395 } 396 397 u16 mlxsw_sp_fid_index(const struct mlxsw_sp_fid *fid) 398 { 399 return fid->fid_index; 400 } 401 402 enum mlxsw_sp_fid_type mlxsw_sp_fid_type(const struct mlxsw_sp_fid *fid) 403 { 404 return fid->fid_family->type; 405 } 406 407 void mlxsw_sp_fid_rif_set(struct mlxsw_sp_fid *fid, struct mlxsw_sp_rif *rif) 408 { 409 fid->rif = rif; 410 } 411 412 struct mlxsw_sp_rif *mlxsw_sp_fid_rif(const struct mlxsw_sp_fid *fid) 413 { 414 return fid->rif; 415 } 416 417 enum mlxsw_sp_rif_type 418 mlxsw_sp_fid_type_rif_type(const struct mlxsw_sp *mlxsw_sp, 419 enum mlxsw_sp_fid_type type) 420 { 421 struct mlxsw_sp_fid_core *fid_core = mlxsw_sp->fid_core; 422 423 return fid_core->fid_family_arr[type]->rif_type; 424 } 425 426 static struct mlxsw_sp_fid_8021q * 427 mlxsw_sp_fid_8021q_fid(const struct mlxsw_sp_fid *fid) 428 { 429 return container_of(fid, struct mlxsw_sp_fid_8021q, common); 430 } 431 432 u16 mlxsw_sp_fid_8021q_vid(const struct mlxsw_sp_fid *fid) 433 { 434 return mlxsw_sp_fid_8021q_fid(fid)->vid; 435 } 436 437 static void mlxsw_sp_fid_8021q_setup(struct mlxsw_sp_fid *fid, const void *arg) 438 { 439 u16 vid = *(u16 *) arg; 440 441 mlxsw_sp_fid_8021q_fid(fid)->vid = vid; 442 fid->fid_offset = 0; 443 } 444 445 static enum mlxsw_reg_sfmr_op mlxsw_sp_sfmr_op(bool valid) 446 { 447 return valid ? MLXSW_REG_SFMR_OP_CREATE_FID : 448 MLXSW_REG_SFMR_OP_DESTROY_FID; 449 } 450 451 static int mlxsw_sp_fid_op(const struct mlxsw_sp_fid *fid, bool valid) 452 { 453 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; 454 enum mlxsw_reg_bridge_type bridge_type = 0; 455 char sfmr_pl[MLXSW_REG_SFMR_LEN]; 456 bool flood_rsp = false; 457 458 if (mlxsw_sp->ubridge) { 459 flood_rsp = fid->fid_family->flood_rsp; 460 bridge_type = fid->fid_family->bridge_type; 461 } 462 463 mlxsw_reg_sfmr_pack(sfmr_pl, mlxsw_sp_sfmr_op(valid), fid->fid_index, 464 fid->fid_offset, flood_rsp, bridge_type); 465 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl); 466 } 467 468 static int mlxsw_sp_fid_edit_op(const struct mlxsw_sp_fid *fid) 469 { 470 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; 471 enum mlxsw_reg_bridge_type bridge_type = 0; 472 char sfmr_pl[MLXSW_REG_SFMR_LEN]; 473 bool flood_rsp = false; 474 475 if (mlxsw_sp->ubridge) { 476 flood_rsp = fid->fid_family->flood_rsp; 477 bridge_type = fid->fid_family->bridge_type; 478 } 479 480 mlxsw_reg_sfmr_pack(sfmr_pl, MLXSW_REG_SFMR_OP_CREATE_FID, 481 fid->fid_index, fid->fid_offset, flood_rsp, 482 bridge_type); 483 mlxsw_reg_sfmr_vv_set(sfmr_pl, fid->vni_valid); 484 mlxsw_reg_sfmr_vni_set(sfmr_pl, be32_to_cpu(fid->vni)); 485 mlxsw_reg_sfmr_vtfp_set(sfmr_pl, fid->nve_flood_index_valid); 486 mlxsw_reg_sfmr_nve_tunnel_flood_ptr_set(sfmr_pl, fid->nve_flood_index); 487 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl); 488 } 489 490 static int __mlxsw_sp_fid_port_vid_map(const struct mlxsw_sp_fid *fid, 491 u16 local_port, u16 vid, bool valid) 492 { 493 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; 494 char svfa_pl[MLXSW_REG_SVFA_LEN]; 495 496 mlxsw_reg_svfa_port_vid_pack(svfa_pl, local_port, valid, fid->fid_index, 497 vid); 498 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl); 499 } 500 501 static struct mlxsw_sp_fid_8021d * 502 mlxsw_sp_fid_8021d_fid(const struct mlxsw_sp_fid *fid) 503 { 504 return container_of(fid, struct mlxsw_sp_fid_8021d, common); 505 } 506 507 static void mlxsw_sp_fid_8021d_setup(struct mlxsw_sp_fid *fid, const void *arg) 508 { 509 int br_ifindex = *(int *) arg; 510 511 mlxsw_sp_fid_8021d_fid(fid)->br_ifindex = br_ifindex; 512 fid->fid_offset = 0; 513 } 514 515 static int mlxsw_sp_fid_8021d_configure(struct mlxsw_sp_fid *fid) 516 { 517 return mlxsw_sp_fid_op(fid, true); 518 } 519 520 static void mlxsw_sp_fid_8021d_deconfigure(struct mlxsw_sp_fid *fid) 521 { 522 if (fid->vni_valid) 523 mlxsw_sp_nve_fid_disable(fid->fid_family->mlxsw_sp, fid); 524 mlxsw_sp_fid_op(fid, false); 525 } 526 527 static int mlxsw_sp_fid_8021d_index_alloc(struct mlxsw_sp_fid *fid, 528 const void *arg, u16 *p_fid_index) 529 { 530 struct mlxsw_sp_fid_family *fid_family = fid->fid_family; 531 u16 nr_fids, fid_index; 532 533 nr_fids = fid_family->end_index - fid_family->start_index + 1; 534 fid_index = find_first_zero_bit(fid_family->fids_bitmap, nr_fids); 535 if (fid_index == nr_fids) 536 return -ENOBUFS; 537 *p_fid_index = fid_family->start_index + fid_index; 538 539 return 0; 540 } 541 542 static bool 543 mlxsw_sp_fid_8021d_compare(const struct mlxsw_sp_fid *fid, const void *arg) 544 { 545 int br_ifindex = *(int *) arg; 546 547 return mlxsw_sp_fid_8021d_fid(fid)->br_ifindex == br_ifindex; 548 } 549 550 static u16 mlxsw_sp_fid_8021d_flood_index(const struct mlxsw_sp_fid *fid) 551 { 552 return fid->fid_index - VLAN_N_VID; 553 } 554 555 static int mlxsw_sp_port_vp_mode_trans(struct mlxsw_sp_port *mlxsw_sp_port) 556 { 557 struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan; 558 int err; 559 560 list_for_each_entry(mlxsw_sp_port_vlan, &mlxsw_sp_port->vlans_list, 561 list) { 562 struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid; 563 u16 vid = mlxsw_sp_port_vlan->vid; 564 565 if (!fid) 566 continue; 567 568 err = __mlxsw_sp_fid_port_vid_map(fid, 569 mlxsw_sp_port->local_port, 570 vid, true); 571 if (err) 572 goto err_fid_port_vid_map; 573 } 574 575 err = mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, true); 576 if (err) 577 goto err_port_vp_mode_set; 578 579 return 0; 580 581 err_port_vp_mode_set: 582 err_fid_port_vid_map: 583 list_for_each_entry_continue_reverse(mlxsw_sp_port_vlan, 584 &mlxsw_sp_port->vlans_list, list) { 585 struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid; 586 u16 vid = mlxsw_sp_port_vlan->vid; 587 588 if (!fid) 589 continue; 590 591 __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, 592 false); 593 } 594 return err; 595 } 596 597 static void mlxsw_sp_port_vlan_mode_trans(struct mlxsw_sp_port *mlxsw_sp_port) 598 { 599 struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan; 600 601 mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, false); 602 603 list_for_each_entry_reverse(mlxsw_sp_port_vlan, 604 &mlxsw_sp_port->vlans_list, list) { 605 struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid; 606 u16 vid = mlxsw_sp_port_vlan->vid; 607 608 if (!fid) 609 continue; 610 611 __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, 612 false); 613 } 614 } 615 616 static int 617 mlxsw_sp_fid_port_vid_list_add(struct mlxsw_sp_fid *fid, u16 local_port, 618 u16 vid) 619 { 620 struct mlxsw_sp_fid_port_vid *port_vid, *tmp_port_vid; 621 622 port_vid = kzalloc(sizeof(*port_vid), GFP_KERNEL); 623 if (!port_vid) 624 return -ENOMEM; 625 626 port_vid->local_port = local_port; 627 port_vid->vid = vid; 628 629 list_for_each_entry(tmp_port_vid, &fid->port_vid_list, list) { 630 if (tmp_port_vid->local_port > local_port) 631 break; 632 } 633 634 list_add_tail(&port_vid->list, &tmp_port_vid->list); 635 return 0; 636 } 637 638 static void 639 mlxsw_sp_fid_port_vid_list_del(struct mlxsw_sp_fid *fid, u16 local_port, 640 u16 vid) 641 { 642 struct mlxsw_sp_fid_port_vid *port_vid, *tmp; 643 644 list_for_each_entry_safe(port_vid, tmp, &fid->port_vid_list, list) { 645 if (port_vid->local_port != local_port || port_vid->vid != vid) 646 continue; 647 648 list_del(&port_vid->list); 649 kfree(port_vid); 650 return; 651 } 652 } 653 654 static int 655 mlxsw_sp_fid_mpe_table_map(const struct mlxsw_sp_fid *fid, u16 local_port, 656 u16 vid, bool valid) 657 { 658 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; 659 char smpe_pl[MLXSW_REG_SMPE_LEN]; 660 661 mlxsw_reg_smpe_pack(smpe_pl, local_port, fid->fid_index, 662 valid ? vid : 0); 663 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(smpe), smpe_pl); 664 } 665 666 static int mlxsw_sp_fid_8021d_port_vid_map(struct mlxsw_sp_fid *fid, 667 struct mlxsw_sp_port *mlxsw_sp_port, 668 u16 vid) 669 { 670 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 671 u16 local_port = mlxsw_sp_port->local_port; 672 int err; 673 674 err = __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, 675 true); 676 if (err) 677 return err; 678 679 if (fid->fid_family->mlxsw_sp->ubridge) { 680 err = mlxsw_sp_fid_mpe_table_map(fid, local_port, vid, true); 681 if (err) 682 goto err_mpe_table_map; 683 } 684 685 err = mlxsw_sp_fid_port_vid_list_add(fid, mlxsw_sp_port->local_port, 686 vid); 687 if (err) 688 goto err_port_vid_list_add; 689 690 if (mlxsw_sp->fid_core->port_fid_mappings[local_port]++ == 0) { 691 err = mlxsw_sp_port_vp_mode_trans(mlxsw_sp_port); 692 if (err) 693 goto err_port_vp_mode_trans; 694 } 695 696 return 0; 697 698 err_port_vp_mode_trans: 699 mlxsw_sp->fid_core->port_fid_mappings[local_port]--; 700 mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid); 701 err_port_vid_list_add: 702 if (fid->fid_family->mlxsw_sp->ubridge) 703 mlxsw_sp_fid_mpe_table_map(fid, local_port, vid, false); 704 err_mpe_table_map: 705 __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, false); 706 return err; 707 } 708 709 static void 710 mlxsw_sp_fid_8021d_port_vid_unmap(struct mlxsw_sp_fid *fid, 711 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid) 712 { 713 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 714 u16 local_port = mlxsw_sp_port->local_port; 715 716 if (mlxsw_sp->fid_core->port_fid_mappings[local_port] == 1) 717 mlxsw_sp_port_vlan_mode_trans(mlxsw_sp_port); 718 mlxsw_sp->fid_core->port_fid_mappings[local_port]--; 719 mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid); 720 if (fid->fid_family->mlxsw_sp->ubridge) 721 mlxsw_sp_fid_mpe_table_map(fid, local_port, vid, false); 722 __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, false); 723 } 724 725 static int mlxsw_sp_fid_8021d_vni_set(struct mlxsw_sp_fid *fid) 726 { 727 return mlxsw_sp_fid_edit_op(fid); 728 } 729 730 static void mlxsw_sp_fid_8021d_vni_clear(struct mlxsw_sp_fid *fid) 731 { 732 mlxsw_sp_fid_edit_op(fid); 733 } 734 735 static int mlxsw_sp_fid_8021d_nve_flood_index_set(struct mlxsw_sp_fid *fid) 736 { 737 return mlxsw_sp_fid_edit_op(fid); 738 } 739 740 static void mlxsw_sp_fid_8021d_nve_flood_index_clear(struct mlxsw_sp_fid *fid) 741 { 742 mlxsw_sp_fid_edit_op(fid); 743 } 744 745 static void 746 mlxsw_sp_fid_8021d_fdb_clear_offload(const struct mlxsw_sp_fid *fid, 747 const struct net_device *nve_dev) 748 { 749 br_fdb_clear_offload(nve_dev, 0); 750 } 751 752 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021d_ops = { 753 .setup = mlxsw_sp_fid_8021d_setup, 754 .configure = mlxsw_sp_fid_8021d_configure, 755 .deconfigure = mlxsw_sp_fid_8021d_deconfigure, 756 .index_alloc = mlxsw_sp_fid_8021d_index_alloc, 757 .compare = mlxsw_sp_fid_8021d_compare, 758 .flood_index = mlxsw_sp_fid_8021d_flood_index, 759 .port_vid_map = mlxsw_sp_fid_8021d_port_vid_map, 760 .port_vid_unmap = mlxsw_sp_fid_8021d_port_vid_unmap, 761 .vni_set = mlxsw_sp_fid_8021d_vni_set, 762 .vni_clear = mlxsw_sp_fid_8021d_vni_clear, 763 .nve_flood_index_set = mlxsw_sp_fid_8021d_nve_flood_index_set, 764 .nve_flood_index_clear = mlxsw_sp_fid_8021d_nve_flood_index_clear, 765 .fdb_clear_offload = mlxsw_sp_fid_8021d_fdb_clear_offload, 766 }; 767 768 #define MLXSW_SP_FID_8021Q_MAX (VLAN_N_VID - 2) 769 #define MLXSW_SP_FID_8021Q_PGT_BASE 0 770 #define MLXSW_SP_FID_8021D_PGT_BASE (3 * MLXSW_SP_FID_8021Q_MAX) 771 772 static const struct mlxsw_sp_flood_table mlxsw_sp_fid_8021d_flood_tables[] = { 773 { 774 .packet_type = MLXSW_SP_FLOOD_TYPE_UC, 775 .table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID, 776 .table_index = 0, 777 }, 778 { 779 .packet_type = MLXSW_SP_FLOOD_TYPE_MC, 780 .table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID, 781 .table_index = 1, 782 }, 783 { 784 .packet_type = MLXSW_SP_FLOOD_TYPE_BC, 785 .table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID, 786 .table_index = 2, 787 }, 788 }; 789 790 /* Range and flood configuration must match mlxsw_config_profile */ 791 static const struct mlxsw_sp_fid_family mlxsw_sp_fid_8021d_family = { 792 .type = MLXSW_SP_FID_TYPE_8021D, 793 .fid_size = sizeof(struct mlxsw_sp_fid_8021d), 794 .start_index = VLAN_N_VID, 795 .end_index = VLAN_N_VID + MLXSW_SP_FID_8021D_MAX - 1, 796 .flood_tables = mlxsw_sp_fid_8021d_flood_tables, 797 .nr_flood_tables = ARRAY_SIZE(mlxsw_sp_fid_8021d_flood_tables), 798 .rif_type = MLXSW_SP_RIF_TYPE_FID, 799 .ops = &mlxsw_sp_fid_8021d_ops, 800 .bridge_type = MLXSW_REG_BRIDGE_TYPE_1, 801 .pgt_base = MLXSW_SP_FID_8021D_PGT_BASE, 802 }; 803 804 static bool 805 mlxsw_sp_fid_8021q_compare(const struct mlxsw_sp_fid *fid, const void *arg) 806 { 807 u16 vid = *(u16 *) arg; 808 809 return mlxsw_sp_fid_8021q_fid(fid)->vid == vid; 810 } 811 812 static void 813 mlxsw_sp_fid_8021q_fdb_clear_offload(const struct mlxsw_sp_fid *fid, 814 const struct net_device *nve_dev) 815 { 816 br_fdb_clear_offload(nve_dev, mlxsw_sp_fid_8021q_vid(fid)); 817 } 818 819 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021q_emu_ops = { 820 .setup = mlxsw_sp_fid_8021q_setup, 821 .configure = mlxsw_sp_fid_8021d_configure, 822 .deconfigure = mlxsw_sp_fid_8021d_deconfigure, 823 .index_alloc = mlxsw_sp_fid_8021d_index_alloc, 824 .compare = mlxsw_sp_fid_8021q_compare, 825 .flood_index = mlxsw_sp_fid_8021d_flood_index, 826 .port_vid_map = mlxsw_sp_fid_8021d_port_vid_map, 827 .port_vid_unmap = mlxsw_sp_fid_8021d_port_vid_unmap, 828 .vni_set = mlxsw_sp_fid_8021d_vni_set, 829 .vni_clear = mlxsw_sp_fid_8021d_vni_clear, 830 .nve_flood_index_set = mlxsw_sp_fid_8021d_nve_flood_index_set, 831 .nve_flood_index_clear = mlxsw_sp_fid_8021d_nve_flood_index_clear, 832 .fdb_clear_offload = mlxsw_sp_fid_8021q_fdb_clear_offload, 833 }; 834 835 /* There are 4K-2 emulated 802.1Q FIDs, starting right after the 802.1D FIDs */ 836 #define MLXSW_SP_FID_8021Q_EMU_START (VLAN_N_VID + MLXSW_SP_FID_8021D_MAX) 837 #define MLXSW_SP_FID_8021Q_EMU_END (MLXSW_SP_FID_8021Q_EMU_START + \ 838 MLXSW_SP_FID_8021Q_MAX - 1) 839 840 /* Range and flood configuration must match mlxsw_config_profile */ 841 static const struct mlxsw_sp_fid_family mlxsw_sp_fid_8021q_emu_family = { 842 .type = MLXSW_SP_FID_TYPE_8021Q, 843 .fid_size = sizeof(struct mlxsw_sp_fid_8021q), 844 .start_index = MLXSW_SP_FID_8021Q_EMU_START, 845 .end_index = MLXSW_SP_FID_8021Q_EMU_END, 846 .flood_tables = mlxsw_sp_fid_8021d_flood_tables, 847 .nr_flood_tables = ARRAY_SIZE(mlxsw_sp_fid_8021d_flood_tables), 848 .rif_type = MLXSW_SP_RIF_TYPE_VLAN_EMU, 849 .ops = &mlxsw_sp_fid_8021q_emu_ops, 850 .bridge_type = MLXSW_REG_BRIDGE_TYPE_1, 851 .pgt_base = MLXSW_SP_FID_8021Q_PGT_BASE, 852 }; 853 854 static void mlxsw_sp_fid_rfid_setup(struct mlxsw_sp_fid *fid, const void *arg) 855 { 856 fid->fid_offset = 0; 857 } 858 859 static int mlxsw_sp_fid_rfid_configure(struct mlxsw_sp_fid *fid) 860 { 861 /* rFIDs are allocated by the device during init */ 862 return 0; 863 } 864 865 static void mlxsw_sp_fid_rfid_deconfigure(struct mlxsw_sp_fid *fid) 866 { 867 } 868 869 static int mlxsw_sp_fid_rfid_index_alloc(struct mlxsw_sp_fid *fid, 870 const void *arg, u16 *p_fid_index) 871 { 872 u16 rif_index = *(u16 *) arg; 873 874 *p_fid_index = fid->fid_family->start_index + rif_index; 875 876 return 0; 877 } 878 879 static bool mlxsw_sp_fid_rfid_compare(const struct mlxsw_sp_fid *fid, 880 const void *arg) 881 { 882 u16 rif_index = *(u16 *) arg; 883 884 return fid->fid_index == rif_index + fid->fid_family->start_index; 885 } 886 887 static int mlxsw_sp_fid_rfid_port_vid_map(struct mlxsw_sp_fid *fid, 888 struct mlxsw_sp_port *mlxsw_sp_port, 889 u16 vid) 890 { 891 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 892 u16 local_port = mlxsw_sp_port->local_port; 893 int err; 894 895 err = mlxsw_sp_fid_port_vid_list_add(fid, mlxsw_sp_port->local_port, 896 vid); 897 if (err) 898 return err; 899 900 /* We only need to transition the port to virtual mode since 901 * {Port, VID} => FID is done by the firmware upon RIF creation. 902 */ 903 if (mlxsw_sp->fid_core->port_fid_mappings[local_port]++ == 0) { 904 err = mlxsw_sp_port_vp_mode_trans(mlxsw_sp_port); 905 if (err) 906 goto err_port_vp_mode_trans; 907 } 908 909 return 0; 910 911 err_port_vp_mode_trans: 912 mlxsw_sp->fid_core->port_fid_mappings[local_port]--; 913 mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid); 914 return err; 915 } 916 917 static void 918 mlxsw_sp_fid_rfid_port_vid_unmap(struct mlxsw_sp_fid *fid, 919 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid) 920 { 921 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 922 u16 local_port = mlxsw_sp_port->local_port; 923 924 if (mlxsw_sp->fid_core->port_fid_mappings[local_port] == 1) 925 mlxsw_sp_port_vlan_mode_trans(mlxsw_sp_port); 926 mlxsw_sp->fid_core->port_fid_mappings[local_port]--; 927 mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid); 928 } 929 930 static int mlxsw_sp_fid_rfid_vni_set(struct mlxsw_sp_fid *fid) 931 { 932 return -EOPNOTSUPP; 933 } 934 935 static void mlxsw_sp_fid_rfid_vni_clear(struct mlxsw_sp_fid *fid) 936 { 937 WARN_ON_ONCE(1); 938 } 939 940 static int mlxsw_sp_fid_rfid_nve_flood_index_set(struct mlxsw_sp_fid *fid) 941 { 942 return -EOPNOTSUPP; 943 } 944 945 static void mlxsw_sp_fid_rfid_nve_flood_index_clear(struct mlxsw_sp_fid *fid) 946 { 947 WARN_ON_ONCE(1); 948 } 949 950 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_rfid_ops = { 951 .setup = mlxsw_sp_fid_rfid_setup, 952 .configure = mlxsw_sp_fid_rfid_configure, 953 .deconfigure = mlxsw_sp_fid_rfid_deconfigure, 954 .index_alloc = mlxsw_sp_fid_rfid_index_alloc, 955 .compare = mlxsw_sp_fid_rfid_compare, 956 .port_vid_map = mlxsw_sp_fid_rfid_port_vid_map, 957 .port_vid_unmap = mlxsw_sp_fid_rfid_port_vid_unmap, 958 .vni_set = mlxsw_sp_fid_rfid_vni_set, 959 .vni_clear = mlxsw_sp_fid_rfid_vni_clear, 960 .nve_flood_index_set = mlxsw_sp_fid_rfid_nve_flood_index_set, 961 .nve_flood_index_clear = mlxsw_sp_fid_rfid_nve_flood_index_clear, 962 }; 963 964 #define MLXSW_SP_RFID_BASE (15 * 1024) 965 #define MLXSW_SP_RFID_MAX 1024 966 967 static const struct mlxsw_sp_fid_family mlxsw_sp_fid_rfid_family = { 968 .type = MLXSW_SP_FID_TYPE_RFID, 969 .fid_size = sizeof(struct mlxsw_sp_fid), 970 .start_index = MLXSW_SP_RFID_BASE, 971 .end_index = MLXSW_SP_RFID_BASE + MLXSW_SP_RFID_MAX - 1, 972 .rif_type = MLXSW_SP_RIF_TYPE_SUBPORT, 973 .ops = &mlxsw_sp_fid_rfid_ops, 974 .flood_rsp = true, 975 }; 976 977 static void mlxsw_sp_fid_dummy_setup(struct mlxsw_sp_fid *fid, const void *arg) 978 { 979 fid->fid_offset = 0; 980 } 981 982 static int mlxsw_sp_fid_dummy_configure(struct mlxsw_sp_fid *fid) 983 { 984 return mlxsw_sp_fid_op(fid, true); 985 } 986 987 static void mlxsw_sp_fid_dummy_deconfigure(struct mlxsw_sp_fid *fid) 988 { 989 mlxsw_sp_fid_op(fid, false); 990 } 991 992 static int mlxsw_sp_fid_dummy_index_alloc(struct mlxsw_sp_fid *fid, 993 const void *arg, u16 *p_fid_index) 994 { 995 *p_fid_index = fid->fid_family->start_index; 996 997 return 0; 998 } 999 1000 static bool mlxsw_sp_fid_dummy_compare(const struct mlxsw_sp_fid *fid, 1001 const void *arg) 1002 { 1003 return true; 1004 } 1005 1006 static int mlxsw_sp_fid_dummy_vni_set(struct mlxsw_sp_fid *fid) 1007 { 1008 return -EOPNOTSUPP; 1009 } 1010 1011 static void mlxsw_sp_fid_dummy_vni_clear(struct mlxsw_sp_fid *fid) 1012 { 1013 WARN_ON_ONCE(1); 1014 } 1015 1016 static int mlxsw_sp_fid_dummy_nve_flood_index_set(struct mlxsw_sp_fid *fid) 1017 { 1018 return -EOPNOTSUPP; 1019 } 1020 1021 static void mlxsw_sp_fid_dummy_nve_flood_index_clear(struct mlxsw_sp_fid *fid) 1022 { 1023 WARN_ON_ONCE(1); 1024 } 1025 1026 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_dummy_ops = { 1027 .setup = mlxsw_sp_fid_dummy_setup, 1028 .configure = mlxsw_sp_fid_dummy_configure, 1029 .deconfigure = mlxsw_sp_fid_dummy_deconfigure, 1030 .index_alloc = mlxsw_sp_fid_dummy_index_alloc, 1031 .compare = mlxsw_sp_fid_dummy_compare, 1032 .vni_set = mlxsw_sp_fid_dummy_vni_set, 1033 .vni_clear = mlxsw_sp_fid_dummy_vni_clear, 1034 .nve_flood_index_set = mlxsw_sp_fid_dummy_nve_flood_index_set, 1035 .nve_flood_index_clear = mlxsw_sp_fid_dummy_nve_flood_index_clear, 1036 }; 1037 1038 static const struct mlxsw_sp_fid_family mlxsw_sp_fid_dummy_family = { 1039 .type = MLXSW_SP_FID_TYPE_DUMMY, 1040 .fid_size = sizeof(struct mlxsw_sp_fid), 1041 .start_index = VLAN_N_VID - 1, 1042 .end_index = VLAN_N_VID - 1, 1043 .ops = &mlxsw_sp_fid_dummy_ops, 1044 }; 1045 1046 const struct mlxsw_sp_fid_family *mlxsw_sp1_fid_family_arr[] = { 1047 [MLXSW_SP_FID_TYPE_8021Q] = &mlxsw_sp_fid_8021q_emu_family, 1048 [MLXSW_SP_FID_TYPE_8021D] = &mlxsw_sp_fid_8021d_family, 1049 [MLXSW_SP_FID_TYPE_RFID] = &mlxsw_sp_fid_rfid_family, 1050 [MLXSW_SP_FID_TYPE_DUMMY] = &mlxsw_sp_fid_dummy_family, 1051 }; 1052 1053 const struct mlxsw_sp_fid_family *mlxsw_sp2_fid_family_arr[] = { 1054 [MLXSW_SP_FID_TYPE_8021Q] = &mlxsw_sp_fid_8021q_emu_family, 1055 [MLXSW_SP_FID_TYPE_8021D] = &mlxsw_sp_fid_8021d_family, 1056 [MLXSW_SP_FID_TYPE_RFID] = &mlxsw_sp_fid_rfid_family, 1057 [MLXSW_SP_FID_TYPE_DUMMY] = &mlxsw_sp_fid_dummy_family, 1058 }; 1059 1060 static struct mlxsw_sp_fid *mlxsw_sp_fid_lookup(struct mlxsw_sp *mlxsw_sp, 1061 enum mlxsw_sp_fid_type type, 1062 const void *arg) 1063 { 1064 struct mlxsw_sp_fid_family *fid_family; 1065 struct mlxsw_sp_fid *fid; 1066 1067 fid_family = mlxsw_sp->fid_core->fid_family_arr[type]; 1068 list_for_each_entry(fid, &fid_family->fids_list, list) { 1069 if (!fid->fid_family->ops->compare(fid, arg)) 1070 continue; 1071 refcount_inc(&fid->ref_count); 1072 return fid; 1073 } 1074 1075 return NULL; 1076 } 1077 1078 static struct mlxsw_sp_fid *mlxsw_sp_fid_get(struct mlxsw_sp *mlxsw_sp, 1079 enum mlxsw_sp_fid_type type, 1080 const void *arg) 1081 { 1082 struct mlxsw_sp_fid_family *fid_family; 1083 struct mlxsw_sp_fid *fid; 1084 u16 fid_index; 1085 int err; 1086 1087 fid = mlxsw_sp_fid_lookup(mlxsw_sp, type, arg); 1088 if (fid) 1089 return fid; 1090 1091 fid_family = mlxsw_sp->fid_core->fid_family_arr[type]; 1092 fid = kzalloc(fid_family->fid_size, GFP_KERNEL); 1093 if (!fid) 1094 return ERR_PTR(-ENOMEM); 1095 1096 INIT_LIST_HEAD(&fid->port_vid_list); 1097 fid->fid_family = fid_family; 1098 1099 err = fid->fid_family->ops->index_alloc(fid, arg, &fid_index); 1100 if (err) 1101 goto err_index_alloc; 1102 fid->fid_index = fid_index; 1103 __set_bit(fid_index - fid_family->start_index, fid_family->fids_bitmap); 1104 1105 fid->fid_family->ops->setup(fid, arg); 1106 1107 err = fid->fid_family->ops->configure(fid); 1108 if (err) 1109 goto err_configure; 1110 1111 err = rhashtable_insert_fast(&mlxsw_sp->fid_core->fid_ht, &fid->ht_node, 1112 mlxsw_sp_fid_ht_params); 1113 if (err) 1114 goto err_rhashtable_insert; 1115 1116 list_add(&fid->list, &fid_family->fids_list); 1117 refcount_set(&fid->ref_count, 1); 1118 return fid; 1119 1120 err_rhashtable_insert: 1121 fid->fid_family->ops->deconfigure(fid); 1122 err_configure: 1123 __clear_bit(fid_index - fid_family->start_index, 1124 fid_family->fids_bitmap); 1125 err_index_alloc: 1126 kfree(fid); 1127 return ERR_PTR(err); 1128 } 1129 1130 void mlxsw_sp_fid_put(struct mlxsw_sp_fid *fid) 1131 { 1132 struct mlxsw_sp_fid_family *fid_family = fid->fid_family; 1133 struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp; 1134 1135 if (!refcount_dec_and_test(&fid->ref_count)) 1136 return; 1137 1138 list_del(&fid->list); 1139 rhashtable_remove_fast(&mlxsw_sp->fid_core->fid_ht, 1140 &fid->ht_node, mlxsw_sp_fid_ht_params); 1141 fid->fid_family->ops->deconfigure(fid); 1142 __clear_bit(fid->fid_index - fid_family->start_index, 1143 fid_family->fids_bitmap); 1144 WARN_ON_ONCE(!list_empty(&fid->port_vid_list)); 1145 kfree(fid); 1146 } 1147 1148 struct mlxsw_sp_fid *mlxsw_sp_fid_8021q_get(struct mlxsw_sp *mlxsw_sp, u16 vid) 1149 { 1150 return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_8021Q, &vid); 1151 } 1152 1153 struct mlxsw_sp_fid *mlxsw_sp_fid_8021d_get(struct mlxsw_sp *mlxsw_sp, 1154 int br_ifindex) 1155 { 1156 return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_8021D, &br_ifindex); 1157 } 1158 1159 struct mlxsw_sp_fid *mlxsw_sp_fid_8021q_lookup(struct mlxsw_sp *mlxsw_sp, 1160 u16 vid) 1161 { 1162 return mlxsw_sp_fid_lookup(mlxsw_sp, MLXSW_SP_FID_TYPE_8021Q, &vid); 1163 } 1164 1165 struct mlxsw_sp_fid *mlxsw_sp_fid_8021d_lookup(struct mlxsw_sp *mlxsw_sp, 1166 int br_ifindex) 1167 { 1168 return mlxsw_sp_fid_lookup(mlxsw_sp, MLXSW_SP_FID_TYPE_8021D, 1169 &br_ifindex); 1170 } 1171 1172 struct mlxsw_sp_fid *mlxsw_sp_fid_rfid_get(struct mlxsw_sp *mlxsw_sp, 1173 u16 rif_index) 1174 { 1175 return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_RFID, &rif_index); 1176 } 1177 1178 struct mlxsw_sp_fid *mlxsw_sp_fid_dummy_get(struct mlxsw_sp *mlxsw_sp) 1179 { 1180 return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_DUMMY, NULL); 1181 } 1182 1183 static int 1184 mlxsw_sp_fid_flood_table_init(struct mlxsw_sp_fid_family *fid_family, 1185 const struct mlxsw_sp_flood_table *flood_table) 1186 { 1187 enum mlxsw_sp_flood_type packet_type = flood_table->packet_type; 1188 struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp; 1189 u16 mid_base, num_fids, table_index; 1190 const int *sfgc_packet_types; 1191 int err, i; 1192 1193 mid_base = mlxsw_sp_fid_flood_table_mid(fid_family, flood_table, 0); 1194 num_fids = mlxsw_sp_fid_family_num_fids(fid_family); 1195 err = mlxsw_sp_pgt_mid_alloc_range(mlxsw_sp, mid_base, num_fids); 1196 if (err) 1197 return err; 1198 1199 sfgc_packet_types = mlxsw_sp_packet_type_sfgc_types[packet_type]; 1200 for (i = 0; i < MLXSW_REG_SFGC_TYPE_MAX; i++) { 1201 char sfgc_pl[MLXSW_REG_SFGC_LEN]; 1202 1203 if (!sfgc_packet_types[i]) 1204 continue; 1205 1206 mid_base = mlxsw_sp->ubridge ? mid_base : 0; 1207 table_index = mlxsw_sp->ubridge ? 0 : flood_table->table_index; 1208 1209 mlxsw_reg_sfgc_pack(sfgc_pl, i, fid_family->bridge_type, 1210 flood_table->table_type, table_index, 1211 mid_base); 1212 1213 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfgc), sfgc_pl); 1214 if (err) 1215 goto err_reg_write; 1216 } 1217 1218 return 0; 1219 1220 err_reg_write: 1221 mid_base = mlxsw_sp_fid_flood_table_mid(fid_family, flood_table, 0); 1222 mlxsw_sp_pgt_mid_free_range(mlxsw_sp, mid_base, num_fids); 1223 return err; 1224 } 1225 1226 static void 1227 mlxsw_sp_fid_flood_table_fini(struct mlxsw_sp_fid_family *fid_family, 1228 const struct mlxsw_sp_flood_table *flood_table) 1229 { 1230 struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp; 1231 u16 num_fids, mid_base; 1232 1233 mid_base = mlxsw_sp_fid_flood_table_mid(fid_family, flood_table, 0); 1234 num_fids = mlxsw_sp_fid_family_num_fids(fid_family); 1235 mlxsw_sp_pgt_mid_free_range(mlxsw_sp, mid_base, num_fids); 1236 } 1237 1238 static int 1239 mlxsw_sp_fid_flood_tables_init(struct mlxsw_sp_fid_family *fid_family) 1240 { 1241 int i; 1242 1243 for (i = 0; i < fid_family->nr_flood_tables; i++) { 1244 const struct mlxsw_sp_flood_table *flood_table; 1245 int err; 1246 1247 flood_table = &fid_family->flood_tables[i]; 1248 err = mlxsw_sp_fid_flood_table_init(fid_family, flood_table); 1249 if (err) 1250 return err; 1251 } 1252 1253 return 0; 1254 } 1255 1256 static void 1257 mlxsw_sp_fid_flood_tables_fini(struct mlxsw_sp_fid_family *fid_family) 1258 { 1259 int i; 1260 1261 for (i = 0; i < fid_family->nr_flood_tables; i++) { 1262 const struct mlxsw_sp_flood_table *flood_table; 1263 1264 flood_table = &fid_family->flood_tables[i]; 1265 mlxsw_sp_fid_flood_table_fini(fid_family, flood_table); 1266 } 1267 } 1268 1269 static int mlxsw_sp_fid_family_register(struct mlxsw_sp *mlxsw_sp, 1270 const struct mlxsw_sp_fid_family *tmpl) 1271 { 1272 u16 nr_fids = tmpl->end_index - tmpl->start_index + 1; 1273 struct mlxsw_sp_fid_family *fid_family; 1274 int err; 1275 1276 fid_family = kmemdup(tmpl, sizeof(*fid_family), GFP_KERNEL); 1277 if (!fid_family) 1278 return -ENOMEM; 1279 1280 fid_family->mlxsw_sp = mlxsw_sp; 1281 INIT_LIST_HEAD(&fid_family->fids_list); 1282 fid_family->fids_bitmap = bitmap_zalloc(nr_fids, GFP_KERNEL); 1283 if (!fid_family->fids_bitmap) { 1284 err = -ENOMEM; 1285 goto err_alloc_fids_bitmap; 1286 } 1287 1288 if (fid_family->flood_tables) { 1289 err = mlxsw_sp_fid_flood_tables_init(fid_family); 1290 if (err) 1291 goto err_fid_flood_tables_init; 1292 } 1293 1294 mlxsw_sp->fid_core->fid_family_arr[tmpl->type] = fid_family; 1295 1296 return 0; 1297 1298 err_fid_flood_tables_init: 1299 bitmap_free(fid_family->fids_bitmap); 1300 err_alloc_fids_bitmap: 1301 kfree(fid_family); 1302 return err; 1303 } 1304 1305 static void 1306 mlxsw_sp_fid_family_unregister(struct mlxsw_sp *mlxsw_sp, 1307 struct mlxsw_sp_fid_family *fid_family) 1308 { 1309 mlxsw_sp->fid_core->fid_family_arr[fid_family->type] = NULL; 1310 1311 if (fid_family->flood_tables) 1312 mlxsw_sp_fid_flood_tables_fini(fid_family); 1313 1314 bitmap_free(fid_family->fids_bitmap); 1315 WARN_ON_ONCE(!list_empty(&fid_family->fids_list)); 1316 kfree(fid_family); 1317 } 1318 1319 int mlxsw_sp_port_fids_init(struct mlxsw_sp_port *mlxsw_sp_port) 1320 { 1321 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 1322 1323 /* Track number of FIDs configured on the port with mapping type 1324 * PORT_VID_TO_FID, so that we know when to transition the port 1325 * back to non-virtual (VLAN) mode. 1326 */ 1327 mlxsw_sp->fid_core->port_fid_mappings[mlxsw_sp_port->local_port] = 0; 1328 1329 return mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, false); 1330 } 1331 1332 void mlxsw_sp_port_fids_fini(struct mlxsw_sp_port *mlxsw_sp_port) 1333 { 1334 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 1335 1336 mlxsw_sp->fid_core->port_fid_mappings[mlxsw_sp_port->local_port] = 0; 1337 } 1338 1339 int mlxsw_sp_fids_init(struct mlxsw_sp *mlxsw_sp) 1340 { 1341 unsigned int max_ports = mlxsw_core_max_ports(mlxsw_sp->core); 1342 struct mlxsw_sp_fid_core *fid_core; 1343 int err, i; 1344 1345 fid_core = kzalloc(sizeof(*mlxsw_sp->fid_core), GFP_KERNEL); 1346 if (!fid_core) 1347 return -ENOMEM; 1348 mlxsw_sp->fid_core = fid_core; 1349 1350 err = rhashtable_init(&fid_core->fid_ht, &mlxsw_sp_fid_ht_params); 1351 if (err) 1352 goto err_rhashtable_fid_init; 1353 1354 err = rhashtable_init(&fid_core->vni_ht, &mlxsw_sp_fid_vni_ht_params); 1355 if (err) 1356 goto err_rhashtable_vni_init; 1357 1358 fid_core->port_fid_mappings = kcalloc(max_ports, sizeof(unsigned int), 1359 GFP_KERNEL); 1360 if (!fid_core->port_fid_mappings) { 1361 err = -ENOMEM; 1362 goto err_alloc_port_fid_mappings; 1363 } 1364 1365 for (i = 0; i < MLXSW_SP_FID_TYPE_MAX; i++) { 1366 err = mlxsw_sp_fid_family_register(mlxsw_sp, 1367 mlxsw_sp->fid_family_arr[i]); 1368 1369 if (err) 1370 goto err_fid_ops_register; 1371 } 1372 1373 return 0; 1374 1375 err_fid_ops_register: 1376 for (i--; i >= 0; i--) { 1377 struct mlxsw_sp_fid_family *fid_family; 1378 1379 fid_family = fid_core->fid_family_arr[i]; 1380 mlxsw_sp_fid_family_unregister(mlxsw_sp, fid_family); 1381 } 1382 kfree(fid_core->port_fid_mappings); 1383 err_alloc_port_fid_mappings: 1384 rhashtable_destroy(&fid_core->vni_ht); 1385 err_rhashtable_vni_init: 1386 rhashtable_destroy(&fid_core->fid_ht); 1387 err_rhashtable_fid_init: 1388 kfree(fid_core); 1389 return err; 1390 } 1391 1392 void mlxsw_sp_fids_fini(struct mlxsw_sp *mlxsw_sp) 1393 { 1394 struct mlxsw_sp_fid_core *fid_core = mlxsw_sp->fid_core; 1395 int i; 1396 1397 for (i = 0; i < MLXSW_SP_FID_TYPE_MAX; i++) 1398 mlxsw_sp_fid_family_unregister(mlxsw_sp, 1399 fid_core->fid_family_arr[i]); 1400 kfree(fid_core->port_fid_mappings); 1401 rhashtable_destroy(&fid_core->vni_ht); 1402 rhashtable_destroy(&fid_core->fid_ht); 1403 kfree(fid_core); 1404 } 1405