18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
28c2ecf20Sopenharmony_ci/* Copyright (c) 2017-2018 Mellanox Technologies. All rights reserved */
38c2ecf20Sopenharmony_ci
48c2ecf20Sopenharmony_ci#include <linux/kernel.h>
58c2ecf20Sopenharmony_ci#include <linux/bitops.h>
68c2ecf20Sopenharmony_ci#include <linux/if_vlan.h>
78c2ecf20Sopenharmony_ci#include <linux/if_bridge.h>
88c2ecf20Sopenharmony_ci#include <linux/netdevice.h>
98c2ecf20Sopenharmony_ci#include <linux/rhashtable.h>
108c2ecf20Sopenharmony_ci#include <linux/rtnetlink.h>
118c2ecf20Sopenharmony_ci#include <linux/refcount.h>
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#include "spectrum.h"
148c2ecf20Sopenharmony_ci#include "reg.h"
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_cistruct mlxsw_sp_fid_family;
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_cistruct mlxsw_sp_fid_core {
198c2ecf20Sopenharmony_ci	struct rhashtable fid_ht;
208c2ecf20Sopenharmony_ci	struct rhashtable vni_ht;
218c2ecf20Sopenharmony_ci	struct mlxsw_sp_fid_family *fid_family_arr[MLXSW_SP_FID_TYPE_MAX];
228c2ecf20Sopenharmony_ci	unsigned int *port_fid_mappings;
238c2ecf20Sopenharmony_ci};
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_cistruct mlxsw_sp_fid {
268c2ecf20Sopenharmony_ci	struct list_head list;
278c2ecf20Sopenharmony_ci	struct mlxsw_sp_rif *rif;
288c2ecf20Sopenharmony_ci	refcount_t ref_count;
298c2ecf20Sopenharmony_ci	u16 fid_index;
308c2ecf20Sopenharmony_ci	struct mlxsw_sp_fid_family *fid_family;
318c2ecf20Sopenharmony_ci	struct rhash_head ht_node;
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci	struct rhash_head vni_ht_node;
348c2ecf20Sopenharmony_ci	enum mlxsw_sp_nve_type nve_type;
358c2ecf20Sopenharmony_ci	__be32 vni;
368c2ecf20Sopenharmony_ci	u32 nve_flood_index;
378c2ecf20Sopenharmony_ci	int nve_ifindex;
388c2ecf20Sopenharmony_ci	u8 vni_valid:1,
398c2ecf20Sopenharmony_ci	   nve_flood_index_valid:1;
408c2ecf20Sopenharmony_ci};
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_cistruct mlxsw_sp_fid_8021q {
438c2ecf20Sopenharmony_ci	struct mlxsw_sp_fid common;
448c2ecf20Sopenharmony_ci	u16 vid;
458c2ecf20Sopenharmony_ci};
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_cistruct mlxsw_sp_fid_8021d {
488c2ecf20Sopenharmony_ci	struct mlxsw_sp_fid common;
498c2ecf20Sopenharmony_ci	int br_ifindex;
508c2ecf20Sopenharmony_ci};
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_cistatic const struct rhashtable_params mlxsw_sp_fid_ht_params = {
538c2ecf20Sopenharmony_ci	.key_len = sizeof_field(struct mlxsw_sp_fid, fid_index),
548c2ecf20Sopenharmony_ci	.key_offset = offsetof(struct mlxsw_sp_fid, fid_index),
558c2ecf20Sopenharmony_ci	.head_offset = offsetof(struct mlxsw_sp_fid, ht_node),
568c2ecf20Sopenharmony_ci};
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_cistatic const struct rhashtable_params mlxsw_sp_fid_vni_ht_params = {
598c2ecf20Sopenharmony_ci	.key_len = sizeof_field(struct mlxsw_sp_fid, vni),
608c2ecf20Sopenharmony_ci	.key_offset = offsetof(struct mlxsw_sp_fid, vni),
618c2ecf20Sopenharmony_ci	.head_offset = offsetof(struct mlxsw_sp_fid, vni_ht_node),
628c2ecf20Sopenharmony_ci};
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_cistruct mlxsw_sp_flood_table {
658c2ecf20Sopenharmony_ci	enum mlxsw_sp_flood_type packet_type;
668c2ecf20Sopenharmony_ci	enum mlxsw_reg_sfgc_bridge_type bridge_type;
678c2ecf20Sopenharmony_ci	enum mlxsw_flood_table_type table_type;
688c2ecf20Sopenharmony_ci	int table_index;
698c2ecf20Sopenharmony_ci};
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_cistruct mlxsw_sp_fid_ops {
728c2ecf20Sopenharmony_ci	void (*setup)(struct mlxsw_sp_fid *fid, const void *arg);
738c2ecf20Sopenharmony_ci	int (*configure)(struct mlxsw_sp_fid *fid);
748c2ecf20Sopenharmony_ci	void (*deconfigure)(struct mlxsw_sp_fid *fid);
758c2ecf20Sopenharmony_ci	int (*index_alloc)(struct mlxsw_sp_fid *fid, const void *arg,
768c2ecf20Sopenharmony_ci			   u16 *p_fid_index);
778c2ecf20Sopenharmony_ci	bool (*compare)(const struct mlxsw_sp_fid *fid,
788c2ecf20Sopenharmony_ci			const void *arg);
798c2ecf20Sopenharmony_ci	u16 (*flood_index)(const struct mlxsw_sp_fid *fid);
808c2ecf20Sopenharmony_ci	int (*port_vid_map)(struct mlxsw_sp_fid *fid,
818c2ecf20Sopenharmony_ci			    struct mlxsw_sp_port *port, u16 vid);
828c2ecf20Sopenharmony_ci	void (*port_vid_unmap)(struct mlxsw_sp_fid *fid,
838c2ecf20Sopenharmony_ci			       struct mlxsw_sp_port *port, u16 vid);
848c2ecf20Sopenharmony_ci	int (*vni_set)(struct mlxsw_sp_fid *fid, __be32 vni);
858c2ecf20Sopenharmony_ci	void (*vni_clear)(struct mlxsw_sp_fid *fid);
868c2ecf20Sopenharmony_ci	int (*nve_flood_index_set)(struct mlxsw_sp_fid *fid,
878c2ecf20Sopenharmony_ci				   u32 nve_flood_index);
888c2ecf20Sopenharmony_ci	void (*nve_flood_index_clear)(struct mlxsw_sp_fid *fid);
898c2ecf20Sopenharmony_ci	void (*fdb_clear_offload)(const struct mlxsw_sp_fid *fid,
908c2ecf20Sopenharmony_ci				  const struct net_device *nve_dev);
918c2ecf20Sopenharmony_ci};
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_cistruct mlxsw_sp_fid_family {
948c2ecf20Sopenharmony_ci	enum mlxsw_sp_fid_type type;
958c2ecf20Sopenharmony_ci	size_t fid_size;
968c2ecf20Sopenharmony_ci	u16 start_index;
978c2ecf20Sopenharmony_ci	u16 end_index;
988c2ecf20Sopenharmony_ci	struct list_head fids_list;
998c2ecf20Sopenharmony_ci	unsigned long *fids_bitmap;
1008c2ecf20Sopenharmony_ci	const struct mlxsw_sp_flood_table *flood_tables;
1018c2ecf20Sopenharmony_ci	int nr_flood_tables;
1028c2ecf20Sopenharmony_ci	enum mlxsw_sp_rif_type rif_type;
1038c2ecf20Sopenharmony_ci	const struct mlxsw_sp_fid_ops *ops;
1048c2ecf20Sopenharmony_ci	struct mlxsw_sp *mlxsw_sp;
1058c2ecf20Sopenharmony_ci	u8 lag_vid_valid:1;
1068c2ecf20Sopenharmony_ci};
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_cistatic const int mlxsw_sp_sfgc_uc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = {
1098c2ecf20Sopenharmony_ci	[MLXSW_REG_SFGC_TYPE_UNKNOWN_UNICAST]			= 1,
1108c2ecf20Sopenharmony_ci};
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_cistatic const int mlxsw_sp_sfgc_bc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = {
1138c2ecf20Sopenharmony_ci	[MLXSW_REG_SFGC_TYPE_BROADCAST]				= 1,
1148c2ecf20Sopenharmony_ci	[MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_NON_IP]	= 1,
1158c2ecf20Sopenharmony_ci	[MLXSW_REG_SFGC_TYPE_IPV4_LINK_LOCAL]			= 1,
1168c2ecf20Sopenharmony_ci	[MLXSW_REG_SFGC_TYPE_IPV6_ALL_HOST]			= 1,
1178c2ecf20Sopenharmony_ci	[MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV6]	= 1,
1188c2ecf20Sopenharmony_ci};
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_cistatic const int mlxsw_sp_sfgc_mc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = {
1218c2ecf20Sopenharmony_ci	[MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV4]	= 1,
1228c2ecf20Sopenharmony_ci};
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_cistatic const int *mlxsw_sp_packet_type_sfgc_types[] = {
1258c2ecf20Sopenharmony_ci	[MLXSW_SP_FLOOD_TYPE_UC]	= mlxsw_sp_sfgc_uc_packet_types,
1268c2ecf20Sopenharmony_ci	[MLXSW_SP_FLOOD_TYPE_BC]	= mlxsw_sp_sfgc_bc_packet_types,
1278c2ecf20Sopenharmony_ci	[MLXSW_SP_FLOOD_TYPE_MC]	= mlxsw_sp_sfgc_mc_packet_types,
1288c2ecf20Sopenharmony_ci};
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_cibool mlxsw_sp_fid_is_dummy(struct mlxsw_sp *mlxsw_sp, u16 fid_index)
1318c2ecf20Sopenharmony_ci{
1328c2ecf20Sopenharmony_ci	enum mlxsw_sp_fid_type fid_type = MLXSW_SP_FID_TYPE_DUMMY;
1338c2ecf20Sopenharmony_ci	struct mlxsw_sp_fid_family *fid_family;
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_ci	fid_family = mlxsw_sp->fid_core->fid_family_arr[fid_type];
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci	return fid_family->start_index == fid_index;
1388c2ecf20Sopenharmony_ci}
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_cibool mlxsw_sp_fid_lag_vid_valid(const struct mlxsw_sp_fid *fid)
1418c2ecf20Sopenharmony_ci{
1428c2ecf20Sopenharmony_ci	return fid->fid_family->lag_vid_valid;
1438c2ecf20Sopenharmony_ci}
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_cistruct mlxsw_sp_fid *mlxsw_sp_fid_lookup_by_index(struct mlxsw_sp *mlxsw_sp,
1468c2ecf20Sopenharmony_ci						  u16 fid_index)
1478c2ecf20Sopenharmony_ci{
1488c2ecf20Sopenharmony_ci	struct mlxsw_sp_fid *fid;
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci	fid = rhashtable_lookup_fast(&mlxsw_sp->fid_core->fid_ht, &fid_index,
1518c2ecf20Sopenharmony_ci				     mlxsw_sp_fid_ht_params);
1528c2ecf20Sopenharmony_ci	if (fid)
1538c2ecf20Sopenharmony_ci		refcount_inc(&fid->ref_count);
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci	return fid;
1568c2ecf20Sopenharmony_ci}
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ciint mlxsw_sp_fid_nve_ifindex(const struct mlxsw_sp_fid *fid, int *nve_ifindex)
1598c2ecf20Sopenharmony_ci{
1608c2ecf20Sopenharmony_ci	if (!fid->vni_valid)
1618c2ecf20Sopenharmony_ci		return -EINVAL;
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ci	*nve_ifindex = fid->nve_ifindex;
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci	return 0;
1668c2ecf20Sopenharmony_ci}
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_ciint mlxsw_sp_fid_nve_type(const struct mlxsw_sp_fid *fid,
1698c2ecf20Sopenharmony_ci			  enum mlxsw_sp_nve_type *p_type)
1708c2ecf20Sopenharmony_ci{
1718c2ecf20Sopenharmony_ci	if (!fid->vni_valid)
1728c2ecf20Sopenharmony_ci		return -EINVAL;
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci	*p_type = fid->nve_type;
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci	return 0;
1778c2ecf20Sopenharmony_ci}
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_cistruct mlxsw_sp_fid *mlxsw_sp_fid_lookup_by_vni(struct mlxsw_sp *mlxsw_sp,
1808c2ecf20Sopenharmony_ci						__be32 vni)
1818c2ecf20Sopenharmony_ci{
1828c2ecf20Sopenharmony_ci	struct mlxsw_sp_fid *fid;
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_ci	fid = rhashtable_lookup_fast(&mlxsw_sp->fid_core->vni_ht, &vni,
1858c2ecf20Sopenharmony_ci				     mlxsw_sp_fid_vni_ht_params);
1868c2ecf20Sopenharmony_ci	if (fid)
1878c2ecf20Sopenharmony_ci		refcount_inc(&fid->ref_count);
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci	return fid;
1908c2ecf20Sopenharmony_ci}
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ciint mlxsw_sp_fid_vni(const struct mlxsw_sp_fid *fid, __be32 *vni)
1938c2ecf20Sopenharmony_ci{
1948c2ecf20Sopenharmony_ci	if (!fid->vni_valid)
1958c2ecf20Sopenharmony_ci		return -EINVAL;
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_ci	*vni = fid->vni;
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci	return 0;
2008c2ecf20Sopenharmony_ci}
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_ciint mlxsw_sp_fid_nve_flood_index_set(struct mlxsw_sp_fid *fid,
2038c2ecf20Sopenharmony_ci				     u32 nve_flood_index)
2048c2ecf20Sopenharmony_ci{
2058c2ecf20Sopenharmony_ci	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
2068c2ecf20Sopenharmony_ci	const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
2078c2ecf20Sopenharmony_ci	int err;
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci	if (WARN_ON(!ops->nve_flood_index_set || fid->nve_flood_index_valid))
2108c2ecf20Sopenharmony_ci		return -EINVAL;
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci	err = ops->nve_flood_index_set(fid, nve_flood_index);
2138c2ecf20Sopenharmony_ci	if (err)
2148c2ecf20Sopenharmony_ci		return err;
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_ci	fid->nve_flood_index = nve_flood_index;
2178c2ecf20Sopenharmony_ci	fid->nve_flood_index_valid = true;
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_ci	return 0;
2208c2ecf20Sopenharmony_ci}
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_civoid mlxsw_sp_fid_nve_flood_index_clear(struct mlxsw_sp_fid *fid)
2238c2ecf20Sopenharmony_ci{
2248c2ecf20Sopenharmony_ci	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
2258c2ecf20Sopenharmony_ci	const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_ci	if (WARN_ON(!ops->nve_flood_index_clear || !fid->nve_flood_index_valid))
2288c2ecf20Sopenharmony_ci		return;
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci	fid->nve_flood_index_valid = false;
2318c2ecf20Sopenharmony_ci	ops->nve_flood_index_clear(fid);
2328c2ecf20Sopenharmony_ci}
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_cibool mlxsw_sp_fid_nve_flood_index_is_set(const struct mlxsw_sp_fid *fid)
2358c2ecf20Sopenharmony_ci{
2368c2ecf20Sopenharmony_ci	return fid->nve_flood_index_valid;
2378c2ecf20Sopenharmony_ci}
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_ciint mlxsw_sp_fid_vni_set(struct mlxsw_sp_fid *fid, enum mlxsw_sp_nve_type type,
2408c2ecf20Sopenharmony_ci			 __be32 vni, int nve_ifindex)
2418c2ecf20Sopenharmony_ci{
2428c2ecf20Sopenharmony_ci	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
2438c2ecf20Sopenharmony_ci	const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
2448c2ecf20Sopenharmony_ci	struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
2458c2ecf20Sopenharmony_ci	int err;
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci	if (WARN_ON(!ops->vni_set || fid->vni_valid))
2488c2ecf20Sopenharmony_ci		return -EINVAL;
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	fid->nve_type = type;
2518c2ecf20Sopenharmony_ci	fid->nve_ifindex = nve_ifindex;
2528c2ecf20Sopenharmony_ci	fid->vni = vni;
2538c2ecf20Sopenharmony_ci	err = rhashtable_lookup_insert_fast(&mlxsw_sp->fid_core->vni_ht,
2548c2ecf20Sopenharmony_ci					    &fid->vni_ht_node,
2558c2ecf20Sopenharmony_ci					    mlxsw_sp_fid_vni_ht_params);
2568c2ecf20Sopenharmony_ci	if (err)
2578c2ecf20Sopenharmony_ci		return err;
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_ci	err = ops->vni_set(fid, vni);
2608c2ecf20Sopenharmony_ci	if (err)
2618c2ecf20Sopenharmony_ci		goto err_vni_set;
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_ci	fid->vni_valid = true;
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_ci	return 0;
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_cierr_vni_set:
2688c2ecf20Sopenharmony_ci	rhashtable_remove_fast(&mlxsw_sp->fid_core->vni_ht, &fid->vni_ht_node,
2698c2ecf20Sopenharmony_ci			       mlxsw_sp_fid_vni_ht_params);
2708c2ecf20Sopenharmony_ci	return err;
2718c2ecf20Sopenharmony_ci}
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_civoid mlxsw_sp_fid_vni_clear(struct mlxsw_sp_fid *fid)
2748c2ecf20Sopenharmony_ci{
2758c2ecf20Sopenharmony_ci	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
2768c2ecf20Sopenharmony_ci	const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
2778c2ecf20Sopenharmony_ci	struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
2788c2ecf20Sopenharmony_ci
2798c2ecf20Sopenharmony_ci	if (WARN_ON(!ops->vni_clear || !fid->vni_valid))
2808c2ecf20Sopenharmony_ci		return;
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_ci	fid->vni_valid = false;
2838c2ecf20Sopenharmony_ci	ops->vni_clear(fid);
2848c2ecf20Sopenharmony_ci	rhashtable_remove_fast(&mlxsw_sp->fid_core->vni_ht, &fid->vni_ht_node,
2858c2ecf20Sopenharmony_ci			       mlxsw_sp_fid_vni_ht_params);
2868c2ecf20Sopenharmony_ci}
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_cibool mlxsw_sp_fid_vni_is_set(const struct mlxsw_sp_fid *fid)
2898c2ecf20Sopenharmony_ci{
2908c2ecf20Sopenharmony_ci	return fid->vni_valid;
2918c2ecf20Sopenharmony_ci}
2928c2ecf20Sopenharmony_ci
2938c2ecf20Sopenharmony_civoid mlxsw_sp_fid_fdb_clear_offload(const struct mlxsw_sp_fid *fid,
2948c2ecf20Sopenharmony_ci				    const struct net_device *nve_dev)
2958c2ecf20Sopenharmony_ci{
2968c2ecf20Sopenharmony_ci	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
2978c2ecf20Sopenharmony_ci	const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci	if (ops->fdb_clear_offload)
3008c2ecf20Sopenharmony_ci		ops->fdb_clear_offload(fid, nve_dev);
3018c2ecf20Sopenharmony_ci}
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_cistatic const struct mlxsw_sp_flood_table *
3048c2ecf20Sopenharmony_cimlxsw_sp_fid_flood_table_lookup(const struct mlxsw_sp_fid *fid,
3058c2ecf20Sopenharmony_ci				enum mlxsw_sp_flood_type packet_type)
3068c2ecf20Sopenharmony_ci{
3078c2ecf20Sopenharmony_ci	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
3088c2ecf20Sopenharmony_ci	int i;
3098c2ecf20Sopenharmony_ci
3108c2ecf20Sopenharmony_ci	for (i = 0; i < fid_family->nr_flood_tables; i++) {
3118c2ecf20Sopenharmony_ci		if (fid_family->flood_tables[i].packet_type != packet_type)
3128c2ecf20Sopenharmony_ci			continue;
3138c2ecf20Sopenharmony_ci		return &fid_family->flood_tables[i];
3148c2ecf20Sopenharmony_ci	}
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_ci	return NULL;
3178c2ecf20Sopenharmony_ci}
3188c2ecf20Sopenharmony_ci
3198c2ecf20Sopenharmony_ciint mlxsw_sp_fid_flood_set(struct mlxsw_sp_fid *fid,
3208c2ecf20Sopenharmony_ci			   enum mlxsw_sp_flood_type packet_type, u8 local_port,
3218c2ecf20Sopenharmony_ci			   bool member)
3228c2ecf20Sopenharmony_ci{
3238c2ecf20Sopenharmony_ci	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
3248c2ecf20Sopenharmony_ci	const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
3258c2ecf20Sopenharmony_ci	const struct mlxsw_sp_flood_table *flood_table;
3268c2ecf20Sopenharmony_ci	char *sftr_pl;
3278c2ecf20Sopenharmony_ci	int err;
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_ci	if (WARN_ON(!fid_family->flood_tables || !ops->flood_index))
3308c2ecf20Sopenharmony_ci		return -EINVAL;
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ci	flood_table = mlxsw_sp_fid_flood_table_lookup(fid, packet_type);
3338c2ecf20Sopenharmony_ci	if (!flood_table)
3348c2ecf20Sopenharmony_ci		return -ESRCH;
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_ci	sftr_pl = kmalloc(MLXSW_REG_SFTR_LEN, GFP_KERNEL);
3378c2ecf20Sopenharmony_ci	if (!sftr_pl)
3388c2ecf20Sopenharmony_ci		return -ENOMEM;
3398c2ecf20Sopenharmony_ci
3408c2ecf20Sopenharmony_ci	mlxsw_reg_sftr_pack(sftr_pl, flood_table->table_index,
3418c2ecf20Sopenharmony_ci			    ops->flood_index(fid), flood_table->table_type, 1,
3428c2ecf20Sopenharmony_ci			    local_port, member);
3438c2ecf20Sopenharmony_ci	err = mlxsw_reg_write(fid_family->mlxsw_sp->core, MLXSW_REG(sftr),
3448c2ecf20Sopenharmony_ci			      sftr_pl);
3458c2ecf20Sopenharmony_ci	kfree(sftr_pl);
3468c2ecf20Sopenharmony_ci	return err;
3478c2ecf20Sopenharmony_ci}
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_ciint mlxsw_sp_fid_port_vid_map(struct mlxsw_sp_fid *fid,
3508c2ecf20Sopenharmony_ci			      struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
3518c2ecf20Sopenharmony_ci{
3528c2ecf20Sopenharmony_ci	if (WARN_ON(!fid->fid_family->ops->port_vid_map))
3538c2ecf20Sopenharmony_ci		return -EINVAL;
3548c2ecf20Sopenharmony_ci	return fid->fid_family->ops->port_vid_map(fid, mlxsw_sp_port, vid);
3558c2ecf20Sopenharmony_ci}
3568c2ecf20Sopenharmony_ci
3578c2ecf20Sopenharmony_civoid mlxsw_sp_fid_port_vid_unmap(struct mlxsw_sp_fid *fid,
3588c2ecf20Sopenharmony_ci				 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
3598c2ecf20Sopenharmony_ci{
3608c2ecf20Sopenharmony_ci	fid->fid_family->ops->port_vid_unmap(fid, mlxsw_sp_port, vid);
3618c2ecf20Sopenharmony_ci}
3628c2ecf20Sopenharmony_ci
3638c2ecf20Sopenharmony_ciu16 mlxsw_sp_fid_index(const struct mlxsw_sp_fid *fid)
3648c2ecf20Sopenharmony_ci{
3658c2ecf20Sopenharmony_ci	return fid->fid_index;
3668c2ecf20Sopenharmony_ci}
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_cienum mlxsw_sp_fid_type mlxsw_sp_fid_type(const struct mlxsw_sp_fid *fid)
3698c2ecf20Sopenharmony_ci{
3708c2ecf20Sopenharmony_ci	return fid->fid_family->type;
3718c2ecf20Sopenharmony_ci}
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_civoid mlxsw_sp_fid_rif_set(struct mlxsw_sp_fid *fid, struct mlxsw_sp_rif *rif)
3748c2ecf20Sopenharmony_ci{
3758c2ecf20Sopenharmony_ci	fid->rif = rif;
3768c2ecf20Sopenharmony_ci}
3778c2ecf20Sopenharmony_ci
3788c2ecf20Sopenharmony_cistruct mlxsw_sp_rif *mlxsw_sp_fid_rif(const struct mlxsw_sp_fid *fid)
3798c2ecf20Sopenharmony_ci{
3808c2ecf20Sopenharmony_ci	return fid->rif;
3818c2ecf20Sopenharmony_ci}
3828c2ecf20Sopenharmony_ci
3838c2ecf20Sopenharmony_cienum mlxsw_sp_rif_type
3848c2ecf20Sopenharmony_cimlxsw_sp_fid_type_rif_type(const struct mlxsw_sp *mlxsw_sp,
3858c2ecf20Sopenharmony_ci			   enum mlxsw_sp_fid_type type)
3868c2ecf20Sopenharmony_ci{
3878c2ecf20Sopenharmony_ci	struct mlxsw_sp_fid_core *fid_core = mlxsw_sp->fid_core;
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_ci	return fid_core->fid_family_arr[type]->rif_type;
3908c2ecf20Sopenharmony_ci}
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_cistatic struct mlxsw_sp_fid_8021q *
3938c2ecf20Sopenharmony_cimlxsw_sp_fid_8021q_fid(const struct mlxsw_sp_fid *fid)
3948c2ecf20Sopenharmony_ci{
3958c2ecf20Sopenharmony_ci	return container_of(fid, struct mlxsw_sp_fid_8021q, common);
3968c2ecf20Sopenharmony_ci}
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_ciu16 mlxsw_sp_fid_8021q_vid(const struct mlxsw_sp_fid *fid)
3998c2ecf20Sopenharmony_ci{
4008c2ecf20Sopenharmony_ci	return mlxsw_sp_fid_8021q_fid(fid)->vid;
4018c2ecf20Sopenharmony_ci}
4028c2ecf20Sopenharmony_ci
4038c2ecf20Sopenharmony_cistatic void mlxsw_sp_fid_8021q_setup(struct mlxsw_sp_fid *fid, const void *arg)
4048c2ecf20Sopenharmony_ci{
4058c2ecf20Sopenharmony_ci	u16 vid = *(u16 *) arg;
4068c2ecf20Sopenharmony_ci
4078c2ecf20Sopenharmony_ci	mlxsw_sp_fid_8021q_fid(fid)->vid = vid;
4088c2ecf20Sopenharmony_ci}
4098c2ecf20Sopenharmony_ci
4108c2ecf20Sopenharmony_cistatic enum mlxsw_reg_sfmr_op mlxsw_sp_sfmr_op(bool valid)
4118c2ecf20Sopenharmony_ci{
4128c2ecf20Sopenharmony_ci	return valid ? MLXSW_REG_SFMR_OP_CREATE_FID :
4138c2ecf20Sopenharmony_ci		       MLXSW_REG_SFMR_OP_DESTROY_FID;
4148c2ecf20Sopenharmony_ci}
4158c2ecf20Sopenharmony_ci
4168c2ecf20Sopenharmony_cistatic int mlxsw_sp_fid_op(struct mlxsw_sp *mlxsw_sp, u16 fid_index,
4178c2ecf20Sopenharmony_ci			   u16 fid_offset, bool valid)
4188c2ecf20Sopenharmony_ci{
4198c2ecf20Sopenharmony_ci	char sfmr_pl[MLXSW_REG_SFMR_LEN];
4208c2ecf20Sopenharmony_ci
4218c2ecf20Sopenharmony_ci	mlxsw_reg_sfmr_pack(sfmr_pl, mlxsw_sp_sfmr_op(valid), fid_index,
4228c2ecf20Sopenharmony_ci			    fid_offset);
4238c2ecf20Sopenharmony_ci	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl);
4248c2ecf20Sopenharmony_ci}
4258c2ecf20Sopenharmony_ci
4268c2ecf20Sopenharmony_cistatic int mlxsw_sp_fid_vni_op(struct mlxsw_sp *mlxsw_sp, u16 fid_index,
4278c2ecf20Sopenharmony_ci			       __be32 vni, bool vni_valid, u32 nve_flood_index,
4288c2ecf20Sopenharmony_ci			       bool nve_flood_index_valid)
4298c2ecf20Sopenharmony_ci{
4308c2ecf20Sopenharmony_ci	char sfmr_pl[MLXSW_REG_SFMR_LEN];
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_ci	mlxsw_reg_sfmr_pack(sfmr_pl, MLXSW_REG_SFMR_OP_CREATE_FID, fid_index,
4338c2ecf20Sopenharmony_ci			    0);
4348c2ecf20Sopenharmony_ci	mlxsw_reg_sfmr_vv_set(sfmr_pl, vni_valid);
4358c2ecf20Sopenharmony_ci	mlxsw_reg_sfmr_vni_set(sfmr_pl, be32_to_cpu(vni));
4368c2ecf20Sopenharmony_ci	mlxsw_reg_sfmr_vtfp_set(sfmr_pl, nve_flood_index_valid);
4378c2ecf20Sopenharmony_ci	mlxsw_reg_sfmr_nve_tunnel_flood_ptr_set(sfmr_pl, nve_flood_index);
4388c2ecf20Sopenharmony_ci	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl);
4398c2ecf20Sopenharmony_ci}
4408c2ecf20Sopenharmony_ci
4418c2ecf20Sopenharmony_cistatic int __mlxsw_sp_fid_port_vid_map(struct mlxsw_sp *mlxsw_sp, u16 fid_index,
4428c2ecf20Sopenharmony_ci				       u8 local_port, u16 vid, bool valid)
4438c2ecf20Sopenharmony_ci{
4448c2ecf20Sopenharmony_ci	enum mlxsw_reg_svfa_mt mt = MLXSW_REG_SVFA_MT_PORT_VID_TO_FID;
4458c2ecf20Sopenharmony_ci	char svfa_pl[MLXSW_REG_SVFA_LEN];
4468c2ecf20Sopenharmony_ci
4478c2ecf20Sopenharmony_ci	mlxsw_reg_svfa_pack(svfa_pl, local_port, mt, valid, fid_index, vid);
4488c2ecf20Sopenharmony_ci	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl);
4498c2ecf20Sopenharmony_ci}
4508c2ecf20Sopenharmony_ci
4518c2ecf20Sopenharmony_cistatic struct mlxsw_sp_fid_8021d *
4528c2ecf20Sopenharmony_cimlxsw_sp_fid_8021d_fid(const struct mlxsw_sp_fid *fid)
4538c2ecf20Sopenharmony_ci{
4548c2ecf20Sopenharmony_ci	return container_of(fid, struct mlxsw_sp_fid_8021d, common);
4558c2ecf20Sopenharmony_ci}
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_cistatic void mlxsw_sp_fid_8021d_setup(struct mlxsw_sp_fid *fid, const void *arg)
4588c2ecf20Sopenharmony_ci{
4598c2ecf20Sopenharmony_ci	int br_ifindex = *(int *) arg;
4608c2ecf20Sopenharmony_ci
4618c2ecf20Sopenharmony_ci	mlxsw_sp_fid_8021d_fid(fid)->br_ifindex = br_ifindex;
4628c2ecf20Sopenharmony_ci}
4638c2ecf20Sopenharmony_ci
4648c2ecf20Sopenharmony_cistatic int mlxsw_sp_fid_8021d_configure(struct mlxsw_sp_fid *fid)
4658c2ecf20Sopenharmony_ci{
4668c2ecf20Sopenharmony_ci	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
4678c2ecf20Sopenharmony_ci
4688c2ecf20Sopenharmony_ci	return mlxsw_sp_fid_op(fid_family->mlxsw_sp, fid->fid_index, 0, true);
4698c2ecf20Sopenharmony_ci}
4708c2ecf20Sopenharmony_ci
4718c2ecf20Sopenharmony_cistatic void mlxsw_sp_fid_8021d_deconfigure(struct mlxsw_sp_fid *fid)
4728c2ecf20Sopenharmony_ci{
4738c2ecf20Sopenharmony_ci	if (fid->vni_valid)
4748c2ecf20Sopenharmony_ci		mlxsw_sp_nve_fid_disable(fid->fid_family->mlxsw_sp, fid);
4758c2ecf20Sopenharmony_ci	mlxsw_sp_fid_op(fid->fid_family->mlxsw_sp, fid->fid_index, 0, false);
4768c2ecf20Sopenharmony_ci}
4778c2ecf20Sopenharmony_ci
4788c2ecf20Sopenharmony_cistatic int mlxsw_sp_fid_8021d_index_alloc(struct mlxsw_sp_fid *fid,
4798c2ecf20Sopenharmony_ci					  const void *arg, u16 *p_fid_index)
4808c2ecf20Sopenharmony_ci{
4818c2ecf20Sopenharmony_ci	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
4828c2ecf20Sopenharmony_ci	u16 nr_fids, fid_index;
4838c2ecf20Sopenharmony_ci
4848c2ecf20Sopenharmony_ci	nr_fids = fid_family->end_index - fid_family->start_index + 1;
4858c2ecf20Sopenharmony_ci	fid_index = find_first_zero_bit(fid_family->fids_bitmap, nr_fids);
4868c2ecf20Sopenharmony_ci	if (fid_index == nr_fids)
4878c2ecf20Sopenharmony_ci		return -ENOBUFS;
4888c2ecf20Sopenharmony_ci	*p_fid_index = fid_family->start_index + fid_index;
4898c2ecf20Sopenharmony_ci
4908c2ecf20Sopenharmony_ci	return 0;
4918c2ecf20Sopenharmony_ci}
4928c2ecf20Sopenharmony_ci
4938c2ecf20Sopenharmony_cistatic bool
4948c2ecf20Sopenharmony_cimlxsw_sp_fid_8021d_compare(const struct mlxsw_sp_fid *fid, const void *arg)
4958c2ecf20Sopenharmony_ci{
4968c2ecf20Sopenharmony_ci	int br_ifindex = *(int *) arg;
4978c2ecf20Sopenharmony_ci
4988c2ecf20Sopenharmony_ci	return mlxsw_sp_fid_8021d_fid(fid)->br_ifindex == br_ifindex;
4998c2ecf20Sopenharmony_ci}
5008c2ecf20Sopenharmony_ci
5018c2ecf20Sopenharmony_cistatic u16 mlxsw_sp_fid_8021d_flood_index(const struct mlxsw_sp_fid *fid)
5028c2ecf20Sopenharmony_ci{
5038c2ecf20Sopenharmony_ci	return fid->fid_index - VLAN_N_VID;
5048c2ecf20Sopenharmony_ci}
5058c2ecf20Sopenharmony_ci
5068c2ecf20Sopenharmony_cistatic int mlxsw_sp_port_vp_mode_trans(struct mlxsw_sp_port *mlxsw_sp_port)
5078c2ecf20Sopenharmony_ci{
5088c2ecf20Sopenharmony_ci	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
5098c2ecf20Sopenharmony_ci	struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
5108c2ecf20Sopenharmony_ci	int err;
5118c2ecf20Sopenharmony_ci
5128c2ecf20Sopenharmony_ci	list_for_each_entry(mlxsw_sp_port_vlan, &mlxsw_sp_port->vlans_list,
5138c2ecf20Sopenharmony_ci			    list) {
5148c2ecf20Sopenharmony_ci		struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid;
5158c2ecf20Sopenharmony_ci		u16 vid = mlxsw_sp_port_vlan->vid;
5168c2ecf20Sopenharmony_ci
5178c2ecf20Sopenharmony_ci		if (!fid)
5188c2ecf20Sopenharmony_ci			continue;
5198c2ecf20Sopenharmony_ci
5208c2ecf20Sopenharmony_ci		err = __mlxsw_sp_fid_port_vid_map(mlxsw_sp, fid->fid_index,
5218c2ecf20Sopenharmony_ci						  mlxsw_sp_port->local_port,
5228c2ecf20Sopenharmony_ci						  vid, true);
5238c2ecf20Sopenharmony_ci		if (err)
5248c2ecf20Sopenharmony_ci			goto err_fid_port_vid_map;
5258c2ecf20Sopenharmony_ci	}
5268c2ecf20Sopenharmony_ci
5278c2ecf20Sopenharmony_ci	err = mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, true);
5288c2ecf20Sopenharmony_ci	if (err)
5298c2ecf20Sopenharmony_ci		goto err_port_vp_mode_set;
5308c2ecf20Sopenharmony_ci
5318c2ecf20Sopenharmony_ci	return 0;
5328c2ecf20Sopenharmony_ci
5338c2ecf20Sopenharmony_cierr_port_vp_mode_set:
5348c2ecf20Sopenharmony_cierr_fid_port_vid_map:
5358c2ecf20Sopenharmony_ci	list_for_each_entry_continue_reverse(mlxsw_sp_port_vlan,
5368c2ecf20Sopenharmony_ci					     &mlxsw_sp_port->vlans_list, list) {
5378c2ecf20Sopenharmony_ci		struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid;
5388c2ecf20Sopenharmony_ci		u16 vid = mlxsw_sp_port_vlan->vid;
5398c2ecf20Sopenharmony_ci
5408c2ecf20Sopenharmony_ci		if (!fid)
5418c2ecf20Sopenharmony_ci			continue;
5428c2ecf20Sopenharmony_ci
5438c2ecf20Sopenharmony_ci		__mlxsw_sp_fid_port_vid_map(mlxsw_sp, fid->fid_index,
5448c2ecf20Sopenharmony_ci					    mlxsw_sp_port->local_port, vid,
5458c2ecf20Sopenharmony_ci					    false);
5468c2ecf20Sopenharmony_ci	}
5478c2ecf20Sopenharmony_ci	return err;
5488c2ecf20Sopenharmony_ci}
5498c2ecf20Sopenharmony_ci
5508c2ecf20Sopenharmony_cistatic void mlxsw_sp_port_vlan_mode_trans(struct mlxsw_sp_port *mlxsw_sp_port)
5518c2ecf20Sopenharmony_ci{
5528c2ecf20Sopenharmony_ci	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
5538c2ecf20Sopenharmony_ci	struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
5548c2ecf20Sopenharmony_ci
5558c2ecf20Sopenharmony_ci	mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, false);
5568c2ecf20Sopenharmony_ci
5578c2ecf20Sopenharmony_ci	list_for_each_entry_reverse(mlxsw_sp_port_vlan,
5588c2ecf20Sopenharmony_ci				    &mlxsw_sp_port->vlans_list, list) {
5598c2ecf20Sopenharmony_ci		struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid;
5608c2ecf20Sopenharmony_ci		u16 vid = mlxsw_sp_port_vlan->vid;
5618c2ecf20Sopenharmony_ci
5628c2ecf20Sopenharmony_ci		if (!fid)
5638c2ecf20Sopenharmony_ci			continue;
5648c2ecf20Sopenharmony_ci
5658c2ecf20Sopenharmony_ci		__mlxsw_sp_fid_port_vid_map(mlxsw_sp, fid->fid_index,
5668c2ecf20Sopenharmony_ci					    mlxsw_sp_port->local_port, vid,
5678c2ecf20Sopenharmony_ci					    false);
5688c2ecf20Sopenharmony_ci	}
5698c2ecf20Sopenharmony_ci}
5708c2ecf20Sopenharmony_ci
5718c2ecf20Sopenharmony_cistatic int mlxsw_sp_fid_8021d_port_vid_map(struct mlxsw_sp_fid *fid,
5728c2ecf20Sopenharmony_ci					   struct mlxsw_sp_port *mlxsw_sp_port,
5738c2ecf20Sopenharmony_ci					   u16 vid)
5748c2ecf20Sopenharmony_ci{
5758c2ecf20Sopenharmony_ci	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
5768c2ecf20Sopenharmony_ci	u8 local_port = mlxsw_sp_port->local_port;
5778c2ecf20Sopenharmony_ci	int err;
5788c2ecf20Sopenharmony_ci
5798c2ecf20Sopenharmony_ci	err = __mlxsw_sp_fid_port_vid_map(mlxsw_sp, fid->fid_index,
5808c2ecf20Sopenharmony_ci					  mlxsw_sp_port->local_port, vid, true);
5818c2ecf20Sopenharmony_ci	if (err)
5828c2ecf20Sopenharmony_ci		return err;
5838c2ecf20Sopenharmony_ci
5848c2ecf20Sopenharmony_ci	if (mlxsw_sp->fid_core->port_fid_mappings[local_port]++ == 0) {
5858c2ecf20Sopenharmony_ci		err = mlxsw_sp_port_vp_mode_trans(mlxsw_sp_port);
5868c2ecf20Sopenharmony_ci		if (err)
5878c2ecf20Sopenharmony_ci			goto err_port_vp_mode_trans;
5888c2ecf20Sopenharmony_ci	}
5898c2ecf20Sopenharmony_ci
5908c2ecf20Sopenharmony_ci	return 0;
5918c2ecf20Sopenharmony_ci
5928c2ecf20Sopenharmony_cierr_port_vp_mode_trans:
5938c2ecf20Sopenharmony_ci	mlxsw_sp->fid_core->port_fid_mappings[local_port]--;
5948c2ecf20Sopenharmony_ci	__mlxsw_sp_fid_port_vid_map(mlxsw_sp, fid->fid_index,
5958c2ecf20Sopenharmony_ci				    mlxsw_sp_port->local_port, vid, false);
5968c2ecf20Sopenharmony_ci	return err;
5978c2ecf20Sopenharmony_ci}
5988c2ecf20Sopenharmony_ci
5998c2ecf20Sopenharmony_cistatic void
6008c2ecf20Sopenharmony_cimlxsw_sp_fid_8021d_port_vid_unmap(struct mlxsw_sp_fid *fid,
6018c2ecf20Sopenharmony_ci				  struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
6028c2ecf20Sopenharmony_ci{
6038c2ecf20Sopenharmony_ci	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
6048c2ecf20Sopenharmony_ci	u8 local_port = mlxsw_sp_port->local_port;
6058c2ecf20Sopenharmony_ci
6068c2ecf20Sopenharmony_ci	if (mlxsw_sp->fid_core->port_fid_mappings[local_port] == 1)
6078c2ecf20Sopenharmony_ci		mlxsw_sp_port_vlan_mode_trans(mlxsw_sp_port);
6088c2ecf20Sopenharmony_ci	mlxsw_sp->fid_core->port_fid_mappings[local_port]--;
6098c2ecf20Sopenharmony_ci	__mlxsw_sp_fid_port_vid_map(mlxsw_sp, fid->fid_index,
6108c2ecf20Sopenharmony_ci				    mlxsw_sp_port->local_port, vid, false);
6118c2ecf20Sopenharmony_ci}
6128c2ecf20Sopenharmony_ci
6138c2ecf20Sopenharmony_cistatic int mlxsw_sp_fid_8021d_vni_set(struct mlxsw_sp_fid *fid, __be32 vni)
6148c2ecf20Sopenharmony_ci{
6158c2ecf20Sopenharmony_ci	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
6168c2ecf20Sopenharmony_ci
6178c2ecf20Sopenharmony_ci	return mlxsw_sp_fid_vni_op(fid_family->mlxsw_sp, fid->fid_index, vni,
6188c2ecf20Sopenharmony_ci				   true, fid->nve_flood_index,
6198c2ecf20Sopenharmony_ci				   fid->nve_flood_index_valid);
6208c2ecf20Sopenharmony_ci}
6218c2ecf20Sopenharmony_ci
6228c2ecf20Sopenharmony_cistatic void mlxsw_sp_fid_8021d_vni_clear(struct mlxsw_sp_fid *fid)
6238c2ecf20Sopenharmony_ci{
6248c2ecf20Sopenharmony_ci	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
6258c2ecf20Sopenharmony_ci
6268c2ecf20Sopenharmony_ci	mlxsw_sp_fid_vni_op(fid_family->mlxsw_sp, fid->fid_index, 0, false,
6278c2ecf20Sopenharmony_ci			    fid->nve_flood_index, fid->nve_flood_index_valid);
6288c2ecf20Sopenharmony_ci}
6298c2ecf20Sopenharmony_ci
6308c2ecf20Sopenharmony_cistatic int mlxsw_sp_fid_8021d_nve_flood_index_set(struct mlxsw_sp_fid *fid,
6318c2ecf20Sopenharmony_ci						  u32 nve_flood_index)
6328c2ecf20Sopenharmony_ci{
6338c2ecf20Sopenharmony_ci	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
6348c2ecf20Sopenharmony_ci
6358c2ecf20Sopenharmony_ci	return mlxsw_sp_fid_vni_op(fid_family->mlxsw_sp, fid->fid_index,
6368c2ecf20Sopenharmony_ci				   fid->vni, fid->vni_valid, nve_flood_index,
6378c2ecf20Sopenharmony_ci				   true);
6388c2ecf20Sopenharmony_ci}
6398c2ecf20Sopenharmony_ci
6408c2ecf20Sopenharmony_cistatic void mlxsw_sp_fid_8021d_nve_flood_index_clear(struct mlxsw_sp_fid *fid)
6418c2ecf20Sopenharmony_ci{
6428c2ecf20Sopenharmony_ci	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
6438c2ecf20Sopenharmony_ci
6448c2ecf20Sopenharmony_ci	mlxsw_sp_fid_vni_op(fid_family->mlxsw_sp, fid->fid_index, fid->vni,
6458c2ecf20Sopenharmony_ci			    fid->vni_valid, 0, false);
6468c2ecf20Sopenharmony_ci}
6478c2ecf20Sopenharmony_ci
6488c2ecf20Sopenharmony_cistatic void
6498c2ecf20Sopenharmony_cimlxsw_sp_fid_8021d_fdb_clear_offload(const struct mlxsw_sp_fid *fid,
6508c2ecf20Sopenharmony_ci				     const struct net_device *nve_dev)
6518c2ecf20Sopenharmony_ci{
6528c2ecf20Sopenharmony_ci	br_fdb_clear_offload(nve_dev, 0);
6538c2ecf20Sopenharmony_ci}
6548c2ecf20Sopenharmony_ci
6558c2ecf20Sopenharmony_cistatic const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021d_ops = {
6568c2ecf20Sopenharmony_ci	.setup			= mlxsw_sp_fid_8021d_setup,
6578c2ecf20Sopenharmony_ci	.configure		= mlxsw_sp_fid_8021d_configure,
6588c2ecf20Sopenharmony_ci	.deconfigure		= mlxsw_sp_fid_8021d_deconfigure,
6598c2ecf20Sopenharmony_ci	.index_alloc		= mlxsw_sp_fid_8021d_index_alloc,
6608c2ecf20Sopenharmony_ci	.compare		= mlxsw_sp_fid_8021d_compare,
6618c2ecf20Sopenharmony_ci	.flood_index		= mlxsw_sp_fid_8021d_flood_index,
6628c2ecf20Sopenharmony_ci	.port_vid_map		= mlxsw_sp_fid_8021d_port_vid_map,
6638c2ecf20Sopenharmony_ci	.port_vid_unmap		= mlxsw_sp_fid_8021d_port_vid_unmap,
6648c2ecf20Sopenharmony_ci	.vni_set		= mlxsw_sp_fid_8021d_vni_set,
6658c2ecf20Sopenharmony_ci	.vni_clear		= mlxsw_sp_fid_8021d_vni_clear,
6668c2ecf20Sopenharmony_ci	.nve_flood_index_set	= mlxsw_sp_fid_8021d_nve_flood_index_set,
6678c2ecf20Sopenharmony_ci	.nve_flood_index_clear	= mlxsw_sp_fid_8021d_nve_flood_index_clear,
6688c2ecf20Sopenharmony_ci	.fdb_clear_offload	= mlxsw_sp_fid_8021d_fdb_clear_offload,
6698c2ecf20Sopenharmony_ci};
6708c2ecf20Sopenharmony_ci
6718c2ecf20Sopenharmony_cistatic const struct mlxsw_sp_flood_table mlxsw_sp_fid_8021d_flood_tables[] = {
6728c2ecf20Sopenharmony_ci	{
6738c2ecf20Sopenharmony_ci		.packet_type	= MLXSW_SP_FLOOD_TYPE_UC,
6748c2ecf20Sopenharmony_ci		.bridge_type	= MLXSW_REG_SFGC_BRIDGE_TYPE_VFID,
6758c2ecf20Sopenharmony_ci		.table_type	= MLXSW_REG_SFGC_TABLE_TYPE_FID,
6768c2ecf20Sopenharmony_ci		.table_index	= 0,
6778c2ecf20Sopenharmony_ci	},
6788c2ecf20Sopenharmony_ci	{
6798c2ecf20Sopenharmony_ci		.packet_type	= MLXSW_SP_FLOOD_TYPE_MC,
6808c2ecf20Sopenharmony_ci		.bridge_type	= MLXSW_REG_SFGC_BRIDGE_TYPE_VFID,
6818c2ecf20Sopenharmony_ci		.table_type	= MLXSW_REG_SFGC_TABLE_TYPE_FID,
6828c2ecf20Sopenharmony_ci		.table_index	= 1,
6838c2ecf20Sopenharmony_ci	},
6848c2ecf20Sopenharmony_ci	{
6858c2ecf20Sopenharmony_ci		.packet_type	= MLXSW_SP_FLOOD_TYPE_BC,
6868c2ecf20Sopenharmony_ci		.bridge_type	= MLXSW_REG_SFGC_BRIDGE_TYPE_VFID,
6878c2ecf20Sopenharmony_ci		.table_type	= MLXSW_REG_SFGC_TABLE_TYPE_FID,
6888c2ecf20Sopenharmony_ci		.table_index	= 2,
6898c2ecf20Sopenharmony_ci	},
6908c2ecf20Sopenharmony_ci};
6918c2ecf20Sopenharmony_ci
6928c2ecf20Sopenharmony_ci/* Range and flood configuration must match mlxsw_config_profile */
6938c2ecf20Sopenharmony_cistatic const struct mlxsw_sp_fid_family mlxsw_sp_fid_8021d_family = {
6948c2ecf20Sopenharmony_ci	.type			= MLXSW_SP_FID_TYPE_8021D,
6958c2ecf20Sopenharmony_ci	.fid_size		= sizeof(struct mlxsw_sp_fid_8021d),
6968c2ecf20Sopenharmony_ci	.start_index		= VLAN_N_VID,
6978c2ecf20Sopenharmony_ci	.end_index		= VLAN_N_VID + MLXSW_SP_FID_8021D_MAX - 1,
6988c2ecf20Sopenharmony_ci	.flood_tables		= mlxsw_sp_fid_8021d_flood_tables,
6998c2ecf20Sopenharmony_ci	.nr_flood_tables	= ARRAY_SIZE(mlxsw_sp_fid_8021d_flood_tables),
7008c2ecf20Sopenharmony_ci	.rif_type		= MLXSW_SP_RIF_TYPE_FID,
7018c2ecf20Sopenharmony_ci	.ops			= &mlxsw_sp_fid_8021d_ops,
7028c2ecf20Sopenharmony_ci	.lag_vid_valid		= 1,
7038c2ecf20Sopenharmony_ci};
7048c2ecf20Sopenharmony_ci
7058c2ecf20Sopenharmony_cistatic bool
7068c2ecf20Sopenharmony_cimlxsw_sp_fid_8021q_compare(const struct mlxsw_sp_fid *fid, const void *arg)
7078c2ecf20Sopenharmony_ci{
7088c2ecf20Sopenharmony_ci	u16 vid = *(u16 *) arg;
7098c2ecf20Sopenharmony_ci
7108c2ecf20Sopenharmony_ci	return mlxsw_sp_fid_8021q_fid(fid)->vid == vid;
7118c2ecf20Sopenharmony_ci}
7128c2ecf20Sopenharmony_ci
7138c2ecf20Sopenharmony_cistatic void
7148c2ecf20Sopenharmony_cimlxsw_sp_fid_8021q_fdb_clear_offload(const struct mlxsw_sp_fid *fid,
7158c2ecf20Sopenharmony_ci				     const struct net_device *nve_dev)
7168c2ecf20Sopenharmony_ci{
7178c2ecf20Sopenharmony_ci	br_fdb_clear_offload(nve_dev, mlxsw_sp_fid_8021q_vid(fid));
7188c2ecf20Sopenharmony_ci}
7198c2ecf20Sopenharmony_ci
7208c2ecf20Sopenharmony_cistatic const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021q_emu_ops = {
7218c2ecf20Sopenharmony_ci	.setup			= mlxsw_sp_fid_8021q_setup,
7228c2ecf20Sopenharmony_ci	.configure		= mlxsw_sp_fid_8021d_configure,
7238c2ecf20Sopenharmony_ci	.deconfigure		= mlxsw_sp_fid_8021d_deconfigure,
7248c2ecf20Sopenharmony_ci	.index_alloc		= mlxsw_sp_fid_8021d_index_alloc,
7258c2ecf20Sopenharmony_ci	.compare		= mlxsw_sp_fid_8021q_compare,
7268c2ecf20Sopenharmony_ci	.flood_index		= mlxsw_sp_fid_8021d_flood_index,
7278c2ecf20Sopenharmony_ci	.port_vid_map		= mlxsw_sp_fid_8021d_port_vid_map,
7288c2ecf20Sopenharmony_ci	.port_vid_unmap		= mlxsw_sp_fid_8021d_port_vid_unmap,
7298c2ecf20Sopenharmony_ci	.vni_set		= mlxsw_sp_fid_8021d_vni_set,
7308c2ecf20Sopenharmony_ci	.vni_clear		= mlxsw_sp_fid_8021d_vni_clear,
7318c2ecf20Sopenharmony_ci	.nve_flood_index_set	= mlxsw_sp_fid_8021d_nve_flood_index_set,
7328c2ecf20Sopenharmony_ci	.nve_flood_index_clear	= mlxsw_sp_fid_8021d_nve_flood_index_clear,
7338c2ecf20Sopenharmony_ci	.fdb_clear_offload	= mlxsw_sp_fid_8021q_fdb_clear_offload,
7348c2ecf20Sopenharmony_ci};
7358c2ecf20Sopenharmony_ci
7368c2ecf20Sopenharmony_ci/* There are 4K-2 emulated 802.1Q FIDs, starting right after the 802.1D FIDs */
7378c2ecf20Sopenharmony_ci#define MLXSW_SP_FID_8021Q_EMU_START	(VLAN_N_VID + MLXSW_SP_FID_8021D_MAX)
7388c2ecf20Sopenharmony_ci#define MLXSW_SP_FID_8021Q_EMU_END	(MLXSW_SP_FID_8021Q_EMU_START + \
7398c2ecf20Sopenharmony_ci					 VLAN_VID_MASK - 2)
7408c2ecf20Sopenharmony_ci
7418c2ecf20Sopenharmony_ci/* Range and flood configuration must match mlxsw_config_profile */
7428c2ecf20Sopenharmony_cistatic const struct mlxsw_sp_fid_family mlxsw_sp_fid_8021q_emu_family = {
7438c2ecf20Sopenharmony_ci	.type			= MLXSW_SP_FID_TYPE_8021Q,
7448c2ecf20Sopenharmony_ci	.fid_size		= sizeof(struct mlxsw_sp_fid_8021q),
7458c2ecf20Sopenharmony_ci	.start_index		= MLXSW_SP_FID_8021Q_EMU_START,
7468c2ecf20Sopenharmony_ci	.end_index		= MLXSW_SP_FID_8021Q_EMU_END,
7478c2ecf20Sopenharmony_ci	.flood_tables		= mlxsw_sp_fid_8021d_flood_tables,
7488c2ecf20Sopenharmony_ci	.nr_flood_tables	= ARRAY_SIZE(mlxsw_sp_fid_8021d_flood_tables),
7498c2ecf20Sopenharmony_ci	.rif_type		= MLXSW_SP_RIF_TYPE_VLAN,
7508c2ecf20Sopenharmony_ci	.ops			= &mlxsw_sp_fid_8021q_emu_ops,
7518c2ecf20Sopenharmony_ci	.lag_vid_valid		= 1,
7528c2ecf20Sopenharmony_ci};
7538c2ecf20Sopenharmony_ci
7548c2ecf20Sopenharmony_cistatic int mlxsw_sp_fid_rfid_configure(struct mlxsw_sp_fid *fid)
7558c2ecf20Sopenharmony_ci{
7568c2ecf20Sopenharmony_ci	/* rFIDs are allocated by the device during init */
7578c2ecf20Sopenharmony_ci	return 0;
7588c2ecf20Sopenharmony_ci}
7598c2ecf20Sopenharmony_ci
7608c2ecf20Sopenharmony_cistatic void mlxsw_sp_fid_rfid_deconfigure(struct mlxsw_sp_fid *fid)
7618c2ecf20Sopenharmony_ci{
7628c2ecf20Sopenharmony_ci}
7638c2ecf20Sopenharmony_ci
7648c2ecf20Sopenharmony_cistatic int mlxsw_sp_fid_rfid_index_alloc(struct mlxsw_sp_fid *fid,
7658c2ecf20Sopenharmony_ci					 const void *arg, u16 *p_fid_index)
7668c2ecf20Sopenharmony_ci{
7678c2ecf20Sopenharmony_ci	u16 rif_index = *(u16 *) arg;
7688c2ecf20Sopenharmony_ci
7698c2ecf20Sopenharmony_ci	*p_fid_index = fid->fid_family->start_index + rif_index;
7708c2ecf20Sopenharmony_ci
7718c2ecf20Sopenharmony_ci	return 0;
7728c2ecf20Sopenharmony_ci}
7738c2ecf20Sopenharmony_ci
7748c2ecf20Sopenharmony_cistatic bool mlxsw_sp_fid_rfid_compare(const struct mlxsw_sp_fid *fid,
7758c2ecf20Sopenharmony_ci				      const void *arg)
7768c2ecf20Sopenharmony_ci{
7778c2ecf20Sopenharmony_ci	u16 rif_index = *(u16 *) arg;
7788c2ecf20Sopenharmony_ci
7798c2ecf20Sopenharmony_ci	return fid->fid_index == rif_index + fid->fid_family->start_index;
7808c2ecf20Sopenharmony_ci}
7818c2ecf20Sopenharmony_ci
7828c2ecf20Sopenharmony_cistatic int mlxsw_sp_fid_rfid_port_vid_map(struct mlxsw_sp_fid *fid,
7838c2ecf20Sopenharmony_ci					  struct mlxsw_sp_port *mlxsw_sp_port,
7848c2ecf20Sopenharmony_ci					  u16 vid)
7858c2ecf20Sopenharmony_ci{
7868c2ecf20Sopenharmony_ci	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
7878c2ecf20Sopenharmony_ci	u8 local_port = mlxsw_sp_port->local_port;
7888c2ecf20Sopenharmony_ci	int err;
7898c2ecf20Sopenharmony_ci
7908c2ecf20Sopenharmony_ci	/* We only need to transition the port to virtual mode since
7918c2ecf20Sopenharmony_ci	 * {Port, VID} => FID is done by the firmware upon RIF creation.
7928c2ecf20Sopenharmony_ci	 */
7938c2ecf20Sopenharmony_ci	if (mlxsw_sp->fid_core->port_fid_mappings[local_port]++ == 0) {
7948c2ecf20Sopenharmony_ci		err = mlxsw_sp_port_vp_mode_trans(mlxsw_sp_port);
7958c2ecf20Sopenharmony_ci		if (err)
7968c2ecf20Sopenharmony_ci			goto err_port_vp_mode_trans;
7978c2ecf20Sopenharmony_ci	}
7988c2ecf20Sopenharmony_ci
7998c2ecf20Sopenharmony_ci	return 0;
8008c2ecf20Sopenharmony_ci
8018c2ecf20Sopenharmony_cierr_port_vp_mode_trans:
8028c2ecf20Sopenharmony_ci	mlxsw_sp->fid_core->port_fid_mappings[local_port]--;
8038c2ecf20Sopenharmony_ci	return err;
8048c2ecf20Sopenharmony_ci}
8058c2ecf20Sopenharmony_ci
8068c2ecf20Sopenharmony_cistatic void
8078c2ecf20Sopenharmony_cimlxsw_sp_fid_rfid_port_vid_unmap(struct mlxsw_sp_fid *fid,
8088c2ecf20Sopenharmony_ci				 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
8098c2ecf20Sopenharmony_ci{
8108c2ecf20Sopenharmony_ci	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
8118c2ecf20Sopenharmony_ci	u8 local_port = mlxsw_sp_port->local_port;
8128c2ecf20Sopenharmony_ci
8138c2ecf20Sopenharmony_ci	if (mlxsw_sp->fid_core->port_fid_mappings[local_port] == 1)
8148c2ecf20Sopenharmony_ci		mlxsw_sp_port_vlan_mode_trans(mlxsw_sp_port);
8158c2ecf20Sopenharmony_ci	mlxsw_sp->fid_core->port_fid_mappings[local_port]--;
8168c2ecf20Sopenharmony_ci}
8178c2ecf20Sopenharmony_ci
8188c2ecf20Sopenharmony_cistatic const struct mlxsw_sp_fid_ops mlxsw_sp_fid_rfid_ops = {
8198c2ecf20Sopenharmony_ci	.configure		= mlxsw_sp_fid_rfid_configure,
8208c2ecf20Sopenharmony_ci	.deconfigure		= mlxsw_sp_fid_rfid_deconfigure,
8218c2ecf20Sopenharmony_ci	.index_alloc		= mlxsw_sp_fid_rfid_index_alloc,
8228c2ecf20Sopenharmony_ci	.compare		= mlxsw_sp_fid_rfid_compare,
8238c2ecf20Sopenharmony_ci	.port_vid_map		= mlxsw_sp_fid_rfid_port_vid_map,
8248c2ecf20Sopenharmony_ci	.port_vid_unmap		= mlxsw_sp_fid_rfid_port_vid_unmap,
8258c2ecf20Sopenharmony_ci};
8268c2ecf20Sopenharmony_ci
8278c2ecf20Sopenharmony_ci#define MLXSW_SP_RFID_BASE	(15 * 1024)
8288c2ecf20Sopenharmony_ci#define MLXSW_SP_RFID_MAX	1024
8298c2ecf20Sopenharmony_ci
8308c2ecf20Sopenharmony_cistatic const struct mlxsw_sp_fid_family mlxsw_sp_fid_rfid_family = {
8318c2ecf20Sopenharmony_ci	.type			= MLXSW_SP_FID_TYPE_RFID,
8328c2ecf20Sopenharmony_ci	.fid_size		= sizeof(struct mlxsw_sp_fid),
8338c2ecf20Sopenharmony_ci	.start_index		= MLXSW_SP_RFID_BASE,
8348c2ecf20Sopenharmony_ci	.end_index		= MLXSW_SP_RFID_BASE + MLXSW_SP_RFID_MAX - 1,
8358c2ecf20Sopenharmony_ci	.rif_type		= MLXSW_SP_RIF_TYPE_SUBPORT,
8368c2ecf20Sopenharmony_ci	.ops			= &mlxsw_sp_fid_rfid_ops,
8378c2ecf20Sopenharmony_ci};
8388c2ecf20Sopenharmony_ci
8398c2ecf20Sopenharmony_cistatic int mlxsw_sp_fid_dummy_configure(struct mlxsw_sp_fid *fid)
8408c2ecf20Sopenharmony_ci{
8418c2ecf20Sopenharmony_ci	struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
8428c2ecf20Sopenharmony_ci
8438c2ecf20Sopenharmony_ci	return mlxsw_sp_fid_op(mlxsw_sp, fid->fid_index, 0, true);
8448c2ecf20Sopenharmony_ci}
8458c2ecf20Sopenharmony_ci
8468c2ecf20Sopenharmony_cistatic void mlxsw_sp_fid_dummy_deconfigure(struct mlxsw_sp_fid *fid)
8478c2ecf20Sopenharmony_ci{
8488c2ecf20Sopenharmony_ci	mlxsw_sp_fid_op(fid->fid_family->mlxsw_sp, fid->fid_index, 0, false);
8498c2ecf20Sopenharmony_ci}
8508c2ecf20Sopenharmony_ci
8518c2ecf20Sopenharmony_cistatic int mlxsw_sp_fid_dummy_index_alloc(struct mlxsw_sp_fid *fid,
8528c2ecf20Sopenharmony_ci					  const void *arg, u16 *p_fid_index)
8538c2ecf20Sopenharmony_ci{
8548c2ecf20Sopenharmony_ci	*p_fid_index = fid->fid_family->start_index;
8558c2ecf20Sopenharmony_ci
8568c2ecf20Sopenharmony_ci	return 0;
8578c2ecf20Sopenharmony_ci}
8588c2ecf20Sopenharmony_ci
8598c2ecf20Sopenharmony_cistatic bool mlxsw_sp_fid_dummy_compare(const struct mlxsw_sp_fid *fid,
8608c2ecf20Sopenharmony_ci				       const void *arg)
8618c2ecf20Sopenharmony_ci{
8628c2ecf20Sopenharmony_ci	return true;
8638c2ecf20Sopenharmony_ci}
8648c2ecf20Sopenharmony_ci
8658c2ecf20Sopenharmony_cistatic const struct mlxsw_sp_fid_ops mlxsw_sp_fid_dummy_ops = {
8668c2ecf20Sopenharmony_ci	.configure		= mlxsw_sp_fid_dummy_configure,
8678c2ecf20Sopenharmony_ci	.deconfigure		= mlxsw_sp_fid_dummy_deconfigure,
8688c2ecf20Sopenharmony_ci	.index_alloc		= mlxsw_sp_fid_dummy_index_alloc,
8698c2ecf20Sopenharmony_ci	.compare		= mlxsw_sp_fid_dummy_compare,
8708c2ecf20Sopenharmony_ci};
8718c2ecf20Sopenharmony_ci
8728c2ecf20Sopenharmony_cistatic const struct mlxsw_sp_fid_family mlxsw_sp_fid_dummy_family = {
8738c2ecf20Sopenharmony_ci	.type			= MLXSW_SP_FID_TYPE_DUMMY,
8748c2ecf20Sopenharmony_ci	.fid_size		= sizeof(struct mlxsw_sp_fid),
8758c2ecf20Sopenharmony_ci	.start_index		= VLAN_N_VID - 1,
8768c2ecf20Sopenharmony_ci	.end_index		= VLAN_N_VID - 1,
8778c2ecf20Sopenharmony_ci	.ops			= &mlxsw_sp_fid_dummy_ops,
8788c2ecf20Sopenharmony_ci};
8798c2ecf20Sopenharmony_ci
8808c2ecf20Sopenharmony_cistatic const struct mlxsw_sp_fid_family *mlxsw_sp_fid_family_arr[] = {
8818c2ecf20Sopenharmony_ci	[MLXSW_SP_FID_TYPE_8021Q]	= &mlxsw_sp_fid_8021q_emu_family,
8828c2ecf20Sopenharmony_ci	[MLXSW_SP_FID_TYPE_8021D]	= &mlxsw_sp_fid_8021d_family,
8838c2ecf20Sopenharmony_ci	[MLXSW_SP_FID_TYPE_RFID]	= &mlxsw_sp_fid_rfid_family,
8848c2ecf20Sopenharmony_ci	[MLXSW_SP_FID_TYPE_DUMMY]	= &mlxsw_sp_fid_dummy_family,
8858c2ecf20Sopenharmony_ci};
8868c2ecf20Sopenharmony_ci
8878c2ecf20Sopenharmony_cistatic struct mlxsw_sp_fid *mlxsw_sp_fid_lookup(struct mlxsw_sp *mlxsw_sp,
8888c2ecf20Sopenharmony_ci						enum mlxsw_sp_fid_type type,
8898c2ecf20Sopenharmony_ci						const void *arg)
8908c2ecf20Sopenharmony_ci{
8918c2ecf20Sopenharmony_ci	struct mlxsw_sp_fid_family *fid_family;
8928c2ecf20Sopenharmony_ci	struct mlxsw_sp_fid *fid;
8938c2ecf20Sopenharmony_ci
8948c2ecf20Sopenharmony_ci	fid_family = mlxsw_sp->fid_core->fid_family_arr[type];
8958c2ecf20Sopenharmony_ci	list_for_each_entry(fid, &fid_family->fids_list, list) {
8968c2ecf20Sopenharmony_ci		if (!fid->fid_family->ops->compare(fid, arg))
8978c2ecf20Sopenharmony_ci			continue;
8988c2ecf20Sopenharmony_ci		refcount_inc(&fid->ref_count);
8998c2ecf20Sopenharmony_ci		return fid;
9008c2ecf20Sopenharmony_ci	}
9018c2ecf20Sopenharmony_ci
9028c2ecf20Sopenharmony_ci	return NULL;
9038c2ecf20Sopenharmony_ci}
9048c2ecf20Sopenharmony_ci
9058c2ecf20Sopenharmony_cistatic struct mlxsw_sp_fid *mlxsw_sp_fid_get(struct mlxsw_sp *mlxsw_sp,
9068c2ecf20Sopenharmony_ci					     enum mlxsw_sp_fid_type type,
9078c2ecf20Sopenharmony_ci					     const void *arg)
9088c2ecf20Sopenharmony_ci{
9098c2ecf20Sopenharmony_ci	struct mlxsw_sp_fid_family *fid_family;
9108c2ecf20Sopenharmony_ci	struct mlxsw_sp_fid *fid;
9118c2ecf20Sopenharmony_ci	u16 fid_index;
9128c2ecf20Sopenharmony_ci	int err;
9138c2ecf20Sopenharmony_ci
9148c2ecf20Sopenharmony_ci	fid = mlxsw_sp_fid_lookup(mlxsw_sp, type, arg);
9158c2ecf20Sopenharmony_ci	if (fid)
9168c2ecf20Sopenharmony_ci		return fid;
9178c2ecf20Sopenharmony_ci
9188c2ecf20Sopenharmony_ci	fid_family = mlxsw_sp->fid_core->fid_family_arr[type];
9198c2ecf20Sopenharmony_ci	fid = kzalloc(fid_family->fid_size, GFP_KERNEL);
9208c2ecf20Sopenharmony_ci	if (!fid)
9218c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
9228c2ecf20Sopenharmony_ci	fid->fid_family = fid_family;
9238c2ecf20Sopenharmony_ci
9248c2ecf20Sopenharmony_ci	err = fid->fid_family->ops->index_alloc(fid, arg, &fid_index);
9258c2ecf20Sopenharmony_ci	if (err)
9268c2ecf20Sopenharmony_ci		goto err_index_alloc;
9278c2ecf20Sopenharmony_ci	fid->fid_index = fid_index;
9288c2ecf20Sopenharmony_ci	__set_bit(fid_index - fid_family->start_index, fid_family->fids_bitmap);
9298c2ecf20Sopenharmony_ci
9308c2ecf20Sopenharmony_ci	if (fid->fid_family->ops->setup)
9318c2ecf20Sopenharmony_ci		fid->fid_family->ops->setup(fid, arg);
9328c2ecf20Sopenharmony_ci
9338c2ecf20Sopenharmony_ci	err = fid->fid_family->ops->configure(fid);
9348c2ecf20Sopenharmony_ci	if (err)
9358c2ecf20Sopenharmony_ci		goto err_configure;
9368c2ecf20Sopenharmony_ci
9378c2ecf20Sopenharmony_ci	err = rhashtable_insert_fast(&mlxsw_sp->fid_core->fid_ht, &fid->ht_node,
9388c2ecf20Sopenharmony_ci				     mlxsw_sp_fid_ht_params);
9398c2ecf20Sopenharmony_ci	if (err)
9408c2ecf20Sopenharmony_ci		goto err_rhashtable_insert;
9418c2ecf20Sopenharmony_ci
9428c2ecf20Sopenharmony_ci	list_add(&fid->list, &fid_family->fids_list);
9438c2ecf20Sopenharmony_ci	refcount_set(&fid->ref_count, 1);
9448c2ecf20Sopenharmony_ci	return fid;
9458c2ecf20Sopenharmony_ci
9468c2ecf20Sopenharmony_cierr_rhashtable_insert:
9478c2ecf20Sopenharmony_ci	fid->fid_family->ops->deconfigure(fid);
9488c2ecf20Sopenharmony_cierr_configure:
9498c2ecf20Sopenharmony_ci	__clear_bit(fid_index - fid_family->start_index,
9508c2ecf20Sopenharmony_ci		    fid_family->fids_bitmap);
9518c2ecf20Sopenharmony_cierr_index_alloc:
9528c2ecf20Sopenharmony_ci	kfree(fid);
9538c2ecf20Sopenharmony_ci	return ERR_PTR(err);
9548c2ecf20Sopenharmony_ci}
9558c2ecf20Sopenharmony_ci
9568c2ecf20Sopenharmony_civoid mlxsw_sp_fid_put(struct mlxsw_sp_fid *fid)
9578c2ecf20Sopenharmony_ci{
9588c2ecf20Sopenharmony_ci	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
9598c2ecf20Sopenharmony_ci	struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
9608c2ecf20Sopenharmony_ci
9618c2ecf20Sopenharmony_ci	if (!refcount_dec_and_test(&fid->ref_count))
9628c2ecf20Sopenharmony_ci		return;
9638c2ecf20Sopenharmony_ci
9648c2ecf20Sopenharmony_ci	list_del(&fid->list);
9658c2ecf20Sopenharmony_ci	rhashtable_remove_fast(&mlxsw_sp->fid_core->fid_ht,
9668c2ecf20Sopenharmony_ci			       &fid->ht_node, mlxsw_sp_fid_ht_params);
9678c2ecf20Sopenharmony_ci	fid->fid_family->ops->deconfigure(fid);
9688c2ecf20Sopenharmony_ci	__clear_bit(fid->fid_index - fid_family->start_index,
9698c2ecf20Sopenharmony_ci		    fid_family->fids_bitmap);
9708c2ecf20Sopenharmony_ci	kfree(fid);
9718c2ecf20Sopenharmony_ci}
9728c2ecf20Sopenharmony_ci
9738c2ecf20Sopenharmony_cistruct mlxsw_sp_fid *mlxsw_sp_fid_8021q_get(struct mlxsw_sp *mlxsw_sp, u16 vid)
9748c2ecf20Sopenharmony_ci{
9758c2ecf20Sopenharmony_ci	return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_8021Q, &vid);
9768c2ecf20Sopenharmony_ci}
9778c2ecf20Sopenharmony_ci
9788c2ecf20Sopenharmony_cistruct mlxsw_sp_fid *mlxsw_sp_fid_8021d_get(struct mlxsw_sp *mlxsw_sp,
9798c2ecf20Sopenharmony_ci					    int br_ifindex)
9808c2ecf20Sopenharmony_ci{
9818c2ecf20Sopenharmony_ci	return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_8021D, &br_ifindex);
9828c2ecf20Sopenharmony_ci}
9838c2ecf20Sopenharmony_ci
9848c2ecf20Sopenharmony_cistruct mlxsw_sp_fid *mlxsw_sp_fid_8021q_lookup(struct mlxsw_sp *mlxsw_sp,
9858c2ecf20Sopenharmony_ci					       u16 vid)
9868c2ecf20Sopenharmony_ci{
9878c2ecf20Sopenharmony_ci	return mlxsw_sp_fid_lookup(mlxsw_sp, MLXSW_SP_FID_TYPE_8021Q, &vid);
9888c2ecf20Sopenharmony_ci}
9898c2ecf20Sopenharmony_ci
9908c2ecf20Sopenharmony_cistruct mlxsw_sp_fid *mlxsw_sp_fid_8021d_lookup(struct mlxsw_sp *mlxsw_sp,
9918c2ecf20Sopenharmony_ci					       int br_ifindex)
9928c2ecf20Sopenharmony_ci{
9938c2ecf20Sopenharmony_ci	return mlxsw_sp_fid_lookup(mlxsw_sp, MLXSW_SP_FID_TYPE_8021D,
9948c2ecf20Sopenharmony_ci				   &br_ifindex);
9958c2ecf20Sopenharmony_ci}
9968c2ecf20Sopenharmony_ci
9978c2ecf20Sopenharmony_cistruct mlxsw_sp_fid *mlxsw_sp_fid_rfid_get(struct mlxsw_sp *mlxsw_sp,
9988c2ecf20Sopenharmony_ci					   u16 rif_index)
9998c2ecf20Sopenharmony_ci{
10008c2ecf20Sopenharmony_ci	return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_RFID, &rif_index);
10018c2ecf20Sopenharmony_ci}
10028c2ecf20Sopenharmony_ci
10038c2ecf20Sopenharmony_cistruct mlxsw_sp_fid *mlxsw_sp_fid_dummy_get(struct mlxsw_sp *mlxsw_sp)
10048c2ecf20Sopenharmony_ci{
10058c2ecf20Sopenharmony_ci	return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_DUMMY, NULL);
10068c2ecf20Sopenharmony_ci}
10078c2ecf20Sopenharmony_ci
10088c2ecf20Sopenharmony_cistatic int
10098c2ecf20Sopenharmony_cimlxsw_sp_fid_flood_table_init(struct mlxsw_sp_fid_family *fid_family,
10108c2ecf20Sopenharmony_ci			      const struct mlxsw_sp_flood_table *flood_table)
10118c2ecf20Sopenharmony_ci{
10128c2ecf20Sopenharmony_ci	enum mlxsw_sp_flood_type packet_type = flood_table->packet_type;
10138c2ecf20Sopenharmony_ci	const int *sfgc_packet_types;
10148c2ecf20Sopenharmony_ci	int i;
10158c2ecf20Sopenharmony_ci
10168c2ecf20Sopenharmony_ci	sfgc_packet_types = mlxsw_sp_packet_type_sfgc_types[packet_type];
10178c2ecf20Sopenharmony_ci	for (i = 0; i < MLXSW_REG_SFGC_TYPE_MAX; i++) {
10188c2ecf20Sopenharmony_ci		struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
10198c2ecf20Sopenharmony_ci		char sfgc_pl[MLXSW_REG_SFGC_LEN];
10208c2ecf20Sopenharmony_ci		int err;
10218c2ecf20Sopenharmony_ci
10228c2ecf20Sopenharmony_ci		if (!sfgc_packet_types[i])
10238c2ecf20Sopenharmony_ci			continue;
10248c2ecf20Sopenharmony_ci		mlxsw_reg_sfgc_pack(sfgc_pl, i, flood_table->bridge_type,
10258c2ecf20Sopenharmony_ci				    flood_table->table_type,
10268c2ecf20Sopenharmony_ci				    flood_table->table_index);
10278c2ecf20Sopenharmony_ci		err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfgc), sfgc_pl);
10288c2ecf20Sopenharmony_ci		if (err)
10298c2ecf20Sopenharmony_ci			return err;
10308c2ecf20Sopenharmony_ci	}
10318c2ecf20Sopenharmony_ci
10328c2ecf20Sopenharmony_ci	return 0;
10338c2ecf20Sopenharmony_ci}
10348c2ecf20Sopenharmony_ci
10358c2ecf20Sopenharmony_cistatic int
10368c2ecf20Sopenharmony_cimlxsw_sp_fid_flood_tables_init(struct mlxsw_sp_fid_family *fid_family)
10378c2ecf20Sopenharmony_ci{
10388c2ecf20Sopenharmony_ci	int i;
10398c2ecf20Sopenharmony_ci
10408c2ecf20Sopenharmony_ci	for (i = 0; i < fid_family->nr_flood_tables; i++) {
10418c2ecf20Sopenharmony_ci		const struct mlxsw_sp_flood_table *flood_table;
10428c2ecf20Sopenharmony_ci		int err;
10438c2ecf20Sopenharmony_ci
10448c2ecf20Sopenharmony_ci		flood_table = &fid_family->flood_tables[i];
10458c2ecf20Sopenharmony_ci		err = mlxsw_sp_fid_flood_table_init(fid_family, flood_table);
10468c2ecf20Sopenharmony_ci		if (err)
10478c2ecf20Sopenharmony_ci			return err;
10488c2ecf20Sopenharmony_ci	}
10498c2ecf20Sopenharmony_ci
10508c2ecf20Sopenharmony_ci	return 0;
10518c2ecf20Sopenharmony_ci}
10528c2ecf20Sopenharmony_ci
10538c2ecf20Sopenharmony_cistatic int mlxsw_sp_fid_family_register(struct mlxsw_sp *mlxsw_sp,
10548c2ecf20Sopenharmony_ci					const struct mlxsw_sp_fid_family *tmpl)
10558c2ecf20Sopenharmony_ci{
10568c2ecf20Sopenharmony_ci	u16 nr_fids = tmpl->end_index - tmpl->start_index + 1;
10578c2ecf20Sopenharmony_ci	struct mlxsw_sp_fid_family *fid_family;
10588c2ecf20Sopenharmony_ci	int err;
10598c2ecf20Sopenharmony_ci
10608c2ecf20Sopenharmony_ci	fid_family = kmemdup(tmpl, sizeof(*fid_family), GFP_KERNEL);
10618c2ecf20Sopenharmony_ci	if (!fid_family)
10628c2ecf20Sopenharmony_ci		return -ENOMEM;
10638c2ecf20Sopenharmony_ci
10648c2ecf20Sopenharmony_ci	fid_family->mlxsw_sp = mlxsw_sp;
10658c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&fid_family->fids_list);
10668c2ecf20Sopenharmony_ci	fid_family->fids_bitmap = bitmap_zalloc(nr_fids, GFP_KERNEL);
10678c2ecf20Sopenharmony_ci	if (!fid_family->fids_bitmap) {
10688c2ecf20Sopenharmony_ci		err = -ENOMEM;
10698c2ecf20Sopenharmony_ci		goto err_alloc_fids_bitmap;
10708c2ecf20Sopenharmony_ci	}
10718c2ecf20Sopenharmony_ci
10728c2ecf20Sopenharmony_ci	if (fid_family->flood_tables) {
10738c2ecf20Sopenharmony_ci		err = mlxsw_sp_fid_flood_tables_init(fid_family);
10748c2ecf20Sopenharmony_ci		if (err)
10758c2ecf20Sopenharmony_ci			goto err_fid_flood_tables_init;
10768c2ecf20Sopenharmony_ci	}
10778c2ecf20Sopenharmony_ci
10788c2ecf20Sopenharmony_ci	mlxsw_sp->fid_core->fid_family_arr[tmpl->type] = fid_family;
10798c2ecf20Sopenharmony_ci
10808c2ecf20Sopenharmony_ci	return 0;
10818c2ecf20Sopenharmony_ci
10828c2ecf20Sopenharmony_cierr_fid_flood_tables_init:
10838c2ecf20Sopenharmony_ci	bitmap_free(fid_family->fids_bitmap);
10848c2ecf20Sopenharmony_cierr_alloc_fids_bitmap:
10858c2ecf20Sopenharmony_ci	kfree(fid_family);
10868c2ecf20Sopenharmony_ci	return err;
10878c2ecf20Sopenharmony_ci}
10888c2ecf20Sopenharmony_ci
10898c2ecf20Sopenharmony_cistatic void
10908c2ecf20Sopenharmony_cimlxsw_sp_fid_family_unregister(struct mlxsw_sp *mlxsw_sp,
10918c2ecf20Sopenharmony_ci			       struct mlxsw_sp_fid_family *fid_family)
10928c2ecf20Sopenharmony_ci{
10938c2ecf20Sopenharmony_ci	mlxsw_sp->fid_core->fid_family_arr[fid_family->type] = NULL;
10948c2ecf20Sopenharmony_ci	bitmap_free(fid_family->fids_bitmap);
10958c2ecf20Sopenharmony_ci	WARN_ON_ONCE(!list_empty(&fid_family->fids_list));
10968c2ecf20Sopenharmony_ci	kfree(fid_family);
10978c2ecf20Sopenharmony_ci}
10988c2ecf20Sopenharmony_ci
10998c2ecf20Sopenharmony_ciint mlxsw_sp_port_fids_init(struct mlxsw_sp_port *mlxsw_sp_port)
11008c2ecf20Sopenharmony_ci{
11018c2ecf20Sopenharmony_ci	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
11028c2ecf20Sopenharmony_ci
11038c2ecf20Sopenharmony_ci	/* Track number of FIDs configured on the port with mapping type
11048c2ecf20Sopenharmony_ci	 * PORT_VID_TO_FID, so that we know when to transition the port
11058c2ecf20Sopenharmony_ci	 * back to non-virtual (VLAN) mode.
11068c2ecf20Sopenharmony_ci	 */
11078c2ecf20Sopenharmony_ci	mlxsw_sp->fid_core->port_fid_mappings[mlxsw_sp_port->local_port] = 0;
11088c2ecf20Sopenharmony_ci
11098c2ecf20Sopenharmony_ci	return mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, false);
11108c2ecf20Sopenharmony_ci}
11118c2ecf20Sopenharmony_ci
11128c2ecf20Sopenharmony_civoid mlxsw_sp_port_fids_fini(struct mlxsw_sp_port *mlxsw_sp_port)
11138c2ecf20Sopenharmony_ci{
11148c2ecf20Sopenharmony_ci	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
11158c2ecf20Sopenharmony_ci
11168c2ecf20Sopenharmony_ci	mlxsw_sp->fid_core->port_fid_mappings[mlxsw_sp_port->local_port] = 0;
11178c2ecf20Sopenharmony_ci}
11188c2ecf20Sopenharmony_ci
11198c2ecf20Sopenharmony_ciint mlxsw_sp_fids_init(struct mlxsw_sp *mlxsw_sp)
11208c2ecf20Sopenharmony_ci{
11218c2ecf20Sopenharmony_ci	unsigned int max_ports = mlxsw_core_max_ports(mlxsw_sp->core);
11228c2ecf20Sopenharmony_ci	struct mlxsw_sp_fid_core *fid_core;
11238c2ecf20Sopenharmony_ci	int err, i;
11248c2ecf20Sopenharmony_ci
11258c2ecf20Sopenharmony_ci	fid_core = kzalloc(sizeof(*mlxsw_sp->fid_core), GFP_KERNEL);
11268c2ecf20Sopenharmony_ci	if (!fid_core)
11278c2ecf20Sopenharmony_ci		return -ENOMEM;
11288c2ecf20Sopenharmony_ci	mlxsw_sp->fid_core = fid_core;
11298c2ecf20Sopenharmony_ci
11308c2ecf20Sopenharmony_ci	err = rhashtable_init(&fid_core->fid_ht, &mlxsw_sp_fid_ht_params);
11318c2ecf20Sopenharmony_ci	if (err)
11328c2ecf20Sopenharmony_ci		goto err_rhashtable_fid_init;
11338c2ecf20Sopenharmony_ci
11348c2ecf20Sopenharmony_ci	err = rhashtable_init(&fid_core->vni_ht, &mlxsw_sp_fid_vni_ht_params);
11358c2ecf20Sopenharmony_ci	if (err)
11368c2ecf20Sopenharmony_ci		goto err_rhashtable_vni_init;
11378c2ecf20Sopenharmony_ci
11388c2ecf20Sopenharmony_ci	fid_core->port_fid_mappings = kcalloc(max_ports, sizeof(unsigned int),
11398c2ecf20Sopenharmony_ci					      GFP_KERNEL);
11408c2ecf20Sopenharmony_ci	if (!fid_core->port_fid_mappings) {
11418c2ecf20Sopenharmony_ci		err = -ENOMEM;
11428c2ecf20Sopenharmony_ci		goto err_alloc_port_fid_mappings;
11438c2ecf20Sopenharmony_ci	}
11448c2ecf20Sopenharmony_ci
11458c2ecf20Sopenharmony_ci	for (i = 0; i < MLXSW_SP_FID_TYPE_MAX; i++) {
11468c2ecf20Sopenharmony_ci		err = mlxsw_sp_fid_family_register(mlxsw_sp,
11478c2ecf20Sopenharmony_ci						   mlxsw_sp_fid_family_arr[i]);
11488c2ecf20Sopenharmony_ci
11498c2ecf20Sopenharmony_ci		if (err)
11508c2ecf20Sopenharmony_ci			goto err_fid_ops_register;
11518c2ecf20Sopenharmony_ci	}
11528c2ecf20Sopenharmony_ci
11538c2ecf20Sopenharmony_ci	return 0;
11548c2ecf20Sopenharmony_ci
11558c2ecf20Sopenharmony_cierr_fid_ops_register:
11568c2ecf20Sopenharmony_ci	for (i--; i >= 0; i--) {
11578c2ecf20Sopenharmony_ci		struct mlxsw_sp_fid_family *fid_family;
11588c2ecf20Sopenharmony_ci
11598c2ecf20Sopenharmony_ci		fid_family = fid_core->fid_family_arr[i];
11608c2ecf20Sopenharmony_ci		mlxsw_sp_fid_family_unregister(mlxsw_sp, fid_family);
11618c2ecf20Sopenharmony_ci	}
11628c2ecf20Sopenharmony_ci	kfree(fid_core->port_fid_mappings);
11638c2ecf20Sopenharmony_cierr_alloc_port_fid_mappings:
11648c2ecf20Sopenharmony_ci	rhashtable_destroy(&fid_core->vni_ht);
11658c2ecf20Sopenharmony_cierr_rhashtable_vni_init:
11668c2ecf20Sopenharmony_ci	rhashtable_destroy(&fid_core->fid_ht);
11678c2ecf20Sopenharmony_cierr_rhashtable_fid_init:
11688c2ecf20Sopenharmony_ci	kfree(fid_core);
11698c2ecf20Sopenharmony_ci	return err;
11708c2ecf20Sopenharmony_ci}
11718c2ecf20Sopenharmony_ci
11728c2ecf20Sopenharmony_civoid mlxsw_sp_fids_fini(struct mlxsw_sp *mlxsw_sp)
11738c2ecf20Sopenharmony_ci{
11748c2ecf20Sopenharmony_ci	struct mlxsw_sp_fid_core *fid_core = mlxsw_sp->fid_core;
11758c2ecf20Sopenharmony_ci	int i;
11768c2ecf20Sopenharmony_ci
11778c2ecf20Sopenharmony_ci	for (i = 0; i < MLXSW_SP_FID_TYPE_MAX; i++)
11788c2ecf20Sopenharmony_ci		mlxsw_sp_fid_family_unregister(mlxsw_sp,
11798c2ecf20Sopenharmony_ci					       fid_core->fid_family_arr[i]);
11808c2ecf20Sopenharmony_ci	kfree(fid_core->port_fid_mappings);
11818c2ecf20Sopenharmony_ci	rhashtable_destroy(&fid_core->vni_ht);
11828c2ecf20Sopenharmony_ci	rhashtable_destroy(&fid_core->fid_ht);
11838c2ecf20Sopenharmony_ci	kfree(fid_core);
11848c2ecf20Sopenharmony_ci}
1185