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/rtnetlink.h> 10 11 #include "spectrum.h" 12 #include "reg.h" 13 14 struct mlxsw_sp_fid_family; 15 16 struct mlxsw_sp_fid_core { 17 struct mlxsw_sp_fid_family *fid_family_arr[MLXSW_SP_FID_TYPE_MAX]; 18 unsigned int *port_fid_mappings; 19 }; 20 21 struct mlxsw_sp_fid { 22 struct list_head list; 23 struct mlxsw_sp_rif *rif; 24 unsigned int ref_count; 25 u16 fid_index; 26 struct mlxsw_sp_fid_family *fid_family; 27 }; 28 29 struct mlxsw_sp_fid_8021q { 30 struct mlxsw_sp_fid common; 31 u16 vid; 32 }; 33 34 struct mlxsw_sp_fid_8021d { 35 struct mlxsw_sp_fid common; 36 int br_ifindex; 37 }; 38 39 struct mlxsw_sp_flood_table { 40 enum mlxsw_sp_flood_type packet_type; 41 enum mlxsw_reg_sfgc_bridge_type bridge_type; 42 enum mlxsw_flood_table_type table_type; 43 int table_index; 44 }; 45 46 struct mlxsw_sp_fid_ops { 47 void (*setup)(struct mlxsw_sp_fid *fid, const void *arg); 48 int (*configure)(struct mlxsw_sp_fid *fid); 49 void (*deconfigure)(struct mlxsw_sp_fid *fid); 50 int (*index_alloc)(struct mlxsw_sp_fid *fid, const void *arg, 51 u16 *p_fid_index); 52 bool (*compare)(const struct mlxsw_sp_fid *fid, 53 const void *arg); 54 u16 (*flood_index)(const struct mlxsw_sp_fid *fid); 55 int (*port_vid_map)(struct mlxsw_sp_fid *fid, 56 struct mlxsw_sp_port *port, u16 vid); 57 void (*port_vid_unmap)(struct mlxsw_sp_fid *fid, 58 struct mlxsw_sp_port *port, u16 vid); 59 }; 60 61 struct mlxsw_sp_fid_family { 62 enum mlxsw_sp_fid_type type; 63 size_t fid_size; 64 u16 start_index; 65 u16 end_index; 66 struct list_head fids_list; 67 unsigned long *fids_bitmap; 68 const struct mlxsw_sp_flood_table *flood_tables; 69 int nr_flood_tables; 70 enum mlxsw_sp_rif_type rif_type; 71 const struct mlxsw_sp_fid_ops *ops; 72 struct mlxsw_sp *mlxsw_sp; 73 }; 74 75 static const int mlxsw_sp_sfgc_uc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = { 76 [MLXSW_REG_SFGC_TYPE_UNKNOWN_UNICAST] = 1, 77 }; 78 79 static const int mlxsw_sp_sfgc_bc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = { 80 [MLXSW_REG_SFGC_TYPE_BROADCAST] = 1, 81 [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_NON_IP] = 1, 82 [MLXSW_REG_SFGC_TYPE_IPV4_LINK_LOCAL] = 1, 83 [MLXSW_REG_SFGC_TYPE_IPV6_ALL_HOST] = 1, 84 [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV6] = 1, 85 }; 86 87 static const int mlxsw_sp_sfgc_mc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = { 88 [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV4] = 1, 89 }; 90 91 static const int *mlxsw_sp_packet_type_sfgc_types[] = { 92 [MLXSW_SP_FLOOD_TYPE_UC] = mlxsw_sp_sfgc_uc_packet_types, 93 [MLXSW_SP_FLOOD_TYPE_BC] = mlxsw_sp_sfgc_bc_packet_types, 94 [MLXSW_SP_FLOOD_TYPE_MC] = mlxsw_sp_sfgc_mc_packet_types, 95 }; 96 97 static const struct mlxsw_sp_flood_table * 98 mlxsw_sp_fid_flood_table_lookup(const struct mlxsw_sp_fid *fid, 99 enum mlxsw_sp_flood_type packet_type) 100 { 101 struct mlxsw_sp_fid_family *fid_family = fid->fid_family; 102 int i; 103 104 for (i = 0; i < fid_family->nr_flood_tables; i++) { 105 if (fid_family->flood_tables[i].packet_type != packet_type) 106 continue; 107 return &fid_family->flood_tables[i]; 108 } 109 110 return NULL; 111 } 112 113 int mlxsw_sp_fid_flood_set(struct mlxsw_sp_fid *fid, 114 enum mlxsw_sp_flood_type packet_type, u8 local_port, 115 bool member) 116 { 117 struct mlxsw_sp_fid_family *fid_family = fid->fid_family; 118 const struct mlxsw_sp_fid_ops *ops = fid_family->ops; 119 const struct mlxsw_sp_flood_table *flood_table; 120 char *sftr_pl; 121 int err; 122 123 if (WARN_ON(!fid_family->flood_tables || !ops->flood_index)) 124 return -EINVAL; 125 126 flood_table = mlxsw_sp_fid_flood_table_lookup(fid, packet_type); 127 if (!flood_table) 128 return -ESRCH; 129 130 sftr_pl = kmalloc(MLXSW_REG_SFTR_LEN, GFP_KERNEL); 131 if (!sftr_pl) 132 return -ENOMEM; 133 134 mlxsw_reg_sftr_pack(sftr_pl, flood_table->table_index, 135 ops->flood_index(fid), flood_table->table_type, 1, 136 local_port, member); 137 err = mlxsw_reg_write(fid_family->mlxsw_sp->core, MLXSW_REG(sftr), 138 sftr_pl); 139 kfree(sftr_pl); 140 return err; 141 } 142 143 int mlxsw_sp_fid_port_vid_map(struct mlxsw_sp_fid *fid, 144 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid) 145 { 146 if (WARN_ON(!fid->fid_family->ops->port_vid_map)) 147 return -EINVAL; 148 return fid->fid_family->ops->port_vid_map(fid, mlxsw_sp_port, vid); 149 } 150 151 void mlxsw_sp_fid_port_vid_unmap(struct mlxsw_sp_fid *fid, 152 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid) 153 { 154 fid->fid_family->ops->port_vid_unmap(fid, mlxsw_sp_port, vid); 155 } 156 157 enum mlxsw_sp_rif_type mlxsw_sp_fid_rif_type(const struct mlxsw_sp_fid *fid) 158 { 159 return fid->fid_family->rif_type; 160 } 161 162 u16 mlxsw_sp_fid_index(const struct mlxsw_sp_fid *fid) 163 { 164 return fid->fid_index; 165 } 166 167 enum mlxsw_sp_fid_type mlxsw_sp_fid_type(const struct mlxsw_sp_fid *fid) 168 { 169 return fid->fid_family->type; 170 } 171 172 void mlxsw_sp_fid_rif_set(struct mlxsw_sp_fid *fid, struct mlxsw_sp_rif *rif) 173 { 174 fid->rif = rif; 175 } 176 177 enum mlxsw_sp_rif_type 178 mlxsw_sp_fid_type_rif_type(const struct mlxsw_sp *mlxsw_sp, 179 enum mlxsw_sp_fid_type type) 180 { 181 struct mlxsw_sp_fid_core *fid_core = mlxsw_sp->fid_core; 182 183 return fid_core->fid_family_arr[type]->rif_type; 184 } 185 186 static struct mlxsw_sp_fid_8021q * 187 mlxsw_sp_fid_8021q_fid(const struct mlxsw_sp_fid *fid) 188 { 189 return container_of(fid, struct mlxsw_sp_fid_8021q, common); 190 } 191 192 u16 mlxsw_sp_fid_8021q_vid(const struct mlxsw_sp_fid *fid) 193 { 194 return mlxsw_sp_fid_8021q_fid(fid)->vid; 195 } 196 197 static void mlxsw_sp_fid_8021q_setup(struct mlxsw_sp_fid *fid, const void *arg) 198 { 199 u16 vid = *(u16 *) arg; 200 201 mlxsw_sp_fid_8021q_fid(fid)->vid = vid; 202 } 203 204 static enum mlxsw_reg_sfmr_op mlxsw_sp_sfmr_op(bool valid) 205 { 206 return valid ? MLXSW_REG_SFMR_OP_CREATE_FID : 207 MLXSW_REG_SFMR_OP_DESTROY_FID; 208 } 209 210 static int mlxsw_sp_fid_op(struct mlxsw_sp *mlxsw_sp, u16 fid_index, 211 u16 fid_offset, bool valid) 212 { 213 char sfmr_pl[MLXSW_REG_SFMR_LEN]; 214 215 mlxsw_reg_sfmr_pack(sfmr_pl, mlxsw_sp_sfmr_op(valid), fid_index, 216 fid_offset); 217 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl); 218 } 219 220 static int mlxsw_sp_fid_vid_map(struct mlxsw_sp *mlxsw_sp, u16 fid_index, 221 u16 vid, bool valid) 222 { 223 enum mlxsw_reg_svfa_mt mt = MLXSW_REG_SVFA_MT_VID_TO_FID; 224 char svfa_pl[MLXSW_REG_SVFA_LEN]; 225 226 mlxsw_reg_svfa_pack(svfa_pl, 0, mt, valid, fid_index, vid); 227 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl); 228 } 229 230 static int __mlxsw_sp_fid_port_vid_map(struct mlxsw_sp *mlxsw_sp, u16 fid_index, 231 u8 local_port, u16 vid, bool valid) 232 { 233 enum mlxsw_reg_svfa_mt mt = MLXSW_REG_SVFA_MT_PORT_VID_TO_FID; 234 char svfa_pl[MLXSW_REG_SVFA_LEN]; 235 236 mlxsw_reg_svfa_pack(svfa_pl, local_port, mt, valid, fid_index, vid); 237 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl); 238 } 239 240 static int mlxsw_sp_fid_8021q_configure(struct mlxsw_sp_fid *fid) 241 { 242 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; 243 struct mlxsw_sp_fid_8021q *fid_8021q; 244 int err; 245 246 err = mlxsw_sp_fid_op(mlxsw_sp, fid->fid_index, fid->fid_index, true); 247 if (err) 248 return err; 249 250 fid_8021q = mlxsw_sp_fid_8021q_fid(fid); 251 err = mlxsw_sp_fid_vid_map(mlxsw_sp, fid->fid_index, fid_8021q->vid, 252 true); 253 if (err) 254 goto err_fid_map; 255 256 return 0; 257 258 err_fid_map: 259 mlxsw_sp_fid_op(mlxsw_sp, fid->fid_index, 0, false); 260 return err; 261 } 262 263 static void mlxsw_sp_fid_8021q_deconfigure(struct mlxsw_sp_fid *fid) 264 { 265 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; 266 struct mlxsw_sp_fid_8021q *fid_8021q; 267 268 fid_8021q = mlxsw_sp_fid_8021q_fid(fid); 269 mlxsw_sp_fid_vid_map(mlxsw_sp, fid->fid_index, fid_8021q->vid, false); 270 mlxsw_sp_fid_op(mlxsw_sp, fid->fid_index, 0, false); 271 } 272 273 static int mlxsw_sp_fid_8021q_index_alloc(struct mlxsw_sp_fid *fid, 274 const void *arg, u16 *p_fid_index) 275 { 276 struct mlxsw_sp_fid_family *fid_family = fid->fid_family; 277 u16 vid = *(u16 *) arg; 278 279 /* Use 1:1 mapping for simplicity although not a must */ 280 if (vid < fid_family->start_index || vid > fid_family->end_index) 281 return -EINVAL; 282 *p_fid_index = vid; 283 284 return 0; 285 } 286 287 static bool 288 mlxsw_sp_fid_8021q_compare(const struct mlxsw_sp_fid *fid, const void *arg) 289 { 290 u16 vid = *(u16 *) arg; 291 292 return mlxsw_sp_fid_8021q_fid(fid)->vid == vid; 293 } 294 295 static u16 mlxsw_sp_fid_8021q_flood_index(const struct mlxsw_sp_fid *fid) 296 { 297 return fid->fid_index; 298 } 299 300 static int mlxsw_sp_fid_8021q_port_vid_map(struct mlxsw_sp_fid *fid, 301 struct mlxsw_sp_port *mlxsw_sp_port, 302 u16 vid) 303 { 304 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 305 u8 local_port = mlxsw_sp_port->local_port; 306 307 /* In case there are no {Port, VID} => FID mappings on the port, 308 * we can use the global VID => FID mapping we created when the 309 * FID was configured. 310 */ 311 if (mlxsw_sp->fid_core->port_fid_mappings[local_port] == 0) 312 return 0; 313 return __mlxsw_sp_fid_port_vid_map(mlxsw_sp, fid->fid_index, local_port, 314 vid, true); 315 } 316 317 static void 318 mlxsw_sp_fid_8021q_port_vid_unmap(struct mlxsw_sp_fid *fid, 319 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid) 320 { 321 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 322 u8 local_port = mlxsw_sp_port->local_port; 323 324 if (mlxsw_sp->fid_core->port_fid_mappings[local_port] == 0) 325 return; 326 __mlxsw_sp_fid_port_vid_map(mlxsw_sp, fid->fid_index, local_port, vid, 327 false); 328 } 329 330 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021q_ops = { 331 .setup = mlxsw_sp_fid_8021q_setup, 332 .configure = mlxsw_sp_fid_8021q_configure, 333 .deconfigure = mlxsw_sp_fid_8021q_deconfigure, 334 .index_alloc = mlxsw_sp_fid_8021q_index_alloc, 335 .compare = mlxsw_sp_fid_8021q_compare, 336 .flood_index = mlxsw_sp_fid_8021q_flood_index, 337 .port_vid_map = mlxsw_sp_fid_8021q_port_vid_map, 338 .port_vid_unmap = mlxsw_sp_fid_8021q_port_vid_unmap, 339 }; 340 341 static const struct mlxsw_sp_flood_table mlxsw_sp_fid_8021q_flood_tables[] = { 342 { 343 .packet_type = MLXSW_SP_FLOOD_TYPE_UC, 344 .bridge_type = MLXSW_REG_SFGC_BRIDGE_TYPE_1Q_FID, 345 .table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFSET, 346 .table_index = 0, 347 }, 348 { 349 .packet_type = MLXSW_SP_FLOOD_TYPE_MC, 350 .bridge_type = MLXSW_REG_SFGC_BRIDGE_TYPE_1Q_FID, 351 .table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFSET, 352 .table_index = 1, 353 }, 354 { 355 .packet_type = MLXSW_SP_FLOOD_TYPE_BC, 356 .bridge_type = MLXSW_REG_SFGC_BRIDGE_TYPE_1Q_FID, 357 .table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFSET, 358 .table_index = 2, 359 }, 360 }; 361 362 /* Range and flood configuration must match mlxsw_config_profile */ 363 static const struct mlxsw_sp_fid_family mlxsw_sp_fid_8021q_family = { 364 .type = MLXSW_SP_FID_TYPE_8021Q, 365 .fid_size = sizeof(struct mlxsw_sp_fid_8021q), 366 .start_index = 1, 367 .end_index = VLAN_VID_MASK, 368 .flood_tables = mlxsw_sp_fid_8021q_flood_tables, 369 .nr_flood_tables = ARRAY_SIZE(mlxsw_sp_fid_8021q_flood_tables), 370 .rif_type = MLXSW_SP_RIF_TYPE_VLAN, 371 .ops = &mlxsw_sp_fid_8021q_ops, 372 }; 373 374 static struct mlxsw_sp_fid_8021d * 375 mlxsw_sp_fid_8021d_fid(const struct mlxsw_sp_fid *fid) 376 { 377 return container_of(fid, struct mlxsw_sp_fid_8021d, common); 378 } 379 380 static void mlxsw_sp_fid_8021d_setup(struct mlxsw_sp_fid *fid, const void *arg) 381 { 382 int br_ifindex = *(int *) arg; 383 384 mlxsw_sp_fid_8021d_fid(fid)->br_ifindex = br_ifindex; 385 } 386 387 static int mlxsw_sp_fid_8021d_configure(struct mlxsw_sp_fid *fid) 388 { 389 struct mlxsw_sp_fid_family *fid_family = fid->fid_family; 390 391 return mlxsw_sp_fid_op(fid_family->mlxsw_sp, fid->fid_index, 0, true); 392 } 393 394 static void mlxsw_sp_fid_8021d_deconfigure(struct mlxsw_sp_fid *fid) 395 { 396 mlxsw_sp_fid_op(fid->fid_family->mlxsw_sp, fid->fid_index, 0, false); 397 } 398 399 static int mlxsw_sp_fid_8021d_index_alloc(struct mlxsw_sp_fid *fid, 400 const void *arg, u16 *p_fid_index) 401 { 402 struct mlxsw_sp_fid_family *fid_family = fid->fid_family; 403 u16 nr_fids, fid_index; 404 405 nr_fids = fid_family->end_index - fid_family->start_index + 1; 406 fid_index = find_first_zero_bit(fid_family->fids_bitmap, nr_fids); 407 if (fid_index == nr_fids) 408 return -ENOBUFS; 409 *p_fid_index = fid_family->start_index + fid_index; 410 411 return 0; 412 } 413 414 static bool 415 mlxsw_sp_fid_8021d_compare(const struct mlxsw_sp_fid *fid, const void *arg) 416 { 417 int br_ifindex = *(int *) arg; 418 419 return mlxsw_sp_fid_8021d_fid(fid)->br_ifindex == br_ifindex; 420 } 421 422 static u16 mlxsw_sp_fid_8021d_flood_index(const struct mlxsw_sp_fid *fid) 423 { 424 return fid->fid_index - fid->fid_family->start_index; 425 } 426 427 static int mlxsw_sp_port_vp_mode_trans(struct mlxsw_sp_port *mlxsw_sp_port) 428 { 429 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 430 struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan; 431 int err; 432 433 list_for_each_entry(mlxsw_sp_port_vlan, &mlxsw_sp_port->vlans_list, 434 list) { 435 struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid; 436 u16 vid = mlxsw_sp_port_vlan->vid; 437 438 if (!fid) 439 continue; 440 441 err = __mlxsw_sp_fid_port_vid_map(mlxsw_sp, fid->fid_index, 442 mlxsw_sp_port->local_port, 443 vid, true); 444 if (err) 445 goto err_fid_port_vid_map; 446 } 447 448 err = mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, true); 449 if (err) 450 goto err_port_vp_mode_set; 451 452 return 0; 453 454 err_port_vp_mode_set: 455 err_fid_port_vid_map: 456 list_for_each_entry_continue_reverse(mlxsw_sp_port_vlan, 457 &mlxsw_sp_port->vlans_list, list) { 458 struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid; 459 u16 vid = mlxsw_sp_port_vlan->vid; 460 461 if (!fid) 462 continue; 463 464 __mlxsw_sp_fid_port_vid_map(mlxsw_sp, fid->fid_index, 465 mlxsw_sp_port->local_port, vid, 466 false); 467 } 468 return err; 469 } 470 471 static void mlxsw_sp_port_vlan_mode_trans(struct mlxsw_sp_port *mlxsw_sp_port) 472 { 473 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 474 struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan; 475 476 mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, false); 477 478 list_for_each_entry_reverse(mlxsw_sp_port_vlan, 479 &mlxsw_sp_port->vlans_list, list) { 480 struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid; 481 u16 vid = mlxsw_sp_port_vlan->vid; 482 483 if (!fid) 484 continue; 485 486 __mlxsw_sp_fid_port_vid_map(mlxsw_sp, fid->fid_index, 487 mlxsw_sp_port->local_port, vid, 488 false); 489 } 490 } 491 492 static int mlxsw_sp_fid_8021d_port_vid_map(struct mlxsw_sp_fid *fid, 493 struct mlxsw_sp_port *mlxsw_sp_port, 494 u16 vid) 495 { 496 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 497 u8 local_port = mlxsw_sp_port->local_port; 498 int err; 499 500 err = __mlxsw_sp_fid_port_vid_map(mlxsw_sp, fid->fid_index, 501 mlxsw_sp_port->local_port, vid, true); 502 if (err) 503 return err; 504 505 if (mlxsw_sp->fid_core->port_fid_mappings[local_port]++ == 0) { 506 err = mlxsw_sp_port_vp_mode_trans(mlxsw_sp_port); 507 if (err) 508 goto err_port_vp_mode_trans; 509 } 510 511 return 0; 512 513 err_port_vp_mode_trans: 514 mlxsw_sp->fid_core->port_fid_mappings[local_port]--; 515 __mlxsw_sp_fid_port_vid_map(mlxsw_sp, fid->fid_index, 516 mlxsw_sp_port->local_port, vid, false); 517 return err; 518 } 519 520 static void 521 mlxsw_sp_fid_8021d_port_vid_unmap(struct mlxsw_sp_fid *fid, 522 struct mlxsw_sp_port *mlxsw_sp_port, 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 if (mlxsw_sp->fid_core->port_fid_mappings[local_port] == 1) 528 mlxsw_sp_port_vlan_mode_trans(mlxsw_sp_port); 529 mlxsw_sp->fid_core->port_fid_mappings[local_port]--; 530 __mlxsw_sp_fid_port_vid_map(mlxsw_sp, fid->fid_index, 531 mlxsw_sp_port->local_port, vid, false); 532 } 533 534 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021d_ops = { 535 .setup = mlxsw_sp_fid_8021d_setup, 536 .configure = mlxsw_sp_fid_8021d_configure, 537 .deconfigure = mlxsw_sp_fid_8021d_deconfigure, 538 .index_alloc = mlxsw_sp_fid_8021d_index_alloc, 539 .compare = mlxsw_sp_fid_8021d_compare, 540 .flood_index = mlxsw_sp_fid_8021d_flood_index, 541 .port_vid_map = mlxsw_sp_fid_8021d_port_vid_map, 542 .port_vid_unmap = mlxsw_sp_fid_8021d_port_vid_unmap, 543 }; 544 545 static const struct mlxsw_sp_flood_table mlxsw_sp_fid_8021d_flood_tables[] = { 546 { 547 .packet_type = MLXSW_SP_FLOOD_TYPE_UC, 548 .bridge_type = MLXSW_REG_SFGC_BRIDGE_TYPE_VFID, 549 .table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID, 550 .table_index = 0, 551 }, 552 { 553 .packet_type = MLXSW_SP_FLOOD_TYPE_MC, 554 .bridge_type = MLXSW_REG_SFGC_BRIDGE_TYPE_VFID, 555 .table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID, 556 .table_index = 1, 557 }, 558 { 559 .packet_type = MLXSW_SP_FLOOD_TYPE_BC, 560 .bridge_type = MLXSW_REG_SFGC_BRIDGE_TYPE_VFID, 561 .table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID, 562 .table_index = 2, 563 }, 564 }; 565 566 /* Range and flood configuration must match mlxsw_config_profile */ 567 static const struct mlxsw_sp_fid_family mlxsw_sp_fid_8021d_family = { 568 .type = MLXSW_SP_FID_TYPE_8021D, 569 .fid_size = sizeof(struct mlxsw_sp_fid_8021d), 570 .start_index = VLAN_N_VID, 571 .end_index = VLAN_N_VID + MLXSW_SP_FID_8021D_MAX - 1, 572 .flood_tables = mlxsw_sp_fid_8021d_flood_tables, 573 .nr_flood_tables = ARRAY_SIZE(mlxsw_sp_fid_8021d_flood_tables), 574 .rif_type = MLXSW_SP_RIF_TYPE_FID, 575 .ops = &mlxsw_sp_fid_8021d_ops, 576 }; 577 578 static int mlxsw_sp_fid_rfid_configure(struct mlxsw_sp_fid *fid) 579 { 580 /* rFIDs are allocated by the device during init */ 581 return 0; 582 } 583 584 static void mlxsw_sp_fid_rfid_deconfigure(struct mlxsw_sp_fid *fid) 585 { 586 } 587 588 static int mlxsw_sp_fid_rfid_index_alloc(struct mlxsw_sp_fid *fid, 589 const void *arg, u16 *p_fid_index) 590 { 591 u16 rif_index = *(u16 *) arg; 592 593 *p_fid_index = fid->fid_family->start_index + rif_index; 594 595 return 0; 596 } 597 598 static bool mlxsw_sp_fid_rfid_compare(const struct mlxsw_sp_fid *fid, 599 const void *arg) 600 { 601 u16 rif_index = *(u16 *) arg; 602 603 return fid->fid_index == rif_index + fid->fid_family->start_index; 604 } 605 606 static int mlxsw_sp_fid_rfid_port_vid_map(struct mlxsw_sp_fid *fid, 607 struct mlxsw_sp_port *mlxsw_sp_port, 608 u16 vid) 609 { 610 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 611 u8 local_port = mlxsw_sp_port->local_port; 612 int err; 613 614 /* We only need to transition the port to virtual mode since 615 * {Port, VID} => FID is done by the firmware upon RIF creation. 616 */ 617 if (mlxsw_sp->fid_core->port_fid_mappings[local_port]++ == 0) { 618 err = mlxsw_sp_port_vp_mode_trans(mlxsw_sp_port); 619 if (err) 620 goto err_port_vp_mode_trans; 621 } 622 623 return 0; 624 625 err_port_vp_mode_trans: 626 mlxsw_sp->fid_core->port_fid_mappings[local_port]--; 627 return err; 628 } 629 630 static void 631 mlxsw_sp_fid_rfid_port_vid_unmap(struct mlxsw_sp_fid *fid, 632 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid) 633 { 634 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 635 u8 local_port = mlxsw_sp_port->local_port; 636 637 if (mlxsw_sp->fid_core->port_fid_mappings[local_port] == 1) 638 mlxsw_sp_port_vlan_mode_trans(mlxsw_sp_port); 639 mlxsw_sp->fid_core->port_fid_mappings[local_port]--; 640 } 641 642 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_rfid_ops = { 643 .configure = mlxsw_sp_fid_rfid_configure, 644 .deconfigure = mlxsw_sp_fid_rfid_deconfigure, 645 .index_alloc = mlxsw_sp_fid_rfid_index_alloc, 646 .compare = mlxsw_sp_fid_rfid_compare, 647 .port_vid_map = mlxsw_sp_fid_rfid_port_vid_map, 648 .port_vid_unmap = mlxsw_sp_fid_rfid_port_vid_unmap, 649 }; 650 651 #define MLXSW_SP_RFID_BASE (15 * 1024) 652 #define MLXSW_SP_RFID_MAX 1024 653 654 static const struct mlxsw_sp_fid_family mlxsw_sp_fid_rfid_family = { 655 .type = MLXSW_SP_FID_TYPE_RFID, 656 .fid_size = sizeof(struct mlxsw_sp_fid), 657 .start_index = MLXSW_SP_RFID_BASE, 658 .end_index = MLXSW_SP_RFID_BASE + MLXSW_SP_RFID_MAX - 1, 659 .rif_type = MLXSW_SP_RIF_TYPE_SUBPORT, 660 .ops = &mlxsw_sp_fid_rfid_ops, 661 }; 662 663 static int mlxsw_sp_fid_dummy_configure(struct mlxsw_sp_fid *fid) 664 { 665 struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; 666 667 return mlxsw_sp_fid_op(mlxsw_sp, fid->fid_index, 0, true); 668 } 669 670 static void mlxsw_sp_fid_dummy_deconfigure(struct mlxsw_sp_fid *fid) 671 { 672 mlxsw_sp_fid_op(fid->fid_family->mlxsw_sp, fid->fid_index, 0, false); 673 } 674 675 static int mlxsw_sp_fid_dummy_index_alloc(struct mlxsw_sp_fid *fid, 676 const void *arg, u16 *p_fid_index) 677 { 678 *p_fid_index = fid->fid_family->start_index; 679 680 return 0; 681 } 682 683 static bool mlxsw_sp_fid_dummy_compare(const struct mlxsw_sp_fid *fid, 684 const void *arg) 685 { 686 return true; 687 } 688 689 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_dummy_ops = { 690 .configure = mlxsw_sp_fid_dummy_configure, 691 .deconfigure = mlxsw_sp_fid_dummy_deconfigure, 692 .index_alloc = mlxsw_sp_fid_dummy_index_alloc, 693 .compare = mlxsw_sp_fid_dummy_compare, 694 }; 695 696 static const struct mlxsw_sp_fid_family mlxsw_sp_fid_dummy_family = { 697 .type = MLXSW_SP_FID_TYPE_DUMMY, 698 .fid_size = sizeof(struct mlxsw_sp_fid), 699 .start_index = MLXSW_SP_RFID_BASE - 1, 700 .end_index = MLXSW_SP_RFID_BASE - 1, 701 .ops = &mlxsw_sp_fid_dummy_ops, 702 }; 703 704 static const struct mlxsw_sp_fid_family *mlxsw_sp_fid_family_arr[] = { 705 [MLXSW_SP_FID_TYPE_8021Q] = &mlxsw_sp_fid_8021q_family, 706 [MLXSW_SP_FID_TYPE_8021D] = &mlxsw_sp_fid_8021d_family, 707 [MLXSW_SP_FID_TYPE_RFID] = &mlxsw_sp_fid_rfid_family, 708 [MLXSW_SP_FID_TYPE_DUMMY] = &mlxsw_sp_fid_dummy_family, 709 }; 710 711 static struct mlxsw_sp_fid *mlxsw_sp_fid_get(struct mlxsw_sp *mlxsw_sp, 712 enum mlxsw_sp_fid_type type, 713 const void *arg) 714 { 715 struct mlxsw_sp_fid_family *fid_family; 716 struct mlxsw_sp_fid *fid; 717 u16 fid_index; 718 int err; 719 720 fid_family = mlxsw_sp->fid_core->fid_family_arr[type]; 721 list_for_each_entry(fid, &fid_family->fids_list, list) { 722 if (!fid->fid_family->ops->compare(fid, arg)) 723 continue; 724 fid->ref_count++; 725 return fid; 726 } 727 728 fid = kzalloc(fid_family->fid_size, GFP_KERNEL); 729 if (!fid) 730 return ERR_PTR(-ENOMEM); 731 fid->fid_family = fid_family; 732 733 err = fid->fid_family->ops->index_alloc(fid, arg, &fid_index); 734 if (err) 735 goto err_index_alloc; 736 fid->fid_index = fid_index; 737 __set_bit(fid_index - fid_family->start_index, fid_family->fids_bitmap); 738 739 if (fid->fid_family->ops->setup) 740 fid->fid_family->ops->setup(fid, arg); 741 742 err = fid->fid_family->ops->configure(fid); 743 if (err) 744 goto err_configure; 745 746 list_add(&fid->list, &fid_family->fids_list); 747 fid->ref_count++; 748 return fid; 749 750 err_configure: 751 __clear_bit(fid_index - fid_family->start_index, 752 fid_family->fids_bitmap); 753 err_index_alloc: 754 kfree(fid); 755 return ERR_PTR(err); 756 } 757 758 void mlxsw_sp_fid_put(struct mlxsw_sp_fid *fid) 759 { 760 struct mlxsw_sp_fid_family *fid_family = fid->fid_family; 761 762 if (--fid->ref_count == 1 && fid->rif) { 763 /* Destroy the associated RIF and let it drop the last 764 * reference on the FID. 765 */ 766 return mlxsw_sp_rif_destroy(fid->rif); 767 } else if (fid->ref_count == 0) { 768 list_del(&fid->list); 769 fid->fid_family->ops->deconfigure(fid); 770 __clear_bit(fid->fid_index - fid_family->start_index, 771 fid_family->fids_bitmap); 772 kfree(fid); 773 } 774 } 775 776 struct mlxsw_sp_fid *mlxsw_sp_fid_8021q_get(struct mlxsw_sp *mlxsw_sp, u16 vid) 777 { 778 return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_8021Q, &vid); 779 } 780 781 struct mlxsw_sp_fid *mlxsw_sp_fid_8021d_get(struct mlxsw_sp *mlxsw_sp, 782 int br_ifindex) 783 { 784 return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_8021D, &br_ifindex); 785 } 786 787 struct mlxsw_sp_fid *mlxsw_sp_fid_rfid_get(struct mlxsw_sp *mlxsw_sp, 788 u16 rif_index) 789 { 790 return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_RFID, &rif_index); 791 } 792 793 struct mlxsw_sp_fid *mlxsw_sp_fid_dummy_get(struct mlxsw_sp *mlxsw_sp) 794 { 795 return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_DUMMY, NULL); 796 } 797 798 static int 799 mlxsw_sp_fid_flood_table_init(struct mlxsw_sp_fid_family *fid_family, 800 const struct mlxsw_sp_flood_table *flood_table) 801 { 802 enum mlxsw_sp_flood_type packet_type = flood_table->packet_type; 803 const int *sfgc_packet_types; 804 int i; 805 806 sfgc_packet_types = mlxsw_sp_packet_type_sfgc_types[packet_type]; 807 for (i = 0; i < MLXSW_REG_SFGC_TYPE_MAX; i++) { 808 struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp; 809 char sfgc_pl[MLXSW_REG_SFGC_LEN]; 810 int err; 811 812 if (!sfgc_packet_types[i]) 813 continue; 814 mlxsw_reg_sfgc_pack(sfgc_pl, i, flood_table->bridge_type, 815 flood_table->table_type, 816 flood_table->table_index); 817 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfgc), sfgc_pl); 818 if (err) 819 return err; 820 } 821 822 return 0; 823 } 824 825 static int 826 mlxsw_sp_fid_flood_tables_init(struct mlxsw_sp_fid_family *fid_family) 827 { 828 int i; 829 830 for (i = 0; i < fid_family->nr_flood_tables; i++) { 831 const struct mlxsw_sp_flood_table *flood_table; 832 int err; 833 834 flood_table = &fid_family->flood_tables[i]; 835 err = mlxsw_sp_fid_flood_table_init(fid_family, flood_table); 836 if (err) 837 return err; 838 } 839 840 return 0; 841 } 842 843 static int mlxsw_sp_fid_family_register(struct mlxsw_sp *mlxsw_sp, 844 const struct mlxsw_sp_fid_family *tmpl) 845 { 846 u16 nr_fids = tmpl->end_index - tmpl->start_index + 1; 847 struct mlxsw_sp_fid_family *fid_family; 848 int err; 849 850 fid_family = kmemdup(tmpl, sizeof(*fid_family), GFP_KERNEL); 851 if (!fid_family) 852 return -ENOMEM; 853 854 fid_family->mlxsw_sp = mlxsw_sp; 855 INIT_LIST_HEAD(&fid_family->fids_list); 856 fid_family->fids_bitmap = kcalloc(BITS_TO_LONGS(nr_fids), 857 sizeof(unsigned long), GFP_KERNEL); 858 if (!fid_family->fids_bitmap) { 859 err = -ENOMEM; 860 goto err_alloc_fids_bitmap; 861 } 862 863 if (fid_family->flood_tables) { 864 err = mlxsw_sp_fid_flood_tables_init(fid_family); 865 if (err) 866 goto err_fid_flood_tables_init; 867 } 868 869 mlxsw_sp->fid_core->fid_family_arr[tmpl->type] = fid_family; 870 871 return 0; 872 873 err_fid_flood_tables_init: 874 kfree(fid_family->fids_bitmap); 875 err_alloc_fids_bitmap: 876 kfree(fid_family); 877 return err; 878 } 879 880 static void 881 mlxsw_sp_fid_family_unregister(struct mlxsw_sp *mlxsw_sp, 882 struct mlxsw_sp_fid_family *fid_family) 883 { 884 mlxsw_sp->fid_core->fid_family_arr[fid_family->type] = NULL; 885 kfree(fid_family->fids_bitmap); 886 WARN_ON_ONCE(!list_empty(&fid_family->fids_list)); 887 kfree(fid_family); 888 } 889 890 int mlxsw_sp_port_fids_init(struct mlxsw_sp_port *mlxsw_sp_port) 891 { 892 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 893 894 /* Track number of FIDs configured on the port with mapping type 895 * PORT_VID_TO_FID, so that we know when to transition the port 896 * back to non-virtual (VLAN) mode. 897 */ 898 mlxsw_sp->fid_core->port_fid_mappings[mlxsw_sp_port->local_port] = 0; 899 900 return mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, false); 901 } 902 903 void mlxsw_sp_port_fids_fini(struct mlxsw_sp_port *mlxsw_sp_port) 904 { 905 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 906 907 mlxsw_sp->fid_core->port_fid_mappings[mlxsw_sp_port->local_port] = 0; 908 } 909 910 int mlxsw_sp_fids_init(struct mlxsw_sp *mlxsw_sp) 911 { 912 unsigned int max_ports = mlxsw_core_max_ports(mlxsw_sp->core); 913 struct mlxsw_sp_fid_core *fid_core; 914 int err, i; 915 916 fid_core = kzalloc(sizeof(*mlxsw_sp->fid_core), GFP_KERNEL); 917 if (!fid_core) 918 return -ENOMEM; 919 mlxsw_sp->fid_core = fid_core; 920 921 fid_core->port_fid_mappings = kcalloc(max_ports, sizeof(unsigned int), 922 GFP_KERNEL); 923 if (!fid_core->port_fid_mappings) { 924 err = -ENOMEM; 925 goto err_alloc_port_fid_mappings; 926 } 927 928 for (i = 0; i < MLXSW_SP_FID_TYPE_MAX; i++) { 929 err = mlxsw_sp_fid_family_register(mlxsw_sp, 930 mlxsw_sp_fid_family_arr[i]); 931 932 if (err) 933 goto err_fid_ops_register; 934 } 935 936 return 0; 937 938 err_fid_ops_register: 939 for (i--; i >= 0; i--) { 940 struct mlxsw_sp_fid_family *fid_family; 941 942 fid_family = fid_core->fid_family_arr[i]; 943 mlxsw_sp_fid_family_unregister(mlxsw_sp, fid_family); 944 } 945 kfree(fid_core->port_fid_mappings); 946 err_alloc_port_fid_mappings: 947 kfree(fid_core); 948 return err; 949 } 950 951 void mlxsw_sp_fids_fini(struct mlxsw_sp *mlxsw_sp) 952 { 953 struct mlxsw_sp_fid_core *fid_core = mlxsw_sp->fid_core; 954 int i; 955 956 for (i = 0; i < MLXSW_SP_FID_TYPE_MAX; i++) 957 mlxsw_sp_fid_family_unregister(mlxsw_sp, 958 fid_core->fid_family_arr[i]); 959 kfree(fid_core->port_fid_mappings); 960 kfree(fid_core); 961 } 962