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