File Index
Files and directories
Sign in
FILE

spectrum_fid.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c C
   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
  17struct mlxsw_sp_fid_family;
  18
  19struct 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
  26struct mlxsw_sp_fid_port_vid {
  27	struct list_head list;
  28	u16 local_port;
  29	u16 vid;
  30};
  31
  32struct 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
  51struct mlxsw_sp_fid_8021q {
  52	struct mlxsw_sp_fid common;
  53	u16 vid;
  54};
  55
  56struct mlxsw_sp_fid_8021d {
  57	struct mlxsw_sp_fid common;
  58	int br_ifindex;
  59};
  60
  61static 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
  67static 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
  73struct 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
  79struct 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
 117enum 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
 123struct 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
 129struct 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
 146static const int mlxsw_sp_sfgc_uc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = {
 147	[MLXSW_REG_SFGC_TYPE_UNKNOWN_UNICAST]			= 1,
 148};
 149
 150static 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
 158static const int mlxsw_sp_sfgc_mc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = {
 159	[MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV4]	= 1,
 160};
 161
 162static 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
 171static 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
 181static 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
 189struct 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
 202int 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
 212int 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
 223struct 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
 236int 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
 246int 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
 264err_nve_flood_index_set:
 265	fid->nve_flood_index_valid = false;
 266	return err;
 267}
 268
 269void 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
 281bool mlxsw_sp_fid_nve_flood_index_is_set(const struct mlxsw_sp_fid *fid)
 282{
 283	return fid->nve_flood_index_valid;
 284}
 285
 286int 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
 313err_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
 320void 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
 335bool mlxsw_sp_fid_vni_is_set(const struct mlxsw_sp_fid *fid)
 336{
 337	return fid->vni_valid;
 338}
 339
 340void 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
 350static const struct mlxsw_sp_flood_table *
 351mlxsw_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
 369static u16
 370mlxsw_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
 375static int
 376mlxsw_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
 385static 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
 393static int
 394mlxsw_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
 415static u16
 416mlxsw_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
 425static u16
 426mlxsw_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
 433int 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
 453int 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
 461void 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
 467u16 mlxsw_sp_fid_index(const struct mlxsw_sp_fid *fid)
 468{
 469	return fid->fid_index;
 470}
 471
 472enum mlxsw_sp_fid_type mlxsw_sp_fid_type(const struct mlxsw_sp_fid *fid)
 473{
 474	return fid->fid_family->type;
 475}
 476
 477struct mlxsw_sp_rif *mlxsw_sp_fid_rif(const struct mlxsw_sp_fid *fid)
 478{
 479	return fid->rif;
 480}
 481
 482enum mlxsw_sp_rif_type
 483mlxsw_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
 491static struct mlxsw_sp_fid_8021q *
 492mlxsw_sp_fid_8021q_fid(const struct mlxsw_sp_fid *fid)
 493{
 494	return container_of(fid, struct mlxsw_sp_fid_8021q, common);
 495}
 496
 497u16 mlxsw_sp_fid_8021q_vid(const struct mlxsw_sp_fid *fid)
 498{
 499	return mlxsw_sp_fid_8021q_fid(fid)->vid;
 500}
 501
 502static 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
 511static 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
 517static 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
 529static 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
 540static u16
 541mlxsw_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
 548static 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
 553static 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
 568static 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
 580static 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
 590static 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
 612static 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
 629static 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
 635static 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
 644static int
 645mlxsw_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
 661static int
 662mlxsw_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
 673static int
 674mlxsw_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
 688static 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
 719err_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
 731static 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
 749static 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
 793err_reg_write:
 794	kfree(reiv_pl);
 795	return err;
 796}
 797
 798static 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
 816err_reiv_handle:
 817	for (; i >= 0; i--)
 818		mlxsw_sp_fid_reiv_handle(fid, rif_index, !valid, i);
 819	return err;
 820}
 821
 822int 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
 846err_erif_eport_to_vid_map:
 847	mlxsw_sp_fid_vid_to_fid_rif_unset(fid);
 848err_vid_to_fid_rif_set:
 849	mlxsw_sp_fid_vni_to_fid_rif_update(fid, NULL);
 850err_vni_to_fid_rif_update:
 851	mlxsw_sp_fid_to_fid_rif_update(fid, NULL);
 852	return err;
 853}
 854
 855void 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
 871static 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
 885err_fid_edit_op:
 886	mlxsw_sp_fid_vni_to_fid_map(fid, fid->rif, !fid->vni_valid);
 887	return err;
 888}
 889
 890static 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
 908static struct mlxsw_sp_fid_8021d *
 909mlxsw_sp_fid_8021d_fid(const struct mlxsw_sp_fid *fid)
 910{
 911	return container_of(fid, struct mlxsw_sp_fid_8021d, common);
 912}
 913
 914static 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
 923static int mlxsw_sp_fid_8021d_configure(struct mlxsw_sp_fid *fid)
 924{
 925	return mlxsw_sp_fid_op(fid, true);
 926}
 927
 928static 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
 935static 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
 950static bool
 951mlxsw_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
 958static 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
 984err_port_vp_mode_set:
 985err_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
1000static 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
1019static int
1020mlxsw_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
1025	port_vid = kzalloc(sizeof(*port_vid), GFP_KERNEL);
1026	if (!port_vid)
1027		return -ENOMEM;
1028
1029	port_vid->local_port = local_port;
1030	port_vid->vid = vid;
1031
1032	list_for_each_entry(tmp_port_vid, &fid->port_vid_list, list) {
1033		if (tmp_port_vid->local_port > local_port)
1034			break;
1035	}
1036
1037	list_add_tail(&port_vid->list, &tmp_port_vid->list);
1038	return 0;
1039}
1040
1041static void
1042mlxsw_sp_fid_port_vid_list_del(struct mlxsw_sp_fid *fid, u16 local_port,
1043			       u16 vid)
1044{
1045	struct mlxsw_sp_fid_port_vid *port_vid, *tmp;
1046
1047	list_for_each_entry_safe(port_vid, tmp, &fid->port_vid_list, list) {
1048		if (port_vid->local_port != local_port || port_vid->vid != vid)
1049			continue;
1050
1051		list_del(&port_vid->list);
1052		kfree(port_vid);
1053		return;
1054	}
1055}
1056
1057static int
1058mlxsw_sp_fid_mpe_table_map(const struct mlxsw_sp_fid *fid, u16 local_port,
1059			   u16 vid, bool valid)
1060{
1061	struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
1062	char smpe_pl[MLXSW_REG_SMPE_LEN];
1063
1064	mlxsw_reg_smpe_pack(smpe_pl, local_port, fid->fid_index,
1065			    valid ? vid : 0);
1066	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(smpe), smpe_pl);
1067}
1068
1069static int
1070mlxsw_sp_fid_erif_eport_to_vid_map_one(const struct mlxsw_sp_fid *fid,
1071				       u16 local_port, u16 vid, bool valid)
1072{
1073	u8 port_page = local_port / MLXSW_REG_REIV_REC_MAX_COUNT;
1074	u8 rec_num = local_port % MLXSW_REG_REIV_REC_MAX_COUNT;
1075	struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
1076	u16 rif_index = mlxsw_sp_rif_index(fid->rif);
1077	char *reiv_pl;
1078	int err;
1079
1080	reiv_pl = kmalloc(MLXSW_REG_REIV_LEN, GFP_KERNEL);
1081	if (!reiv_pl)
1082		return -ENOMEM;
1083
1084	mlxsw_reg_reiv_pack(reiv_pl, port_page, rif_index);
1085	mlxsw_reg_reiv_rec_update_set(reiv_pl, rec_num, true);
1086	mlxsw_reg_reiv_rec_evid_set(reiv_pl, rec_num, valid ? vid : 0);
1087	err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(reiv), reiv_pl);
1088	kfree(reiv_pl);
1089	return err;
1090}
1091
1092static int mlxsw_sp_fid_evid_map(const struct mlxsw_sp_fid *fid, u16 local_port,
1093				 u16 vid, bool valid)
1094{
1095	int err;
1096
1097	err = mlxsw_sp_fid_mpe_table_map(fid, local_port, vid, valid);
1098	if (err)
1099		return err;
1100
1101	if (!fid->rif)
1102		return 0;
1103
1104	err = mlxsw_sp_fid_erif_eport_to_vid_map_one(fid, local_port, vid,
1105						     valid);
1106	if (err)
1107		goto err_erif_eport_to_vid_map_one;
1108
1109	return 0;
1110
1111err_erif_eport_to_vid_map_one:
1112	mlxsw_sp_fid_mpe_table_map(fid, local_port, vid, !valid);
1113	return err;
1114}
1115
1116static int mlxsw_sp_fid_8021d_port_vid_map(struct mlxsw_sp_fid *fid,
1117					   struct mlxsw_sp_port *mlxsw_sp_port,
1118					   u16 vid)
1119{
1120	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1121	u16 local_port = mlxsw_sp_port->local_port;
1122	int err;
1123
1124	err = __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid,
1125					  true);
1126	if (err)
1127		return err;
1128
1129	err = mlxsw_sp_fid_evid_map(fid, local_port, vid, true);
1130	if (err)
1131		goto err_fid_evid_map;
1132
1133	err = mlxsw_sp_fid_port_vid_list_add(fid, mlxsw_sp_port->local_port,
1134					     vid);
1135	if (err)
1136		goto err_port_vid_list_add;
1137
1138	if (mlxsw_sp->fid_core->port_fid_mappings[local_port]++ == 0) {
1139		err = mlxsw_sp_port_vp_mode_trans(mlxsw_sp_port);
1140		if (err)
1141			goto err_port_vp_mode_trans;
1142	}
1143
1144	return 0;
1145
1146err_port_vp_mode_trans:
1147	mlxsw_sp->fid_core->port_fid_mappings[local_port]--;
1148	mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid);
1149err_port_vid_list_add:
1150	mlxsw_sp_fid_evid_map(fid, local_port, vid, false);
1151err_fid_evid_map:
1152	__mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, false);
1153	return err;
1154}
1155
1156static void
1157mlxsw_sp_fid_8021d_port_vid_unmap(struct mlxsw_sp_fid *fid,
1158				  struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
1159{
1160	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1161	u16 local_port = mlxsw_sp_port->local_port;
1162
1163	if (mlxsw_sp->fid_core->port_fid_mappings[local_port] == 1)
1164		mlxsw_sp_port_vlan_mode_trans(mlxsw_sp_port);
1165	mlxsw_sp->fid_core->port_fid_mappings[local_port]--;
1166	mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid);
1167	mlxsw_sp_fid_evid_map(fid, local_port, vid, false);
1168	__mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, false);
1169}
1170
1171static int mlxsw_sp_fid_8021d_vni_set(struct mlxsw_sp_fid *fid)
1172{
1173	return mlxsw_sp_fid_vni_op(fid);
1174}
1175
1176static void mlxsw_sp_fid_8021d_vni_clear(struct mlxsw_sp_fid *fid)
1177{
1178	mlxsw_sp_fid_vni_op(fid);
1179}
1180
1181static int mlxsw_sp_fid_8021d_nve_flood_index_set(struct mlxsw_sp_fid *fid)
1182{
1183	return mlxsw_sp_fid_edit_op(fid, fid->rif);
1184}
1185
1186static void mlxsw_sp_fid_8021d_nve_flood_index_clear(struct mlxsw_sp_fid *fid)
1187{
1188	mlxsw_sp_fid_edit_op(fid, fid->rif);
1189}
1190
1191static void
1192mlxsw_sp_fid_8021d_fdb_clear_offload(const struct mlxsw_sp_fid *fid,
1193				     const struct net_device *nve_dev)
1194{
1195	br_fdb_clear_offload(nve_dev, 0);
1196}
1197
1198static int
1199mlxsw_sp_fid_8021d_vid_to_fid_rif_update(const struct mlxsw_sp_fid *fid,
1200					 const struct mlxsw_sp_rif *rif)
1201{
1202	return 0;
1203}
1204
1205static int
1206mlxsw_sp_fid_flood_table_init_ctl(struct mlxsw_sp_fid_family *fid_family,
1207				  const struct mlxsw_sp_flood_table *flood_table)
1208{
1209	enum mlxsw_sp_flood_type packet_type = flood_table->packet_type;
1210	struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
1211	const int *sfgc_packet_types;
1212	u16 mid_base;
1213	int err, i;
1214
1215	mid_base = mlxsw_sp_fid_pgt_base_ctl(fid_family, flood_table);
1216
1217	sfgc_packet_types = mlxsw_sp_packet_type_sfgc_types[packet_type];
1218	for (i = 0; i < MLXSW_REG_SFGC_TYPE_MAX; i++) {
1219		char sfgc_pl[MLXSW_REG_SFGC_LEN];
1220
1221		if (!sfgc_packet_types[i])
1222			continue;
1223
1224		mlxsw_reg_sfgc_pack(sfgc_pl, i, fid_family->bridge_type,
1225				    flood_table->table_type, 0, mid_base);
1226
1227		err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfgc), sfgc_pl);
1228		if (err)
1229			return err;
1230	}
1231
1232	return 0;
1233}
1234
1235static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021d_ops_ctl = {
1236	.setup			= mlxsw_sp_fid_8021d_setup,
1237	.configure		= mlxsw_sp_fid_8021d_configure,
1238	.deconfigure		= mlxsw_sp_fid_8021d_deconfigure,
1239	.index_alloc		= mlxsw_sp_fid_8021d_index_alloc,
1240	.compare		= mlxsw_sp_fid_8021d_compare,
1241	.port_vid_map		= mlxsw_sp_fid_8021d_port_vid_map,
1242	.port_vid_unmap		= mlxsw_sp_fid_8021d_port_vid_unmap,
1243	.vni_set		= mlxsw_sp_fid_8021d_vni_set,
1244	.vni_clear		= mlxsw_sp_fid_8021d_vni_clear,
1245	.nve_flood_index_set	= mlxsw_sp_fid_8021d_nve_flood_index_set,
1246	.nve_flood_index_clear	= mlxsw_sp_fid_8021d_nve_flood_index_clear,
1247	.fdb_clear_offload	= mlxsw_sp_fid_8021d_fdb_clear_offload,
1248	.vid_to_fid_rif_update  = mlxsw_sp_fid_8021d_vid_to_fid_rif_update,
1249	.flood_table_init	= mlxsw_sp_fid_flood_table_init_ctl,
1250	.pgt_size		= mlxsw_sp_fid_8021d_pgt_size,
1251	.fid_mid		= mlxsw_sp_fid_fid_mid_ctl,
1252	.fid_pack		= mlxsw_sp_fid_pack_ctl,
1253};
1254
1255static u16
1256mlxsw_sp_fid_fid_mid_cff(const struct mlxsw_sp_fid *fid,
1257			 const struct mlxsw_sp_flood_table *flood_table)
1258{
1259	return mlxsw_sp_fid_pgt_base_cff(fid) + flood_table->table_index;
1260}
1261
1262static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021d_ops_cff = {
1263	.setup			= mlxsw_sp_fid_8021d_setup,
1264	.configure		= mlxsw_sp_fid_8021d_configure,
1265	.deconfigure		= mlxsw_sp_fid_8021d_deconfigure,
1266	.index_alloc		= mlxsw_sp_fid_8021d_index_alloc,
1267	.compare		= mlxsw_sp_fid_8021d_compare,
1268	.port_vid_map		= mlxsw_sp_fid_8021d_port_vid_map,
1269	.port_vid_unmap		= mlxsw_sp_fid_8021d_port_vid_unmap,
1270	.vni_set		= mlxsw_sp_fid_8021d_vni_set,
1271	.vni_clear		= mlxsw_sp_fid_8021d_vni_clear,
1272	.nve_flood_index_set	= mlxsw_sp_fid_8021d_nve_flood_index_set,
1273	.nve_flood_index_clear	= mlxsw_sp_fid_8021d_nve_flood_index_clear,
1274	.fdb_clear_offload	= mlxsw_sp_fid_8021d_fdb_clear_offload,
1275	.vid_to_fid_rif_update	= mlxsw_sp_fid_8021d_vid_to_fid_rif_update,
1276	.pgt_size		= mlxsw_sp_fid_8021d_pgt_size,
1277	.fid_mid		= mlxsw_sp_fid_fid_mid_cff,
1278	.fid_pack		= mlxsw_sp_fid_fid_pack_cff,
1279};
1280
1281#define MLXSW_SP_FID_8021Q_MAX (VLAN_N_VID - 2)
1282#define MLXSW_SP_FID_RFID_MAX (11 * 1024)
1283
1284static const struct mlxsw_sp_flood_table mlxsw_sp_fid_8021d_flood_tables[] = {
1285	{
1286		.packet_type	= MLXSW_SP_FLOOD_TYPE_UC,
1287		.table_type	= MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFSET,
1288		.table_index	= 0,
1289	},
1290	{
1291		.packet_type	= MLXSW_SP_FLOOD_TYPE_MC,
1292		.table_type	= MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFSET,
1293		.table_index	= 1,
1294	},
1295	{
1296		.packet_type	= MLXSW_SP_FLOOD_TYPE_BC,
1297		.table_type	= MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFSET,
1298		.table_index	= 2,
1299	},
1300};
1301
1302static const
1303struct mlxsw_sp_fid_flood_profile mlxsw_sp_fid_8021d_flood_profile = {
1304	.flood_tables		= mlxsw_sp_fid_8021d_flood_tables,
1305	.nr_flood_tables	= ARRAY_SIZE(mlxsw_sp_fid_8021d_flood_tables),
1306	.profile_id		= MLXSW_SP_FID_FLOOD_PROFILE_ID_BRIDGE,
1307};
1308
1309static const struct mlxsw_sp_flood_table mlxsw_sp_fid_rsp_flood_tables_cff[] = {
1310	{
1311		.packet_type	= MLXSW_SP_FLOOD_TYPE_UC,
1312		.table_index	= 0,
1313	},
1314	{
1315		.packet_type	= MLXSW_SP_FLOOD_TYPE_NOT_UC,
1316		.table_index	= 1,
1317	},
1318};
1319
1320static const
1321struct mlxsw_sp_fid_flood_profile mlxsw_sp_fid_rsp_flood_profile_cff = {
1322	.flood_tables		= mlxsw_sp_fid_rsp_flood_tables_cff,
1323	.nr_flood_tables	= ARRAY_SIZE(mlxsw_sp_fid_rsp_flood_tables_cff),
1324	.profile_id		= MLXSW_SP_FID_FLOOD_PROFILE_ID_RSP,
1325};
1326
1327static const struct mlxsw_sp_flood_table mlxsw_sp_fid_nve_flood_tables_cff[] = {
1328	{
1329		.packet_type	= MLXSW_SP_FLOOD_TYPE_ANY,
1330		.table_index	= 0,
1331	},
1332};
1333
1334static const
1335struct mlxsw_sp_fid_flood_profile mlxsw_sp_fid_nve_flood_profile_cff = {
1336	.flood_tables		= mlxsw_sp_fid_nve_flood_tables_cff,
1337	.nr_flood_tables	= ARRAY_SIZE(mlxsw_sp_fid_nve_flood_tables_cff),
1338	.profile_id		= MLXSW_SP_FID_FLOOD_PROFILE_ID_NVE,
1339};
1340
1341static bool
1342mlxsw_sp_fid_8021q_compare(const struct mlxsw_sp_fid *fid, const void *arg)
1343{
1344	u16 vid = *(u16 *) arg;
1345
1346	return mlxsw_sp_fid_8021q_fid(fid)->vid == vid;
1347}
1348
1349static void
1350mlxsw_sp_fid_8021q_fdb_clear_offload(const struct mlxsw_sp_fid *fid,
1351				     const struct net_device *nve_dev)
1352{
1353	br_fdb_clear_offload(nve_dev, mlxsw_sp_fid_8021q_vid(fid));
1354}
1355
1356static int mlxsw_sp_fid_rfid_setup_ctl(struct mlxsw_sp_fid *fid,
1357				       const void *arg)
1358{
1359	/* In controlled mode, the FW takes care of FID placement. */
1360	fid->fid_offset = 0;
1361	return 0;
1362}
1363
1364static int mlxsw_sp_fid_rfid_setup_cff(struct mlxsw_sp_fid *fid,
1365				       const void *arg)
1366{
1367	struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
1368	u16 rif_index = *(const u16 *)arg;
1369	struct mlxsw_sp_rif *rif;
1370	bool is_lag;
1371	u16 port;
1372	int err;
1373
1374	rif = mlxsw_sp_rif_by_index(mlxsw_sp, rif_index);
1375	if (!rif)
1376		return -ENOENT;
1377
1378	err = mlxsw_sp_rif_subport_port(rif, &port, &is_lag);
1379	if (err)
1380		return err;
1381
1382	fid->fid_offset = mlxsw_sp_fid_rfid_fid_offset_cff(mlxsw_sp, port,
1383							   is_lag);
1384	return 0;
1385}
1386
1387static int mlxsw_sp_fid_rfid_configure(struct mlxsw_sp_fid *fid)
1388{
1389	return mlxsw_sp_fid_op(fid, true);
1390}
1391
1392static void mlxsw_sp_fid_rfid_deconfigure(struct mlxsw_sp_fid *fid)
1393{
1394	mlxsw_sp_fid_op(fid, false);
1395}
1396
1397static int mlxsw_sp_fid_rfid_index_alloc(struct mlxsw_sp_fid *fid,
1398					 const void *arg, u16 *p_fid_index)
1399{
1400	u16 rif_index = *(u16 *) arg;
1401
1402	*p_fid_index = fid->fid_family->start_index + rif_index;
1403
1404	return 0;
1405}
1406
1407static bool mlxsw_sp_fid_rfid_compare(const struct mlxsw_sp_fid *fid,
1408				      const void *arg)
1409{
1410	u16 rif_index = *(u16 *) arg;
1411
1412	return fid->fid_index == rif_index + fid->fid_family->start_index;
1413}
1414
1415static int mlxsw_sp_fid_rfid_port_vid_map(struct mlxsw_sp_fid *fid,
1416					  struct mlxsw_sp_port *mlxsw_sp_port,
1417					  u16 vid)
1418{
1419	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1420	u16 local_port = mlxsw_sp_port->local_port;
1421	int err;
1422
1423	err = mlxsw_sp_fid_port_vid_list_add(fid, mlxsw_sp_port->local_port,
1424					     vid);
1425	if (err)
1426		return err;
1427
1428	/* Using legacy bridge model, we only need to transition the port to
1429	 * virtual mode since {Port, VID} => FID is done by the firmware upon
1430	 * RIF creation. Using unified bridge model, we need to map
1431	 * {Port, VID} => FID and map egress VID.
1432	 */
1433	err = __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid,
1434					  true);
1435	if (err)
1436		goto err_port_vid_map;
1437
1438	if (fid->rif) {
1439		err = mlxsw_sp_fid_erif_eport_to_vid_map_one(fid, local_port,
1440							     vid, true);
1441		if (err)
1442			goto err_erif_eport_to_vid_map_one;
1443	}
1444
1445	if (mlxsw_sp->fid_core->port_fid_mappings[local_port]++ == 0) {
1446		err = mlxsw_sp_port_vp_mode_trans(mlxsw_sp_port);
1447		if (err)
1448			goto err_port_vp_mode_trans;
1449	}
1450
1451	return 0;
1452
1453err_port_vp_mode_trans:
1454	mlxsw_sp->fid_core->port_fid_mappings[local_port]--;
1455	if (fid->rif)
1456		mlxsw_sp_fid_erif_eport_to_vid_map_one(fid, local_port, vid,
1457						       false);
1458err_erif_eport_to_vid_map_one:
1459	__mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, false);
1460err_port_vid_map:
1461	mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid);
1462	return err;
1463}
1464
1465static void
1466mlxsw_sp_fid_rfid_port_vid_unmap(struct mlxsw_sp_fid *fid,
1467				 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
1468{
1469	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1470	u16 local_port = mlxsw_sp_port->local_port;
1471
1472	if (mlxsw_sp->fid_core->port_fid_mappings[local_port] == 1)
1473		mlxsw_sp_port_vlan_mode_trans(mlxsw_sp_port);
1474	mlxsw_sp->fid_core->port_fid_mappings[local_port]--;
1475
1476	if (fid->rif)
1477		mlxsw_sp_fid_erif_eport_to_vid_map_one(fid, local_port, vid,
1478						       false);
1479	__mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, false);
1480	mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid);
1481}
1482
1483static int mlxsw_sp_fid_rfid_vni_set(struct mlxsw_sp_fid *fid)
1484{
1485	return -EOPNOTSUPP;
1486}
1487
1488static void mlxsw_sp_fid_rfid_vni_clear(struct mlxsw_sp_fid *fid)
1489{
1490	WARN_ON_ONCE(1);
1491}
1492
1493static int mlxsw_sp_fid_rfid_nve_flood_index_set(struct mlxsw_sp_fid *fid)
1494{
1495	return -EOPNOTSUPP;
1496}
1497
1498static void mlxsw_sp_fid_rfid_nve_flood_index_clear(struct mlxsw_sp_fid *fid)
1499{
1500	WARN_ON_ONCE(1);
1501}
1502
1503static int
1504mlxsw_sp_fid_rfid_vid_to_fid_rif_update(const struct mlxsw_sp_fid *fid,
1505					const struct mlxsw_sp_rif *rif)
1506{
1507	return 0;
1508}
1509
1510static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_rfid_ops_ctl = {
1511	.setup			= mlxsw_sp_fid_rfid_setup_ctl,
1512	.configure		= mlxsw_sp_fid_rfid_configure,
1513	.deconfigure		= mlxsw_sp_fid_rfid_deconfigure,
1514	.index_alloc		= mlxsw_sp_fid_rfid_index_alloc,
1515	.compare		= mlxsw_sp_fid_rfid_compare,
1516	.port_vid_map		= mlxsw_sp_fid_rfid_port_vid_map,
1517	.port_vid_unmap		= mlxsw_sp_fid_rfid_port_vid_unmap,
1518	.vni_set                = mlxsw_sp_fid_rfid_vni_set,
1519	.vni_clear		= mlxsw_sp_fid_rfid_vni_clear,
1520	.nve_flood_index_set	= mlxsw_sp_fid_rfid_nve_flood_index_set,
1521	.nve_flood_index_clear	= mlxsw_sp_fid_rfid_nve_flood_index_clear,
1522	.vid_to_fid_rif_update  = mlxsw_sp_fid_rfid_vid_to_fid_rif_update,
1523	.fid_pack		= mlxsw_sp_fid_pack_ctl,
1524};
1525
1526static int
1527mlxsw_sp_fid_rfid_port_add_cff(struct mlxsw_sp *mlxsw_sp,
1528			       const struct mlxsw_sp_flood_table *flood_table,
1529			       u16 pgt_addr, u16 smpe, unsigned int local_port)
1530{
1531	int err;
1532
1533	err = mlxsw_sp_pgt_entry_port_set(mlxsw_sp, pgt_addr, smpe,
1534					  local_port, true);
1535	if (err)
1536		return err;
1537
1538	if (flood_table->packet_type == MLXSW_SP_FLOOD_TYPE_NOT_UC) {
1539		u16 router_port = mlxsw_sp_router_port(mlxsw_sp);
1540
1541		err = mlxsw_sp_pgt_entry_port_set(mlxsw_sp, pgt_addr, smpe,
1542						  router_port, true);
1543		if (err)
1544			goto err_entry_port_set;
1545	}
1546
1547	return 0;
1548
1549err_entry_port_set:
1550	mlxsw_sp_pgt_entry_port_set(mlxsw_sp, pgt_addr, smpe, local_port,
1551				    false);
1552	return err;
1553}
1554
1555static void
1556mlxsw_sp_fid_rfid_port_del_cff(struct mlxsw_sp *mlxsw_sp,
1557			       const struct mlxsw_sp_flood_table *flood_table,
1558			       u16 pgt_addr, u16 smpe, u16 local_port)
1559{
1560	if (flood_table->packet_type == MLXSW_SP_FLOOD_TYPE_NOT_UC) {
1561		u16 router_port = mlxsw_sp_router_port(mlxsw_sp);
1562
1563		mlxsw_sp_pgt_entry_port_set(mlxsw_sp, pgt_addr, smpe,
1564					    router_port, false);
1565	}
1566	mlxsw_sp_pgt_entry_port_set(mlxsw_sp, pgt_addr, smpe, local_port,
1567				    false);
1568}
1569
1570static int
1571mlxsw_sp_fid_rfid_port_memb_ft_cff(const struct mlxsw_sp_fid_family *fid_family,
1572				   const struct mlxsw_sp_flood_table *flood_table,
1573				   const struct mlxsw_sp_port *mlxsw_sp_port,
1574				   bool member)
1575{
1576	struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
1577	u16 local_port = mlxsw_sp_port->local_port;
1578	u16 fid_pgt_base;
1579	u16 fid_offset;
1580	u16 pgt_addr;
1581	u16 smpe;
1582	u16 port;
1583
1584	/* In-PGT SMPE is only valid on Spectrum-1, CFF only on Spectrum>1. */
1585	smpe = 0;
1586
1587	port = mlxsw_sp_port->lagged ? mlxsw_sp_port->lag_id : local_port;
1588	fid_offset = mlxsw_sp_fid_rfid_fid_offset_cff(mlxsw_sp, port,
1589						      mlxsw_sp_port->lagged);
1590	fid_pgt_base = mlxsw_sp_fid_off_pgt_base_cff(fid_family, fid_offset);
1591	pgt_addr = fid_pgt_base + flood_table->table_index;
1592
1593	if (member)
1594		return mlxsw_sp_fid_rfid_port_add_cff(mlxsw_sp, flood_table,
1595						      pgt_addr, smpe,
1596						      local_port);
1597
1598	mlxsw_sp_fid_rfid_port_del_cff(mlxsw_sp, flood_table, pgt_addr, smpe,
1599				       local_port);
1600	return 0;
1601}
1602
1603static int
1604mlxsw_sp_fid_rfid_port_memb_cff(const struct mlxsw_sp_fid_family *fid_family,
1605				const struct mlxsw_sp_port *mlxsw_sp_port,
1606				bool member)
1607{
1608	int i;
1609
1610	for (i = 0; i < fid_family->flood_profile->nr_flood_tables; i++) {
1611		const struct mlxsw_sp_flood_table *flood_table =
1612			&fid_family->flood_profile->flood_tables[i];
1613		int err;
1614
1615		err = mlxsw_sp_fid_rfid_port_memb_ft_cff(fid_family,
1616							 flood_table,
1617							 mlxsw_sp_port, member);
1618		if (err)
1619			return err;
1620	}
1621
1622	return 0;
1623}
1624
1625static int
1626mlxsw_sp_fid_rfid_port_init_cff(const struct mlxsw_sp_fid_family *fid_family,
1627				const struct mlxsw_sp_port *mlxsw_sp_port)
1628{
1629	return mlxsw_sp_fid_rfid_port_memb_cff(fid_family, mlxsw_sp_port, true);
1630}
1631
1632static void
1633mlxsw_sp_fid_rfid_port_fini_cff(const struct mlxsw_sp_fid_family *fid_family,
1634				const struct mlxsw_sp_port *mlxsw_sp_port)
1635{
1636	mlxsw_sp_fid_rfid_port_memb_cff(fid_family, mlxsw_sp_port, false);
1637}
1638
1639static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_rfid_ops_cff = {
1640	.setup			= mlxsw_sp_fid_rfid_setup_cff,
1641	.configure		= mlxsw_sp_fid_rfid_configure,
1642	.deconfigure		= mlxsw_sp_fid_rfid_deconfigure,
1643	.index_alloc		= mlxsw_sp_fid_rfid_index_alloc,
1644	.compare		= mlxsw_sp_fid_rfid_compare,
1645	.port_vid_map		= mlxsw_sp_fid_rfid_port_vid_map,
1646	.port_vid_unmap		= mlxsw_sp_fid_rfid_port_vid_unmap,
1647	.vni_set		= mlxsw_sp_fid_rfid_vni_set,
1648	.vni_clear		= mlxsw_sp_fid_rfid_vni_clear,
1649	.nve_flood_index_set	= mlxsw_sp_fid_rfid_nve_flood_index_set,
1650	.nve_flood_index_clear	= mlxsw_sp_fid_rfid_nve_flood_index_clear,
1651	.vid_to_fid_rif_update	= mlxsw_sp_fid_rfid_vid_to_fid_rif_update,
1652	.pgt_size		= mlxsw_sp_fid_rfid_pgt_size_cff,
1653	.fid_port_init		= mlxsw_sp_fid_rfid_port_init_cff,
1654	.fid_port_fini		= mlxsw_sp_fid_rfid_port_fini_cff,
1655	.fid_mid		= mlxsw_sp_fid_fid_mid_cff,
1656	.fid_pack		= mlxsw_sp_fid_fid_pack_cff,
1657};
1658
1659static int mlxsw_sp_fid_dummy_setup(struct mlxsw_sp_fid *fid, const void *arg)
1660{
1661	fid->fid_offset = 0;
1662	return 0;
1663}
1664
1665static int mlxsw_sp_fid_dummy_configure(struct mlxsw_sp_fid *fid)
1666{
1667	return mlxsw_sp_fid_op(fid, true);
1668}
1669
1670static void mlxsw_sp_fid_dummy_deconfigure(struct mlxsw_sp_fid *fid)
1671{
1672	mlxsw_sp_fid_op(fid, false);
1673}
1674
1675static int mlxsw_sp_fid_dummy_index_alloc(struct mlxsw_sp_fid *fid,
1676					  const void *arg, u16 *p_fid_index)
1677{
1678	*p_fid_index = fid->fid_family->start_index;
1679
1680	return 0;
1681}
1682
1683static bool mlxsw_sp_fid_dummy_compare(const struct mlxsw_sp_fid *fid,
1684				       const void *arg)
1685{
1686	return true;
1687}
1688
1689static int mlxsw_sp_fid_dummy_vni_set(struct mlxsw_sp_fid *fid)
1690{
1691	return -EOPNOTSUPP;
1692}
1693
1694static void mlxsw_sp_fid_dummy_vni_clear(struct mlxsw_sp_fid *fid)
1695{
1696	WARN_ON_ONCE(1);
1697}
1698
1699static int mlxsw_sp_fid_dummy_nve_flood_index_set(struct mlxsw_sp_fid *fid)
1700{
1701	return -EOPNOTSUPP;
1702}
1703
1704static void mlxsw_sp_fid_dummy_nve_flood_index_clear(struct mlxsw_sp_fid *fid)
1705{
1706	WARN_ON_ONCE(1);
1707}
1708
1709static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_dummy_ops = {
1710	.setup			= mlxsw_sp_fid_dummy_setup,
1711	.configure		= mlxsw_sp_fid_dummy_configure,
1712	.deconfigure		= mlxsw_sp_fid_dummy_deconfigure,
1713	.index_alloc		= mlxsw_sp_fid_dummy_index_alloc,
1714	.compare		= mlxsw_sp_fid_dummy_compare,
1715	.vni_set                = mlxsw_sp_fid_dummy_vni_set,
1716	.vni_clear		= mlxsw_sp_fid_dummy_vni_clear,
1717	.nve_flood_index_set	= mlxsw_sp_fid_dummy_nve_flood_index_set,
1718	.nve_flood_index_clear	= mlxsw_sp_fid_dummy_nve_flood_index_clear,
1719	.fid_pack		= mlxsw_sp_fid_pack,
1720};
1721
1722static int mlxsw_sp_fid_8021q_configure(struct mlxsw_sp_fid *fid)
1723{
1724	struct mlxsw_sp_fid_8021q *fid_8021q = mlxsw_sp_fid_8021q_fid(fid);
1725	int err;
1726
1727	err = mlxsw_sp_fid_op(fid, true);
1728	if (err)
1729		return err;
1730
1731	err = mlxsw_sp_fid_vid_to_fid_map(fid, fid_8021q->vid, true, fid->rif);
1732	if (err)
1733		goto err_vid_to_fid_map;
1734
1735	return 0;
1736
1737err_vid_to_fid_map:
1738	mlxsw_sp_fid_op(fid, false);
1739	return err;
1740}
1741
1742static void mlxsw_sp_fid_8021q_deconfigure(struct mlxsw_sp_fid *fid)
1743{
1744	struct mlxsw_sp_fid_8021q *fid_8021q = mlxsw_sp_fid_8021q_fid(fid);
1745
1746	if (fid->vni_valid)
1747		mlxsw_sp_nve_fid_disable(fid->fid_family->mlxsw_sp, fid);
1748
1749	mlxsw_sp_fid_vid_to_fid_map(fid, fid_8021q->vid, false, NULL);
1750	mlxsw_sp_fid_op(fid, false);
1751}
1752
1753static int mlxsw_sp_fid_8021q_port_vid_map(struct mlxsw_sp_fid *fid,
1754					   struct mlxsw_sp_port *mlxsw_sp_port,
1755					   u16 vid)
1756{
1757	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1758	u16 local_port = mlxsw_sp_port->local_port;
1759	int err;
1760
1761	/* In case there are no {Port, VID} => FID mappings on the port,
1762	 * we can use the global VID => FID mapping we created when the
1763	 * FID was configured, otherwise, configure new mapping.
1764	 */
1765	if (mlxsw_sp->fid_core->port_fid_mappings[local_port]) {
1766		err =  __mlxsw_sp_fid_port_vid_map(fid, local_port, vid, true);
1767		if (err)
1768			return err;
1769	}
1770
1771	err = mlxsw_sp_fid_evid_map(fid, local_port, vid, true);
1772	if (err)
1773		goto err_fid_evid_map;
1774
1775	err = mlxsw_sp_fid_port_vid_list_add(fid, mlxsw_sp_port->local_port,
1776					     vid);
1777	if (err)
1778		goto err_port_vid_list_add;
1779
1780	return 0;
1781
1782err_port_vid_list_add:
1783	 mlxsw_sp_fid_evid_map(fid, local_port, vid, false);
1784err_fid_evid_map:
1785	if (mlxsw_sp->fid_core->port_fid_mappings[local_port])
1786		__mlxsw_sp_fid_port_vid_map(fid, local_port, vid, false);
1787	return err;
1788}
1789
1790static void
1791mlxsw_sp_fid_8021q_port_vid_unmap(struct mlxsw_sp_fid *fid,
1792				  struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
1793{
1794	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1795	u16 local_port = mlxsw_sp_port->local_port;
1796
1797	mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid);
1798	mlxsw_sp_fid_evid_map(fid, local_port, vid, false);
1799	if (mlxsw_sp->fid_core->port_fid_mappings[local_port])
1800		__mlxsw_sp_fid_port_vid_map(fid, local_port, vid, false);
1801}
1802
1803static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021q_ops_ctl = {
1804	.setup			= mlxsw_sp_fid_8021q_setup,
1805	.configure		= mlxsw_sp_fid_8021q_configure,
1806	.deconfigure		= mlxsw_sp_fid_8021q_deconfigure,
1807	.index_alloc		= mlxsw_sp_fid_8021d_index_alloc,
1808	.compare		= mlxsw_sp_fid_8021q_compare,
1809	.port_vid_map		= mlxsw_sp_fid_8021q_port_vid_map,
1810	.port_vid_unmap		= mlxsw_sp_fid_8021q_port_vid_unmap,
1811	.vni_set		= mlxsw_sp_fid_8021d_vni_set,
1812	.vni_clear		= mlxsw_sp_fid_8021d_vni_clear,
1813	.nve_flood_index_set	= mlxsw_sp_fid_8021d_nve_flood_index_set,
1814	.nve_flood_index_clear	= mlxsw_sp_fid_8021d_nve_flood_index_clear,
1815	.fdb_clear_offload	= mlxsw_sp_fid_8021q_fdb_clear_offload,
1816	.vid_to_fid_rif_update  = mlxsw_sp_fid_8021q_vid_to_fid_rif_update,
1817	.flood_table_init	= mlxsw_sp_fid_flood_table_init_ctl,
1818	.pgt_size		= mlxsw_sp_fid_8021d_pgt_size,
1819	.fid_mid		= mlxsw_sp_fid_fid_mid_ctl,
1820	.fid_pack		= mlxsw_sp_fid_pack_ctl,
1821};
1822
1823static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021q_ops_cff = {
1824	.setup			= mlxsw_sp_fid_8021q_setup,
1825	.configure		= mlxsw_sp_fid_8021q_configure,
1826	.deconfigure		= mlxsw_sp_fid_8021q_deconfigure,
1827	.index_alloc		= mlxsw_sp_fid_8021d_index_alloc,
1828	.compare		= mlxsw_sp_fid_8021q_compare,
1829	.port_vid_map		= mlxsw_sp_fid_8021q_port_vid_map,
1830	.port_vid_unmap		= mlxsw_sp_fid_8021q_port_vid_unmap,
1831	.vni_set		= mlxsw_sp_fid_8021d_vni_set,
1832	.vni_clear		= mlxsw_sp_fid_8021d_vni_clear,
1833	.nve_flood_index_set	= mlxsw_sp_fid_8021d_nve_flood_index_set,
1834	.nve_flood_index_clear	= mlxsw_sp_fid_8021d_nve_flood_index_clear,
1835	.fdb_clear_offload	= mlxsw_sp_fid_8021q_fdb_clear_offload,
1836	.vid_to_fid_rif_update	= mlxsw_sp_fid_8021q_vid_to_fid_rif_update,
1837	.pgt_size		= mlxsw_sp_fid_8021d_pgt_size,
1838	.fid_mid		= mlxsw_sp_fid_fid_mid_cff,
1839	.fid_pack		= mlxsw_sp_fid_fid_pack_cff,
1840};
1841
1842/* There are 4K-2 802.1Q FIDs */
1843#define MLXSW_SP_FID_8021Q_START	1 /* FID 0 is reserved. */
1844#define MLXSW_SP_FID_8021Q_END		(MLXSW_SP_FID_8021Q_START + \
1845					 MLXSW_SP_FID_8021Q_MAX - 1)
1846
1847/* There are 1K 802.1D FIDs */
1848#define MLXSW_SP_FID_8021D_START	(MLXSW_SP_FID_8021Q_END + 1)
1849#define MLXSW_SP_FID_8021D_END		(MLXSW_SP_FID_8021D_START + \
1850					 MLXSW_SP_FID_8021D_MAX - 1)
1851
1852/* There is one dummy FID */
1853#define MLXSW_SP_FID_DUMMY		(MLXSW_SP_FID_8021D_END + 1)
1854
1855/* There are 11K rFIDs */
1856#define MLXSW_SP_RFID_START		(MLXSW_SP_FID_DUMMY + 1)
1857#define MLXSW_SP_RFID_END		(MLXSW_SP_RFID_START + \
1858					 MLXSW_SP_FID_RFID_MAX - 1)
1859
1860static const struct mlxsw_sp_fid_family mlxsw_sp1_fid_8021q_family = {
1861	.type			= MLXSW_SP_FID_TYPE_8021Q,
1862	.fid_size		= sizeof(struct mlxsw_sp_fid_8021q),
1863	.start_index		= MLXSW_SP_FID_8021Q_START,
1864	.end_index		= MLXSW_SP_FID_8021Q_END,
1865	.flood_profile		= &mlxsw_sp_fid_8021d_flood_profile,
1866	.rif_type		= MLXSW_SP_RIF_TYPE_VLAN,
1867	.ops			= &mlxsw_sp_fid_8021q_ops_ctl,
1868	.flood_rsp              = false,
1869	.bridge_type            = MLXSW_REG_BRIDGE_TYPE_0,
1870	.smpe_index_valid	= false,
1871};
1872
1873static const struct mlxsw_sp_fid_family mlxsw_sp1_fid_8021d_family = {
1874	.type			= MLXSW_SP_FID_TYPE_8021D,
1875	.fid_size		= sizeof(struct mlxsw_sp_fid_8021d),
1876	.start_index		= MLXSW_SP_FID_8021D_START,
1877	.end_index		= MLXSW_SP_FID_8021D_END,
1878	.flood_profile		= &mlxsw_sp_fid_8021d_flood_profile,
1879	.rif_type		= MLXSW_SP_RIF_TYPE_FID,
1880	.ops			= &mlxsw_sp_fid_8021d_ops_ctl,
1881	.bridge_type            = MLXSW_REG_BRIDGE_TYPE_1,
1882	.smpe_index_valid       = false,
1883};
1884
1885static const struct mlxsw_sp_fid_family mlxsw_sp1_fid_dummy_family = {
1886	.type			= MLXSW_SP_FID_TYPE_DUMMY,
1887	.fid_size		= sizeof(struct mlxsw_sp_fid),
1888	.start_index		= MLXSW_SP_FID_DUMMY,
1889	.end_index		= MLXSW_SP_FID_DUMMY,
1890	.ops			= &mlxsw_sp_fid_dummy_ops,
1891	.smpe_index_valid       = false,
1892};
1893
1894static const struct mlxsw_sp_fid_family mlxsw_sp_fid_rfid_family_ctl = {
1895	.type			= MLXSW_SP_FID_TYPE_RFID,
1896	.fid_size		= sizeof(struct mlxsw_sp_fid),
1897	.start_index		= MLXSW_SP_RFID_START,
1898	.end_index		= MLXSW_SP_RFID_END,
1899	.rif_type		= MLXSW_SP_RIF_TYPE_SUBPORT,
1900	.ops			= &mlxsw_sp_fid_rfid_ops_ctl,
1901	.flood_rsp              = true,
1902	.smpe_index_valid       = false,
1903};
1904
1905static const struct mlxsw_sp_fid_family *mlxsw_sp1_fid_family_arr[] = {
1906	[MLXSW_SP_FID_TYPE_8021Q]	= &mlxsw_sp1_fid_8021q_family,
1907	[MLXSW_SP_FID_TYPE_8021D]	= &mlxsw_sp1_fid_8021d_family,
1908	[MLXSW_SP_FID_TYPE_DUMMY]	= &mlxsw_sp1_fid_dummy_family,
1909	[MLXSW_SP_FID_TYPE_RFID]	= &mlxsw_sp_fid_rfid_family_ctl,
1910};
1911
1912static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_8021q_family_ctl = {
1913	.type			= MLXSW_SP_FID_TYPE_8021Q,
1914	.fid_size		= sizeof(struct mlxsw_sp_fid_8021q),
1915	.start_index		= MLXSW_SP_FID_8021Q_START,
1916	.end_index		= MLXSW_SP_FID_8021Q_END,
1917	.flood_profile		= &mlxsw_sp_fid_8021d_flood_profile,
1918	.rif_type		= MLXSW_SP_RIF_TYPE_VLAN,
1919	.ops			= &mlxsw_sp_fid_8021q_ops_ctl,
1920	.flood_rsp              = false,
1921	.bridge_type            = MLXSW_REG_BRIDGE_TYPE_0,
1922	.smpe_index_valid	= true,
1923};
1924
1925static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_8021d_family_ctl = {
1926	.type			= MLXSW_SP_FID_TYPE_8021D,
1927	.fid_size		= sizeof(struct mlxsw_sp_fid_8021d),
1928	.start_index		= MLXSW_SP_FID_8021D_START,
1929	.end_index		= MLXSW_SP_FID_8021D_END,
1930	.flood_profile		= &mlxsw_sp_fid_8021d_flood_profile,
1931	.rif_type		= MLXSW_SP_RIF_TYPE_FID,
1932	.ops			= &mlxsw_sp_fid_8021d_ops_ctl,
1933	.bridge_type            = MLXSW_REG_BRIDGE_TYPE_1,
1934	.smpe_index_valid       = true,
1935};
1936
1937static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_dummy_family = {
1938	.type			= MLXSW_SP_FID_TYPE_DUMMY,
1939	.fid_size		= sizeof(struct mlxsw_sp_fid),
1940	.start_index		= MLXSW_SP_FID_DUMMY,
1941	.end_index		= MLXSW_SP_FID_DUMMY,
1942	.ops			= &mlxsw_sp_fid_dummy_ops,
1943	.smpe_index_valid       = false,
1944};
1945
1946static const struct mlxsw_sp_fid_family *mlxsw_sp2_fid_family_arr_ctl[] = {
1947	[MLXSW_SP_FID_TYPE_8021Q]	= &mlxsw_sp2_fid_8021q_family_ctl,
1948	[MLXSW_SP_FID_TYPE_8021D]	= &mlxsw_sp2_fid_8021d_family_ctl,
1949	[MLXSW_SP_FID_TYPE_DUMMY]	= &mlxsw_sp2_fid_dummy_family,
1950	[MLXSW_SP_FID_TYPE_RFID]	= &mlxsw_sp_fid_rfid_family_ctl,
1951};
1952
1953static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_8021q_family_cff = {
1954	.type			= MLXSW_SP_FID_TYPE_8021Q,
1955	.fid_size		= sizeof(struct mlxsw_sp_fid_8021q),
1956	.start_index		= MLXSW_SP_FID_8021Q_START,
1957	.end_index		= MLXSW_SP_FID_8021Q_END,
1958	.flood_profile		= &mlxsw_sp_fid_8021d_flood_profile,
1959	.rif_type		= MLXSW_SP_RIF_TYPE_VLAN,
1960	.ops			= &mlxsw_sp_fid_8021q_ops_cff,
1961	.smpe_index_valid	= true,
1962};
1963
1964static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_8021d_family_cff = {
1965	.type			= MLXSW_SP_FID_TYPE_8021D,
1966	.fid_size		= sizeof(struct mlxsw_sp_fid_8021d),
1967	.start_index		= MLXSW_SP_FID_8021D_START,
1968	.end_index		= MLXSW_SP_FID_8021D_END,
1969	.flood_profile		= &mlxsw_sp_fid_8021d_flood_profile,
1970	.rif_type		= MLXSW_SP_RIF_TYPE_FID,
1971	.ops			= &mlxsw_sp_fid_8021d_ops_cff,
1972	.smpe_index_valid	= true,
1973};
1974
1975static const struct mlxsw_sp_fid_family mlxsw_sp_fid_rfid_family_cff = {
1976	.type			= MLXSW_SP_FID_TYPE_RFID,
1977	.fid_size		= sizeof(struct mlxsw_sp_fid),
1978	.start_index		= MLXSW_SP_RFID_START,
1979	.end_index		= MLXSW_SP_RFID_END,
1980	.flood_profile		= &mlxsw_sp_fid_rsp_flood_profile_cff,
1981	.rif_type		= MLXSW_SP_RIF_TYPE_SUBPORT,
1982	.ops			= &mlxsw_sp_fid_rfid_ops_cff,
1983	.smpe_index_valid	= false,
1984};
1985
1986static const struct mlxsw_sp_fid_family *mlxsw_sp2_fid_family_arr_cff[] = {
1987	[MLXSW_SP_FID_TYPE_8021Q]	= &mlxsw_sp2_fid_8021q_family_cff,
1988	[MLXSW_SP_FID_TYPE_8021D]	= &mlxsw_sp2_fid_8021d_family_cff,
1989	[MLXSW_SP_FID_TYPE_DUMMY]	= &mlxsw_sp2_fid_dummy_family,
1990	[MLXSW_SP_FID_TYPE_RFID]	= &mlxsw_sp_fid_rfid_family_cff,
1991};
1992
1993static struct mlxsw_sp_fid *mlxsw_sp_fid_lookup(struct mlxsw_sp *mlxsw_sp,
1994						enum mlxsw_sp_fid_type type,
1995						const void *arg)
1996{
1997	struct mlxsw_sp_fid_family *fid_family;
1998	struct mlxsw_sp_fid *fid;
1999
2000	fid_family = mlxsw_sp->fid_core->fid_family_arr[type];
2001	list_for_each_entry(fid, &fid_family->fids_list, list) {
2002		if (!fid->fid_family->ops->compare(fid, arg))
2003			continue;
2004		refcount_inc(&fid->ref_count);
2005		return fid;
2006	}
2007
2008	return NULL;
2009}
2010
2011static struct mlxsw_sp_fid *mlxsw_sp_fid_get(struct mlxsw_sp *mlxsw_sp,
2012					     enum mlxsw_sp_fid_type type,
2013					     const void *arg)
2014{
2015	struct mlxsw_sp_fid_family *fid_family;
2016	struct mlxsw_sp_fid *fid;
2017	u16 fid_index;
2018	int err;
2019
2020	fid = mlxsw_sp_fid_lookup(mlxsw_sp, type, arg);
2021	if (fid)
2022		return fid;
2023
2024	fid_family = mlxsw_sp->fid_core->fid_family_arr[type];
2025	fid = kzalloc(fid_family->fid_size, GFP_KERNEL);
2026	if (!fid)
2027		return ERR_PTR(-ENOMEM);
2028
2029	INIT_LIST_HEAD(&fid->port_vid_list);
2030	fid->fid_family = fid_family;
2031
2032	err = fid->fid_family->ops->index_alloc(fid, arg, &fid_index);
2033	if (err)
2034		goto err_index_alloc;
2035	fid->fid_index = fid_index;
2036	__set_bit(fid_index - fid_family->start_index, fid_family->fids_bitmap);
2037
2038	err = fid->fid_family->ops->setup(fid, arg);
2039	if (err)
2040		goto err_setup;
2041
2042	err = fid->fid_family->ops->configure(fid);
2043	if (err)
2044		goto err_configure;
2045
2046	err = rhashtable_insert_fast(&mlxsw_sp->fid_core->fid_ht, &fid->ht_node,
2047				     mlxsw_sp_fid_ht_params);
2048	if (err)
2049		goto err_rhashtable_insert;
2050
2051	list_add(&fid->list, &fid_family->fids_list);
2052	refcount_set(&fid->ref_count, 1);
2053	return fid;
2054
2055err_rhashtable_insert:
2056	fid->fid_family->ops->deconfigure(fid);
2057err_configure:
2058err_setup:
2059	__clear_bit(fid_index - fid_family->start_index,
2060		    fid_family->fids_bitmap);
2061err_index_alloc:
2062	kfree(fid);
2063	return ERR_PTR(err);
2064}
2065
2066void mlxsw_sp_fid_put(struct mlxsw_sp_fid *fid)
2067{
2068	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
2069	struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
2070
2071	if (!refcount_dec_and_test(&fid->ref_count))
2072		return;
2073
2074	list_del(&fid->list);
2075	rhashtable_remove_fast(&mlxsw_sp->fid_core->fid_ht,
2076			       &fid->ht_node, mlxsw_sp_fid_ht_params);
2077	fid->fid_family->ops->deconfigure(fid);
2078	__clear_bit(fid->fid_index - fid_family->start_index,
2079		    fid_family->fids_bitmap);
2080	WARN_ON_ONCE(!list_empty(&fid->port_vid_list));
2081	kfree(fid);
2082}
2083
2084struct mlxsw_sp_fid *mlxsw_sp_fid_8021q_get(struct mlxsw_sp *mlxsw_sp, u16 vid)
2085{
2086	return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_8021Q, &vid);
2087}
2088
2089struct mlxsw_sp_fid *mlxsw_sp_fid_8021d_get(struct mlxsw_sp *mlxsw_sp,
2090					    int br_ifindex)
2091{
2092	return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_8021D, &br_ifindex);
2093}
2094
2095struct mlxsw_sp_fid *mlxsw_sp_fid_8021q_lookup(struct mlxsw_sp *mlxsw_sp,
2096					       u16 vid)
2097{
2098	return mlxsw_sp_fid_lookup(mlxsw_sp, MLXSW_SP_FID_TYPE_8021Q, &vid);
2099}
2100
2101struct mlxsw_sp_fid *mlxsw_sp_fid_8021d_lookup(struct mlxsw_sp *mlxsw_sp,
2102					       int br_ifindex)
2103{
2104	return mlxsw_sp_fid_lookup(mlxsw_sp, MLXSW_SP_FID_TYPE_8021D,
2105				   &br_ifindex);
2106}
2107
2108struct mlxsw_sp_fid *mlxsw_sp_fid_rfid_get(struct mlxsw_sp *mlxsw_sp,
2109					   u16 rif_index)
2110{
2111	return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_RFID, &rif_index);
2112}
2113
2114struct mlxsw_sp_fid *mlxsw_sp_fid_dummy_get(struct mlxsw_sp *mlxsw_sp)
2115{
2116	return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_DUMMY, NULL);
2117}
2118
2119static int
2120mlxsw_sp_fid_flood_tables_init(struct mlxsw_sp_fid_family *fid_family)
2121{
2122	struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
2123	u16 pgt_size;
2124	int err;
2125	int i;
2126
2127	err = fid_family->ops->pgt_size(fid_family, &pgt_size);
2128	if (err)
2129		return err;
2130
2131	err = mlxsw_sp_pgt_mid_alloc_range(mlxsw_sp, &fid_family->pgt_base,
2132					   pgt_size);
2133	if (err)
2134		return err;
2135
2136	if (!fid_family->flood_profile)
2137		return 0;
2138
2139	for (i = 0; i < fid_family->flood_profile->nr_flood_tables; i++) {
2140		const struct mlxsw_sp_flood_table *flood_table;
2141
2142		flood_table = &fid_family->flood_profile->flood_tables[i];
2143		if (fid_family->ops->flood_table_init) {
2144			err = fid_family->ops->flood_table_init(fid_family,
2145								flood_table);
2146			if (err)
2147				goto err_flood_table_init;
2148		}
2149	}
2150
2151	return 0;
2152
2153err_flood_table_init:
2154	mlxsw_sp_pgt_mid_free_range(mlxsw_sp, fid_family->pgt_base, pgt_size);
2155	return err;
2156}
2157
2158static void
2159mlxsw_sp_fid_flood_tables_fini(struct mlxsw_sp_fid_family *fid_family)
2160{
2161	struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
2162	u16 pgt_size;
2163	int err;
2164
2165	err = fid_family->ops->pgt_size(fid_family, &pgt_size);
2166	if (WARN_ON_ONCE(err))
2167		return;
2168
2169	mlxsw_sp_pgt_mid_free_range(mlxsw_sp, fid_family->pgt_base, pgt_size);
2170}
2171
2172static int mlxsw_sp_fid_family_register(struct mlxsw_sp *mlxsw_sp,
2173					const struct mlxsw_sp_fid_family *tmpl)
2174{
2175	u16 nr_fids = tmpl->end_index - tmpl->start_index + 1;
2176	struct mlxsw_sp_fid_family *fid_family;
2177	int err;
2178
2179	fid_family = kmemdup(tmpl, sizeof(*fid_family), GFP_KERNEL);
2180	if (!fid_family)
2181		return -ENOMEM;
2182
2183	fid_family->mlxsw_sp = mlxsw_sp;
2184	INIT_LIST_HEAD(&fid_family->fids_list);
2185	fid_family->fids_bitmap = bitmap_zalloc(nr_fids, GFP_KERNEL);
2186	if (!fid_family->fids_bitmap) {
2187		err = -ENOMEM;
2188		goto err_alloc_fids_bitmap;
2189	}
2190
2191	if (fid_family->flood_profile) {
2192		err = mlxsw_sp_fid_flood_tables_init(fid_family);
2193		if (err)
2194			goto err_fid_flood_tables_init;
2195	}
2196
2197	mlxsw_sp->fid_core->fid_family_arr[tmpl->type] = fid_family;
2198
2199	return 0;
2200
2201err_fid_flood_tables_init:
2202	bitmap_free(fid_family->fids_bitmap);
2203err_alloc_fids_bitmap:
2204	kfree(fid_family);
2205	return err;
2206}
2207
2208static void
2209mlxsw_sp_fid_family_unregister(struct mlxsw_sp *mlxsw_sp,
2210			       struct mlxsw_sp_fid_family *fid_family)
2211{
2212	mlxsw_sp->fid_core->fid_family_arr[fid_family->type] = NULL;
2213
2214	if (fid_family->flood_profile)
2215		mlxsw_sp_fid_flood_tables_fini(fid_family);
2216
2217	bitmap_free(fid_family->fids_bitmap);
2218	WARN_ON_ONCE(!list_empty(&fid_family->fids_list));
2219	kfree(fid_family);
2220}
2221
2222static int mlxsw_sp_fid_port_init(const struct mlxsw_sp_port *mlxsw_sp_port)
2223{
2224	const enum mlxsw_sp_fid_type type_rfid = MLXSW_SP_FID_TYPE_RFID;
2225	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
2226	struct mlxsw_sp_fid_family *rfid_family;
2227
2228	rfid_family = mlxsw_sp->fid_core->fid_family_arr[type_rfid];
2229	if (rfid_family->ops->fid_port_init)
2230		return rfid_family->ops->fid_port_init(rfid_family,
2231						       mlxsw_sp_port);
2232	return 0;
2233}
2234
2235static void mlxsw_sp_fid_port_fini(const struct mlxsw_sp_port *mlxsw_sp_port)
2236{
2237	const enum mlxsw_sp_fid_type type_rfid = MLXSW_SP_FID_TYPE_RFID;
2238	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
2239	struct mlxsw_sp_fid_family *rfid_family;
2240
2241	rfid_family = mlxsw_sp->fid_core->fid_family_arr[type_rfid];
2242	if (rfid_family->ops->fid_port_fini)
2243		rfid_family->ops->fid_port_fini(rfid_family, mlxsw_sp_port);
2244}
2245
2246int mlxsw_sp_port_fids_init(struct mlxsw_sp_port *mlxsw_sp_port)
2247{
2248	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
2249	int err;
2250
2251	/* Track number of FIDs configured on the port with mapping type
2252	 * PORT_VID_TO_FID, so that we know when to transition the port
2253	 * back to non-virtual (VLAN) mode.
2254	 */
2255	mlxsw_sp->fid_core->port_fid_mappings[mlxsw_sp_port->local_port] = 0;
2256
2257	err = mlxsw_sp_fid_port_init(mlxsw_sp_port);
2258	if (err)
2259		return err;
2260
2261	err = mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, false);
2262	if (err)
2263		goto err_vp_mode_set;
2264
2265	return 0;
2266
2267err_vp_mode_set:
2268	mlxsw_sp_fid_port_fini(mlxsw_sp_port);
2269	return err;
2270}
2271
2272void mlxsw_sp_port_fids_fini(struct mlxsw_sp_port *mlxsw_sp_port)
2273{
2274	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
2275
2276	mlxsw_sp_fid_port_fini(mlxsw_sp_port);
2277	mlxsw_sp->fid_core->port_fid_mappings[mlxsw_sp_port->local_port] = 0;
2278}
2279
2280int mlxsw_sp_fid_port_join_lag(const struct mlxsw_sp_port *mlxsw_sp_port)
2281{
2282	return mlxsw_sp_fid_port_init(mlxsw_sp_port);
2283}
2284
2285void mlxsw_sp_fid_port_leave_lag(const struct mlxsw_sp_port *mlxsw_sp_port)
2286{
2287	mlxsw_sp_fid_port_fini(mlxsw_sp_port);
2288}
2289
2290static int
2291mlxsw_sp_fids_init(struct mlxsw_sp *mlxsw_sp,
2292		   const struct mlxsw_sp_fid_family *fid_family_arr[])
2293{
2294	unsigned int max_ports = mlxsw_core_max_ports(mlxsw_sp->core);
2295	struct mlxsw_sp_fid_core *fid_core;
2296	int err, i;
2297
2298	fid_core = kzalloc(sizeof(*mlxsw_sp->fid_core), GFP_KERNEL);
2299	if (!fid_core)
2300		return -ENOMEM;
2301	mlxsw_sp->fid_core = fid_core;
2302
2303	err = rhashtable_init(&fid_core->fid_ht, &mlxsw_sp_fid_ht_params);
2304	if (err)
2305		goto err_rhashtable_fid_init;
2306
2307	err = rhashtable_init(&fid_core->vni_ht, &mlxsw_sp_fid_vni_ht_params);
2308	if (err)
2309		goto err_rhashtable_vni_init;
2310
2311	fid_core->port_fid_mappings = kcalloc(max_ports, sizeof(unsigned int),
2312					      GFP_KERNEL);
2313	if (!fid_core->port_fid_mappings) {
2314		err = -ENOMEM;
2315		goto err_alloc_port_fid_mappings;
2316	}
2317
2318	for (i = 0; i < MLXSW_SP_FID_TYPE_MAX; i++) {
2319		err = mlxsw_sp_fid_family_register(mlxsw_sp, fid_family_arr[i]);
2320
2321		if (err)
2322			goto err_fid_ops_register;
2323	}
2324
2325	return 0;
2326
2327err_fid_ops_register:
2328	for (i--; i >= 0; i--) {
2329		struct mlxsw_sp_fid_family *fid_family;
2330
2331		fid_family = fid_core->fid_family_arr[i];
2332		mlxsw_sp_fid_family_unregister(mlxsw_sp, fid_family);
2333	}
2334	kfree(fid_core->port_fid_mappings);
2335err_alloc_port_fid_mappings:
2336	rhashtable_destroy(&fid_core->vni_ht);
2337err_rhashtable_vni_init:
2338	rhashtable_destroy(&fid_core->fid_ht);
2339err_rhashtable_fid_init:
2340	kfree(fid_core);
2341	return err;
2342}
2343
2344static void mlxsw_sp_fids_fini(struct mlxsw_sp *mlxsw_sp)
2345{
2346	struct mlxsw_sp_fid_core *fid_core = mlxsw_sp->fid_core;
2347	int i;
2348
2349	for (i = 0; i < MLXSW_SP_FID_TYPE_MAX; i++)
2350		mlxsw_sp_fid_family_unregister(mlxsw_sp,
2351					       fid_core->fid_family_arr[i]);
2352	kfree(fid_core->port_fid_mappings);
2353	rhashtable_destroy(&fid_core->vni_ht);
2354	rhashtable_destroy(&fid_core->fid_ht);
2355	kfree(fid_core);
2356}
2357
2358static int mlxsw_sp1_fids_init(struct mlxsw_sp *mlxsw_sp)
2359{
2360	return mlxsw_sp_fids_init(mlxsw_sp, mlxsw_sp1_fid_family_arr);
2361}
2362
2363const struct mlxsw_sp_fid_core_ops mlxsw_sp1_fid_core_ops = {
2364	.init = mlxsw_sp1_fids_init,
2365	.fini = mlxsw_sp_fids_fini,
2366};
2367
2368static int mlxsw_sp_fid_check_flood_profile_id(struct mlxsw_sp *mlxsw_sp,
2369					       int profile_id)
2370{
2371	u32 max_profiles;
2372
2373	if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_NVE_FLOOD_PRF))
2374		return -EIO;
2375
2376	max_profiles = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_NVE_FLOOD_PRF);
2377	if (WARN_ON_ONCE(!profile_id) ||
2378	    WARN_ON_ONCE(profile_id >= max_profiles))
2379		return -EINVAL;
2380
2381	return 0;
2382}
2383
2384static int
2385mlxsw_sp2_fids_init_flood_table(struct mlxsw_sp *mlxsw_sp,
2386				enum mlxsw_sp_fid_flood_profile_id profile_id,
2387				const struct mlxsw_sp_flood_table *flood_table)
2388{
2389	enum mlxsw_sp_flood_type packet_type = flood_table->packet_type;
2390	const int *sfgc_packet_types;
2391	int err;
2392	int i;
2393
2394	sfgc_packet_types = mlxsw_sp_packet_type_sfgc_types[packet_type];
2395	for (i = 0; i < MLXSW_REG_SFGC_TYPE_MAX; i++) {
2396		char sffp_pl[MLXSW_REG_SFFP_LEN];
2397
2398		if (!sfgc_packet_types[i])
2399			continue;
2400
2401		mlxsw_reg_sffp_pack(sffp_pl, profile_id, i,
2402				    flood_table->table_index);
2403		err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sffp), sffp_pl);
2404		if (err)
2405			return err;
2406	}
2407
2408	return 0;
2409}
2410
2411static int
2412mlxsw_sp2_fids_init_flood_profile(struct mlxsw_sp *mlxsw_sp,
2413				  const struct mlxsw_sp_fid_flood_profile *
2414					flood_profile)
2415{
2416	int err;
2417	int i;
2418
2419	err = mlxsw_sp_fid_check_flood_profile_id(mlxsw_sp,
2420						  flood_profile->profile_id);
2421	if (err)
2422		return err;
2423
2424	for (i = 0; i < flood_profile->nr_flood_tables; i++) {
2425		const struct mlxsw_sp_flood_table *flood_table;
2426
2427		flood_table = &flood_profile->flood_tables[i];
2428		err = mlxsw_sp2_fids_init_flood_table(mlxsw_sp,
2429						      flood_profile->profile_id,
2430						      flood_table);
2431		if (err)
2432			return err;
2433	}
2434
2435	return 0;
2436}
2437
2438static const
2439struct mlxsw_sp_fid_flood_profile *mlxsw_sp_fid_flood_profiles[] = {
2440	&mlxsw_sp_fid_8021d_flood_profile,
2441	&mlxsw_sp_fid_rsp_flood_profile_cff,
2442	&mlxsw_sp_fid_nve_flood_profile_cff,
2443};
2444
2445static int
2446mlxsw_sp2_fids_init_flood_profiles(struct mlxsw_sp *mlxsw_sp)
2447{
2448	int err;
2449	int i;
2450
2451	for (i = 0; i < ARRAY_SIZE(mlxsw_sp_fid_flood_profiles); i++) {
2452		const struct mlxsw_sp_fid_flood_profile *flood_profile;
2453
2454		flood_profile = mlxsw_sp_fid_flood_profiles[i];
2455		err = mlxsw_sp2_fids_init_flood_profile(mlxsw_sp,
2456							flood_profile);
2457		if (err)
2458			return err;
2459	}
2460
2461	return 0;
2462}
2463
2464static int mlxsw_sp2_fids_init_ctl(struct mlxsw_sp *mlxsw_sp)
2465{
2466	return mlxsw_sp_fids_init(mlxsw_sp, mlxsw_sp2_fid_family_arr_ctl);
2467}
2468
2469static int mlxsw_sp2_fids_init_cff(struct mlxsw_sp *mlxsw_sp)
2470{
2471	int err;
2472
2473	err = mlxsw_sp2_fids_init_flood_profiles(mlxsw_sp);
2474	if (err)
2475		return err;
2476
2477	return mlxsw_sp_fids_init(mlxsw_sp, mlxsw_sp2_fid_family_arr_cff);
2478}
2479
2480static int mlxsw_sp2_fids_init(struct mlxsw_sp *mlxsw_sp)
2481{
2482	switch (mlxsw_core_flood_mode(mlxsw_sp->core)) {
2483	case MLXSW_CMD_MBOX_CONFIG_PROFILE_FLOOD_MODE_CONTROLLED:
2484		return mlxsw_sp2_fids_init_ctl(mlxsw_sp);
2485	case MLXSW_CMD_MBOX_CONFIG_PROFILE_FLOOD_MODE_CFF:
2486		return mlxsw_sp2_fids_init_cff(mlxsw_sp);
2487	default:
2488		WARN_ON_ONCE(1);
2489		return -EINVAL;
2490	}
2491}
2492
2493const struct mlxsw_sp_fid_core_ops mlxsw_sp2_fid_core_ops = {
2494	.init = mlxsw_sp2_fids_init,
2495	.fini = mlxsw_sp_fids_fini,
2496};
~/ Read-only file preview.