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