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