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 "spectrum_router.h" 15 #include "reg.h" 16 17 struct mlxsw_sp_fid_family; 18 19 struct mlxsw_sp_fid_core { 20 struct rhashtable fid_ht; 21 struct rhashtable vni_ht; 22 struct mlxsw_sp_fid_family *fid_family_arr[MLXSW_SP_FID_TYPE_MAX]; 23 unsigned int *port_fid_mappings; 24 }; 25 26 struct mlxsw_sp_fid_port_vid { 27 struct list_head list; 28 u16 local_port; 29 u16 vid; 30 }; 31 32 struct mlxsw_sp_fid { 33 struct list_head list; 34 struct mlxsw_sp_rif *rif; 35 refcount_t ref_count; 36 u16 fid_index; 37 u16 fid_offset; 38 struct mlxsw_sp_fid_family *fid_family; 39 struct rhash_head ht_node; 40 41 struct rhash_head vni_ht_node; 42 enum mlxsw_sp_nve_type nve_type; 43 __be32 vni; 44 u32 nve_flood_index; 45 int nve_ifindex; 46 u8 vni_valid:1, 47 nve_flood_index_valid:1; 48 struct list_head port_vid_list; /* Ordered by local port. */ 49 }; 50 51 struct mlxsw_sp_fid_8021q { 52 struct mlxsw_sp_fid common; 53 u16 vid; 54 }; 55 56 struct mlxsw_sp_fid_8021d { 57 struct mlxsw_sp_fid common; 58 int br_ifindex; 59 }; 60 61 static const struct rhashtable_params mlxsw_sp_fid_ht_params = { 62 .key_len = sizeof_field(struct mlxsw_sp_fid, fid_index), 63 .key_offset = offsetof(struct mlxsw_sp_fid, fid_index), 64 .head_offset = offsetof(struct mlxsw_sp_fid, ht_node), 65 }; 66 67 static const struct rhashtable_params mlxsw_sp_fid_vni_ht_params = { 68 .key_len = sizeof_field(struct mlxsw_sp_fid, vni), 69 .key_offset = offsetof(struct mlxsw_sp_fid, vni), 70 .head_offset = offsetof(struct mlxsw_sp_fid, vni_ht_node), 71 }; 72 73 struct mlxsw_sp_flood_table { 74 enum mlxsw_sp_flood_type packet_type; 75 enum mlxsw_flood_table_type table_type; /* For flood_mode!=CFF. */ 76 int table_index; 77 }; 78 79 struct mlxsw_sp_fid_ops { 80 int (*setup)(struct mlxsw_sp_fid *fid, const void *arg); 81 int (*configure)(struct mlxsw_sp_fid *fid); 82 void (*deconfigure)(struct mlxsw_sp_fid *fid); 83 int (*index_alloc)(struct mlxsw_sp_fid *fid, const void *arg, 84 u16 *p_fid_index); 85 bool (*compare)(const struct mlxsw_sp_fid *fid, 86 const void *arg); 87 int (*port_vid_map)(struct mlxsw_sp_fid *fid, 88 struct mlxsw_sp_port *port, u16 vid); 89 void (*port_vid_unmap)(struct mlxsw_sp_fid *fid, 90 struct mlxsw_sp_port *port, u16 vid); 91 int (*vni_set)(struct mlxsw_sp_fid *fid); 92 void (*vni_clear)(struct mlxsw_sp_fid *fid); 93 int (*nve_flood_index_set)(struct mlxsw_sp_fid *fid); 94 void (*nve_flood_index_clear)(struct mlxsw_sp_fid *fid); 95 void (*fdb_clear_offload)(const struct mlxsw_sp_fid *fid, 96 const struct net_device *nve_dev); 97 int (*vid_to_fid_rif_update)(const struct mlxsw_sp_fid *fid, 98 const struct mlxsw_sp_rif *rif); 99 int (*flood_table_init)(struct mlxsw_sp_fid_family *fid_family, 100 const struct mlxsw_sp_flood_table *flood_table); 101 int (*pgt_size)(const struct mlxsw_sp_fid_family *fid_family, 102 u16 *p_pgt_size); 103 u16 (*fid_mid)(const struct mlxsw_sp_fid *fid, 104 const struct mlxsw_sp_flood_table *flood_table); 105 void (*fid_pack)(char *sfmr_pl, const struct mlxsw_sp_fid *fid, 106 enum mlxsw_reg_sfmr_op op); 107 108 /* These are specific to RFID families and we assume are only 109 * implemented by RFID families, if at all. 110 */ 111 int (*fid_port_init)(const struct mlxsw_sp_fid_family *fid_family, 112 const struct mlxsw_sp_port *mlxsw_sp_port); 113 void (*fid_port_fini)(const struct mlxsw_sp_fid_family *fid_family, 114 const struct mlxsw_sp_port *mlxsw_sp_port); 115 }; 116 117 enum mlxsw_sp_fid_flood_profile_id { 118 MLXSW_SP_FID_FLOOD_PROFILE_ID_BRIDGE = 1, 119 MLXSW_SP_FID_FLOOD_PROFILE_ID_RSP, 120 MLXSW_SP_FID_FLOOD_PROFILE_ID_NVE, 121 }; 122 123 struct mlxsw_sp_fid_flood_profile { 124 const struct mlxsw_sp_flood_table *flood_tables; 125 int nr_flood_tables; 126 const enum mlxsw_sp_fid_flood_profile_id profile_id; /* For CFF mode. */ 127 }; 128 129 struct mlxsw_sp_fid_family { 130 enum mlxsw_sp_fid_type type; 131 size_t fid_size; 132 u16 start_index; 133 u16 end_index; 134 struct list_head fids_list; 135 unsigned long *fids_bitmap; 136 const struct mlxsw_sp_fid_flood_profile *flood_profile; 137 enum mlxsw_sp_rif_type rif_type; 138 const struct mlxsw_sp_fid_ops *ops; 139 struct mlxsw_sp *mlxsw_sp; 140 bool flood_rsp; /* For flood_mode!=CFF. */ 141 enum mlxsw_reg_bridge_type bridge_type; 142 u16 pgt_base; 143 bool smpe_index_valid; 144 }; 145 146 static const int mlxsw_sp_sfgc_uc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = { 147 [MLXSW_REG_SFGC_TYPE_UNKNOWN_UNICAST] = 1, 148 }; 149 150 static const int mlxsw_sp_sfgc_bc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = { 151 [MLXSW_REG_SFGC_TYPE_BROADCAST] = 1, 152 [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_NON_IP] = 1, 153 [MLXSW_REG_SFGC_TYPE_IPV4_LINK_LOCAL] = 1, 154 [MLXSW_REG_SFGC_TYPE_IPV6_ALL_HOST] = 1, 155 [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV6] = 1, 156 }; 157 158 static const int mlxsw_sp_sfgc_mc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = { 159 [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV4] = 1, 160 }; 161 162 static const int mlxsw_sp_sfgc_not_uc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = { 163 [MLXSW_REG_SFGC_TYPE_BROADCAST] = 1, 164 [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_NON_IP] = 1, 165 [MLXSW_REG_SFGC_TYPE_IPV4_LINK_LOCAL] = 1, 166 [MLXSW_REG_SFGC_TYPE_IPV6_ALL_HOST] = 1, 167 [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV6] = 1, 168 [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV4] = 1, 169 }; 170 171 static const int mlxsw_sp_sfgc_any_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = { 172 [MLXSW_REG_SFGC_TYPE_UNKNOWN_UNICAST] = 1, 173 [MLXSW_REG_SFGC_TYPE_BROADCAST] = 1, 174 [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_NON_IP] = 1, 175 [MLXSW_REG_SFGC_TYPE_IPV4_LINK_LOCAL] = 1, 176 [MLXSW_REG_SFGC_TYPE_IPV6_ALL_HOST] = 1, 177 [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV6] = 1, 178 [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV4] = 1, 179 }; 180 181 static const int *mlxsw_sp_packet_type_sfgc_types[] = { 182 [MLXSW_SP_FLOOD_TYPE_UC] = mlxsw_sp_sfgc_uc_packet_types, 183 [MLXSW_SP_FLOOD_TYPE_BC] = mlxsw_sp_sfgc_bc_packet_types, 184 [MLXSW_SP_FLOOD_TYPE_MC] = mlxsw_sp_sfgc_mc_packet_types, 185 [MLXSW_SP_FLOOD_TYPE_NOT_UC] = mlxsw_sp_sfgc_not_uc_packet_types, 186 [MLXSW_SP_FLOOD_TYPE_ANY] = mlxsw_sp_sfgc_any_packet_types, 187 }; 188 189 struct mlxsw_sp_fid *mlxsw_sp_fid_lookup_by_index(struct mlxsw_sp *mlxsw_sp, 190 u16 fid_index) 191 { 192 struct mlxsw_sp_fid *fid; 193 194 fid = rhashtable_lookup_fast(&mlxsw_sp->fid_core->fid_ht, &fid_index, 195 mlxsw_sp_fid_ht_params); 196 if (fid) 197 refcount_inc(&fid->ref_count); 198 199 return fid; 200 } 201 202 int mlxsw_sp_fid_nve_ifindex(const struct mlxsw_sp_fid *fid, int *nve_ifindex) 203 { 204 if (!fid->vni_valid) 205 return -EINVAL; 206 207 *nve_ifindex = fid->nve_ifindex; 208 209 return 0; 210 } 211 212 int mlxsw_sp_fid_nve_type(const struct mlxsw_sp_fid *fid, 213 enum mlxsw_sp_nve_type *p_type) 214 { 215 if (!fid->vni_valid) 216 return -EINVAL; 217 218 *p_type = fid->nve_type; 219 220 return 0; 221 } 222 223 struct mlxsw_sp_fid *mlxsw_sp_fid_lookup_by_vni(struct mlxsw_sp *mlxsw_sp, 224 __be32 vni) 225 { 226 struct mlxsw_sp_fid *fid; 227 228 fid = rhashtable_lookup_fast(&mlxsw_sp->fid_core->vni_ht, &vni, 229 mlxsw_sp_fid_vni_ht_params); 230 if (fid) 231 refcount_inc(&fid->ref_count); 232 233 return fid; 234 } 235 236 int mlxsw_sp_fid_vni(const struct mlxsw_sp_fid *fid, __be32 *vni) 237 { 238 if (!fid->vni_valid) 239 return -EINVAL; 240 241 *vni = fid->vni; 242 243 return 0; 244 } 245 246 int mlxsw_sp_fid_nve_flood_index_set(struct mlxsw_sp_fid *fid, 247 u32 nve_flood_index) 248 { 249 struct mlxsw_sp_fid_family *fid_family = fid->fid_family; 250 const struct mlxsw_sp_fid_ops *ops = fid_family->ops; 251 int err; 252 253 if (WARN_ON(fid->nve_flood_index_valid)) 254 return -EINVAL; 255 256 fid->nve_flood_index = nve_flood_index; 257 fid->nve_flood_index_valid = true; 258 err = ops->nve_flood_index_set(fid); 259 if (err) 260 goto err_nve_flood_index_set; 261 262 return 0; 263 264 err_nve_flood_index_set: 265 fid->nve_flood_index_valid = false; 266 return err; 267 } 268 269 void mlxsw_sp_fid_nve_flood_index_clear(struct mlxsw_sp_fid *fid) 270 { 271 struct mlxsw_sp_fid_family *fid_family = fid->fid_family; 272 const struct mlxsw_sp_fid_ops *ops = fid_family->ops; 273 274 if (WARN_ON(!fid->nve_flood_index_valid)) 275 return; 276 277 fid->nve_flood_index_valid = false; 278 ops->nve_flood_index_clear(fid); 279 } 280 281 bool mlxsw_sp_fid_nve_flood_index_is_set(const struct mlxsw_sp_fid *fid) 282 { 283 return fid->nve_flood_index_valid; 284 } 285 286 int mlxsw_sp_fid_vni_set(struct mlxsw_sp_fid *fid, enum mlxsw_sp_nve_type type, 287 __be32 vni, int nve_ifindex) 288 { 289 struct mlxsw_sp_fid_family *fid_family = fid->fid_family; 290 const struct mlxsw_sp_fid_ops *ops = fid_family->ops; 291 struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp; 292 int err; 293 294 if (WARN_ON(fid->vni_valid)) 295 return -EINVAL; 296 297 fid->nve_type = type; 298 fid->nve_ifindex = nve_ifindex; 299 fid->vni = vni; 300 err = rhashtable_lookup_insert_fast(&mlxsw_sp->fid_core->vni_ht, 301 &fid->vni_ht_node, 302 mlxsw_sp_fid_vni_ht_params); 303 if (err) 304 return err; 305 306 fid->vni_valid = true; 307 err = ops->vni_set(fid); 308 if (err) 309 goto err_vni_set; 310 311 return 0; 312 313 err_vni_set: 314 fid->vni_valid = false; 315 rhashtable_remove_fast(&mlxsw_sp->fid_core->vni_ht, &fid->vni_ht_node, 316 mlxsw_sp_fid_vni_ht_params); 317 return err; 318 } 319 320 void mlxsw_sp_fid_vni_clear(struct mlxsw_sp_fid *fid) 321 { 322 struct mlxsw_sp_fid_family *fid_family = fid->fid_family; 323 const struct mlxsw_sp_fid_ops *ops = fid_family->ops; 324 struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp; 325 326 if (WARN_ON(!fid->vni_valid)) 327 return; 328 329 fid->vni_valid = false; 330 ops->vni_clear(fid); 331 rhashtable_remove_fast(&mlxsw_sp->fid_core->vni_ht, &fid->vni_ht_node, 332 mlxsw_sp_fid_vni_ht_params); 333 } 334 335 bool mlxsw_sp_fid_vni_is_set(const struct mlxsw_sp_fid *fid) 336 { 337 return fid->vni_valid; 338 } 339 340 void mlxsw_sp_fid_fdb_clear_offload(const struct mlxsw_sp_fid *fid, 341 const struct net_device *nve_dev) 342 { 343 struct mlxsw_sp_fid_family *fid_family = fid->fid_family; 344 const struct mlxsw_sp_fid_ops *ops = fid_family->ops; 345 346 if (ops->fdb_clear_offload) 347 ops->fdb_clear_offload(fid, nve_dev); 348 } 349 350 static const struct mlxsw_sp_flood_table * 351 mlxsw_sp_fid_flood_table_lookup(const struct mlxsw_sp_fid *fid, 352 enum mlxsw_sp_flood_type packet_type) 353 { 354 struct mlxsw_sp_fid_family *fid_family = fid->fid_family; 355 int i; 356 357 for (i = 0; i < fid_family->flood_profile->nr_flood_tables; i++) { 358 const struct mlxsw_sp_flood_table *flood_table; 359 360 flood_table = &fid_family->flood_profile->flood_tables[i]; 361 if (flood_table->packet_type != packet_type) 362 continue; 363 return flood_table; 364 } 365 366 return NULL; 367 } 368 369 static u16 370 mlxsw_sp_fid_family_num_fids(const struct mlxsw_sp_fid_family *fid_family) 371 { 372 return fid_family->end_index - fid_family->start_index + 1; 373 } 374 375 static int 376 mlxsw_sp_fid_8021d_pgt_size(const struct mlxsw_sp_fid_family *fid_family, 377 u16 *p_pgt_size) 378 { 379 u16 num_fids = mlxsw_sp_fid_family_num_fids(fid_family); 380 381 *p_pgt_size = num_fids * fid_family->flood_profile->nr_flood_tables; 382 return 0; 383 } 384 385 static unsigned int mlxsw_sp_fid_rfid_port_offset_cff(unsigned int local_port) 386 { 387 /* Port 0 is the CPU port. Since we never create RIFs based off that 388 * port, we don't need to count it. 389 */ 390 return WARN_ON_ONCE(!local_port) ? 0 : local_port - 1; 391 } 392 393 static int 394 mlxsw_sp_fid_rfid_pgt_size_cff(const struct mlxsw_sp_fid_family *fid_family, 395 u16 *p_pgt_size) 396 { 397 struct mlxsw_core *core = fid_family->mlxsw_sp->core; 398 unsigned int max_ports; 399 u16 pgt_size; 400 u16 max_lags; 401 int err; 402 403 max_ports = mlxsw_core_max_ports(core); 404 405 err = mlxsw_core_max_lag(core, &max_lags); 406 if (err) 407 return err; 408 409 pgt_size = (mlxsw_sp_fid_rfid_port_offset_cff(max_ports) + max_lags) * 410 fid_family->flood_profile->nr_flood_tables; 411 *p_pgt_size = pgt_size; 412 return 0; 413 } 414 415 static u16 416 mlxsw_sp_fid_pgt_base_ctl(const struct mlxsw_sp_fid_family *fid_family, 417 const struct mlxsw_sp_flood_table *flood_table) 418 { 419 u16 num_fids; 420 421 num_fids = mlxsw_sp_fid_family_num_fids(fid_family); 422 return fid_family->pgt_base + num_fids * flood_table->table_index; 423 } 424 425 static u16 426 mlxsw_sp_fid_fid_mid_ctl(const struct mlxsw_sp_fid *fid, 427 const struct mlxsw_sp_flood_table *flood_table) 428 { 429 return mlxsw_sp_fid_pgt_base_ctl(fid->fid_family, flood_table) + 430 fid->fid_offset; 431 } 432 433 int mlxsw_sp_fid_flood_set(struct mlxsw_sp_fid *fid, 434 enum mlxsw_sp_flood_type packet_type, u16 local_port, 435 bool member) 436 { 437 struct mlxsw_sp_fid_family *fid_family = fid->fid_family; 438 const struct mlxsw_sp_flood_table *flood_table; 439 u16 mid_index; 440 441 if (WARN_ON(!fid_family->flood_profile)) 442 return -EINVAL; 443 444 flood_table = mlxsw_sp_fid_flood_table_lookup(fid, packet_type); 445 if (!flood_table) 446 return -ESRCH; 447 448 mid_index = fid_family->ops->fid_mid(fid, flood_table); 449 return mlxsw_sp_pgt_entry_port_set(fid_family->mlxsw_sp, mid_index, 450 fid->fid_index, local_port, member); 451 } 452 453 int mlxsw_sp_fid_port_vid_map(struct mlxsw_sp_fid *fid, 454 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid) 455 { 456 if (WARN_ON(!fid->fid_family->ops->port_vid_map)) 457 return -EINVAL; 458 return fid->fid_family->ops->port_vid_map(fid, mlxsw_sp_port, vid); 459 } 460 461 void mlxsw_sp_fid_port_vid_unmap(struct mlxsw_sp_fid *fid, 462 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid) 463 { 464 fid->fid_family->ops->port_vid_unmap(fid, mlxsw_sp_port, vid); 465 } 466 467 u16 mlxsw_sp_fid_index(const struct mlxsw_sp_fid *fid) 468 { 469 return fid->fid_index; 470 } 471 472 enum mlxsw_sp_fid_type mlxsw_sp_fid_type(const struct mlxsw_sp_fid *fid) 473 { 474 return fid->fid_family->type; 475 } 476 477 struct mlxsw_sp_rif *mlxsw_sp_fid_rif(const struct mlxsw_sp_fid *fid) 478 { 479 return fid->rif; 480 } 481 482 enum mlxsw_sp_rif_type 483 mlxsw_sp_fid_type_rif_type(const struct mlxsw_sp *mlxsw_sp, 484 enum mlxsw_sp_fid_type type) 485 { 486 struct mlxsw_sp_fid_core *fid_core = mlxsw_sp->fid_core; 487 488 return fid_core->fid_family_arr[type]->rif_type; 489 } 490 491 static struct mlxsw_sp_fid_8021q * 492 mlxsw_sp_fid_8021q_fid(const struct mlxsw_sp_fid *fid) 493 { 494 return container_of(fid, struct mlxsw_sp_fid_8021q, common); 495 } 496 497 u16 mlxsw_sp_fid_8021q_vid(const struct mlxsw_sp_fid *fid) 498 { 499 return mlxsw_sp_fid_8021q_fid(fid)->vid; 500 } 501 502 static int mlxsw_sp_fid_8021q_setup(struct mlxsw_sp_fid *fid, const void *arg) 503 { 504 u16 vid = *(u16 *) arg; 505 506 mlxsw_sp_fid_8021q_fid(fid)->vid = vid; 507 fid->fid_offset = fid->fid_index - fid->fid_family->start_index; 508 return 0; 509 } 510 511 static enum mlxsw_reg_sfmr_op mlxsw_sp_sfmr_op(bool valid) 512 { 513 return valid ? MLXSW_REG_SFMR_OP_CREATE_FID : 514 MLXSW_REG_SFMR_OP_DESTROY_FID; 515 } 516 517 static void mlxsw_sp_fid_pack(char *sfmr_pl, 518 const struct mlxsw_sp_fid *fid, 519 enum mlxsw_reg_sfmr_op op) 520 { 521 u16 smpe; 522 523 smpe = fid->fid_family->smpe_index_valid ? fid->fid_index : 0; 524 525 mlxsw_reg_sfmr_pack(sfmr_pl, op, fid->fid_index, 526 fid->fid_family->smpe_index_valid, smpe); 527 } 528 529 static void mlxsw_sp_fid_pack_ctl(char *sfmr_pl, 530 const struct mlxsw_sp_fid *fid, 531 enum mlxsw_reg_sfmr_op op) 532 { 533 mlxsw_sp_fid_pack(sfmr_pl, fid, op); 534 mlxsw_reg_sfmr_fid_offset_set(sfmr_pl, fid->fid_offset); 535 mlxsw_reg_sfmr_flood_rsp_set(sfmr_pl, fid->fid_family->flood_rsp); 536 mlxsw_reg_sfmr_flood_bridge_type_set(sfmr_pl, 537 fid->fid_family->bridge_type); 538 } 539 540 static u16 541 mlxsw_sp_fid_off_pgt_base_cff(const struct mlxsw_sp_fid_family *fid_family, 542 u16 fid_offset) 543 { 544 return fid_family->pgt_base + 545 fid_offset * fid_family->flood_profile->nr_flood_tables; 546 } 547 548 static u16 mlxsw_sp_fid_pgt_base_cff(const struct mlxsw_sp_fid *fid) 549 { 550 return mlxsw_sp_fid_off_pgt_base_cff(fid->fid_family, fid->fid_offset); 551 } 552 553 static void mlxsw_sp_fid_fid_pack_cff(char *sfmr_pl, 554 const struct mlxsw_sp_fid *fid, 555 enum mlxsw_reg_sfmr_op op) 556 { 557 struct mlxsw_sp_fid_family *fid_family = fid->fid_family; 558 u16 pgt_base = mlxsw_sp_fid_pgt_base_cff(fid); 559 560 mlxsw_sp_fid_pack(sfmr_pl, fid, op); 561 mlxsw_reg_sfmr_cff_mid_base_set(sfmr_pl, pgt_base); 562 mlxsw_reg_sfmr_cff_prf_id_set(sfmr_pl, 563 fid_family->flood_profile->profile_id); 564 mlxsw_reg_sfmr_nve_flood_prf_id_set(sfmr_pl, 565 MLXSW_SP_FID_FLOOD_PROFILE_ID_NVE); 566 } 567 568 static u16 mlxsw_sp_fid_rfid_fid_offset_cff(struct mlxsw_sp *mlxsw_sp, 569 u16 port_lag_id, bool is_lag) 570 { 571 u16 max_ports = mlxsw_core_max_ports(mlxsw_sp->core); 572 573 if (is_lag) 574 return mlxsw_sp_fid_rfid_port_offset_cff(max_ports) + 575 port_lag_id; 576 else 577 return mlxsw_sp_fid_rfid_port_offset_cff(port_lag_id); 578 } 579 580 static int mlxsw_sp_fid_op(const struct mlxsw_sp_fid *fid, bool valid) 581 { 582 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; 583 char sfmr_pl[MLXSW_REG_SFMR_LEN]; 584 585 fid->fid_family->ops->fid_pack(sfmr_pl, fid, 586 mlxsw_sp_sfmr_op(valid)); 587 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl); 588 } 589 590 static int mlxsw_sp_fid_edit_op(const struct mlxsw_sp_fid *fid, 591 const struct mlxsw_sp_rif *rif) 592 { 593 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; 594 char sfmr_pl[MLXSW_REG_SFMR_LEN]; 595 596 fid->fid_family->ops->fid_pack(sfmr_pl, fid, 597 MLXSW_REG_SFMR_OP_CREATE_FID); 598 599 mlxsw_reg_sfmr_vv_set(sfmr_pl, fid->vni_valid); 600 mlxsw_reg_sfmr_vni_set(sfmr_pl, be32_to_cpu(fid->vni)); 601 mlxsw_reg_sfmr_vtfp_set(sfmr_pl, fid->nve_flood_index_valid); 602 mlxsw_reg_sfmr_nve_tunnel_flood_ptr_set(sfmr_pl, fid->nve_flood_index); 603 604 if (rif) { 605 mlxsw_reg_sfmr_irif_v_set(sfmr_pl, true); 606 mlxsw_reg_sfmr_irif_set(sfmr_pl, mlxsw_sp_rif_index(rif)); 607 } 608 609 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl); 610 } 611 612 static int mlxsw_sp_fid_vni_to_fid_map(const struct mlxsw_sp_fid *fid, 613 const struct mlxsw_sp_rif *rif, 614 bool valid) 615 { 616 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; 617 char svfa_pl[MLXSW_REG_SVFA_LEN]; 618 bool irif_valid; 619 u16 irif_index; 620 621 irif_valid = !!rif; 622 irif_index = rif ? mlxsw_sp_rif_index(rif) : 0; 623 624 mlxsw_reg_svfa_vni_pack(svfa_pl, valid, fid->fid_index, 625 be32_to_cpu(fid->vni), irif_valid, irif_index); 626 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl); 627 } 628 629 static int mlxsw_sp_fid_to_fid_rif_update(const struct mlxsw_sp_fid *fid, 630 const struct mlxsw_sp_rif *rif) 631 { 632 return mlxsw_sp_fid_edit_op(fid, rif); 633 } 634 635 static int mlxsw_sp_fid_vni_to_fid_rif_update(const struct mlxsw_sp_fid *fid, 636 const struct mlxsw_sp_rif *rif) 637 { 638 if (!fid->vni_valid) 639 return 0; 640 641 return mlxsw_sp_fid_vni_to_fid_map(fid, rif, fid->vni_valid); 642 } 643 644 static int 645 mlxsw_sp_fid_vid_to_fid_map(const struct mlxsw_sp_fid *fid, u16 vid, bool valid, 646 const struct mlxsw_sp_rif *rif) 647 { 648 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; 649 char svfa_pl[MLXSW_REG_SVFA_LEN]; 650 bool irif_valid; 651 u16 irif_index; 652 653 irif_valid = !!rif; 654 irif_index = rif ? mlxsw_sp_rif_index(rif) : 0; 655 656 mlxsw_reg_svfa_vid_pack(svfa_pl, valid, fid->fid_index, vid, irif_valid, 657 irif_index); 658 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl); 659 } 660 661 static int 662 mlxsw_sp_fid_8021q_vid_to_fid_rif_update(const struct mlxsw_sp_fid *fid, 663 const struct mlxsw_sp_rif *rif) 664 { 665 struct mlxsw_sp_fid_8021q *fid_8021q = mlxsw_sp_fid_8021q_fid(fid); 666 667 /* Update the global VID => FID mapping we created when the FID was 668 * configured. 669 */ 670 return mlxsw_sp_fid_vid_to_fid_map(fid, fid_8021q->vid, true, rif); 671 } 672 673 static int 674 mlxsw_sp_fid_port_vid_to_fid_rif_update_one(const struct mlxsw_sp_fid *fid, 675 struct mlxsw_sp_fid_port_vid *pv, 676 bool irif_valid, u16 irif_index) 677 { 678 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; 679 char svfa_pl[MLXSW_REG_SVFA_LEN]; 680 681 mlxsw_reg_svfa_port_vid_pack(svfa_pl, pv->local_port, true, 682 fid->fid_index, pv->vid, irif_valid, 683 irif_index); 684 685 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl); 686 } 687 688 static int mlxsw_sp_fid_vid_to_fid_rif_set(const struct mlxsw_sp_fid *fid, 689 const struct mlxsw_sp_rif *rif) 690 { 691 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; 692 struct mlxsw_sp_fid_port_vid *pv; 693 u16 irif_index; 694 int err; 695 696 err = fid->fid_family->ops->vid_to_fid_rif_update(fid, rif); 697 if (err) 698 return err; 699 700 irif_index = mlxsw_sp_rif_index(rif); 701 702 list_for_each_entry(pv, &fid->port_vid_list, list) { 703 /* If port is not in virtual mode, then it does not have any 704 * {Port, VID}->FID mappings that need to be updated with the 705 * ingress RIF. 706 */ 707 if (!mlxsw_sp->fid_core->port_fid_mappings[pv->local_port]) 708 continue; 709 710 err = mlxsw_sp_fid_port_vid_to_fid_rif_update_one(fid, pv, 711 true, 712 irif_index); 713 if (err) 714 goto err_port_vid_to_fid_rif_update_one; 715 } 716 717 return 0; 718 719 err_port_vid_to_fid_rif_update_one: 720 list_for_each_entry_continue_reverse(pv, &fid->port_vid_list, list) { 721 if (!mlxsw_sp->fid_core->port_fid_mappings[pv->local_port]) 722 continue; 723 724 mlxsw_sp_fid_port_vid_to_fid_rif_update_one(fid, pv, false, 0); 725 } 726 727 fid->fid_family->ops->vid_to_fid_rif_update(fid, NULL); 728 return err; 729 } 730 731 static void mlxsw_sp_fid_vid_to_fid_rif_unset(const struct mlxsw_sp_fid *fid) 732 { 733 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; 734 struct mlxsw_sp_fid_port_vid *pv; 735 736 list_for_each_entry(pv, &fid->port_vid_list, list) { 737 /* If port is not in virtual mode, then it does not have any 738 * {Port, VID}->FID mappings that need to be updated. 739 */ 740 if (!mlxsw_sp->fid_core->port_fid_mappings[pv->local_port]) 741 continue; 742 743 mlxsw_sp_fid_port_vid_to_fid_rif_update_one(fid, pv, false, 0); 744 } 745 746 fid->fid_family->ops->vid_to_fid_rif_update(fid, NULL); 747 } 748 749 static int mlxsw_sp_fid_reiv_handle(struct mlxsw_sp_fid *fid, u16 rif_index, 750 bool valid, u8 port_page) 751 { 752 u16 local_port_end = (port_page + 1) * MLXSW_REG_REIV_REC_MAX_COUNT - 1; 753 u16 local_port_start = port_page * MLXSW_REG_REIV_REC_MAX_COUNT; 754 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; 755 struct mlxsw_sp_fid_port_vid *port_vid; 756 u8 rec_num, entries_num = 0; 757 char *reiv_pl; 758 int err; 759 760 reiv_pl = kmalloc(MLXSW_REG_REIV_LEN, GFP_KERNEL); 761 if (!reiv_pl) 762 return -ENOMEM; 763 764 mlxsw_reg_reiv_pack(reiv_pl, port_page, rif_index); 765 766 list_for_each_entry(port_vid, &fid->port_vid_list, list) { 767 /* port_vid_list is sorted by local_port. */ 768 if (port_vid->local_port < local_port_start) 769 continue; 770 771 if (port_vid->local_port > local_port_end) 772 break; 773 774 rec_num = port_vid->local_port % MLXSW_REG_REIV_REC_MAX_COUNT; 775 mlxsw_reg_reiv_rec_update_set(reiv_pl, rec_num, true); 776 mlxsw_reg_reiv_rec_evid_set(reiv_pl, rec_num, 777 valid ? port_vid->vid : 0); 778 entries_num++; 779 } 780 781 if (!entries_num) { 782 kfree(reiv_pl); 783 return 0; 784 } 785 786 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(reiv), reiv_pl); 787 if (err) 788 goto err_reg_write; 789 790 kfree(reiv_pl); 791 return 0; 792 793 err_reg_write: 794 kfree(reiv_pl); 795 return err; 796 } 797 798 static int mlxsw_sp_fid_erif_eport_to_vid_map(struct mlxsw_sp_fid *fid, 799 u16 rif_index, bool valid) 800 { 801 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; 802 u8 num_port_pages; 803 int err, i; 804 805 num_port_pages = mlxsw_core_max_ports(mlxsw_sp->core) / 806 MLXSW_REG_REIV_REC_MAX_COUNT + 1; 807 808 for (i = 0; i < num_port_pages; i++) { 809 err = mlxsw_sp_fid_reiv_handle(fid, rif_index, valid, i); 810 if (err) 811 goto err_reiv_handle; 812 } 813 814 return 0; 815 816 err_reiv_handle: 817 for (; i >= 0; i--) 818 mlxsw_sp_fid_reiv_handle(fid, rif_index, !valid, i); 819 return err; 820 } 821 822 int mlxsw_sp_fid_rif_set(struct mlxsw_sp_fid *fid, struct mlxsw_sp_rif *rif) 823 { 824 u16 rif_index = mlxsw_sp_rif_index(rif); 825 int err; 826 827 err = mlxsw_sp_fid_to_fid_rif_update(fid, rif); 828 if (err) 829 return err; 830 831 err = mlxsw_sp_fid_vni_to_fid_rif_update(fid, rif); 832 if (err) 833 goto err_vni_to_fid_rif_update; 834 835 err = mlxsw_sp_fid_vid_to_fid_rif_set(fid, rif); 836 if (err) 837 goto err_vid_to_fid_rif_set; 838 839 err = mlxsw_sp_fid_erif_eport_to_vid_map(fid, rif_index, true); 840 if (err) 841 goto err_erif_eport_to_vid_map; 842 843 fid->rif = rif; 844 return 0; 845 846 err_erif_eport_to_vid_map: 847 mlxsw_sp_fid_vid_to_fid_rif_unset(fid); 848 err_vid_to_fid_rif_set: 849 mlxsw_sp_fid_vni_to_fid_rif_update(fid, NULL); 850 err_vni_to_fid_rif_update: 851 mlxsw_sp_fid_to_fid_rif_update(fid, NULL); 852 return err; 853 } 854 855 void mlxsw_sp_fid_rif_unset(struct mlxsw_sp_fid *fid) 856 { 857 u16 rif_index; 858 859 if (!fid->rif) 860 return; 861 862 rif_index = mlxsw_sp_rif_index(fid->rif); 863 fid->rif = NULL; 864 865 mlxsw_sp_fid_erif_eport_to_vid_map(fid, rif_index, false); 866 mlxsw_sp_fid_vid_to_fid_rif_unset(fid); 867 mlxsw_sp_fid_vni_to_fid_rif_update(fid, NULL); 868 mlxsw_sp_fid_to_fid_rif_update(fid, NULL); 869 } 870 871 static int mlxsw_sp_fid_vni_op(const struct mlxsw_sp_fid *fid) 872 { 873 int err; 874 875 err = mlxsw_sp_fid_vni_to_fid_map(fid, fid->rif, fid->vni_valid); 876 if (err) 877 return err; 878 879 err = mlxsw_sp_fid_edit_op(fid, fid->rif); 880 if (err) 881 goto err_fid_edit_op; 882 883 return 0; 884 885 err_fid_edit_op: 886 mlxsw_sp_fid_vni_to_fid_map(fid, fid->rif, !fid->vni_valid); 887 return err; 888 } 889 890 static int __mlxsw_sp_fid_port_vid_map(const struct mlxsw_sp_fid *fid, 891 u16 local_port, u16 vid, bool valid) 892 { 893 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; 894 char svfa_pl[MLXSW_REG_SVFA_LEN]; 895 bool irif_valid = false; 896 u16 irif_index = 0; 897 898 if (fid->rif) { 899 irif_valid = true; 900 irif_index = mlxsw_sp_rif_index(fid->rif); 901 } 902 903 mlxsw_reg_svfa_port_vid_pack(svfa_pl, local_port, valid, fid->fid_index, 904 vid, irif_valid, irif_index); 905 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl); 906 } 907 908 static struct mlxsw_sp_fid_8021d * 909 mlxsw_sp_fid_8021d_fid(const struct mlxsw_sp_fid *fid) 910 { 911 return container_of(fid, struct mlxsw_sp_fid_8021d, common); 912 } 913 914 static int mlxsw_sp_fid_8021d_setup(struct mlxsw_sp_fid *fid, const void *arg) 915 { 916 int br_ifindex = *(int *) arg; 917 918 mlxsw_sp_fid_8021d_fid(fid)->br_ifindex = br_ifindex; 919 fid->fid_offset = fid->fid_index - fid->fid_family->start_index; 920 return 0; 921 } 922 923 static int mlxsw_sp_fid_8021d_configure(struct mlxsw_sp_fid *fid) 924 { 925 return mlxsw_sp_fid_op(fid, true); 926 } 927 928 static void mlxsw_sp_fid_8021d_deconfigure(struct mlxsw_sp_fid *fid) 929 { 930 if (fid->vni_valid) 931 mlxsw_sp_nve_fid_disable(fid->fid_family->mlxsw_sp, fid); 932 mlxsw_sp_fid_op(fid, false); 933 } 934 935 static int mlxsw_sp_fid_8021d_index_alloc(struct mlxsw_sp_fid *fid, 936 const void *arg, u16 *p_fid_index) 937 { 938 struct mlxsw_sp_fid_family *fid_family = fid->fid_family; 939 u16 nr_fids, fid_index; 940 941 nr_fids = fid_family->end_index - fid_family->start_index + 1; 942 fid_index = find_first_zero_bit(fid_family->fids_bitmap, nr_fids); 943 if (fid_index == nr_fids) 944 return -ENOBUFS; 945 *p_fid_index = fid_family->start_index + fid_index; 946 947 return 0; 948 } 949 950 static bool 951 mlxsw_sp_fid_8021d_compare(const struct mlxsw_sp_fid *fid, const void *arg) 952 { 953 int br_ifindex = *(int *) arg; 954 955 return mlxsw_sp_fid_8021d_fid(fid)->br_ifindex == br_ifindex; 956 } 957 958 static int mlxsw_sp_port_vp_mode_trans(struct mlxsw_sp_port *mlxsw_sp_port) 959 { 960 struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan; 961 int err; 962 963 list_for_each_entry(mlxsw_sp_port_vlan, &mlxsw_sp_port->vlans_list, 964 list) { 965 struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid; 966 u16 vid = mlxsw_sp_port_vlan->vid; 967 968 if (!fid) 969 continue; 970 971 err = __mlxsw_sp_fid_port_vid_map(fid, 972 mlxsw_sp_port->local_port, 973 vid, true); 974 if (err) 975 goto err_fid_port_vid_map; 976 } 977 978 err = mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, true); 979 if (err) 980 goto err_port_vp_mode_set; 981 982 return 0; 983 984 err_port_vp_mode_set: 985 err_fid_port_vid_map: 986 list_for_each_entry_continue_reverse(mlxsw_sp_port_vlan, 987 &mlxsw_sp_port->vlans_list, list) { 988 struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid; 989 u16 vid = mlxsw_sp_port_vlan->vid; 990 991 if (!fid) 992 continue; 993 994 __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, 995 false); 996 } 997 return err; 998 } 999 1000 static void mlxsw_sp_port_vlan_mode_trans(struct mlxsw_sp_port *mlxsw_sp_port) 1001 { 1002 struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan; 1003 1004 mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, false); 1005 1006 list_for_each_entry_reverse(mlxsw_sp_port_vlan, 1007 &mlxsw_sp_port->vlans_list, list) { 1008 struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid; 1009 u16 vid = mlxsw_sp_port_vlan->vid; 1010 1011 if (!fid) 1012 continue; 1013 1014 __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, 1015 false); 1016 } 1017 } 1018 1019 static int 1020 mlxsw_sp_fid_port_vid_list_add(struct mlxsw_sp_fid *fid, u16 local_port, 1021 u16 vid) 1022 { 1023 struct mlxsw_sp_fid_port_vid *port_vid, *tmp_port_vid; 1024 struct list_head *insert_before = &fid->port_vid_list; 1025 1026 port_vid = kzalloc_obj(*port_vid); 1027 if (!port_vid) 1028 return -ENOMEM; 1029 1030 port_vid->local_port = local_port; 1031 port_vid->vid = vid; 1032 1033 list_for_each_entry(tmp_port_vid, &fid->port_vid_list, list) { 1034 if (tmp_port_vid->local_port > local_port) { 1035 insert_before = &tmp_port_vid->list; 1036 break; 1037 } 1038 } 1039 1040 list_add_tail(&port_vid->list, insert_before); 1041 return 0; 1042 } 1043 1044 static void 1045 mlxsw_sp_fid_port_vid_list_del(struct mlxsw_sp_fid *fid, u16 local_port, 1046 u16 vid) 1047 { 1048 struct mlxsw_sp_fid_port_vid *port_vid, *tmp; 1049 1050 list_for_each_entry_safe(port_vid, tmp, &fid->port_vid_list, list) { 1051 if (port_vid->local_port != local_port || port_vid->vid != vid) 1052 continue; 1053 1054 list_del(&port_vid->list); 1055 kfree(port_vid); 1056 return; 1057 } 1058 } 1059 1060 static int 1061 mlxsw_sp_fid_mpe_table_map(const struct mlxsw_sp_fid *fid, u16 local_port, 1062 u16 vid, bool valid) 1063 { 1064 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; 1065 char smpe_pl[MLXSW_REG_SMPE_LEN]; 1066 1067 mlxsw_reg_smpe_pack(smpe_pl, local_port, fid->fid_index, 1068 valid ? vid : 0); 1069 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(smpe), smpe_pl); 1070 } 1071 1072 static int 1073 mlxsw_sp_fid_erif_eport_to_vid_map_one(const struct mlxsw_sp_fid *fid, 1074 u16 local_port, u16 vid, bool valid) 1075 { 1076 u8 port_page = local_port / MLXSW_REG_REIV_REC_MAX_COUNT; 1077 u8 rec_num = local_port % MLXSW_REG_REIV_REC_MAX_COUNT; 1078 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; 1079 u16 rif_index = mlxsw_sp_rif_index(fid->rif); 1080 char *reiv_pl; 1081 int err; 1082 1083 reiv_pl = kmalloc(MLXSW_REG_REIV_LEN, GFP_KERNEL); 1084 if (!reiv_pl) 1085 return -ENOMEM; 1086 1087 mlxsw_reg_reiv_pack(reiv_pl, port_page, rif_index); 1088 mlxsw_reg_reiv_rec_update_set(reiv_pl, rec_num, true); 1089 mlxsw_reg_reiv_rec_evid_set(reiv_pl, rec_num, valid ? vid : 0); 1090 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(reiv), reiv_pl); 1091 kfree(reiv_pl); 1092 return err; 1093 } 1094 1095 static int mlxsw_sp_fid_evid_map(const struct mlxsw_sp_fid *fid, u16 local_port, 1096 u16 vid, bool valid) 1097 { 1098 int err; 1099 1100 err = mlxsw_sp_fid_mpe_table_map(fid, local_port, vid, valid); 1101 if (err) 1102 return err; 1103 1104 if (!fid->rif) 1105 return 0; 1106 1107 err = mlxsw_sp_fid_erif_eport_to_vid_map_one(fid, local_port, vid, 1108 valid); 1109 if (err) 1110 goto err_erif_eport_to_vid_map_one; 1111 1112 return 0; 1113 1114 err_erif_eport_to_vid_map_one: 1115 mlxsw_sp_fid_mpe_table_map(fid, local_port, vid, !valid); 1116 return err; 1117 } 1118 1119 static int mlxsw_sp_fid_8021d_port_vid_map(struct mlxsw_sp_fid *fid, 1120 struct mlxsw_sp_port *mlxsw_sp_port, 1121 u16 vid) 1122 { 1123 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 1124 u16 local_port = mlxsw_sp_port->local_port; 1125 int err; 1126 1127 err = __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, 1128 true); 1129 if (err) 1130 return err; 1131 1132 err = mlxsw_sp_fid_evid_map(fid, local_port, vid, true); 1133 if (err) 1134 goto err_fid_evid_map; 1135 1136 err = mlxsw_sp_fid_port_vid_list_add(fid, mlxsw_sp_port->local_port, 1137 vid); 1138 if (err) 1139 goto err_port_vid_list_add; 1140 1141 if (mlxsw_sp->fid_core->port_fid_mappings[local_port]++ == 0) { 1142 err = mlxsw_sp_port_vp_mode_trans(mlxsw_sp_port); 1143 if (err) 1144 goto err_port_vp_mode_trans; 1145 } 1146 1147 return 0; 1148 1149 err_port_vp_mode_trans: 1150 mlxsw_sp->fid_core->port_fid_mappings[local_port]--; 1151 mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid); 1152 err_port_vid_list_add: 1153 mlxsw_sp_fid_evid_map(fid, local_port, vid, false); 1154 err_fid_evid_map: 1155 __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, false); 1156 return err; 1157 } 1158 1159 static void 1160 mlxsw_sp_fid_8021d_port_vid_unmap(struct mlxsw_sp_fid *fid, 1161 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid) 1162 { 1163 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 1164 u16 local_port = mlxsw_sp_port->local_port; 1165 1166 if (mlxsw_sp->fid_core->port_fid_mappings[local_port] == 1) 1167 mlxsw_sp_port_vlan_mode_trans(mlxsw_sp_port); 1168 mlxsw_sp->fid_core->port_fid_mappings[local_port]--; 1169 mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid); 1170 mlxsw_sp_fid_evid_map(fid, local_port, vid, false); 1171 __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, false); 1172 } 1173 1174 static int mlxsw_sp_fid_8021d_vni_set(struct mlxsw_sp_fid *fid) 1175 { 1176 return mlxsw_sp_fid_vni_op(fid); 1177 } 1178 1179 static void mlxsw_sp_fid_8021d_vni_clear(struct mlxsw_sp_fid *fid) 1180 { 1181 mlxsw_sp_fid_vni_op(fid); 1182 } 1183 1184 static int mlxsw_sp_fid_8021d_nve_flood_index_set(struct mlxsw_sp_fid *fid) 1185 { 1186 return mlxsw_sp_fid_edit_op(fid, fid->rif); 1187 } 1188 1189 static void mlxsw_sp_fid_8021d_nve_flood_index_clear(struct mlxsw_sp_fid *fid) 1190 { 1191 mlxsw_sp_fid_edit_op(fid, fid->rif); 1192 } 1193 1194 static void 1195 mlxsw_sp_fid_8021d_fdb_clear_offload(const struct mlxsw_sp_fid *fid, 1196 const struct net_device *nve_dev) 1197 { 1198 br_fdb_clear_offload(nve_dev, 0); 1199 } 1200 1201 static int 1202 mlxsw_sp_fid_8021d_vid_to_fid_rif_update(const struct mlxsw_sp_fid *fid, 1203 const struct mlxsw_sp_rif *rif) 1204 { 1205 return 0; 1206 } 1207 1208 static int 1209 mlxsw_sp_fid_flood_table_init_ctl(struct mlxsw_sp_fid_family *fid_family, 1210 const struct mlxsw_sp_flood_table *flood_table) 1211 { 1212 enum mlxsw_sp_flood_type packet_type = flood_table->packet_type; 1213 struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp; 1214 const int *sfgc_packet_types; 1215 u16 mid_base; 1216 int err, i; 1217 1218 mid_base = mlxsw_sp_fid_pgt_base_ctl(fid_family, flood_table); 1219 1220 sfgc_packet_types = mlxsw_sp_packet_type_sfgc_types[packet_type]; 1221 for (i = 0; i < MLXSW_REG_SFGC_TYPE_MAX; i++) { 1222 char sfgc_pl[MLXSW_REG_SFGC_LEN]; 1223 1224 if (!sfgc_packet_types[i]) 1225 continue; 1226 1227 mlxsw_reg_sfgc_pack(sfgc_pl, i, fid_family->bridge_type, 1228 flood_table->table_type, 0, mid_base); 1229 1230 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfgc), sfgc_pl); 1231 if (err) 1232 return err; 1233 } 1234 1235 return 0; 1236 } 1237 1238 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021d_ops_ctl = { 1239 .setup = mlxsw_sp_fid_8021d_setup, 1240 .configure = mlxsw_sp_fid_8021d_configure, 1241 .deconfigure = mlxsw_sp_fid_8021d_deconfigure, 1242 .index_alloc = mlxsw_sp_fid_8021d_index_alloc, 1243 .compare = mlxsw_sp_fid_8021d_compare, 1244 .port_vid_map = mlxsw_sp_fid_8021d_port_vid_map, 1245 .port_vid_unmap = mlxsw_sp_fid_8021d_port_vid_unmap, 1246 .vni_set = mlxsw_sp_fid_8021d_vni_set, 1247 .vni_clear = mlxsw_sp_fid_8021d_vni_clear, 1248 .nve_flood_index_set = mlxsw_sp_fid_8021d_nve_flood_index_set, 1249 .nve_flood_index_clear = mlxsw_sp_fid_8021d_nve_flood_index_clear, 1250 .fdb_clear_offload = mlxsw_sp_fid_8021d_fdb_clear_offload, 1251 .vid_to_fid_rif_update = mlxsw_sp_fid_8021d_vid_to_fid_rif_update, 1252 .flood_table_init = mlxsw_sp_fid_flood_table_init_ctl, 1253 .pgt_size = mlxsw_sp_fid_8021d_pgt_size, 1254 .fid_mid = mlxsw_sp_fid_fid_mid_ctl, 1255 .fid_pack = mlxsw_sp_fid_pack_ctl, 1256 }; 1257 1258 static u16 1259 mlxsw_sp_fid_fid_mid_cff(const struct mlxsw_sp_fid *fid, 1260 const struct mlxsw_sp_flood_table *flood_table) 1261 { 1262 return mlxsw_sp_fid_pgt_base_cff(fid) + flood_table->table_index; 1263 } 1264 1265 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021d_ops_cff = { 1266 .setup = mlxsw_sp_fid_8021d_setup, 1267 .configure = mlxsw_sp_fid_8021d_configure, 1268 .deconfigure = mlxsw_sp_fid_8021d_deconfigure, 1269 .index_alloc = mlxsw_sp_fid_8021d_index_alloc, 1270 .compare = mlxsw_sp_fid_8021d_compare, 1271 .port_vid_map = mlxsw_sp_fid_8021d_port_vid_map, 1272 .port_vid_unmap = mlxsw_sp_fid_8021d_port_vid_unmap, 1273 .vni_set = mlxsw_sp_fid_8021d_vni_set, 1274 .vni_clear = mlxsw_sp_fid_8021d_vni_clear, 1275 .nve_flood_index_set = mlxsw_sp_fid_8021d_nve_flood_index_set, 1276 .nve_flood_index_clear = mlxsw_sp_fid_8021d_nve_flood_index_clear, 1277 .fdb_clear_offload = mlxsw_sp_fid_8021d_fdb_clear_offload, 1278 .vid_to_fid_rif_update = mlxsw_sp_fid_8021d_vid_to_fid_rif_update, 1279 .pgt_size = mlxsw_sp_fid_8021d_pgt_size, 1280 .fid_mid = mlxsw_sp_fid_fid_mid_cff, 1281 .fid_pack = mlxsw_sp_fid_fid_pack_cff, 1282 }; 1283 1284 #define MLXSW_SP_FID_8021Q_MAX (VLAN_N_VID - 2) 1285 #define MLXSW_SP_FID_RFID_MAX (11 * 1024) 1286 1287 static const struct mlxsw_sp_flood_table mlxsw_sp_fid_8021d_flood_tables[] = { 1288 { 1289 .packet_type = MLXSW_SP_FLOOD_TYPE_UC, 1290 .table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFSET, 1291 .table_index = 0, 1292 }, 1293 { 1294 .packet_type = MLXSW_SP_FLOOD_TYPE_MC, 1295 .table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFSET, 1296 .table_index = 1, 1297 }, 1298 { 1299 .packet_type = MLXSW_SP_FLOOD_TYPE_BC, 1300 .table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFSET, 1301 .table_index = 2, 1302 }, 1303 }; 1304 1305 static const 1306 struct mlxsw_sp_fid_flood_profile mlxsw_sp_fid_8021d_flood_profile = { 1307 .flood_tables = mlxsw_sp_fid_8021d_flood_tables, 1308 .nr_flood_tables = ARRAY_SIZE(mlxsw_sp_fid_8021d_flood_tables), 1309 .profile_id = MLXSW_SP_FID_FLOOD_PROFILE_ID_BRIDGE, 1310 }; 1311 1312 static const struct mlxsw_sp_flood_table mlxsw_sp_fid_rsp_flood_tables_cff[] = { 1313 { 1314 .packet_type = MLXSW_SP_FLOOD_TYPE_UC, 1315 .table_index = 0, 1316 }, 1317 { 1318 .packet_type = MLXSW_SP_FLOOD_TYPE_NOT_UC, 1319 .table_index = 1, 1320 }, 1321 }; 1322 1323 static const 1324 struct mlxsw_sp_fid_flood_profile mlxsw_sp_fid_rsp_flood_profile_cff = { 1325 .flood_tables = mlxsw_sp_fid_rsp_flood_tables_cff, 1326 .nr_flood_tables = ARRAY_SIZE(mlxsw_sp_fid_rsp_flood_tables_cff), 1327 .profile_id = MLXSW_SP_FID_FLOOD_PROFILE_ID_RSP, 1328 }; 1329 1330 static const struct mlxsw_sp_flood_table mlxsw_sp_fid_nve_flood_tables_cff[] = { 1331 { 1332 .packet_type = MLXSW_SP_FLOOD_TYPE_ANY, 1333 .table_index = 0, 1334 }, 1335 }; 1336 1337 static const 1338 struct mlxsw_sp_fid_flood_profile mlxsw_sp_fid_nve_flood_profile_cff = { 1339 .flood_tables = mlxsw_sp_fid_nve_flood_tables_cff, 1340 .nr_flood_tables = ARRAY_SIZE(mlxsw_sp_fid_nve_flood_tables_cff), 1341 .profile_id = MLXSW_SP_FID_FLOOD_PROFILE_ID_NVE, 1342 }; 1343 1344 static bool 1345 mlxsw_sp_fid_8021q_compare(const struct mlxsw_sp_fid *fid, const void *arg) 1346 { 1347 u16 vid = *(u16 *) arg; 1348 1349 return mlxsw_sp_fid_8021q_fid(fid)->vid == vid; 1350 } 1351 1352 static void 1353 mlxsw_sp_fid_8021q_fdb_clear_offload(const struct mlxsw_sp_fid *fid, 1354 const struct net_device *nve_dev) 1355 { 1356 br_fdb_clear_offload(nve_dev, mlxsw_sp_fid_8021q_vid(fid)); 1357 } 1358 1359 static int mlxsw_sp_fid_rfid_setup_ctl(struct mlxsw_sp_fid *fid, 1360 const void *arg) 1361 { 1362 /* In controlled mode, the FW takes care of FID placement. */ 1363 fid->fid_offset = 0; 1364 return 0; 1365 } 1366 1367 static int mlxsw_sp_fid_rfid_setup_cff(struct mlxsw_sp_fid *fid, 1368 const void *arg) 1369 { 1370 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; 1371 u16 rif_index = *(const u16 *)arg; 1372 struct mlxsw_sp_rif *rif; 1373 bool is_lag; 1374 u16 port; 1375 int err; 1376 1377 rif = mlxsw_sp_rif_by_index(mlxsw_sp, rif_index); 1378 if (!rif) 1379 return -ENOENT; 1380 1381 err = mlxsw_sp_rif_subport_port(rif, &port, &is_lag); 1382 if (err) 1383 return err; 1384 1385 fid->fid_offset = mlxsw_sp_fid_rfid_fid_offset_cff(mlxsw_sp, port, 1386 is_lag); 1387 return 0; 1388 } 1389 1390 static int mlxsw_sp_fid_rfid_configure(struct mlxsw_sp_fid *fid) 1391 { 1392 return mlxsw_sp_fid_op(fid, true); 1393 } 1394 1395 static void mlxsw_sp_fid_rfid_deconfigure(struct mlxsw_sp_fid *fid) 1396 { 1397 mlxsw_sp_fid_op(fid, false); 1398 } 1399 1400 static int mlxsw_sp_fid_rfid_index_alloc(struct mlxsw_sp_fid *fid, 1401 const void *arg, u16 *p_fid_index) 1402 { 1403 u16 rif_index = *(u16 *) arg; 1404 1405 *p_fid_index = fid->fid_family->start_index + rif_index; 1406 1407 return 0; 1408 } 1409 1410 static bool mlxsw_sp_fid_rfid_compare(const struct mlxsw_sp_fid *fid, 1411 const void *arg) 1412 { 1413 u16 rif_index = *(u16 *) arg; 1414 1415 return fid->fid_index == rif_index + fid->fid_family->start_index; 1416 } 1417 1418 static int mlxsw_sp_fid_rfid_port_vid_map(struct mlxsw_sp_fid *fid, 1419 struct mlxsw_sp_port *mlxsw_sp_port, 1420 u16 vid) 1421 { 1422 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 1423 u16 local_port = mlxsw_sp_port->local_port; 1424 int err; 1425 1426 err = mlxsw_sp_fid_port_vid_list_add(fid, mlxsw_sp_port->local_port, 1427 vid); 1428 if (err) 1429 return err; 1430 1431 /* Using legacy bridge model, we only need to transition the port to 1432 * virtual mode since {Port, VID} => FID is done by the firmware upon 1433 * RIF creation. Using unified bridge model, we need to map 1434 * {Port, VID} => FID and map egress VID. 1435 */ 1436 err = __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, 1437 true); 1438 if (err) 1439 goto err_port_vid_map; 1440 1441 if (fid->rif) { 1442 err = mlxsw_sp_fid_erif_eport_to_vid_map_one(fid, local_port, 1443 vid, true); 1444 if (err) 1445 goto err_erif_eport_to_vid_map_one; 1446 } 1447 1448 if (mlxsw_sp->fid_core->port_fid_mappings[local_port]++ == 0) { 1449 err = mlxsw_sp_port_vp_mode_trans(mlxsw_sp_port); 1450 if (err) 1451 goto err_port_vp_mode_trans; 1452 } 1453 1454 return 0; 1455 1456 err_port_vp_mode_trans: 1457 mlxsw_sp->fid_core->port_fid_mappings[local_port]--; 1458 if (fid->rif) 1459 mlxsw_sp_fid_erif_eport_to_vid_map_one(fid, local_port, vid, 1460 false); 1461 err_erif_eport_to_vid_map_one: 1462 __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, false); 1463 err_port_vid_map: 1464 mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid); 1465 return err; 1466 } 1467 1468 static void 1469 mlxsw_sp_fid_rfid_port_vid_unmap(struct mlxsw_sp_fid *fid, 1470 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid) 1471 { 1472 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 1473 u16 local_port = mlxsw_sp_port->local_port; 1474 1475 if (mlxsw_sp->fid_core->port_fid_mappings[local_port] == 1) 1476 mlxsw_sp_port_vlan_mode_trans(mlxsw_sp_port); 1477 mlxsw_sp->fid_core->port_fid_mappings[local_port]--; 1478 1479 if (fid->rif) 1480 mlxsw_sp_fid_erif_eport_to_vid_map_one(fid, local_port, vid, 1481 false); 1482 __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, false); 1483 mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid); 1484 } 1485 1486 static int mlxsw_sp_fid_rfid_vni_set(struct mlxsw_sp_fid *fid) 1487 { 1488 return -EOPNOTSUPP; 1489 } 1490 1491 static void mlxsw_sp_fid_rfid_vni_clear(struct mlxsw_sp_fid *fid) 1492 { 1493 WARN_ON_ONCE(1); 1494 } 1495 1496 static int mlxsw_sp_fid_rfid_nve_flood_index_set(struct mlxsw_sp_fid *fid) 1497 { 1498 return -EOPNOTSUPP; 1499 } 1500 1501 static void mlxsw_sp_fid_rfid_nve_flood_index_clear(struct mlxsw_sp_fid *fid) 1502 { 1503 WARN_ON_ONCE(1); 1504 } 1505 1506 static int 1507 mlxsw_sp_fid_rfid_vid_to_fid_rif_update(const struct mlxsw_sp_fid *fid, 1508 const struct mlxsw_sp_rif *rif) 1509 { 1510 return 0; 1511 } 1512 1513 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_rfid_ops_ctl = { 1514 .setup = mlxsw_sp_fid_rfid_setup_ctl, 1515 .configure = mlxsw_sp_fid_rfid_configure, 1516 .deconfigure = mlxsw_sp_fid_rfid_deconfigure, 1517 .index_alloc = mlxsw_sp_fid_rfid_index_alloc, 1518 .compare = mlxsw_sp_fid_rfid_compare, 1519 .port_vid_map = mlxsw_sp_fid_rfid_port_vid_map, 1520 .port_vid_unmap = mlxsw_sp_fid_rfid_port_vid_unmap, 1521 .vni_set = mlxsw_sp_fid_rfid_vni_set, 1522 .vni_clear = mlxsw_sp_fid_rfid_vni_clear, 1523 .nve_flood_index_set = mlxsw_sp_fid_rfid_nve_flood_index_set, 1524 .nve_flood_index_clear = mlxsw_sp_fid_rfid_nve_flood_index_clear, 1525 .vid_to_fid_rif_update = mlxsw_sp_fid_rfid_vid_to_fid_rif_update, 1526 .fid_pack = mlxsw_sp_fid_pack_ctl, 1527 }; 1528 1529 static int 1530 mlxsw_sp_fid_rfid_port_add_cff(struct mlxsw_sp *mlxsw_sp, 1531 const struct mlxsw_sp_flood_table *flood_table, 1532 u16 pgt_addr, u16 smpe, unsigned int local_port) 1533 { 1534 int err; 1535 1536 err = mlxsw_sp_pgt_entry_port_set(mlxsw_sp, pgt_addr, smpe, 1537 local_port, true); 1538 if (err) 1539 return err; 1540 1541 if (flood_table->packet_type == MLXSW_SP_FLOOD_TYPE_NOT_UC) { 1542 u16 router_port = mlxsw_sp_router_port(mlxsw_sp); 1543 1544 err = mlxsw_sp_pgt_entry_port_set(mlxsw_sp, pgt_addr, smpe, 1545 router_port, true); 1546 if (err) 1547 goto err_entry_port_set; 1548 } 1549 1550 return 0; 1551 1552 err_entry_port_set: 1553 mlxsw_sp_pgt_entry_port_set(mlxsw_sp, pgt_addr, smpe, local_port, 1554 false); 1555 return err; 1556 } 1557 1558 static void 1559 mlxsw_sp_fid_rfid_port_del_cff(struct mlxsw_sp *mlxsw_sp, 1560 const struct mlxsw_sp_flood_table *flood_table, 1561 u16 pgt_addr, u16 smpe, u16 local_port) 1562 { 1563 if (flood_table->packet_type == MLXSW_SP_FLOOD_TYPE_NOT_UC) { 1564 u16 router_port = mlxsw_sp_router_port(mlxsw_sp); 1565 1566 mlxsw_sp_pgt_entry_port_set(mlxsw_sp, pgt_addr, smpe, 1567 router_port, false); 1568 } 1569 mlxsw_sp_pgt_entry_port_set(mlxsw_sp, pgt_addr, smpe, local_port, 1570 false); 1571 } 1572 1573 static int 1574 mlxsw_sp_fid_rfid_port_memb_ft_cff(const struct mlxsw_sp_fid_family *fid_family, 1575 const struct mlxsw_sp_flood_table *flood_table, 1576 const struct mlxsw_sp_port *mlxsw_sp_port, 1577 bool member) 1578 { 1579 struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp; 1580 u16 local_port = mlxsw_sp_port->local_port; 1581 u16 fid_pgt_base; 1582 u16 fid_offset; 1583 u16 pgt_addr; 1584 u16 smpe; 1585 u16 port; 1586 1587 /* In-PGT SMPE is only valid on Spectrum-1, CFF only on Spectrum>1. */ 1588 smpe = 0; 1589 1590 port = mlxsw_sp_port->lagged ? mlxsw_sp_port->lag_id : local_port; 1591 fid_offset = mlxsw_sp_fid_rfid_fid_offset_cff(mlxsw_sp, port, 1592 mlxsw_sp_port->lagged); 1593 fid_pgt_base = mlxsw_sp_fid_off_pgt_base_cff(fid_family, fid_offset); 1594 pgt_addr = fid_pgt_base + flood_table->table_index; 1595 1596 if (member) 1597 return mlxsw_sp_fid_rfid_port_add_cff(mlxsw_sp, flood_table, 1598 pgt_addr, smpe, 1599 local_port); 1600 1601 mlxsw_sp_fid_rfid_port_del_cff(mlxsw_sp, flood_table, pgt_addr, smpe, 1602 local_port); 1603 return 0; 1604 } 1605 1606 static int 1607 mlxsw_sp_fid_rfid_port_memb_cff(const struct mlxsw_sp_fid_family *fid_family, 1608 const struct mlxsw_sp_port *mlxsw_sp_port, 1609 bool member) 1610 { 1611 int i; 1612 1613 for (i = 0; i < fid_family->flood_profile->nr_flood_tables; i++) { 1614 const struct mlxsw_sp_flood_table *flood_table = 1615 &fid_family->flood_profile->flood_tables[i]; 1616 int err; 1617 1618 err = mlxsw_sp_fid_rfid_port_memb_ft_cff(fid_family, 1619 flood_table, 1620 mlxsw_sp_port, member); 1621 if (err) 1622 return err; 1623 } 1624 1625 return 0; 1626 } 1627 1628 static int 1629 mlxsw_sp_fid_rfid_port_init_cff(const struct mlxsw_sp_fid_family *fid_family, 1630 const struct mlxsw_sp_port *mlxsw_sp_port) 1631 { 1632 return mlxsw_sp_fid_rfid_port_memb_cff(fid_family, mlxsw_sp_port, true); 1633 } 1634 1635 static void 1636 mlxsw_sp_fid_rfid_port_fini_cff(const struct mlxsw_sp_fid_family *fid_family, 1637 const struct mlxsw_sp_port *mlxsw_sp_port) 1638 { 1639 mlxsw_sp_fid_rfid_port_memb_cff(fid_family, mlxsw_sp_port, false); 1640 } 1641 1642 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_rfid_ops_cff = { 1643 .setup = mlxsw_sp_fid_rfid_setup_cff, 1644 .configure = mlxsw_sp_fid_rfid_configure, 1645 .deconfigure = mlxsw_sp_fid_rfid_deconfigure, 1646 .index_alloc = mlxsw_sp_fid_rfid_index_alloc, 1647 .compare = mlxsw_sp_fid_rfid_compare, 1648 .port_vid_map = mlxsw_sp_fid_rfid_port_vid_map, 1649 .port_vid_unmap = mlxsw_sp_fid_rfid_port_vid_unmap, 1650 .vni_set = mlxsw_sp_fid_rfid_vni_set, 1651 .vni_clear = mlxsw_sp_fid_rfid_vni_clear, 1652 .nve_flood_index_set = mlxsw_sp_fid_rfid_nve_flood_index_set, 1653 .nve_flood_index_clear = mlxsw_sp_fid_rfid_nve_flood_index_clear, 1654 .vid_to_fid_rif_update = mlxsw_sp_fid_rfid_vid_to_fid_rif_update, 1655 .pgt_size = mlxsw_sp_fid_rfid_pgt_size_cff, 1656 .fid_port_init = mlxsw_sp_fid_rfid_port_init_cff, 1657 .fid_port_fini = mlxsw_sp_fid_rfid_port_fini_cff, 1658 .fid_mid = mlxsw_sp_fid_fid_mid_cff, 1659 .fid_pack = mlxsw_sp_fid_fid_pack_cff, 1660 }; 1661 1662 static int mlxsw_sp_fid_dummy_setup(struct mlxsw_sp_fid *fid, const void *arg) 1663 { 1664 fid->fid_offset = 0; 1665 return 0; 1666 } 1667 1668 static int mlxsw_sp_fid_dummy_configure(struct mlxsw_sp_fid *fid) 1669 { 1670 return mlxsw_sp_fid_op(fid, true); 1671 } 1672 1673 static void mlxsw_sp_fid_dummy_deconfigure(struct mlxsw_sp_fid *fid) 1674 { 1675 mlxsw_sp_fid_op(fid, false); 1676 } 1677 1678 static int mlxsw_sp_fid_dummy_index_alloc(struct mlxsw_sp_fid *fid, 1679 const void *arg, u16 *p_fid_index) 1680 { 1681 *p_fid_index = fid->fid_family->start_index; 1682 1683 return 0; 1684 } 1685 1686 static bool mlxsw_sp_fid_dummy_compare(const struct mlxsw_sp_fid *fid, 1687 const void *arg) 1688 { 1689 return true; 1690 } 1691 1692 static int mlxsw_sp_fid_dummy_vni_set(struct mlxsw_sp_fid *fid) 1693 { 1694 return -EOPNOTSUPP; 1695 } 1696 1697 static void mlxsw_sp_fid_dummy_vni_clear(struct mlxsw_sp_fid *fid) 1698 { 1699 WARN_ON_ONCE(1); 1700 } 1701 1702 static int mlxsw_sp_fid_dummy_nve_flood_index_set(struct mlxsw_sp_fid *fid) 1703 { 1704 return -EOPNOTSUPP; 1705 } 1706 1707 static void mlxsw_sp_fid_dummy_nve_flood_index_clear(struct mlxsw_sp_fid *fid) 1708 { 1709 WARN_ON_ONCE(1); 1710 } 1711 1712 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_dummy_ops = { 1713 .setup = mlxsw_sp_fid_dummy_setup, 1714 .configure = mlxsw_sp_fid_dummy_configure, 1715 .deconfigure = mlxsw_sp_fid_dummy_deconfigure, 1716 .index_alloc = mlxsw_sp_fid_dummy_index_alloc, 1717 .compare = mlxsw_sp_fid_dummy_compare, 1718 .vni_set = mlxsw_sp_fid_dummy_vni_set, 1719 .vni_clear = mlxsw_sp_fid_dummy_vni_clear, 1720 .nve_flood_index_set = mlxsw_sp_fid_dummy_nve_flood_index_set, 1721 .nve_flood_index_clear = mlxsw_sp_fid_dummy_nve_flood_index_clear, 1722 .fid_pack = mlxsw_sp_fid_pack, 1723 }; 1724 1725 static int mlxsw_sp_fid_8021q_configure(struct mlxsw_sp_fid *fid) 1726 { 1727 struct mlxsw_sp_fid_8021q *fid_8021q = mlxsw_sp_fid_8021q_fid(fid); 1728 int err; 1729 1730 err = mlxsw_sp_fid_op(fid, true); 1731 if (err) 1732 return err; 1733 1734 err = mlxsw_sp_fid_vid_to_fid_map(fid, fid_8021q->vid, true, fid->rif); 1735 if (err) 1736 goto err_vid_to_fid_map; 1737 1738 return 0; 1739 1740 err_vid_to_fid_map: 1741 mlxsw_sp_fid_op(fid, false); 1742 return err; 1743 } 1744 1745 static void mlxsw_sp_fid_8021q_deconfigure(struct mlxsw_sp_fid *fid) 1746 { 1747 struct mlxsw_sp_fid_8021q *fid_8021q = mlxsw_sp_fid_8021q_fid(fid); 1748 1749 if (fid->vni_valid) 1750 mlxsw_sp_nve_fid_disable(fid->fid_family->mlxsw_sp, fid); 1751 1752 mlxsw_sp_fid_vid_to_fid_map(fid, fid_8021q->vid, false, NULL); 1753 mlxsw_sp_fid_op(fid, false); 1754 } 1755 1756 static int mlxsw_sp_fid_8021q_port_vid_map(struct mlxsw_sp_fid *fid, 1757 struct mlxsw_sp_port *mlxsw_sp_port, 1758 u16 vid) 1759 { 1760 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 1761 u16 local_port = mlxsw_sp_port->local_port; 1762 int err; 1763 1764 /* In case there are no {Port, VID} => FID mappings on the port, 1765 * we can use the global VID => FID mapping we created when the 1766 * FID was configured, otherwise, configure new mapping. 1767 */ 1768 if (mlxsw_sp->fid_core->port_fid_mappings[local_port]) { 1769 err = __mlxsw_sp_fid_port_vid_map(fid, local_port, vid, true); 1770 if (err) 1771 return err; 1772 } 1773 1774 err = mlxsw_sp_fid_evid_map(fid, local_port, vid, true); 1775 if (err) 1776 goto err_fid_evid_map; 1777 1778 err = mlxsw_sp_fid_port_vid_list_add(fid, mlxsw_sp_port->local_port, 1779 vid); 1780 if (err) 1781 goto err_port_vid_list_add; 1782 1783 return 0; 1784 1785 err_port_vid_list_add: 1786 mlxsw_sp_fid_evid_map(fid, local_port, vid, false); 1787 err_fid_evid_map: 1788 if (mlxsw_sp->fid_core->port_fid_mappings[local_port]) 1789 __mlxsw_sp_fid_port_vid_map(fid, local_port, vid, false); 1790 return err; 1791 } 1792 1793 static void 1794 mlxsw_sp_fid_8021q_port_vid_unmap(struct mlxsw_sp_fid *fid, 1795 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid) 1796 { 1797 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 1798 u16 local_port = mlxsw_sp_port->local_port; 1799 1800 mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid); 1801 mlxsw_sp_fid_evid_map(fid, local_port, vid, false); 1802 if (mlxsw_sp->fid_core->port_fid_mappings[local_port]) 1803 __mlxsw_sp_fid_port_vid_map(fid, local_port, vid, false); 1804 } 1805 1806 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021q_ops_ctl = { 1807 .setup = mlxsw_sp_fid_8021q_setup, 1808 .configure = mlxsw_sp_fid_8021q_configure, 1809 .deconfigure = mlxsw_sp_fid_8021q_deconfigure, 1810 .index_alloc = mlxsw_sp_fid_8021d_index_alloc, 1811 .compare = mlxsw_sp_fid_8021q_compare, 1812 .port_vid_map = mlxsw_sp_fid_8021q_port_vid_map, 1813 .port_vid_unmap = mlxsw_sp_fid_8021q_port_vid_unmap, 1814 .vni_set = mlxsw_sp_fid_8021d_vni_set, 1815 .vni_clear = mlxsw_sp_fid_8021d_vni_clear, 1816 .nve_flood_index_set = mlxsw_sp_fid_8021d_nve_flood_index_set, 1817 .nve_flood_index_clear = mlxsw_sp_fid_8021d_nve_flood_index_clear, 1818 .fdb_clear_offload = mlxsw_sp_fid_8021q_fdb_clear_offload, 1819 .vid_to_fid_rif_update = mlxsw_sp_fid_8021q_vid_to_fid_rif_update, 1820 .flood_table_init = mlxsw_sp_fid_flood_table_init_ctl, 1821 .pgt_size = mlxsw_sp_fid_8021d_pgt_size, 1822 .fid_mid = mlxsw_sp_fid_fid_mid_ctl, 1823 .fid_pack = mlxsw_sp_fid_pack_ctl, 1824 }; 1825 1826 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021q_ops_cff = { 1827 .setup = mlxsw_sp_fid_8021q_setup, 1828 .configure = mlxsw_sp_fid_8021q_configure, 1829 .deconfigure = mlxsw_sp_fid_8021q_deconfigure, 1830 .index_alloc = mlxsw_sp_fid_8021d_index_alloc, 1831 .compare = mlxsw_sp_fid_8021q_compare, 1832 .port_vid_map = mlxsw_sp_fid_8021q_port_vid_map, 1833 .port_vid_unmap = mlxsw_sp_fid_8021q_port_vid_unmap, 1834 .vni_set = mlxsw_sp_fid_8021d_vni_set, 1835 .vni_clear = mlxsw_sp_fid_8021d_vni_clear, 1836 .nve_flood_index_set = mlxsw_sp_fid_8021d_nve_flood_index_set, 1837 .nve_flood_index_clear = mlxsw_sp_fid_8021d_nve_flood_index_clear, 1838 .fdb_clear_offload = mlxsw_sp_fid_8021q_fdb_clear_offload, 1839 .vid_to_fid_rif_update = mlxsw_sp_fid_8021q_vid_to_fid_rif_update, 1840 .pgt_size = mlxsw_sp_fid_8021d_pgt_size, 1841 .fid_mid = mlxsw_sp_fid_fid_mid_cff, 1842 .fid_pack = mlxsw_sp_fid_fid_pack_cff, 1843 }; 1844 1845 /* There are 4K-2 802.1Q FIDs */ 1846 #define MLXSW_SP_FID_8021Q_START 1 /* FID 0 is reserved. */ 1847 #define MLXSW_SP_FID_8021Q_END (MLXSW_SP_FID_8021Q_START + \ 1848 MLXSW_SP_FID_8021Q_MAX - 1) 1849 1850 /* There are 1K 802.1D FIDs */ 1851 #define MLXSW_SP_FID_8021D_START (MLXSW_SP_FID_8021Q_END + 1) 1852 #define MLXSW_SP_FID_8021D_END (MLXSW_SP_FID_8021D_START + \ 1853 MLXSW_SP_FID_8021D_MAX - 1) 1854 1855 /* There is one dummy FID */ 1856 #define MLXSW_SP_FID_DUMMY (MLXSW_SP_FID_8021D_END + 1) 1857 1858 /* There are 11K rFIDs */ 1859 #define MLXSW_SP_RFID_START (MLXSW_SP_FID_DUMMY + 1) 1860 #define MLXSW_SP_RFID_END (MLXSW_SP_RFID_START + \ 1861 MLXSW_SP_FID_RFID_MAX - 1) 1862 1863 static const struct mlxsw_sp_fid_family mlxsw_sp1_fid_8021q_family = { 1864 .type = MLXSW_SP_FID_TYPE_8021Q, 1865 .fid_size = sizeof(struct mlxsw_sp_fid_8021q), 1866 .start_index = MLXSW_SP_FID_8021Q_START, 1867 .end_index = MLXSW_SP_FID_8021Q_END, 1868 .flood_profile = &mlxsw_sp_fid_8021d_flood_profile, 1869 .rif_type = MLXSW_SP_RIF_TYPE_VLAN, 1870 .ops = &mlxsw_sp_fid_8021q_ops_ctl, 1871 .flood_rsp = false, 1872 .bridge_type = MLXSW_REG_BRIDGE_TYPE_0, 1873 .smpe_index_valid = false, 1874 }; 1875 1876 static const struct mlxsw_sp_fid_family mlxsw_sp1_fid_8021d_family = { 1877 .type = MLXSW_SP_FID_TYPE_8021D, 1878 .fid_size = sizeof(struct mlxsw_sp_fid_8021d), 1879 .start_index = MLXSW_SP_FID_8021D_START, 1880 .end_index = MLXSW_SP_FID_8021D_END, 1881 .flood_profile = &mlxsw_sp_fid_8021d_flood_profile, 1882 .rif_type = MLXSW_SP_RIF_TYPE_FID, 1883 .ops = &mlxsw_sp_fid_8021d_ops_ctl, 1884 .bridge_type = MLXSW_REG_BRIDGE_TYPE_1, 1885 .smpe_index_valid = false, 1886 }; 1887 1888 static const struct mlxsw_sp_fid_family mlxsw_sp1_fid_dummy_family = { 1889 .type = MLXSW_SP_FID_TYPE_DUMMY, 1890 .fid_size = sizeof(struct mlxsw_sp_fid), 1891 .start_index = MLXSW_SP_FID_DUMMY, 1892 .end_index = MLXSW_SP_FID_DUMMY, 1893 .ops = &mlxsw_sp_fid_dummy_ops, 1894 .smpe_index_valid = false, 1895 }; 1896 1897 static const struct mlxsw_sp_fid_family mlxsw_sp_fid_rfid_family_ctl = { 1898 .type = MLXSW_SP_FID_TYPE_RFID, 1899 .fid_size = sizeof(struct mlxsw_sp_fid), 1900 .start_index = MLXSW_SP_RFID_START, 1901 .end_index = MLXSW_SP_RFID_END, 1902 .rif_type = MLXSW_SP_RIF_TYPE_SUBPORT, 1903 .ops = &mlxsw_sp_fid_rfid_ops_ctl, 1904 .flood_rsp = true, 1905 .smpe_index_valid = false, 1906 }; 1907 1908 static const struct mlxsw_sp_fid_family *mlxsw_sp1_fid_family_arr[] = { 1909 [MLXSW_SP_FID_TYPE_8021Q] = &mlxsw_sp1_fid_8021q_family, 1910 [MLXSW_SP_FID_TYPE_8021D] = &mlxsw_sp1_fid_8021d_family, 1911 [MLXSW_SP_FID_TYPE_DUMMY] = &mlxsw_sp1_fid_dummy_family, 1912 [MLXSW_SP_FID_TYPE_RFID] = &mlxsw_sp_fid_rfid_family_ctl, 1913 }; 1914 1915 static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_8021q_family_ctl = { 1916 .type = MLXSW_SP_FID_TYPE_8021Q, 1917 .fid_size = sizeof(struct mlxsw_sp_fid_8021q), 1918 .start_index = MLXSW_SP_FID_8021Q_START, 1919 .end_index = MLXSW_SP_FID_8021Q_END, 1920 .flood_profile = &mlxsw_sp_fid_8021d_flood_profile, 1921 .rif_type = MLXSW_SP_RIF_TYPE_VLAN, 1922 .ops = &mlxsw_sp_fid_8021q_ops_ctl, 1923 .flood_rsp = false, 1924 .bridge_type = MLXSW_REG_BRIDGE_TYPE_0, 1925 .smpe_index_valid = true, 1926 }; 1927 1928 static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_8021d_family_ctl = { 1929 .type = MLXSW_SP_FID_TYPE_8021D, 1930 .fid_size = sizeof(struct mlxsw_sp_fid_8021d), 1931 .start_index = MLXSW_SP_FID_8021D_START, 1932 .end_index = MLXSW_SP_FID_8021D_END, 1933 .flood_profile = &mlxsw_sp_fid_8021d_flood_profile, 1934 .rif_type = MLXSW_SP_RIF_TYPE_FID, 1935 .ops = &mlxsw_sp_fid_8021d_ops_ctl, 1936 .bridge_type = MLXSW_REG_BRIDGE_TYPE_1, 1937 .smpe_index_valid = true, 1938 }; 1939 1940 static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_dummy_family = { 1941 .type = MLXSW_SP_FID_TYPE_DUMMY, 1942 .fid_size = sizeof(struct mlxsw_sp_fid), 1943 .start_index = MLXSW_SP_FID_DUMMY, 1944 .end_index = MLXSW_SP_FID_DUMMY, 1945 .ops = &mlxsw_sp_fid_dummy_ops, 1946 .smpe_index_valid = false, 1947 }; 1948 1949 static const struct mlxsw_sp_fid_family *mlxsw_sp2_fid_family_arr_ctl[] = { 1950 [MLXSW_SP_FID_TYPE_8021Q] = &mlxsw_sp2_fid_8021q_family_ctl, 1951 [MLXSW_SP_FID_TYPE_8021D] = &mlxsw_sp2_fid_8021d_family_ctl, 1952 [MLXSW_SP_FID_TYPE_DUMMY] = &mlxsw_sp2_fid_dummy_family, 1953 [MLXSW_SP_FID_TYPE_RFID] = &mlxsw_sp_fid_rfid_family_ctl, 1954 }; 1955 1956 static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_8021q_family_cff = { 1957 .type = MLXSW_SP_FID_TYPE_8021Q, 1958 .fid_size = sizeof(struct mlxsw_sp_fid_8021q), 1959 .start_index = MLXSW_SP_FID_8021Q_START, 1960 .end_index = MLXSW_SP_FID_8021Q_END, 1961 .flood_profile = &mlxsw_sp_fid_8021d_flood_profile, 1962 .rif_type = MLXSW_SP_RIF_TYPE_VLAN, 1963 .ops = &mlxsw_sp_fid_8021q_ops_cff, 1964 .smpe_index_valid = true, 1965 }; 1966 1967 static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_8021d_family_cff = { 1968 .type = MLXSW_SP_FID_TYPE_8021D, 1969 .fid_size = sizeof(struct mlxsw_sp_fid_8021d), 1970 .start_index = MLXSW_SP_FID_8021D_START, 1971 .end_index = MLXSW_SP_FID_8021D_END, 1972 .flood_profile = &mlxsw_sp_fid_8021d_flood_profile, 1973 .rif_type = MLXSW_SP_RIF_TYPE_FID, 1974 .ops = &mlxsw_sp_fid_8021d_ops_cff, 1975 .smpe_index_valid = true, 1976 }; 1977 1978 static const struct mlxsw_sp_fid_family mlxsw_sp_fid_rfid_family_cff = { 1979 .type = MLXSW_SP_FID_TYPE_RFID, 1980 .fid_size = sizeof(struct mlxsw_sp_fid), 1981 .start_index = MLXSW_SP_RFID_START, 1982 .end_index = MLXSW_SP_RFID_END, 1983 .flood_profile = &mlxsw_sp_fid_rsp_flood_profile_cff, 1984 .rif_type = MLXSW_SP_RIF_TYPE_SUBPORT, 1985 .ops = &mlxsw_sp_fid_rfid_ops_cff, 1986 .smpe_index_valid = false, 1987 }; 1988 1989 static const struct mlxsw_sp_fid_family *mlxsw_sp2_fid_family_arr_cff[] = { 1990 [MLXSW_SP_FID_TYPE_8021Q] = &mlxsw_sp2_fid_8021q_family_cff, 1991 [MLXSW_SP_FID_TYPE_8021D] = &mlxsw_sp2_fid_8021d_family_cff, 1992 [MLXSW_SP_FID_TYPE_DUMMY] = &mlxsw_sp2_fid_dummy_family, 1993 [MLXSW_SP_FID_TYPE_RFID] = &mlxsw_sp_fid_rfid_family_cff, 1994 }; 1995 1996 static struct mlxsw_sp_fid *mlxsw_sp_fid_lookup(struct mlxsw_sp *mlxsw_sp, 1997 enum mlxsw_sp_fid_type type, 1998 const void *arg) 1999 { 2000 struct mlxsw_sp_fid_family *fid_family; 2001 struct mlxsw_sp_fid *fid; 2002 2003 fid_family = mlxsw_sp->fid_core->fid_family_arr[type]; 2004 list_for_each_entry(fid, &fid_family->fids_list, list) { 2005 if (!fid->fid_family->ops->compare(fid, arg)) 2006 continue; 2007 refcount_inc(&fid->ref_count); 2008 return fid; 2009 } 2010 2011 return NULL; 2012 } 2013 2014 static struct mlxsw_sp_fid *mlxsw_sp_fid_get(struct mlxsw_sp *mlxsw_sp, 2015 enum mlxsw_sp_fid_type type, 2016 const void *arg) 2017 { 2018 struct mlxsw_sp_fid_family *fid_family; 2019 struct mlxsw_sp_fid *fid; 2020 u16 fid_index; 2021 int err; 2022 2023 fid = mlxsw_sp_fid_lookup(mlxsw_sp, type, arg); 2024 if (fid) 2025 return fid; 2026 2027 fid_family = mlxsw_sp->fid_core->fid_family_arr[type]; 2028 fid = kzalloc(fid_family->fid_size, GFP_KERNEL); 2029 if (!fid) 2030 return ERR_PTR(-ENOMEM); 2031 2032 INIT_LIST_HEAD(&fid->port_vid_list); 2033 fid->fid_family = fid_family; 2034 2035 err = fid->fid_family->ops->index_alloc(fid, arg, &fid_index); 2036 if (err) 2037 goto err_index_alloc; 2038 fid->fid_index = fid_index; 2039 __set_bit(fid_index - fid_family->start_index, fid_family->fids_bitmap); 2040 2041 err = fid->fid_family->ops->setup(fid, arg); 2042 if (err) 2043 goto err_setup; 2044 2045 err = fid->fid_family->ops->configure(fid); 2046 if (err) 2047 goto err_configure; 2048 2049 err = rhashtable_insert_fast(&mlxsw_sp->fid_core->fid_ht, &fid->ht_node, 2050 mlxsw_sp_fid_ht_params); 2051 if (err) 2052 goto err_rhashtable_insert; 2053 2054 list_add(&fid->list, &fid_family->fids_list); 2055 refcount_set(&fid->ref_count, 1); 2056 return fid; 2057 2058 err_rhashtable_insert: 2059 fid->fid_family->ops->deconfigure(fid); 2060 err_configure: 2061 err_setup: 2062 __clear_bit(fid_index - fid_family->start_index, 2063 fid_family->fids_bitmap); 2064 err_index_alloc: 2065 kfree(fid); 2066 return ERR_PTR(err); 2067 } 2068 2069 void mlxsw_sp_fid_put(struct mlxsw_sp_fid *fid) 2070 { 2071 struct mlxsw_sp_fid_family *fid_family = fid->fid_family; 2072 struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp; 2073 2074 if (!refcount_dec_and_test(&fid->ref_count)) 2075 return; 2076 2077 list_del(&fid->list); 2078 rhashtable_remove_fast(&mlxsw_sp->fid_core->fid_ht, 2079 &fid->ht_node, mlxsw_sp_fid_ht_params); 2080 fid->fid_family->ops->deconfigure(fid); 2081 __clear_bit(fid->fid_index - fid_family->start_index, 2082 fid_family->fids_bitmap); 2083 WARN_ON_ONCE(!list_empty(&fid->port_vid_list)); 2084 kfree(fid); 2085 } 2086 2087 struct mlxsw_sp_fid *mlxsw_sp_fid_8021q_get(struct mlxsw_sp *mlxsw_sp, u16 vid) 2088 { 2089 return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_8021Q, &vid); 2090 } 2091 2092 struct mlxsw_sp_fid *mlxsw_sp_fid_8021d_get(struct mlxsw_sp *mlxsw_sp, 2093 int br_ifindex) 2094 { 2095 return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_8021D, &br_ifindex); 2096 } 2097 2098 struct mlxsw_sp_fid *mlxsw_sp_fid_8021q_lookup(struct mlxsw_sp *mlxsw_sp, 2099 u16 vid) 2100 { 2101 return mlxsw_sp_fid_lookup(mlxsw_sp, MLXSW_SP_FID_TYPE_8021Q, &vid); 2102 } 2103 2104 struct mlxsw_sp_fid *mlxsw_sp_fid_8021d_lookup(struct mlxsw_sp *mlxsw_sp, 2105 int br_ifindex) 2106 { 2107 return mlxsw_sp_fid_lookup(mlxsw_sp, MLXSW_SP_FID_TYPE_8021D, 2108 &br_ifindex); 2109 } 2110 2111 struct mlxsw_sp_fid *mlxsw_sp_fid_rfid_get(struct mlxsw_sp *mlxsw_sp, 2112 u16 rif_index) 2113 { 2114 return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_RFID, &rif_index); 2115 } 2116 2117 struct mlxsw_sp_fid *mlxsw_sp_fid_dummy_get(struct mlxsw_sp *mlxsw_sp) 2118 { 2119 return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_DUMMY, NULL); 2120 } 2121 2122 static int 2123 mlxsw_sp_fid_flood_tables_init(struct mlxsw_sp_fid_family *fid_family) 2124 { 2125 struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp; 2126 u16 pgt_size; 2127 int err; 2128 int i; 2129 2130 err = fid_family->ops->pgt_size(fid_family, &pgt_size); 2131 if (err) 2132 return err; 2133 2134 err = mlxsw_sp_pgt_mid_alloc_range(mlxsw_sp, &fid_family->pgt_base, 2135 pgt_size); 2136 if (err) 2137 return err; 2138 2139 if (!fid_family->flood_profile) 2140 return 0; 2141 2142 for (i = 0; i < fid_family->flood_profile->nr_flood_tables; i++) { 2143 const struct mlxsw_sp_flood_table *flood_table; 2144 2145 flood_table = &fid_family->flood_profile->flood_tables[i]; 2146 if (fid_family->ops->flood_table_init) { 2147 err = fid_family->ops->flood_table_init(fid_family, 2148 flood_table); 2149 if (err) 2150 goto err_flood_table_init; 2151 } 2152 } 2153 2154 return 0; 2155 2156 err_flood_table_init: 2157 mlxsw_sp_pgt_mid_free_range(mlxsw_sp, fid_family->pgt_base, pgt_size); 2158 return err; 2159 } 2160 2161 static void 2162 mlxsw_sp_fid_flood_tables_fini(struct mlxsw_sp_fid_family *fid_family) 2163 { 2164 struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp; 2165 u16 pgt_size; 2166 int err; 2167 2168 err = fid_family->ops->pgt_size(fid_family, &pgt_size); 2169 if (WARN_ON_ONCE(err)) 2170 return; 2171 2172 mlxsw_sp_pgt_mid_free_range(mlxsw_sp, fid_family->pgt_base, pgt_size); 2173 } 2174 2175 static int mlxsw_sp_fid_family_register(struct mlxsw_sp *mlxsw_sp, 2176 const struct mlxsw_sp_fid_family *tmpl) 2177 { 2178 u16 nr_fids = tmpl->end_index - tmpl->start_index + 1; 2179 struct mlxsw_sp_fid_family *fid_family; 2180 int err; 2181 2182 fid_family = kmemdup(tmpl, sizeof(*fid_family), GFP_KERNEL); 2183 if (!fid_family) 2184 return -ENOMEM; 2185 2186 fid_family->mlxsw_sp = mlxsw_sp; 2187 INIT_LIST_HEAD(&fid_family->fids_list); 2188 fid_family->fids_bitmap = bitmap_zalloc(nr_fids, GFP_KERNEL); 2189 if (!fid_family->fids_bitmap) { 2190 err = -ENOMEM; 2191 goto err_alloc_fids_bitmap; 2192 } 2193 2194 if (fid_family->flood_profile) { 2195 err = mlxsw_sp_fid_flood_tables_init(fid_family); 2196 if (err) 2197 goto err_fid_flood_tables_init; 2198 } 2199 2200 mlxsw_sp->fid_core->fid_family_arr[tmpl->type] = fid_family; 2201 2202 return 0; 2203 2204 err_fid_flood_tables_init: 2205 bitmap_free(fid_family->fids_bitmap); 2206 err_alloc_fids_bitmap: 2207 kfree(fid_family); 2208 return err; 2209 } 2210 2211 static void 2212 mlxsw_sp_fid_family_unregister(struct mlxsw_sp *mlxsw_sp, 2213 struct mlxsw_sp_fid_family *fid_family) 2214 { 2215 mlxsw_sp->fid_core->fid_family_arr[fid_family->type] = NULL; 2216 2217 if (fid_family->flood_profile) 2218 mlxsw_sp_fid_flood_tables_fini(fid_family); 2219 2220 bitmap_free(fid_family->fids_bitmap); 2221 WARN_ON_ONCE(!list_empty(&fid_family->fids_list)); 2222 kfree(fid_family); 2223 } 2224 2225 static int mlxsw_sp_fid_port_init(const struct mlxsw_sp_port *mlxsw_sp_port) 2226 { 2227 const enum mlxsw_sp_fid_type type_rfid = MLXSW_SP_FID_TYPE_RFID; 2228 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 2229 struct mlxsw_sp_fid_family *rfid_family; 2230 2231 rfid_family = mlxsw_sp->fid_core->fid_family_arr[type_rfid]; 2232 if (rfid_family->ops->fid_port_init) 2233 return rfid_family->ops->fid_port_init(rfid_family, 2234 mlxsw_sp_port); 2235 return 0; 2236 } 2237 2238 static void mlxsw_sp_fid_port_fini(const struct mlxsw_sp_port *mlxsw_sp_port) 2239 { 2240 const enum mlxsw_sp_fid_type type_rfid = MLXSW_SP_FID_TYPE_RFID; 2241 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 2242 struct mlxsw_sp_fid_family *rfid_family; 2243 2244 rfid_family = mlxsw_sp->fid_core->fid_family_arr[type_rfid]; 2245 if (rfid_family->ops->fid_port_fini) 2246 rfid_family->ops->fid_port_fini(rfid_family, mlxsw_sp_port); 2247 } 2248 2249 int mlxsw_sp_port_fids_init(struct mlxsw_sp_port *mlxsw_sp_port) 2250 { 2251 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 2252 int err; 2253 2254 /* Track number of FIDs configured on the port with mapping type 2255 * PORT_VID_TO_FID, so that we know when to transition the port 2256 * back to non-virtual (VLAN) mode. 2257 */ 2258 mlxsw_sp->fid_core->port_fid_mappings[mlxsw_sp_port->local_port] = 0; 2259 2260 err = mlxsw_sp_fid_port_init(mlxsw_sp_port); 2261 if (err) 2262 return err; 2263 2264 err = mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, false); 2265 if (err) 2266 goto err_vp_mode_set; 2267 2268 return 0; 2269 2270 err_vp_mode_set: 2271 mlxsw_sp_fid_port_fini(mlxsw_sp_port); 2272 return err; 2273 } 2274 2275 void mlxsw_sp_port_fids_fini(struct mlxsw_sp_port *mlxsw_sp_port) 2276 { 2277 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 2278 2279 mlxsw_sp_fid_port_fini(mlxsw_sp_port); 2280 mlxsw_sp->fid_core->port_fid_mappings[mlxsw_sp_port->local_port] = 0; 2281 } 2282 2283 int mlxsw_sp_fid_port_join_lag(const struct mlxsw_sp_port *mlxsw_sp_port) 2284 { 2285 return mlxsw_sp_fid_port_init(mlxsw_sp_port); 2286 } 2287 2288 void mlxsw_sp_fid_port_leave_lag(const struct mlxsw_sp_port *mlxsw_sp_port) 2289 { 2290 mlxsw_sp_fid_port_fini(mlxsw_sp_port); 2291 } 2292 2293 static int 2294 mlxsw_sp_fids_init(struct mlxsw_sp *mlxsw_sp, 2295 const struct mlxsw_sp_fid_family *fid_family_arr[]) 2296 { 2297 unsigned int max_ports = mlxsw_core_max_ports(mlxsw_sp->core); 2298 struct mlxsw_sp_fid_core *fid_core; 2299 int err, i; 2300 2301 fid_core = kzalloc_obj(*mlxsw_sp->fid_core); 2302 if (!fid_core) 2303 return -ENOMEM; 2304 mlxsw_sp->fid_core = fid_core; 2305 2306 err = rhashtable_init(&fid_core->fid_ht, &mlxsw_sp_fid_ht_params); 2307 if (err) 2308 goto err_rhashtable_fid_init; 2309 2310 err = rhashtable_init(&fid_core->vni_ht, &mlxsw_sp_fid_vni_ht_params); 2311 if (err) 2312 goto err_rhashtable_vni_init; 2313 2314 fid_core->port_fid_mappings = kcalloc(max_ports, sizeof(unsigned int), 2315 GFP_KERNEL); 2316 if (!fid_core->port_fid_mappings) { 2317 err = -ENOMEM; 2318 goto err_alloc_port_fid_mappings; 2319 } 2320 2321 for (i = 0; i < MLXSW_SP_FID_TYPE_MAX; i++) { 2322 err = mlxsw_sp_fid_family_register(mlxsw_sp, fid_family_arr[i]); 2323 2324 if (err) 2325 goto err_fid_ops_register; 2326 } 2327 2328 return 0; 2329 2330 err_fid_ops_register: 2331 for (i--; i >= 0; i--) { 2332 struct mlxsw_sp_fid_family *fid_family; 2333 2334 fid_family = fid_core->fid_family_arr[i]; 2335 mlxsw_sp_fid_family_unregister(mlxsw_sp, fid_family); 2336 } 2337 kfree(fid_core->port_fid_mappings); 2338 err_alloc_port_fid_mappings: 2339 rhashtable_destroy(&fid_core->vni_ht); 2340 err_rhashtable_vni_init: 2341 rhashtable_destroy(&fid_core->fid_ht); 2342 err_rhashtable_fid_init: 2343 kfree(fid_core); 2344 return err; 2345 } 2346 2347 static void mlxsw_sp_fids_fini(struct mlxsw_sp *mlxsw_sp) 2348 { 2349 struct mlxsw_sp_fid_core *fid_core = mlxsw_sp->fid_core; 2350 int i; 2351 2352 for (i = 0; i < MLXSW_SP_FID_TYPE_MAX; i++) 2353 mlxsw_sp_fid_family_unregister(mlxsw_sp, 2354 fid_core->fid_family_arr[i]); 2355 kfree(fid_core->port_fid_mappings); 2356 rhashtable_destroy(&fid_core->vni_ht); 2357 rhashtable_destroy(&fid_core->fid_ht); 2358 kfree(fid_core); 2359 } 2360 2361 static int mlxsw_sp1_fids_init(struct mlxsw_sp *mlxsw_sp) 2362 { 2363 return mlxsw_sp_fids_init(mlxsw_sp, mlxsw_sp1_fid_family_arr); 2364 } 2365 2366 const struct mlxsw_sp_fid_core_ops mlxsw_sp1_fid_core_ops = { 2367 .init = mlxsw_sp1_fids_init, 2368 .fini = mlxsw_sp_fids_fini, 2369 }; 2370 2371 static int mlxsw_sp_fid_check_flood_profile_id(struct mlxsw_sp *mlxsw_sp, 2372 int profile_id) 2373 { 2374 u32 max_profiles; 2375 2376 if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_NVE_FLOOD_PRF)) 2377 return -EIO; 2378 2379 max_profiles = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_NVE_FLOOD_PRF); 2380 if (WARN_ON_ONCE(!profile_id) || 2381 WARN_ON_ONCE(profile_id >= max_profiles)) 2382 return -EINVAL; 2383 2384 return 0; 2385 } 2386 2387 static int 2388 mlxsw_sp2_fids_init_flood_table(struct mlxsw_sp *mlxsw_sp, 2389 enum mlxsw_sp_fid_flood_profile_id profile_id, 2390 const struct mlxsw_sp_flood_table *flood_table) 2391 { 2392 enum mlxsw_sp_flood_type packet_type = flood_table->packet_type; 2393 const int *sfgc_packet_types; 2394 int err; 2395 int i; 2396 2397 sfgc_packet_types = mlxsw_sp_packet_type_sfgc_types[packet_type]; 2398 for (i = 0; i < MLXSW_REG_SFGC_TYPE_MAX; i++) { 2399 char sffp_pl[MLXSW_REG_SFFP_LEN]; 2400 2401 if (!sfgc_packet_types[i]) 2402 continue; 2403 2404 mlxsw_reg_sffp_pack(sffp_pl, profile_id, i, 2405 flood_table->table_index); 2406 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sffp), sffp_pl); 2407 if (err) 2408 return err; 2409 } 2410 2411 return 0; 2412 } 2413 2414 static int 2415 mlxsw_sp2_fids_init_flood_profile(struct mlxsw_sp *mlxsw_sp, 2416 const struct mlxsw_sp_fid_flood_profile * 2417 flood_profile) 2418 { 2419 int err; 2420 int i; 2421 2422 err = mlxsw_sp_fid_check_flood_profile_id(mlxsw_sp, 2423 flood_profile->profile_id); 2424 if (err) 2425 return err; 2426 2427 for (i = 0; i < flood_profile->nr_flood_tables; i++) { 2428 const struct mlxsw_sp_flood_table *flood_table; 2429 2430 flood_table = &flood_profile->flood_tables[i]; 2431 err = mlxsw_sp2_fids_init_flood_table(mlxsw_sp, 2432 flood_profile->profile_id, 2433 flood_table); 2434 if (err) 2435 return err; 2436 } 2437 2438 return 0; 2439 } 2440 2441 static const 2442 struct mlxsw_sp_fid_flood_profile *mlxsw_sp_fid_flood_profiles[] = { 2443 &mlxsw_sp_fid_8021d_flood_profile, 2444 &mlxsw_sp_fid_rsp_flood_profile_cff, 2445 &mlxsw_sp_fid_nve_flood_profile_cff, 2446 }; 2447 2448 static int 2449 mlxsw_sp2_fids_init_flood_profiles(struct mlxsw_sp *mlxsw_sp) 2450 { 2451 int err; 2452 int i; 2453 2454 for (i = 0; i < ARRAY_SIZE(mlxsw_sp_fid_flood_profiles); i++) { 2455 const struct mlxsw_sp_fid_flood_profile *flood_profile; 2456 2457 flood_profile = mlxsw_sp_fid_flood_profiles[i]; 2458 err = mlxsw_sp2_fids_init_flood_profile(mlxsw_sp, 2459 flood_profile); 2460 if (err) 2461 return err; 2462 } 2463 2464 return 0; 2465 } 2466 2467 static int mlxsw_sp2_fids_init_ctl(struct mlxsw_sp *mlxsw_sp) 2468 { 2469 return mlxsw_sp_fids_init(mlxsw_sp, mlxsw_sp2_fid_family_arr_ctl); 2470 } 2471 2472 static int mlxsw_sp2_fids_init_cff(struct mlxsw_sp *mlxsw_sp) 2473 { 2474 int err; 2475 2476 err = mlxsw_sp2_fids_init_flood_profiles(mlxsw_sp); 2477 if (err) 2478 return err; 2479 2480 return mlxsw_sp_fids_init(mlxsw_sp, mlxsw_sp2_fid_family_arr_cff); 2481 } 2482 2483 static int mlxsw_sp2_fids_init(struct mlxsw_sp *mlxsw_sp) 2484 { 2485 switch (mlxsw_core_flood_mode(mlxsw_sp->core)) { 2486 case MLXSW_CMD_MBOX_CONFIG_PROFILE_FLOOD_MODE_CONTROLLED: 2487 return mlxsw_sp2_fids_init_ctl(mlxsw_sp); 2488 case MLXSW_CMD_MBOX_CONFIG_PROFILE_FLOOD_MODE_CFF: 2489 return mlxsw_sp2_fids_init_cff(mlxsw_sp); 2490 default: 2491 WARN_ON_ONCE(1); 2492 return -EINVAL; 2493 } 2494 } 2495 2496 const struct mlxsw_sp_fid_core_ops mlxsw_sp2_fid_core_ops = { 2497 .init = mlxsw_sp2_fids_init, 2498 .fini = mlxsw_sp_fids_fini, 2499 }; 2500