xref: /OK3568_Linux_fs/kernel/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2*4882a593Smuzhiyun /* Copyright (c) 2017-2018 Mellanox Technologies. All rights reserved */
3*4882a593Smuzhiyun 
4*4882a593Smuzhiyun #include <linux/kernel.h>
5*4882a593Smuzhiyun #include <linux/bitops.h>
6*4882a593Smuzhiyun #include <linux/if_vlan.h>
7*4882a593Smuzhiyun #include <linux/if_bridge.h>
8*4882a593Smuzhiyun #include <linux/netdevice.h>
9*4882a593Smuzhiyun #include <linux/rhashtable.h>
10*4882a593Smuzhiyun #include <linux/rtnetlink.h>
11*4882a593Smuzhiyun #include <linux/refcount.h>
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun #include "spectrum.h"
14*4882a593Smuzhiyun #include "reg.h"
15*4882a593Smuzhiyun 
16*4882a593Smuzhiyun struct mlxsw_sp_fid_family;
17*4882a593Smuzhiyun 
18*4882a593Smuzhiyun struct mlxsw_sp_fid_core {
19*4882a593Smuzhiyun 	struct rhashtable fid_ht;
20*4882a593Smuzhiyun 	struct rhashtable vni_ht;
21*4882a593Smuzhiyun 	struct mlxsw_sp_fid_family *fid_family_arr[MLXSW_SP_FID_TYPE_MAX];
22*4882a593Smuzhiyun 	unsigned int *port_fid_mappings;
23*4882a593Smuzhiyun };
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun struct mlxsw_sp_fid {
26*4882a593Smuzhiyun 	struct list_head list;
27*4882a593Smuzhiyun 	struct mlxsw_sp_rif *rif;
28*4882a593Smuzhiyun 	refcount_t ref_count;
29*4882a593Smuzhiyun 	u16 fid_index;
30*4882a593Smuzhiyun 	struct mlxsw_sp_fid_family *fid_family;
31*4882a593Smuzhiyun 	struct rhash_head ht_node;
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun 	struct rhash_head vni_ht_node;
34*4882a593Smuzhiyun 	enum mlxsw_sp_nve_type nve_type;
35*4882a593Smuzhiyun 	__be32 vni;
36*4882a593Smuzhiyun 	u32 nve_flood_index;
37*4882a593Smuzhiyun 	int nve_ifindex;
38*4882a593Smuzhiyun 	u8 vni_valid:1,
39*4882a593Smuzhiyun 	   nve_flood_index_valid:1;
40*4882a593Smuzhiyun };
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun struct mlxsw_sp_fid_8021q {
43*4882a593Smuzhiyun 	struct mlxsw_sp_fid common;
44*4882a593Smuzhiyun 	u16 vid;
45*4882a593Smuzhiyun };
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun struct mlxsw_sp_fid_8021d {
48*4882a593Smuzhiyun 	struct mlxsw_sp_fid common;
49*4882a593Smuzhiyun 	int br_ifindex;
50*4882a593Smuzhiyun };
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun static const struct rhashtable_params mlxsw_sp_fid_ht_params = {
53*4882a593Smuzhiyun 	.key_len = sizeof_field(struct mlxsw_sp_fid, fid_index),
54*4882a593Smuzhiyun 	.key_offset = offsetof(struct mlxsw_sp_fid, fid_index),
55*4882a593Smuzhiyun 	.head_offset = offsetof(struct mlxsw_sp_fid, ht_node),
56*4882a593Smuzhiyun };
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun static const struct rhashtable_params mlxsw_sp_fid_vni_ht_params = {
59*4882a593Smuzhiyun 	.key_len = sizeof_field(struct mlxsw_sp_fid, vni),
60*4882a593Smuzhiyun 	.key_offset = offsetof(struct mlxsw_sp_fid, vni),
61*4882a593Smuzhiyun 	.head_offset = offsetof(struct mlxsw_sp_fid, vni_ht_node),
62*4882a593Smuzhiyun };
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun struct mlxsw_sp_flood_table {
65*4882a593Smuzhiyun 	enum mlxsw_sp_flood_type packet_type;
66*4882a593Smuzhiyun 	enum mlxsw_reg_sfgc_bridge_type bridge_type;
67*4882a593Smuzhiyun 	enum mlxsw_flood_table_type table_type;
68*4882a593Smuzhiyun 	int table_index;
69*4882a593Smuzhiyun };
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun struct mlxsw_sp_fid_ops {
72*4882a593Smuzhiyun 	void (*setup)(struct mlxsw_sp_fid *fid, const void *arg);
73*4882a593Smuzhiyun 	int (*configure)(struct mlxsw_sp_fid *fid);
74*4882a593Smuzhiyun 	void (*deconfigure)(struct mlxsw_sp_fid *fid);
75*4882a593Smuzhiyun 	int (*index_alloc)(struct mlxsw_sp_fid *fid, const void *arg,
76*4882a593Smuzhiyun 			   u16 *p_fid_index);
77*4882a593Smuzhiyun 	bool (*compare)(const struct mlxsw_sp_fid *fid,
78*4882a593Smuzhiyun 			const void *arg);
79*4882a593Smuzhiyun 	u16 (*flood_index)(const struct mlxsw_sp_fid *fid);
80*4882a593Smuzhiyun 	int (*port_vid_map)(struct mlxsw_sp_fid *fid,
81*4882a593Smuzhiyun 			    struct mlxsw_sp_port *port, u16 vid);
82*4882a593Smuzhiyun 	void (*port_vid_unmap)(struct mlxsw_sp_fid *fid,
83*4882a593Smuzhiyun 			       struct mlxsw_sp_port *port, u16 vid);
84*4882a593Smuzhiyun 	int (*vni_set)(struct mlxsw_sp_fid *fid, __be32 vni);
85*4882a593Smuzhiyun 	void (*vni_clear)(struct mlxsw_sp_fid *fid);
86*4882a593Smuzhiyun 	int (*nve_flood_index_set)(struct mlxsw_sp_fid *fid,
87*4882a593Smuzhiyun 				   u32 nve_flood_index);
88*4882a593Smuzhiyun 	void (*nve_flood_index_clear)(struct mlxsw_sp_fid *fid);
89*4882a593Smuzhiyun 	void (*fdb_clear_offload)(const struct mlxsw_sp_fid *fid,
90*4882a593Smuzhiyun 				  const struct net_device *nve_dev);
91*4882a593Smuzhiyun };
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun struct mlxsw_sp_fid_family {
94*4882a593Smuzhiyun 	enum mlxsw_sp_fid_type type;
95*4882a593Smuzhiyun 	size_t fid_size;
96*4882a593Smuzhiyun 	u16 start_index;
97*4882a593Smuzhiyun 	u16 end_index;
98*4882a593Smuzhiyun 	struct list_head fids_list;
99*4882a593Smuzhiyun 	unsigned long *fids_bitmap;
100*4882a593Smuzhiyun 	const struct mlxsw_sp_flood_table *flood_tables;
101*4882a593Smuzhiyun 	int nr_flood_tables;
102*4882a593Smuzhiyun 	enum mlxsw_sp_rif_type rif_type;
103*4882a593Smuzhiyun 	const struct mlxsw_sp_fid_ops *ops;
104*4882a593Smuzhiyun 	struct mlxsw_sp *mlxsw_sp;
105*4882a593Smuzhiyun 	u8 lag_vid_valid:1;
106*4882a593Smuzhiyun };
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun static const int mlxsw_sp_sfgc_uc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = {
109*4882a593Smuzhiyun 	[MLXSW_REG_SFGC_TYPE_UNKNOWN_UNICAST]			= 1,
110*4882a593Smuzhiyun };
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun static const int mlxsw_sp_sfgc_bc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = {
113*4882a593Smuzhiyun 	[MLXSW_REG_SFGC_TYPE_BROADCAST]				= 1,
114*4882a593Smuzhiyun 	[MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_NON_IP]	= 1,
115*4882a593Smuzhiyun 	[MLXSW_REG_SFGC_TYPE_IPV4_LINK_LOCAL]			= 1,
116*4882a593Smuzhiyun 	[MLXSW_REG_SFGC_TYPE_IPV6_ALL_HOST]			= 1,
117*4882a593Smuzhiyun 	[MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV6]	= 1,
118*4882a593Smuzhiyun };
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun static const int mlxsw_sp_sfgc_mc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = {
121*4882a593Smuzhiyun 	[MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV4]	= 1,
122*4882a593Smuzhiyun };
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun static const int *mlxsw_sp_packet_type_sfgc_types[] = {
125*4882a593Smuzhiyun 	[MLXSW_SP_FLOOD_TYPE_UC]	= mlxsw_sp_sfgc_uc_packet_types,
126*4882a593Smuzhiyun 	[MLXSW_SP_FLOOD_TYPE_BC]	= mlxsw_sp_sfgc_bc_packet_types,
127*4882a593Smuzhiyun 	[MLXSW_SP_FLOOD_TYPE_MC]	= mlxsw_sp_sfgc_mc_packet_types,
128*4882a593Smuzhiyun };
129*4882a593Smuzhiyun 
mlxsw_sp_fid_is_dummy(struct mlxsw_sp * mlxsw_sp,u16 fid_index)130*4882a593Smuzhiyun bool mlxsw_sp_fid_is_dummy(struct mlxsw_sp *mlxsw_sp, u16 fid_index)
131*4882a593Smuzhiyun {
132*4882a593Smuzhiyun 	enum mlxsw_sp_fid_type fid_type = MLXSW_SP_FID_TYPE_DUMMY;
133*4882a593Smuzhiyun 	struct mlxsw_sp_fid_family *fid_family;
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun 	fid_family = mlxsw_sp->fid_core->fid_family_arr[fid_type];
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun 	return fid_family->start_index == fid_index;
138*4882a593Smuzhiyun }
139*4882a593Smuzhiyun 
mlxsw_sp_fid_lag_vid_valid(const struct mlxsw_sp_fid * fid)140*4882a593Smuzhiyun bool mlxsw_sp_fid_lag_vid_valid(const struct mlxsw_sp_fid *fid)
141*4882a593Smuzhiyun {
142*4882a593Smuzhiyun 	return fid->fid_family->lag_vid_valid;
143*4882a593Smuzhiyun }
144*4882a593Smuzhiyun 
mlxsw_sp_fid_lookup_by_index(struct mlxsw_sp * mlxsw_sp,u16 fid_index)145*4882a593Smuzhiyun struct mlxsw_sp_fid *mlxsw_sp_fid_lookup_by_index(struct mlxsw_sp *mlxsw_sp,
146*4882a593Smuzhiyun 						  u16 fid_index)
147*4882a593Smuzhiyun {
148*4882a593Smuzhiyun 	struct mlxsw_sp_fid *fid;
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun 	fid = rhashtable_lookup_fast(&mlxsw_sp->fid_core->fid_ht, &fid_index,
151*4882a593Smuzhiyun 				     mlxsw_sp_fid_ht_params);
152*4882a593Smuzhiyun 	if (fid)
153*4882a593Smuzhiyun 		refcount_inc(&fid->ref_count);
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun 	return fid;
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun 
mlxsw_sp_fid_nve_ifindex(const struct mlxsw_sp_fid * fid,int * nve_ifindex)158*4882a593Smuzhiyun int mlxsw_sp_fid_nve_ifindex(const struct mlxsw_sp_fid *fid, int *nve_ifindex)
159*4882a593Smuzhiyun {
160*4882a593Smuzhiyun 	if (!fid->vni_valid)
161*4882a593Smuzhiyun 		return -EINVAL;
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun 	*nve_ifindex = fid->nve_ifindex;
164*4882a593Smuzhiyun 
165*4882a593Smuzhiyun 	return 0;
166*4882a593Smuzhiyun }
167*4882a593Smuzhiyun 
mlxsw_sp_fid_nve_type(const struct mlxsw_sp_fid * fid,enum mlxsw_sp_nve_type * p_type)168*4882a593Smuzhiyun int mlxsw_sp_fid_nve_type(const struct mlxsw_sp_fid *fid,
169*4882a593Smuzhiyun 			  enum mlxsw_sp_nve_type *p_type)
170*4882a593Smuzhiyun {
171*4882a593Smuzhiyun 	if (!fid->vni_valid)
172*4882a593Smuzhiyun 		return -EINVAL;
173*4882a593Smuzhiyun 
174*4882a593Smuzhiyun 	*p_type = fid->nve_type;
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun 	return 0;
177*4882a593Smuzhiyun }
178*4882a593Smuzhiyun 
mlxsw_sp_fid_lookup_by_vni(struct mlxsw_sp * mlxsw_sp,__be32 vni)179*4882a593Smuzhiyun struct mlxsw_sp_fid *mlxsw_sp_fid_lookup_by_vni(struct mlxsw_sp *mlxsw_sp,
180*4882a593Smuzhiyun 						__be32 vni)
181*4882a593Smuzhiyun {
182*4882a593Smuzhiyun 	struct mlxsw_sp_fid *fid;
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun 	fid = rhashtable_lookup_fast(&mlxsw_sp->fid_core->vni_ht, &vni,
185*4882a593Smuzhiyun 				     mlxsw_sp_fid_vni_ht_params);
186*4882a593Smuzhiyun 	if (fid)
187*4882a593Smuzhiyun 		refcount_inc(&fid->ref_count);
188*4882a593Smuzhiyun 
189*4882a593Smuzhiyun 	return fid;
190*4882a593Smuzhiyun }
191*4882a593Smuzhiyun 
mlxsw_sp_fid_vni(const struct mlxsw_sp_fid * fid,__be32 * vni)192*4882a593Smuzhiyun int mlxsw_sp_fid_vni(const struct mlxsw_sp_fid *fid, __be32 *vni)
193*4882a593Smuzhiyun {
194*4882a593Smuzhiyun 	if (!fid->vni_valid)
195*4882a593Smuzhiyun 		return -EINVAL;
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun 	*vni = fid->vni;
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun 	return 0;
200*4882a593Smuzhiyun }
201*4882a593Smuzhiyun 
mlxsw_sp_fid_nve_flood_index_set(struct mlxsw_sp_fid * fid,u32 nve_flood_index)202*4882a593Smuzhiyun int mlxsw_sp_fid_nve_flood_index_set(struct mlxsw_sp_fid *fid,
203*4882a593Smuzhiyun 				     u32 nve_flood_index)
204*4882a593Smuzhiyun {
205*4882a593Smuzhiyun 	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
206*4882a593Smuzhiyun 	const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
207*4882a593Smuzhiyun 	int err;
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun 	if (WARN_ON(!ops->nve_flood_index_set || fid->nve_flood_index_valid))
210*4882a593Smuzhiyun 		return -EINVAL;
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun 	err = ops->nve_flood_index_set(fid, nve_flood_index);
213*4882a593Smuzhiyun 	if (err)
214*4882a593Smuzhiyun 		return err;
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun 	fid->nve_flood_index = nve_flood_index;
217*4882a593Smuzhiyun 	fid->nve_flood_index_valid = true;
218*4882a593Smuzhiyun 
219*4882a593Smuzhiyun 	return 0;
220*4882a593Smuzhiyun }
221*4882a593Smuzhiyun 
mlxsw_sp_fid_nve_flood_index_clear(struct mlxsw_sp_fid * fid)222*4882a593Smuzhiyun void mlxsw_sp_fid_nve_flood_index_clear(struct mlxsw_sp_fid *fid)
223*4882a593Smuzhiyun {
224*4882a593Smuzhiyun 	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
225*4882a593Smuzhiyun 	const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun 	if (WARN_ON(!ops->nve_flood_index_clear || !fid->nve_flood_index_valid))
228*4882a593Smuzhiyun 		return;
229*4882a593Smuzhiyun 
230*4882a593Smuzhiyun 	fid->nve_flood_index_valid = false;
231*4882a593Smuzhiyun 	ops->nve_flood_index_clear(fid);
232*4882a593Smuzhiyun }
233*4882a593Smuzhiyun 
mlxsw_sp_fid_nve_flood_index_is_set(const struct mlxsw_sp_fid * fid)234*4882a593Smuzhiyun bool mlxsw_sp_fid_nve_flood_index_is_set(const struct mlxsw_sp_fid *fid)
235*4882a593Smuzhiyun {
236*4882a593Smuzhiyun 	return fid->nve_flood_index_valid;
237*4882a593Smuzhiyun }
238*4882a593Smuzhiyun 
mlxsw_sp_fid_vni_set(struct mlxsw_sp_fid * fid,enum mlxsw_sp_nve_type type,__be32 vni,int nve_ifindex)239*4882a593Smuzhiyun int mlxsw_sp_fid_vni_set(struct mlxsw_sp_fid *fid, enum mlxsw_sp_nve_type type,
240*4882a593Smuzhiyun 			 __be32 vni, int nve_ifindex)
241*4882a593Smuzhiyun {
242*4882a593Smuzhiyun 	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
243*4882a593Smuzhiyun 	const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
244*4882a593Smuzhiyun 	struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
245*4882a593Smuzhiyun 	int err;
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun 	if (WARN_ON(!ops->vni_set || fid->vni_valid))
248*4882a593Smuzhiyun 		return -EINVAL;
249*4882a593Smuzhiyun 
250*4882a593Smuzhiyun 	fid->nve_type = type;
251*4882a593Smuzhiyun 	fid->nve_ifindex = nve_ifindex;
252*4882a593Smuzhiyun 	fid->vni = vni;
253*4882a593Smuzhiyun 	err = rhashtable_lookup_insert_fast(&mlxsw_sp->fid_core->vni_ht,
254*4882a593Smuzhiyun 					    &fid->vni_ht_node,
255*4882a593Smuzhiyun 					    mlxsw_sp_fid_vni_ht_params);
256*4882a593Smuzhiyun 	if (err)
257*4882a593Smuzhiyun 		return err;
258*4882a593Smuzhiyun 
259*4882a593Smuzhiyun 	err = ops->vni_set(fid, vni);
260*4882a593Smuzhiyun 	if (err)
261*4882a593Smuzhiyun 		goto err_vni_set;
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun 	fid->vni_valid = true;
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun 	return 0;
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun err_vni_set:
268*4882a593Smuzhiyun 	rhashtable_remove_fast(&mlxsw_sp->fid_core->vni_ht, &fid->vni_ht_node,
269*4882a593Smuzhiyun 			       mlxsw_sp_fid_vni_ht_params);
270*4882a593Smuzhiyun 	return err;
271*4882a593Smuzhiyun }
272*4882a593Smuzhiyun 
mlxsw_sp_fid_vni_clear(struct mlxsw_sp_fid * fid)273*4882a593Smuzhiyun void mlxsw_sp_fid_vni_clear(struct mlxsw_sp_fid *fid)
274*4882a593Smuzhiyun {
275*4882a593Smuzhiyun 	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
276*4882a593Smuzhiyun 	const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
277*4882a593Smuzhiyun 	struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
278*4882a593Smuzhiyun 
279*4882a593Smuzhiyun 	if (WARN_ON(!ops->vni_clear || !fid->vni_valid))
280*4882a593Smuzhiyun 		return;
281*4882a593Smuzhiyun 
282*4882a593Smuzhiyun 	fid->vni_valid = false;
283*4882a593Smuzhiyun 	ops->vni_clear(fid);
284*4882a593Smuzhiyun 	rhashtable_remove_fast(&mlxsw_sp->fid_core->vni_ht, &fid->vni_ht_node,
285*4882a593Smuzhiyun 			       mlxsw_sp_fid_vni_ht_params);
286*4882a593Smuzhiyun }
287*4882a593Smuzhiyun 
mlxsw_sp_fid_vni_is_set(const struct mlxsw_sp_fid * fid)288*4882a593Smuzhiyun bool mlxsw_sp_fid_vni_is_set(const struct mlxsw_sp_fid *fid)
289*4882a593Smuzhiyun {
290*4882a593Smuzhiyun 	return fid->vni_valid;
291*4882a593Smuzhiyun }
292*4882a593Smuzhiyun 
mlxsw_sp_fid_fdb_clear_offload(const struct mlxsw_sp_fid * fid,const struct net_device * nve_dev)293*4882a593Smuzhiyun void mlxsw_sp_fid_fdb_clear_offload(const struct mlxsw_sp_fid *fid,
294*4882a593Smuzhiyun 				    const struct net_device *nve_dev)
295*4882a593Smuzhiyun {
296*4882a593Smuzhiyun 	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
297*4882a593Smuzhiyun 	const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
298*4882a593Smuzhiyun 
299*4882a593Smuzhiyun 	if (ops->fdb_clear_offload)
300*4882a593Smuzhiyun 		ops->fdb_clear_offload(fid, nve_dev);
301*4882a593Smuzhiyun }
302*4882a593Smuzhiyun 
303*4882a593Smuzhiyun static const struct mlxsw_sp_flood_table *
mlxsw_sp_fid_flood_table_lookup(const struct mlxsw_sp_fid * fid,enum mlxsw_sp_flood_type packet_type)304*4882a593Smuzhiyun mlxsw_sp_fid_flood_table_lookup(const struct mlxsw_sp_fid *fid,
305*4882a593Smuzhiyun 				enum mlxsw_sp_flood_type packet_type)
306*4882a593Smuzhiyun {
307*4882a593Smuzhiyun 	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
308*4882a593Smuzhiyun 	int i;
309*4882a593Smuzhiyun 
310*4882a593Smuzhiyun 	for (i = 0; i < fid_family->nr_flood_tables; i++) {
311*4882a593Smuzhiyun 		if (fid_family->flood_tables[i].packet_type != packet_type)
312*4882a593Smuzhiyun 			continue;
313*4882a593Smuzhiyun 		return &fid_family->flood_tables[i];
314*4882a593Smuzhiyun 	}
315*4882a593Smuzhiyun 
316*4882a593Smuzhiyun 	return NULL;
317*4882a593Smuzhiyun }
318*4882a593Smuzhiyun 
mlxsw_sp_fid_flood_set(struct mlxsw_sp_fid * fid,enum mlxsw_sp_flood_type packet_type,u8 local_port,bool member)319*4882a593Smuzhiyun int mlxsw_sp_fid_flood_set(struct mlxsw_sp_fid *fid,
320*4882a593Smuzhiyun 			   enum mlxsw_sp_flood_type packet_type, u8 local_port,
321*4882a593Smuzhiyun 			   bool member)
322*4882a593Smuzhiyun {
323*4882a593Smuzhiyun 	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
324*4882a593Smuzhiyun 	const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
325*4882a593Smuzhiyun 	const struct mlxsw_sp_flood_table *flood_table;
326*4882a593Smuzhiyun 	char *sftr_pl;
327*4882a593Smuzhiyun 	int err;
328*4882a593Smuzhiyun 
329*4882a593Smuzhiyun 	if (WARN_ON(!fid_family->flood_tables || !ops->flood_index))
330*4882a593Smuzhiyun 		return -EINVAL;
331*4882a593Smuzhiyun 
332*4882a593Smuzhiyun 	flood_table = mlxsw_sp_fid_flood_table_lookup(fid, packet_type);
333*4882a593Smuzhiyun 	if (!flood_table)
334*4882a593Smuzhiyun 		return -ESRCH;
335*4882a593Smuzhiyun 
336*4882a593Smuzhiyun 	sftr_pl = kmalloc(MLXSW_REG_SFTR_LEN, GFP_KERNEL);
337*4882a593Smuzhiyun 	if (!sftr_pl)
338*4882a593Smuzhiyun 		return -ENOMEM;
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun 	mlxsw_reg_sftr_pack(sftr_pl, flood_table->table_index,
341*4882a593Smuzhiyun 			    ops->flood_index(fid), flood_table->table_type, 1,
342*4882a593Smuzhiyun 			    local_port, member);
343*4882a593Smuzhiyun 	err = mlxsw_reg_write(fid_family->mlxsw_sp->core, MLXSW_REG(sftr),
344*4882a593Smuzhiyun 			      sftr_pl);
345*4882a593Smuzhiyun 	kfree(sftr_pl);
346*4882a593Smuzhiyun 	return err;
347*4882a593Smuzhiyun }
348*4882a593Smuzhiyun 
mlxsw_sp_fid_port_vid_map(struct mlxsw_sp_fid * fid,struct mlxsw_sp_port * mlxsw_sp_port,u16 vid)349*4882a593Smuzhiyun int mlxsw_sp_fid_port_vid_map(struct mlxsw_sp_fid *fid,
350*4882a593Smuzhiyun 			      struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
351*4882a593Smuzhiyun {
352*4882a593Smuzhiyun 	if (WARN_ON(!fid->fid_family->ops->port_vid_map))
353*4882a593Smuzhiyun 		return -EINVAL;
354*4882a593Smuzhiyun 	return fid->fid_family->ops->port_vid_map(fid, mlxsw_sp_port, vid);
355*4882a593Smuzhiyun }
356*4882a593Smuzhiyun 
mlxsw_sp_fid_port_vid_unmap(struct mlxsw_sp_fid * fid,struct mlxsw_sp_port * mlxsw_sp_port,u16 vid)357*4882a593Smuzhiyun void mlxsw_sp_fid_port_vid_unmap(struct mlxsw_sp_fid *fid,
358*4882a593Smuzhiyun 				 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
359*4882a593Smuzhiyun {
360*4882a593Smuzhiyun 	fid->fid_family->ops->port_vid_unmap(fid, mlxsw_sp_port, vid);
361*4882a593Smuzhiyun }
362*4882a593Smuzhiyun 
mlxsw_sp_fid_index(const struct mlxsw_sp_fid * fid)363*4882a593Smuzhiyun u16 mlxsw_sp_fid_index(const struct mlxsw_sp_fid *fid)
364*4882a593Smuzhiyun {
365*4882a593Smuzhiyun 	return fid->fid_index;
366*4882a593Smuzhiyun }
367*4882a593Smuzhiyun 
mlxsw_sp_fid_type(const struct mlxsw_sp_fid * fid)368*4882a593Smuzhiyun enum mlxsw_sp_fid_type mlxsw_sp_fid_type(const struct mlxsw_sp_fid *fid)
369*4882a593Smuzhiyun {
370*4882a593Smuzhiyun 	return fid->fid_family->type;
371*4882a593Smuzhiyun }
372*4882a593Smuzhiyun 
mlxsw_sp_fid_rif_set(struct mlxsw_sp_fid * fid,struct mlxsw_sp_rif * rif)373*4882a593Smuzhiyun void mlxsw_sp_fid_rif_set(struct mlxsw_sp_fid *fid, struct mlxsw_sp_rif *rif)
374*4882a593Smuzhiyun {
375*4882a593Smuzhiyun 	fid->rif = rif;
376*4882a593Smuzhiyun }
377*4882a593Smuzhiyun 
mlxsw_sp_fid_rif(const struct mlxsw_sp_fid * fid)378*4882a593Smuzhiyun struct mlxsw_sp_rif *mlxsw_sp_fid_rif(const struct mlxsw_sp_fid *fid)
379*4882a593Smuzhiyun {
380*4882a593Smuzhiyun 	return fid->rif;
381*4882a593Smuzhiyun }
382*4882a593Smuzhiyun 
383*4882a593Smuzhiyun enum mlxsw_sp_rif_type
mlxsw_sp_fid_type_rif_type(const struct mlxsw_sp * mlxsw_sp,enum mlxsw_sp_fid_type type)384*4882a593Smuzhiyun mlxsw_sp_fid_type_rif_type(const struct mlxsw_sp *mlxsw_sp,
385*4882a593Smuzhiyun 			   enum mlxsw_sp_fid_type type)
386*4882a593Smuzhiyun {
387*4882a593Smuzhiyun 	struct mlxsw_sp_fid_core *fid_core = mlxsw_sp->fid_core;
388*4882a593Smuzhiyun 
389*4882a593Smuzhiyun 	return fid_core->fid_family_arr[type]->rif_type;
390*4882a593Smuzhiyun }
391*4882a593Smuzhiyun 
392*4882a593Smuzhiyun static struct mlxsw_sp_fid_8021q *
mlxsw_sp_fid_8021q_fid(const struct mlxsw_sp_fid * fid)393*4882a593Smuzhiyun mlxsw_sp_fid_8021q_fid(const struct mlxsw_sp_fid *fid)
394*4882a593Smuzhiyun {
395*4882a593Smuzhiyun 	return container_of(fid, struct mlxsw_sp_fid_8021q, common);
396*4882a593Smuzhiyun }
397*4882a593Smuzhiyun 
mlxsw_sp_fid_8021q_vid(const struct mlxsw_sp_fid * fid)398*4882a593Smuzhiyun u16 mlxsw_sp_fid_8021q_vid(const struct mlxsw_sp_fid *fid)
399*4882a593Smuzhiyun {
400*4882a593Smuzhiyun 	return mlxsw_sp_fid_8021q_fid(fid)->vid;
401*4882a593Smuzhiyun }
402*4882a593Smuzhiyun 
mlxsw_sp_fid_8021q_setup(struct mlxsw_sp_fid * fid,const void * arg)403*4882a593Smuzhiyun static void mlxsw_sp_fid_8021q_setup(struct mlxsw_sp_fid *fid, const void *arg)
404*4882a593Smuzhiyun {
405*4882a593Smuzhiyun 	u16 vid = *(u16 *) arg;
406*4882a593Smuzhiyun 
407*4882a593Smuzhiyun 	mlxsw_sp_fid_8021q_fid(fid)->vid = vid;
408*4882a593Smuzhiyun }
409*4882a593Smuzhiyun 
mlxsw_sp_sfmr_op(bool valid)410*4882a593Smuzhiyun static enum mlxsw_reg_sfmr_op mlxsw_sp_sfmr_op(bool valid)
411*4882a593Smuzhiyun {
412*4882a593Smuzhiyun 	return valid ? MLXSW_REG_SFMR_OP_CREATE_FID :
413*4882a593Smuzhiyun 		       MLXSW_REG_SFMR_OP_DESTROY_FID;
414*4882a593Smuzhiyun }
415*4882a593Smuzhiyun 
mlxsw_sp_fid_op(struct mlxsw_sp * mlxsw_sp,u16 fid_index,u16 fid_offset,bool valid)416*4882a593Smuzhiyun static int mlxsw_sp_fid_op(struct mlxsw_sp *mlxsw_sp, u16 fid_index,
417*4882a593Smuzhiyun 			   u16 fid_offset, bool valid)
418*4882a593Smuzhiyun {
419*4882a593Smuzhiyun 	char sfmr_pl[MLXSW_REG_SFMR_LEN];
420*4882a593Smuzhiyun 
421*4882a593Smuzhiyun 	mlxsw_reg_sfmr_pack(sfmr_pl, mlxsw_sp_sfmr_op(valid), fid_index,
422*4882a593Smuzhiyun 			    fid_offset);
423*4882a593Smuzhiyun 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl);
424*4882a593Smuzhiyun }
425*4882a593Smuzhiyun 
mlxsw_sp_fid_vni_op(struct mlxsw_sp * mlxsw_sp,u16 fid_index,__be32 vni,bool vni_valid,u32 nve_flood_index,bool nve_flood_index_valid)426*4882a593Smuzhiyun static int mlxsw_sp_fid_vni_op(struct mlxsw_sp *mlxsw_sp, u16 fid_index,
427*4882a593Smuzhiyun 			       __be32 vni, bool vni_valid, u32 nve_flood_index,
428*4882a593Smuzhiyun 			       bool nve_flood_index_valid)
429*4882a593Smuzhiyun {
430*4882a593Smuzhiyun 	char sfmr_pl[MLXSW_REG_SFMR_LEN];
431*4882a593Smuzhiyun 
432*4882a593Smuzhiyun 	mlxsw_reg_sfmr_pack(sfmr_pl, MLXSW_REG_SFMR_OP_CREATE_FID, fid_index,
433*4882a593Smuzhiyun 			    0);
434*4882a593Smuzhiyun 	mlxsw_reg_sfmr_vv_set(sfmr_pl, vni_valid);
435*4882a593Smuzhiyun 	mlxsw_reg_sfmr_vni_set(sfmr_pl, be32_to_cpu(vni));
436*4882a593Smuzhiyun 	mlxsw_reg_sfmr_vtfp_set(sfmr_pl, nve_flood_index_valid);
437*4882a593Smuzhiyun 	mlxsw_reg_sfmr_nve_tunnel_flood_ptr_set(sfmr_pl, nve_flood_index);
438*4882a593Smuzhiyun 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl);
439*4882a593Smuzhiyun }
440*4882a593Smuzhiyun 
__mlxsw_sp_fid_port_vid_map(struct mlxsw_sp * mlxsw_sp,u16 fid_index,u8 local_port,u16 vid,bool valid)441*4882a593Smuzhiyun static int __mlxsw_sp_fid_port_vid_map(struct mlxsw_sp *mlxsw_sp, u16 fid_index,
442*4882a593Smuzhiyun 				       u8 local_port, u16 vid, bool valid)
443*4882a593Smuzhiyun {
444*4882a593Smuzhiyun 	enum mlxsw_reg_svfa_mt mt = MLXSW_REG_SVFA_MT_PORT_VID_TO_FID;
445*4882a593Smuzhiyun 	char svfa_pl[MLXSW_REG_SVFA_LEN];
446*4882a593Smuzhiyun 
447*4882a593Smuzhiyun 	mlxsw_reg_svfa_pack(svfa_pl, local_port, mt, valid, fid_index, vid);
448*4882a593Smuzhiyun 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl);
449*4882a593Smuzhiyun }
450*4882a593Smuzhiyun 
451*4882a593Smuzhiyun static struct mlxsw_sp_fid_8021d *
mlxsw_sp_fid_8021d_fid(const struct mlxsw_sp_fid * fid)452*4882a593Smuzhiyun mlxsw_sp_fid_8021d_fid(const struct mlxsw_sp_fid *fid)
453*4882a593Smuzhiyun {
454*4882a593Smuzhiyun 	return container_of(fid, struct mlxsw_sp_fid_8021d, common);
455*4882a593Smuzhiyun }
456*4882a593Smuzhiyun 
mlxsw_sp_fid_8021d_setup(struct mlxsw_sp_fid * fid,const void * arg)457*4882a593Smuzhiyun static void mlxsw_sp_fid_8021d_setup(struct mlxsw_sp_fid *fid, const void *arg)
458*4882a593Smuzhiyun {
459*4882a593Smuzhiyun 	int br_ifindex = *(int *) arg;
460*4882a593Smuzhiyun 
461*4882a593Smuzhiyun 	mlxsw_sp_fid_8021d_fid(fid)->br_ifindex = br_ifindex;
462*4882a593Smuzhiyun }
463*4882a593Smuzhiyun 
mlxsw_sp_fid_8021d_configure(struct mlxsw_sp_fid * fid)464*4882a593Smuzhiyun static int mlxsw_sp_fid_8021d_configure(struct mlxsw_sp_fid *fid)
465*4882a593Smuzhiyun {
466*4882a593Smuzhiyun 	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
467*4882a593Smuzhiyun 
468*4882a593Smuzhiyun 	return mlxsw_sp_fid_op(fid_family->mlxsw_sp, fid->fid_index, 0, true);
469*4882a593Smuzhiyun }
470*4882a593Smuzhiyun 
mlxsw_sp_fid_8021d_deconfigure(struct mlxsw_sp_fid * fid)471*4882a593Smuzhiyun static void mlxsw_sp_fid_8021d_deconfigure(struct mlxsw_sp_fid *fid)
472*4882a593Smuzhiyun {
473*4882a593Smuzhiyun 	if (fid->vni_valid)
474*4882a593Smuzhiyun 		mlxsw_sp_nve_fid_disable(fid->fid_family->mlxsw_sp, fid);
475*4882a593Smuzhiyun 	mlxsw_sp_fid_op(fid->fid_family->mlxsw_sp, fid->fid_index, 0, false);
476*4882a593Smuzhiyun }
477*4882a593Smuzhiyun 
mlxsw_sp_fid_8021d_index_alloc(struct mlxsw_sp_fid * fid,const void * arg,u16 * p_fid_index)478*4882a593Smuzhiyun static int mlxsw_sp_fid_8021d_index_alloc(struct mlxsw_sp_fid *fid,
479*4882a593Smuzhiyun 					  const void *arg, u16 *p_fid_index)
480*4882a593Smuzhiyun {
481*4882a593Smuzhiyun 	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
482*4882a593Smuzhiyun 	u16 nr_fids, fid_index;
483*4882a593Smuzhiyun 
484*4882a593Smuzhiyun 	nr_fids = fid_family->end_index - fid_family->start_index + 1;
485*4882a593Smuzhiyun 	fid_index = find_first_zero_bit(fid_family->fids_bitmap, nr_fids);
486*4882a593Smuzhiyun 	if (fid_index == nr_fids)
487*4882a593Smuzhiyun 		return -ENOBUFS;
488*4882a593Smuzhiyun 	*p_fid_index = fid_family->start_index + fid_index;
489*4882a593Smuzhiyun 
490*4882a593Smuzhiyun 	return 0;
491*4882a593Smuzhiyun }
492*4882a593Smuzhiyun 
493*4882a593Smuzhiyun static bool
mlxsw_sp_fid_8021d_compare(const struct mlxsw_sp_fid * fid,const void * arg)494*4882a593Smuzhiyun mlxsw_sp_fid_8021d_compare(const struct mlxsw_sp_fid *fid, const void *arg)
495*4882a593Smuzhiyun {
496*4882a593Smuzhiyun 	int br_ifindex = *(int *) arg;
497*4882a593Smuzhiyun 
498*4882a593Smuzhiyun 	return mlxsw_sp_fid_8021d_fid(fid)->br_ifindex == br_ifindex;
499*4882a593Smuzhiyun }
500*4882a593Smuzhiyun 
mlxsw_sp_fid_8021d_flood_index(const struct mlxsw_sp_fid * fid)501*4882a593Smuzhiyun static u16 mlxsw_sp_fid_8021d_flood_index(const struct mlxsw_sp_fid *fid)
502*4882a593Smuzhiyun {
503*4882a593Smuzhiyun 	return fid->fid_index - VLAN_N_VID;
504*4882a593Smuzhiyun }
505*4882a593Smuzhiyun 
mlxsw_sp_port_vp_mode_trans(struct mlxsw_sp_port * mlxsw_sp_port)506*4882a593Smuzhiyun static int mlxsw_sp_port_vp_mode_trans(struct mlxsw_sp_port *mlxsw_sp_port)
507*4882a593Smuzhiyun {
508*4882a593Smuzhiyun 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
509*4882a593Smuzhiyun 	struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
510*4882a593Smuzhiyun 	int err;
511*4882a593Smuzhiyun 
512*4882a593Smuzhiyun 	list_for_each_entry(mlxsw_sp_port_vlan, &mlxsw_sp_port->vlans_list,
513*4882a593Smuzhiyun 			    list) {
514*4882a593Smuzhiyun 		struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid;
515*4882a593Smuzhiyun 		u16 vid = mlxsw_sp_port_vlan->vid;
516*4882a593Smuzhiyun 
517*4882a593Smuzhiyun 		if (!fid)
518*4882a593Smuzhiyun 			continue;
519*4882a593Smuzhiyun 
520*4882a593Smuzhiyun 		err = __mlxsw_sp_fid_port_vid_map(mlxsw_sp, fid->fid_index,
521*4882a593Smuzhiyun 						  mlxsw_sp_port->local_port,
522*4882a593Smuzhiyun 						  vid, true);
523*4882a593Smuzhiyun 		if (err)
524*4882a593Smuzhiyun 			goto err_fid_port_vid_map;
525*4882a593Smuzhiyun 	}
526*4882a593Smuzhiyun 
527*4882a593Smuzhiyun 	err = mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, true);
528*4882a593Smuzhiyun 	if (err)
529*4882a593Smuzhiyun 		goto err_port_vp_mode_set;
530*4882a593Smuzhiyun 
531*4882a593Smuzhiyun 	return 0;
532*4882a593Smuzhiyun 
533*4882a593Smuzhiyun err_port_vp_mode_set:
534*4882a593Smuzhiyun err_fid_port_vid_map:
535*4882a593Smuzhiyun 	list_for_each_entry_continue_reverse(mlxsw_sp_port_vlan,
536*4882a593Smuzhiyun 					     &mlxsw_sp_port->vlans_list, list) {
537*4882a593Smuzhiyun 		struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid;
538*4882a593Smuzhiyun 		u16 vid = mlxsw_sp_port_vlan->vid;
539*4882a593Smuzhiyun 
540*4882a593Smuzhiyun 		if (!fid)
541*4882a593Smuzhiyun 			continue;
542*4882a593Smuzhiyun 
543*4882a593Smuzhiyun 		__mlxsw_sp_fid_port_vid_map(mlxsw_sp, fid->fid_index,
544*4882a593Smuzhiyun 					    mlxsw_sp_port->local_port, vid,
545*4882a593Smuzhiyun 					    false);
546*4882a593Smuzhiyun 	}
547*4882a593Smuzhiyun 	return err;
548*4882a593Smuzhiyun }
549*4882a593Smuzhiyun 
mlxsw_sp_port_vlan_mode_trans(struct mlxsw_sp_port * mlxsw_sp_port)550*4882a593Smuzhiyun static void mlxsw_sp_port_vlan_mode_trans(struct mlxsw_sp_port *mlxsw_sp_port)
551*4882a593Smuzhiyun {
552*4882a593Smuzhiyun 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
553*4882a593Smuzhiyun 	struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
554*4882a593Smuzhiyun 
555*4882a593Smuzhiyun 	mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, false);
556*4882a593Smuzhiyun 
557*4882a593Smuzhiyun 	list_for_each_entry_reverse(mlxsw_sp_port_vlan,
558*4882a593Smuzhiyun 				    &mlxsw_sp_port->vlans_list, list) {
559*4882a593Smuzhiyun 		struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid;
560*4882a593Smuzhiyun 		u16 vid = mlxsw_sp_port_vlan->vid;
561*4882a593Smuzhiyun 
562*4882a593Smuzhiyun 		if (!fid)
563*4882a593Smuzhiyun 			continue;
564*4882a593Smuzhiyun 
565*4882a593Smuzhiyun 		__mlxsw_sp_fid_port_vid_map(mlxsw_sp, fid->fid_index,
566*4882a593Smuzhiyun 					    mlxsw_sp_port->local_port, vid,
567*4882a593Smuzhiyun 					    false);
568*4882a593Smuzhiyun 	}
569*4882a593Smuzhiyun }
570*4882a593Smuzhiyun 
mlxsw_sp_fid_8021d_port_vid_map(struct mlxsw_sp_fid * fid,struct mlxsw_sp_port * mlxsw_sp_port,u16 vid)571*4882a593Smuzhiyun static int mlxsw_sp_fid_8021d_port_vid_map(struct mlxsw_sp_fid *fid,
572*4882a593Smuzhiyun 					   struct mlxsw_sp_port *mlxsw_sp_port,
573*4882a593Smuzhiyun 					   u16 vid)
574*4882a593Smuzhiyun {
575*4882a593Smuzhiyun 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
576*4882a593Smuzhiyun 	u8 local_port = mlxsw_sp_port->local_port;
577*4882a593Smuzhiyun 	int err;
578*4882a593Smuzhiyun 
579*4882a593Smuzhiyun 	err = __mlxsw_sp_fid_port_vid_map(mlxsw_sp, fid->fid_index,
580*4882a593Smuzhiyun 					  mlxsw_sp_port->local_port, vid, true);
581*4882a593Smuzhiyun 	if (err)
582*4882a593Smuzhiyun 		return err;
583*4882a593Smuzhiyun 
584*4882a593Smuzhiyun 	if (mlxsw_sp->fid_core->port_fid_mappings[local_port]++ == 0) {
585*4882a593Smuzhiyun 		err = mlxsw_sp_port_vp_mode_trans(mlxsw_sp_port);
586*4882a593Smuzhiyun 		if (err)
587*4882a593Smuzhiyun 			goto err_port_vp_mode_trans;
588*4882a593Smuzhiyun 	}
589*4882a593Smuzhiyun 
590*4882a593Smuzhiyun 	return 0;
591*4882a593Smuzhiyun 
592*4882a593Smuzhiyun err_port_vp_mode_trans:
593*4882a593Smuzhiyun 	mlxsw_sp->fid_core->port_fid_mappings[local_port]--;
594*4882a593Smuzhiyun 	__mlxsw_sp_fid_port_vid_map(mlxsw_sp, fid->fid_index,
595*4882a593Smuzhiyun 				    mlxsw_sp_port->local_port, vid, false);
596*4882a593Smuzhiyun 	return err;
597*4882a593Smuzhiyun }
598*4882a593Smuzhiyun 
599*4882a593Smuzhiyun static void
mlxsw_sp_fid_8021d_port_vid_unmap(struct mlxsw_sp_fid * fid,struct mlxsw_sp_port * mlxsw_sp_port,u16 vid)600*4882a593Smuzhiyun mlxsw_sp_fid_8021d_port_vid_unmap(struct mlxsw_sp_fid *fid,
601*4882a593Smuzhiyun 				  struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
602*4882a593Smuzhiyun {
603*4882a593Smuzhiyun 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
604*4882a593Smuzhiyun 	u8 local_port = mlxsw_sp_port->local_port;
605*4882a593Smuzhiyun 
606*4882a593Smuzhiyun 	if (mlxsw_sp->fid_core->port_fid_mappings[local_port] == 1)
607*4882a593Smuzhiyun 		mlxsw_sp_port_vlan_mode_trans(mlxsw_sp_port);
608*4882a593Smuzhiyun 	mlxsw_sp->fid_core->port_fid_mappings[local_port]--;
609*4882a593Smuzhiyun 	__mlxsw_sp_fid_port_vid_map(mlxsw_sp, fid->fid_index,
610*4882a593Smuzhiyun 				    mlxsw_sp_port->local_port, vid, false);
611*4882a593Smuzhiyun }
612*4882a593Smuzhiyun 
mlxsw_sp_fid_8021d_vni_set(struct mlxsw_sp_fid * fid,__be32 vni)613*4882a593Smuzhiyun static int mlxsw_sp_fid_8021d_vni_set(struct mlxsw_sp_fid *fid, __be32 vni)
614*4882a593Smuzhiyun {
615*4882a593Smuzhiyun 	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
616*4882a593Smuzhiyun 
617*4882a593Smuzhiyun 	return mlxsw_sp_fid_vni_op(fid_family->mlxsw_sp, fid->fid_index, vni,
618*4882a593Smuzhiyun 				   true, fid->nve_flood_index,
619*4882a593Smuzhiyun 				   fid->nve_flood_index_valid);
620*4882a593Smuzhiyun }
621*4882a593Smuzhiyun 
mlxsw_sp_fid_8021d_vni_clear(struct mlxsw_sp_fid * fid)622*4882a593Smuzhiyun static void mlxsw_sp_fid_8021d_vni_clear(struct mlxsw_sp_fid *fid)
623*4882a593Smuzhiyun {
624*4882a593Smuzhiyun 	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
625*4882a593Smuzhiyun 
626*4882a593Smuzhiyun 	mlxsw_sp_fid_vni_op(fid_family->mlxsw_sp, fid->fid_index, 0, false,
627*4882a593Smuzhiyun 			    fid->nve_flood_index, fid->nve_flood_index_valid);
628*4882a593Smuzhiyun }
629*4882a593Smuzhiyun 
mlxsw_sp_fid_8021d_nve_flood_index_set(struct mlxsw_sp_fid * fid,u32 nve_flood_index)630*4882a593Smuzhiyun static int mlxsw_sp_fid_8021d_nve_flood_index_set(struct mlxsw_sp_fid *fid,
631*4882a593Smuzhiyun 						  u32 nve_flood_index)
632*4882a593Smuzhiyun {
633*4882a593Smuzhiyun 	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
634*4882a593Smuzhiyun 
635*4882a593Smuzhiyun 	return mlxsw_sp_fid_vni_op(fid_family->mlxsw_sp, fid->fid_index,
636*4882a593Smuzhiyun 				   fid->vni, fid->vni_valid, nve_flood_index,
637*4882a593Smuzhiyun 				   true);
638*4882a593Smuzhiyun }
639*4882a593Smuzhiyun 
mlxsw_sp_fid_8021d_nve_flood_index_clear(struct mlxsw_sp_fid * fid)640*4882a593Smuzhiyun static void mlxsw_sp_fid_8021d_nve_flood_index_clear(struct mlxsw_sp_fid *fid)
641*4882a593Smuzhiyun {
642*4882a593Smuzhiyun 	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
643*4882a593Smuzhiyun 
644*4882a593Smuzhiyun 	mlxsw_sp_fid_vni_op(fid_family->mlxsw_sp, fid->fid_index, fid->vni,
645*4882a593Smuzhiyun 			    fid->vni_valid, 0, false);
646*4882a593Smuzhiyun }
647*4882a593Smuzhiyun 
648*4882a593Smuzhiyun static void
mlxsw_sp_fid_8021d_fdb_clear_offload(const struct mlxsw_sp_fid * fid,const struct net_device * nve_dev)649*4882a593Smuzhiyun mlxsw_sp_fid_8021d_fdb_clear_offload(const struct mlxsw_sp_fid *fid,
650*4882a593Smuzhiyun 				     const struct net_device *nve_dev)
651*4882a593Smuzhiyun {
652*4882a593Smuzhiyun 	br_fdb_clear_offload(nve_dev, 0);
653*4882a593Smuzhiyun }
654*4882a593Smuzhiyun 
655*4882a593Smuzhiyun static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021d_ops = {
656*4882a593Smuzhiyun 	.setup			= mlxsw_sp_fid_8021d_setup,
657*4882a593Smuzhiyun 	.configure		= mlxsw_sp_fid_8021d_configure,
658*4882a593Smuzhiyun 	.deconfigure		= mlxsw_sp_fid_8021d_deconfigure,
659*4882a593Smuzhiyun 	.index_alloc		= mlxsw_sp_fid_8021d_index_alloc,
660*4882a593Smuzhiyun 	.compare		= mlxsw_sp_fid_8021d_compare,
661*4882a593Smuzhiyun 	.flood_index		= mlxsw_sp_fid_8021d_flood_index,
662*4882a593Smuzhiyun 	.port_vid_map		= mlxsw_sp_fid_8021d_port_vid_map,
663*4882a593Smuzhiyun 	.port_vid_unmap		= mlxsw_sp_fid_8021d_port_vid_unmap,
664*4882a593Smuzhiyun 	.vni_set		= mlxsw_sp_fid_8021d_vni_set,
665*4882a593Smuzhiyun 	.vni_clear		= mlxsw_sp_fid_8021d_vni_clear,
666*4882a593Smuzhiyun 	.nve_flood_index_set	= mlxsw_sp_fid_8021d_nve_flood_index_set,
667*4882a593Smuzhiyun 	.nve_flood_index_clear	= mlxsw_sp_fid_8021d_nve_flood_index_clear,
668*4882a593Smuzhiyun 	.fdb_clear_offload	= mlxsw_sp_fid_8021d_fdb_clear_offload,
669*4882a593Smuzhiyun };
670*4882a593Smuzhiyun 
671*4882a593Smuzhiyun static const struct mlxsw_sp_flood_table mlxsw_sp_fid_8021d_flood_tables[] = {
672*4882a593Smuzhiyun 	{
673*4882a593Smuzhiyun 		.packet_type	= MLXSW_SP_FLOOD_TYPE_UC,
674*4882a593Smuzhiyun 		.bridge_type	= MLXSW_REG_SFGC_BRIDGE_TYPE_VFID,
675*4882a593Smuzhiyun 		.table_type	= MLXSW_REG_SFGC_TABLE_TYPE_FID,
676*4882a593Smuzhiyun 		.table_index	= 0,
677*4882a593Smuzhiyun 	},
678*4882a593Smuzhiyun 	{
679*4882a593Smuzhiyun 		.packet_type	= MLXSW_SP_FLOOD_TYPE_MC,
680*4882a593Smuzhiyun 		.bridge_type	= MLXSW_REG_SFGC_BRIDGE_TYPE_VFID,
681*4882a593Smuzhiyun 		.table_type	= MLXSW_REG_SFGC_TABLE_TYPE_FID,
682*4882a593Smuzhiyun 		.table_index	= 1,
683*4882a593Smuzhiyun 	},
684*4882a593Smuzhiyun 	{
685*4882a593Smuzhiyun 		.packet_type	= MLXSW_SP_FLOOD_TYPE_BC,
686*4882a593Smuzhiyun 		.bridge_type	= MLXSW_REG_SFGC_BRIDGE_TYPE_VFID,
687*4882a593Smuzhiyun 		.table_type	= MLXSW_REG_SFGC_TABLE_TYPE_FID,
688*4882a593Smuzhiyun 		.table_index	= 2,
689*4882a593Smuzhiyun 	},
690*4882a593Smuzhiyun };
691*4882a593Smuzhiyun 
692*4882a593Smuzhiyun /* Range and flood configuration must match mlxsw_config_profile */
693*4882a593Smuzhiyun static const struct mlxsw_sp_fid_family mlxsw_sp_fid_8021d_family = {
694*4882a593Smuzhiyun 	.type			= MLXSW_SP_FID_TYPE_8021D,
695*4882a593Smuzhiyun 	.fid_size		= sizeof(struct mlxsw_sp_fid_8021d),
696*4882a593Smuzhiyun 	.start_index		= VLAN_N_VID,
697*4882a593Smuzhiyun 	.end_index		= VLAN_N_VID + MLXSW_SP_FID_8021D_MAX - 1,
698*4882a593Smuzhiyun 	.flood_tables		= mlxsw_sp_fid_8021d_flood_tables,
699*4882a593Smuzhiyun 	.nr_flood_tables	= ARRAY_SIZE(mlxsw_sp_fid_8021d_flood_tables),
700*4882a593Smuzhiyun 	.rif_type		= MLXSW_SP_RIF_TYPE_FID,
701*4882a593Smuzhiyun 	.ops			= &mlxsw_sp_fid_8021d_ops,
702*4882a593Smuzhiyun 	.lag_vid_valid		= 1,
703*4882a593Smuzhiyun };
704*4882a593Smuzhiyun 
705*4882a593Smuzhiyun static bool
mlxsw_sp_fid_8021q_compare(const struct mlxsw_sp_fid * fid,const void * arg)706*4882a593Smuzhiyun mlxsw_sp_fid_8021q_compare(const struct mlxsw_sp_fid *fid, const void *arg)
707*4882a593Smuzhiyun {
708*4882a593Smuzhiyun 	u16 vid = *(u16 *) arg;
709*4882a593Smuzhiyun 
710*4882a593Smuzhiyun 	return mlxsw_sp_fid_8021q_fid(fid)->vid == vid;
711*4882a593Smuzhiyun }
712*4882a593Smuzhiyun 
713*4882a593Smuzhiyun static void
mlxsw_sp_fid_8021q_fdb_clear_offload(const struct mlxsw_sp_fid * fid,const struct net_device * nve_dev)714*4882a593Smuzhiyun mlxsw_sp_fid_8021q_fdb_clear_offload(const struct mlxsw_sp_fid *fid,
715*4882a593Smuzhiyun 				     const struct net_device *nve_dev)
716*4882a593Smuzhiyun {
717*4882a593Smuzhiyun 	br_fdb_clear_offload(nve_dev, mlxsw_sp_fid_8021q_vid(fid));
718*4882a593Smuzhiyun }
719*4882a593Smuzhiyun 
720*4882a593Smuzhiyun static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021q_emu_ops = {
721*4882a593Smuzhiyun 	.setup			= mlxsw_sp_fid_8021q_setup,
722*4882a593Smuzhiyun 	.configure		= mlxsw_sp_fid_8021d_configure,
723*4882a593Smuzhiyun 	.deconfigure		= mlxsw_sp_fid_8021d_deconfigure,
724*4882a593Smuzhiyun 	.index_alloc		= mlxsw_sp_fid_8021d_index_alloc,
725*4882a593Smuzhiyun 	.compare		= mlxsw_sp_fid_8021q_compare,
726*4882a593Smuzhiyun 	.flood_index		= mlxsw_sp_fid_8021d_flood_index,
727*4882a593Smuzhiyun 	.port_vid_map		= mlxsw_sp_fid_8021d_port_vid_map,
728*4882a593Smuzhiyun 	.port_vid_unmap		= mlxsw_sp_fid_8021d_port_vid_unmap,
729*4882a593Smuzhiyun 	.vni_set		= mlxsw_sp_fid_8021d_vni_set,
730*4882a593Smuzhiyun 	.vni_clear		= mlxsw_sp_fid_8021d_vni_clear,
731*4882a593Smuzhiyun 	.nve_flood_index_set	= mlxsw_sp_fid_8021d_nve_flood_index_set,
732*4882a593Smuzhiyun 	.nve_flood_index_clear	= mlxsw_sp_fid_8021d_nve_flood_index_clear,
733*4882a593Smuzhiyun 	.fdb_clear_offload	= mlxsw_sp_fid_8021q_fdb_clear_offload,
734*4882a593Smuzhiyun };
735*4882a593Smuzhiyun 
736*4882a593Smuzhiyun /* There are 4K-2 emulated 802.1Q FIDs, starting right after the 802.1D FIDs */
737*4882a593Smuzhiyun #define MLXSW_SP_FID_8021Q_EMU_START	(VLAN_N_VID + MLXSW_SP_FID_8021D_MAX)
738*4882a593Smuzhiyun #define MLXSW_SP_FID_8021Q_EMU_END	(MLXSW_SP_FID_8021Q_EMU_START + \
739*4882a593Smuzhiyun 					 VLAN_VID_MASK - 2)
740*4882a593Smuzhiyun 
741*4882a593Smuzhiyun /* Range and flood configuration must match mlxsw_config_profile */
742*4882a593Smuzhiyun static const struct mlxsw_sp_fid_family mlxsw_sp_fid_8021q_emu_family = {
743*4882a593Smuzhiyun 	.type			= MLXSW_SP_FID_TYPE_8021Q,
744*4882a593Smuzhiyun 	.fid_size		= sizeof(struct mlxsw_sp_fid_8021q),
745*4882a593Smuzhiyun 	.start_index		= MLXSW_SP_FID_8021Q_EMU_START,
746*4882a593Smuzhiyun 	.end_index		= MLXSW_SP_FID_8021Q_EMU_END,
747*4882a593Smuzhiyun 	.flood_tables		= mlxsw_sp_fid_8021d_flood_tables,
748*4882a593Smuzhiyun 	.nr_flood_tables	= ARRAY_SIZE(mlxsw_sp_fid_8021d_flood_tables),
749*4882a593Smuzhiyun 	.rif_type		= MLXSW_SP_RIF_TYPE_VLAN,
750*4882a593Smuzhiyun 	.ops			= &mlxsw_sp_fid_8021q_emu_ops,
751*4882a593Smuzhiyun 	.lag_vid_valid		= 1,
752*4882a593Smuzhiyun };
753*4882a593Smuzhiyun 
mlxsw_sp_fid_rfid_configure(struct mlxsw_sp_fid * fid)754*4882a593Smuzhiyun static int mlxsw_sp_fid_rfid_configure(struct mlxsw_sp_fid *fid)
755*4882a593Smuzhiyun {
756*4882a593Smuzhiyun 	/* rFIDs are allocated by the device during init */
757*4882a593Smuzhiyun 	return 0;
758*4882a593Smuzhiyun }
759*4882a593Smuzhiyun 
mlxsw_sp_fid_rfid_deconfigure(struct mlxsw_sp_fid * fid)760*4882a593Smuzhiyun static void mlxsw_sp_fid_rfid_deconfigure(struct mlxsw_sp_fid *fid)
761*4882a593Smuzhiyun {
762*4882a593Smuzhiyun }
763*4882a593Smuzhiyun 
mlxsw_sp_fid_rfid_index_alloc(struct mlxsw_sp_fid * fid,const void * arg,u16 * p_fid_index)764*4882a593Smuzhiyun static int mlxsw_sp_fid_rfid_index_alloc(struct mlxsw_sp_fid *fid,
765*4882a593Smuzhiyun 					 const void *arg, u16 *p_fid_index)
766*4882a593Smuzhiyun {
767*4882a593Smuzhiyun 	u16 rif_index = *(u16 *) arg;
768*4882a593Smuzhiyun 
769*4882a593Smuzhiyun 	*p_fid_index = fid->fid_family->start_index + rif_index;
770*4882a593Smuzhiyun 
771*4882a593Smuzhiyun 	return 0;
772*4882a593Smuzhiyun }
773*4882a593Smuzhiyun 
mlxsw_sp_fid_rfid_compare(const struct mlxsw_sp_fid * fid,const void * arg)774*4882a593Smuzhiyun static bool mlxsw_sp_fid_rfid_compare(const struct mlxsw_sp_fid *fid,
775*4882a593Smuzhiyun 				      const void *arg)
776*4882a593Smuzhiyun {
777*4882a593Smuzhiyun 	u16 rif_index = *(u16 *) arg;
778*4882a593Smuzhiyun 
779*4882a593Smuzhiyun 	return fid->fid_index == rif_index + fid->fid_family->start_index;
780*4882a593Smuzhiyun }
781*4882a593Smuzhiyun 
mlxsw_sp_fid_rfid_port_vid_map(struct mlxsw_sp_fid * fid,struct mlxsw_sp_port * mlxsw_sp_port,u16 vid)782*4882a593Smuzhiyun static int mlxsw_sp_fid_rfid_port_vid_map(struct mlxsw_sp_fid *fid,
783*4882a593Smuzhiyun 					  struct mlxsw_sp_port *mlxsw_sp_port,
784*4882a593Smuzhiyun 					  u16 vid)
785*4882a593Smuzhiyun {
786*4882a593Smuzhiyun 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
787*4882a593Smuzhiyun 	u8 local_port = mlxsw_sp_port->local_port;
788*4882a593Smuzhiyun 	int err;
789*4882a593Smuzhiyun 
790*4882a593Smuzhiyun 	/* We only need to transition the port to virtual mode since
791*4882a593Smuzhiyun 	 * {Port, VID} => FID is done by the firmware upon RIF creation.
792*4882a593Smuzhiyun 	 */
793*4882a593Smuzhiyun 	if (mlxsw_sp->fid_core->port_fid_mappings[local_port]++ == 0) {
794*4882a593Smuzhiyun 		err = mlxsw_sp_port_vp_mode_trans(mlxsw_sp_port);
795*4882a593Smuzhiyun 		if (err)
796*4882a593Smuzhiyun 			goto err_port_vp_mode_trans;
797*4882a593Smuzhiyun 	}
798*4882a593Smuzhiyun 
799*4882a593Smuzhiyun 	return 0;
800*4882a593Smuzhiyun 
801*4882a593Smuzhiyun err_port_vp_mode_trans:
802*4882a593Smuzhiyun 	mlxsw_sp->fid_core->port_fid_mappings[local_port]--;
803*4882a593Smuzhiyun 	return err;
804*4882a593Smuzhiyun }
805*4882a593Smuzhiyun 
806*4882a593Smuzhiyun static void
mlxsw_sp_fid_rfid_port_vid_unmap(struct mlxsw_sp_fid * fid,struct mlxsw_sp_port * mlxsw_sp_port,u16 vid)807*4882a593Smuzhiyun mlxsw_sp_fid_rfid_port_vid_unmap(struct mlxsw_sp_fid *fid,
808*4882a593Smuzhiyun 				 struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
809*4882a593Smuzhiyun {
810*4882a593Smuzhiyun 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
811*4882a593Smuzhiyun 	u8 local_port = mlxsw_sp_port->local_port;
812*4882a593Smuzhiyun 
813*4882a593Smuzhiyun 	if (mlxsw_sp->fid_core->port_fid_mappings[local_port] == 1)
814*4882a593Smuzhiyun 		mlxsw_sp_port_vlan_mode_trans(mlxsw_sp_port);
815*4882a593Smuzhiyun 	mlxsw_sp->fid_core->port_fid_mappings[local_port]--;
816*4882a593Smuzhiyun }
817*4882a593Smuzhiyun 
818*4882a593Smuzhiyun static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_rfid_ops = {
819*4882a593Smuzhiyun 	.configure		= mlxsw_sp_fid_rfid_configure,
820*4882a593Smuzhiyun 	.deconfigure		= mlxsw_sp_fid_rfid_deconfigure,
821*4882a593Smuzhiyun 	.index_alloc		= mlxsw_sp_fid_rfid_index_alloc,
822*4882a593Smuzhiyun 	.compare		= mlxsw_sp_fid_rfid_compare,
823*4882a593Smuzhiyun 	.port_vid_map		= mlxsw_sp_fid_rfid_port_vid_map,
824*4882a593Smuzhiyun 	.port_vid_unmap		= mlxsw_sp_fid_rfid_port_vid_unmap,
825*4882a593Smuzhiyun };
826*4882a593Smuzhiyun 
827*4882a593Smuzhiyun #define MLXSW_SP_RFID_BASE	(15 * 1024)
828*4882a593Smuzhiyun #define MLXSW_SP_RFID_MAX	1024
829*4882a593Smuzhiyun 
830*4882a593Smuzhiyun static const struct mlxsw_sp_fid_family mlxsw_sp_fid_rfid_family = {
831*4882a593Smuzhiyun 	.type			= MLXSW_SP_FID_TYPE_RFID,
832*4882a593Smuzhiyun 	.fid_size		= sizeof(struct mlxsw_sp_fid),
833*4882a593Smuzhiyun 	.start_index		= MLXSW_SP_RFID_BASE,
834*4882a593Smuzhiyun 	.end_index		= MLXSW_SP_RFID_BASE + MLXSW_SP_RFID_MAX - 1,
835*4882a593Smuzhiyun 	.rif_type		= MLXSW_SP_RIF_TYPE_SUBPORT,
836*4882a593Smuzhiyun 	.ops			= &mlxsw_sp_fid_rfid_ops,
837*4882a593Smuzhiyun };
838*4882a593Smuzhiyun 
mlxsw_sp_fid_dummy_configure(struct mlxsw_sp_fid * fid)839*4882a593Smuzhiyun static int mlxsw_sp_fid_dummy_configure(struct mlxsw_sp_fid *fid)
840*4882a593Smuzhiyun {
841*4882a593Smuzhiyun 	struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
842*4882a593Smuzhiyun 
843*4882a593Smuzhiyun 	return mlxsw_sp_fid_op(mlxsw_sp, fid->fid_index, 0, true);
844*4882a593Smuzhiyun }
845*4882a593Smuzhiyun 
mlxsw_sp_fid_dummy_deconfigure(struct mlxsw_sp_fid * fid)846*4882a593Smuzhiyun static void mlxsw_sp_fid_dummy_deconfigure(struct mlxsw_sp_fid *fid)
847*4882a593Smuzhiyun {
848*4882a593Smuzhiyun 	mlxsw_sp_fid_op(fid->fid_family->mlxsw_sp, fid->fid_index, 0, false);
849*4882a593Smuzhiyun }
850*4882a593Smuzhiyun 
mlxsw_sp_fid_dummy_index_alloc(struct mlxsw_sp_fid * fid,const void * arg,u16 * p_fid_index)851*4882a593Smuzhiyun static int mlxsw_sp_fid_dummy_index_alloc(struct mlxsw_sp_fid *fid,
852*4882a593Smuzhiyun 					  const void *arg, u16 *p_fid_index)
853*4882a593Smuzhiyun {
854*4882a593Smuzhiyun 	*p_fid_index = fid->fid_family->start_index;
855*4882a593Smuzhiyun 
856*4882a593Smuzhiyun 	return 0;
857*4882a593Smuzhiyun }
858*4882a593Smuzhiyun 
mlxsw_sp_fid_dummy_compare(const struct mlxsw_sp_fid * fid,const void * arg)859*4882a593Smuzhiyun static bool mlxsw_sp_fid_dummy_compare(const struct mlxsw_sp_fid *fid,
860*4882a593Smuzhiyun 				       const void *arg)
861*4882a593Smuzhiyun {
862*4882a593Smuzhiyun 	return true;
863*4882a593Smuzhiyun }
864*4882a593Smuzhiyun 
865*4882a593Smuzhiyun static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_dummy_ops = {
866*4882a593Smuzhiyun 	.configure		= mlxsw_sp_fid_dummy_configure,
867*4882a593Smuzhiyun 	.deconfigure		= mlxsw_sp_fid_dummy_deconfigure,
868*4882a593Smuzhiyun 	.index_alloc		= mlxsw_sp_fid_dummy_index_alloc,
869*4882a593Smuzhiyun 	.compare		= mlxsw_sp_fid_dummy_compare,
870*4882a593Smuzhiyun };
871*4882a593Smuzhiyun 
872*4882a593Smuzhiyun static const struct mlxsw_sp_fid_family mlxsw_sp_fid_dummy_family = {
873*4882a593Smuzhiyun 	.type			= MLXSW_SP_FID_TYPE_DUMMY,
874*4882a593Smuzhiyun 	.fid_size		= sizeof(struct mlxsw_sp_fid),
875*4882a593Smuzhiyun 	.start_index		= VLAN_N_VID - 1,
876*4882a593Smuzhiyun 	.end_index		= VLAN_N_VID - 1,
877*4882a593Smuzhiyun 	.ops			= &mlxsw_sp_fid_dummy_ops,
878*4882a593Smuzhiyun };
879*4882a593Smuzhiyun 
880*4882a593Smuzhiyun static const struct mlxsw_sp_fid_family *mlxsw_sp_fid_family_arr[] = {
881*4882a593Smuzhiyun 	[MLXSW_SP_FID_TYPE_8021Q]	= &mlxsw_sp_fid_8021q_emu_family,
882*4882a593Smuzhiyun 	[MLXSW_SP_FID_TYPE_8021D]	= &mlxsw_sp_fid_8021d_family,
883*4882a593Smuzhiyun 	[MLXSW_SP_FID_TYPE_RFID]	= &mlxsw_sp_fid_rfid_family,
884*4882a593Smuzhiyun 	[MLXSW_SP_FID_TYPE_DUMMY]	= &mlxsw_sp_fid_dummy_family,
885*4882a593Smuzhiyun };
886*4882a593Smuzhiyun 
mlxsw_sp_fid_lookup(struct mlxsw_sp * mlxsw_sp,enum mlxsw_sp_fid_type type,const void * arg)887*4882a593Smuzhiyun static struct mlxsw_sp_fid *mlxsw_sp_fid_lookup(struct mlxsw_sp *mlxsw_sp,
888*4882a593Smuzhiyun 						enum mlxsw_sp_fid_type type,
889*4882a593Smuzhiyun 						const void *arg)
890*4882a593Smuzhiyun {
891*4882a593Smuzhiyun 	struct mlxsw_sp_fid_family *fid_family;
892*4882a593Smuzhiyun 	struct mlxsw_sp_fid *fid;
893*4882a593Smuzhiyun 
894*4882a593Smuzhiyun 	fid_family = mlxsw_sp->fid_core->fid_family_arr[type];
895*4882a593Smuzhiyun 	list_for_each_entry(fid, &fid_family->fids_list, list) {
896*4882a593Smuzhiyun 		if (!fid->fid_family->ops->compare(fid, arg))
897*4882a593Smuzhiyun 			continue;
898*4882a593Smuzhiyun 		refcount_inc(&fid->ref_count);
899*4882a593Smuzhiyun 		return fid;
900*4882a593Smuzhiyun 	}
901*4882a593Smuzhiyun 
902*4882a593Smuzhiyun 	return NULL;
903*4882a593Smuzhiyun }
904*4882a593Smuzhiyun 
mlxsw_sp_fid_get(struct mlxsw_sp * mlxsw_sp,enum mlxsw_sp_fid_type type,const void * arg)905*4882a593Smuzhiyun static struct mlxsw_sp_fid *mlxsw_sp_fid_get(struct mlxsw_sp *mlxsw_sp,
906*4882a593Smuzhiyun 					     enum mlxsw_sp_fid_type type,
907*4882a593Smuzhiyun 					     const void *arg)
908*4882a593Smuzhiyun {
909*4882a593Smuzhiyun 	struct mlxsw_sp_fid_family *fid_family;
910*4882a593Smuzhiyun 	struct mlxsw_sp_fid *fid;
911*4882a593Smuzhiyun 	u16 fid_index;
912*4882a593Smuzhiyun 	int err;
913*4882a593Smuzhiyun 
914*4882a593Smuzhiyun 	fid = mlxsw_sp_fid_lookup(mlxsw_sp, type, arg);
915*4882a593Smuzhiyun 	if (fid)
916*4882a593Smuzhiyun 		return fid;
917*4882a593Smuzhiyun 
918*4882a593Smuzhiyun 	fid_family = mlxsw_sp->fid_core->fid_family_arr[type];
919*4882a593Smuzhiyun 	fid = kzalloc(fid_family->fid_size, GFP_KERNEL);
920*4882a593Smuzhiyun 	if (!fid)
921*4882a593Smuzhiyun 		return ERR_PTR(-ENOMEM);
922*4882a593Smuzhiyun 	fid->fid_family = fid_family;
923*4882a593Smuzhiyun 
924*4882a593Smuzhiyun 	err = fid->fid_family->ops->index_alloc(fid, arg, &fid_index);
925*4882a593Smuzhiyun 	if (err)
926*4882a593Smuzhiyun 		goto err_index_alloc;
927*4882a593Smuzhiyun 	fid->fid_index = fid_index;
928*4882a593Smuzhiyun 	__set_bit(fid_index - fid_family->start_index, fid_family->fids_bitmap);
929*4882a593Smuzhiyun 
930*4882a593Smuzhiyun 	if (fid->fid_family->ops->setup)
931*4882a593Smuzhiyun 		fid->fid_family->ops->setup(fid, arg);
932*4882a593Smuzhiyun 
933*4882a593Smuzhiyun 	err = fid->fid_family->ops->configure(fid);
934*4882a593Smuzhiyun 	if (err)
935*4882a593Smuzhiyun 		goto err_configure;
936*4882a593Smuzhiyun 
937*4882a593Smuzhiyun 	err = rhashtable_insert_fast(&mlxsw_sp->fid_core->fid_ht, &fid->ht_node,
938*4882a593Smuzhiyun 				     mlxsw_sp_fid_ht_params);
939*4882a593Smuzhiyun 	if (err)
940*4882a593Smuzhiyun 		goto err_rhashtable_insert;
941*4882a593Smuzhiyun 
942*4882a593Smuzhiyun 	list_add(&fid->list, &fid_family->fids_list);
943*4882a593Smuzhiyun 	refcount_set(&fid->ref_count, 1);
944*4882a593Smuzhiyun 	return fid;
945*4882a593Smuzhiyun 
946*4882a593Smuzhiyun err_rhashtable_insert:
947*4882a593Smuzhiyun 	fid->fid_family->ops->deconfigure(fid);
948*4882a593Smuzhiyun err_configure:
949*4882a593Smuzhiyun 	__clear_bit(fid_index - fid_family->start_index,
950*4882a593Smuzhiyun 		    fid_family->fids_bitmap);
951*4882a593Smuzhiyun err_index_alloc:
952*4882a593Smuzhiyun 	kfree(fid);
953*4882a593Smuzhiyun 	return ERR_PTR(err);
954*4882a593Smuzhiyun }
955*4882a593Smuzhiyun 
mlxsw_sp_fid_put(struct mlxsw_sp_fid * fid)956*4882a593Smuzhiyun void mlxsw_sp_fid_put(struct mlxsw_sp_fid *fid)
957*4882a593Smuzhiyun {
958*4882a593Smuzhiyun 	struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
959*4882a593Smuzhiyun 	struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
960*4882a593Smuzhiyun 
961*4882a593Smuzhiyun 	if (!refcount_dec_and_test(&fid->ref_count))
962*4882a593Smuzhiyun 		return;
963*4882a593Smuzhiyun 
964*4882a593Smuzhiyun 	list_del(&fid->list);
965*4882a593Smuzhiyun 	rhashtable_remove_fast(&mlxsw_sp->fid_core->fid_ht,
966*4882a593Smuzhiyun 			       &fid->ht_node, mlxsw_sp_fid_ht_params);
967*4882a593Smuzhiyun 	fid->fid_family->ops->deconfigure(fid);
968*4882a593Smuzhiyun 	__clear_bit(fid->fid_index - fid_family->start_index,
969*4882a593Smuzhiyun 		    fid_family->fids_bitmap);
970*4882a593Smuzhiyun 	kfree(fid);
971*4882a593Smuzhiyun }
972*4882a593Smuzhiyun 
mlxsw_sp_fid_8021q_get(struct mlxsw_sp * mlxsw_sp,u16 vid)973*4882a593Smuzhiyun struct mlxsw_sp_fid *mlxsw_sp_fid_8021q_get(struct mlxsw_sp *mlxsw_sp, u16 vid)
974*4882a593Smuzhiyun {
975*4882a593Smuzhiyun 	return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_8021Q, &vid);
976*4882a593Smuzhiyun }
977*4882a593Smuzhiyun 
mlxsw_sp_fid_8021d_get(struct mlxsw_sp * mlxsw_sp,int br_ifindex)978*4882a593Smuzhiyun struct mlxsw_sp_fid *mlxsw_sp_fid_8021d_get(struct mlxsw_sp *mlxsw_sp,
979*4882a593Smuzhiyun 					    int br_ifindex)
980*4882a593Smuzhiyun {
981*4882a593Smuzhiyun 	return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_8021D, &br_ifindex);
982*4882a593Smuzhiyun }
983*4882a593Smuzhiyun 
mlxsw_sp_fid_8021q_lookup(struct mlxsw_sp * mlxsw_sp,u16 vid)984*4882a593Smuzhiyun struct mlxsw_sp_fid *mlxsw_sp_fid_8021q_lookup(struct mlxsw_sp *mlxsw_sp,
985*4882a593Smuzhiyun 					       u16 vid)
986*4882a593Smuzhiyun {
987*4882a593Smuzhiyun 	return mlxsw_sp_fid_lookup(mlxsw_sp, MLXSW_SP_FID_TYPE_8021Q, &vid);
988*4882a593Smuzhiyun }
989*4882a593Smuzhiyun 
mlxsw_sp_fid_8021d_lookup(struct mlxsw_sp * mlxsw_sp,int br_ifindex)990*4882a593Smuzhiyun struct mlxsw_sp_fid *mlxsw_sp_fid_8021d_lookup(struct mlxsw_sp *mlxsw_sp,
991*4882a593Smuzhiyun 					       int br_ifindex)
992*4882a593Smuzhiyun {
993*4882a593Smuzhiyun 	return mlxsw_sp_fid_lookup(mlxsw_sp, MLXSW_SP_FID_TYPE_8021D,
994*4882a593Smuzhiyun 				   &br_ifindex);
995*4882a593Smuzhiyun }
996*4882a593Smuzhiyun 
mlxsw_sp_fid_rfid_get(struct mlxsw_sp * mlxsw_sp,u16 rif_index)997*4882a593Smuzhiyun struct mlxsw_sp_fid *mlxsw_sp_fid_rfid_get(struct mlxsw_sp *mlxsw_sp,
998*4882a593Smuzhiyun 					   u16 rif_index)
999*4882a593Smuzhiyun {
1000*4882a593Smuzhiyun 	return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_RFID, &rif_index);
1001*4882a593Smuzhiyun }
1002*4882a593Smuzhiyun 
mlxsw_sp_fid_dummy_get(struct mlxsw_sp * mlxsw_sp)1003*4882a593Smuzhiyun struct mlxsw_sp_fid *mlxsw_sp_fid_dummy_get(struct mlxsw_sp *mlxsw_sp)
1004*4882a593Smuzhiyun {
1005*4882a593Smuzhiyun 	return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_DUMMY, NULL);
1006*4882a593Smuzhiyun }
1007*4882a593Smuzhiyun 
1008*4882a593Smuzhiyun static int
mlxsw_sp_fid_flood_table_init(struct mlxsw_sp_fid_family * fid_family,const struct mlxsw_sp_flood_table * flood_table)1009*4882a593Smuzhiyun mlxsw_sp_fid_flood_table_init(struct mlxsw_sp_fid_family *fid_family,
1010*4882a593Smuzhiyun 			      const struct mlxsw_sp_flood_table *flood_table)
1011*4882a593Smuzhiyun {
1012*4882a593Smuzhiyun 	enum mlxsw_sp_flood_type packet_type = flood_table->packet_type;
1013*4882a593Smuzhiyun 	const int *sfgc_packet_types;
1014*4882a593Smuzhiyun 	int i;
1015*4882a593Smuzhiyun 
1016*4882a593Smuzhiyun 	sfgc_packet_types = mlxsw_sp_packet_type_sfgc_types[packet_type];
1017*4882a593Smuzhiyun 	for (i = 0; i < MLXSW_REG_SFGC_TYPE_MAX; i++) {
1018*4882a593Smuzhiyun 		struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
1019*4882a593Smuzhiyun 		char sfgc_pl[MLXSW_REG_SFGC_LEN];
1020*4882a593Smuzhiyun 		int err;
1021*4882a593Smuzhiyun 
1022*4882a593Smuzhiyun 		if (!sfgc_packet_types[i])
1023*4882a593Smuzhiyun 			continue;
1024*4882a593Smuzhiyun 		mlxsw_reg_sfgc_pack(sfgc_pl, i, flood_table->bridge_type,
1025*4882a593Smuzhiyun 				    flood_table->table_type,
1026*4882a593Smuzhiyun 				    flood_table->table_index);
1027*4882a593Smuzhiyun 		err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfgc), sfgc_pl);
1028*4882a593Smuzhiyun 		if (err)
1029*4882a593Smuzhiyun 			return err;
1030*4882a593Smuzhiyun 	}
1031*4882a593Smuzhiyun 
1032*4882a593Smuzhiyun 	return 0;
1033*4882a593Smuzhiyun }
1034*4882a593Smuzhiyun 
1035*4882a593Smuzhiyun static int
mlxsw_sp_fid_flood_tables_init(struct mlxsw_sp_fid_family * fid_family)1036*4882a593Smuzhiyun mlxsw_sp_fid_flood_tables_init(struct mlxsw_sp_fid_family *fid_family)
1037*4882a593Smuzhiyun {
1038*4882a593Smuzhiyun 	int i;
1039*4882a593Smuzhiyun 
1040*4882a593Smuzhiyun 	for (i = 0; i < fid_family->nr_flood_tables; i++) {
1041*4882a593Smuzhiyun 		const struct mlxsw_sp_flood_table *flood_table;
1042*4882a593Smuzhiyun 		int err;
1043*4882a593Smuzhiyun 
1044*4882a593Smuzhiyun 		flood_table = &fid_family->flood_tables[i];
1045*4882a593Smuzhiyun 		err = mlxsw_sp_fid_flood_table_init(fid_family, flood_table);
1046*4882a593Smuzhiyun 		if (err)
1047*4882a593Smuzhiyun 			return err;
1048*4882a593Smuzhiyun 	}
1049*4882a593Smuzhiyun 
1050*4882a593Smuzhiyun 	return 0;
1051*4882a593Smuzhiyun }
1052*4882a593Smuzhiyun 
mlxsw_sp_fid_family_register(struct mlxsw_sp * mlxsw_sp,const struct mlxsw_sp_fid_family * tmpl)1053*4882a593Smuzhiyun static int mlxsw_sp_fid_family_register(struct mlxsw_sp *mlxsw_sp,
1054*4882a593Smuzhiyun 					const struct mlxsw_sp_fid_family *tmpl)
1055*4882a593Smuzhiyun {
1056*4882a593Smuzhiyun 	u16 nr_fids = tmpl->end_index - tmpl->start_index + 1;
1057*4882a593Smuzhiyun 	struct mlxsw_sp_fid_family *fid_family;
1058*4882a593Smuzhiyun 	int err;
1059*4882a593Smuzhiyun 
1060*4882a593Smuzhiyun 	fid_family = kmemdup(tmpl, sizeof(*fid_family), GFP_KERNEL);
1061*4882a593Smuzhiyun 	if (!fid_family)
1062*4882a593Smuzhiyun 		return -ENOMEM;
1063*4882a593Smuzhiyun 
1064*4882a593Smuzhiyun 	fid_family->mlxsw_sp = mlxsw_sp;
1065*4882a593Smuzhiyun 	INIT_LIST_HEAD(&fid_family->fids_list);
1066*4882a593Smuzhiyun 	fid_family->fids_bitmap = bitmap_zalloc(nr_fids, GFP_KERNEL);
1067*4882a593Smuzhiyun 	if (!fid_family->fids_bitmap) {
1068*4882a593Smuzhiyun 		err = -ENOMEM;
1069*4882a593Smuzhiyun 		goto err_alloc_fids_bitmap;
1070*4882a593Smuzhiyun 	}
1071*4882a593Smuzhiyun 
1072*4882a593Smuzhiyun 	if (fid_family->flood_tables) {
1073*4882a593Smuzhiyun 		err = mlxsw_sp_fid_flood_tables_init(fid_family);
1074*4882a593Smuzhiyun 		if (err)
1075*4882a593Smuzhiyun 			goto err_fid_flood_tables_init;
1076*4882a593Smuzhiyun 	}
1077*4882a593Smuzhiyun 
1078*4882a593Smuzhiyun 	mlxsw_sp->fid_core->fid_family_arr[tmpl->type] = fid_family;
1079*4882a593Smuzhiyun 
1080*4882a593Smuzhiyun 	return 0;
1081*4882a593Smuzhiyun 
1082*4882a593Smuzhiyun err_fid_flood_tables_init:
1083*4882a593Smuzhiyun 	bitmap_free(fid_family->fids_bitmap);
1084*4882a593Smuzhiyun err_alloc_fids_bitmap:
1085*4882a593Smuzhiyun 	kfree(fid_family);
1086*4882a593Smuzhiyun 	return err;
1087*4882a593Smuzhiyun }
1088*4882a593Smuzhiyun 
1089*4882a593Smuzhiyun static void
mlxsw_sp_fid_family_unregister(struct mlxsw_sp * mlxsw_sp,struct mlxsw_sp_fid_family * fid_family)1090*4882a593Smuzhiyun mlxsw_sp_fid_family_unregister(struct mlxsw_sp *mlxsw_sp,
1091*4882a593Smuzhiyun 			       struct mlxsw_sp_fid_family *fid_family)
1092*4882a593Smuzhiyun {
1093*4882a593Smuzhiyun 	mlxsw_sp->fid_core->fid_family_arr[fid_family->type] = NULL;
1094*4882a593Smuzhiyun 	bitmap_free(fid_family->fids_bitmap);
1095*4882a593Smuzhiyun 	WARN_ON_ONCE(!list_empty(&fid_family->fids_list));
1096*4882a593Smuzhiyun 	kfree(fid_family);
1097*4882a593Smuzhiyun }
1098*4882a593Smuzhiyun 
mlxsw_sp_port_fids_init(struct mlxsw_sp_port * mlxsw_sp_port)1099*4882a593Smuzhiyun int mlxsw_sp_port_fids_init(struct mlxsw_sp_port *mlxsw_sp_port)
1100*4882a593Smuzhiyun {
1101*4882a593Smuzhiyun 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1102*4882a593Smuzhiyun 
1103*4882a593Smuzhiyun 	/* Track number of FIDs configured on the port with mapping type
1104*4882a593Smuzhiyun 	 * PORT_VID_TO_FID, so that we know when to transition the port
1105*4882a593Smuzhiyun 	 * back to non-virtual (VLAN) mode.
1106*4882a593Smuzhiyun 	 */
1107*4882a593Smuzhiyun 	mlxsw_sp->fid_core->port_fid_mappings[mlxsw_sp_port->local_port] = 0;
1108*4882a593Smuzhiyun 
1109*4882a593Smuzhiyun 	return mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, false);
1110*4882a593Smuzhiyun }
1111*4882a593Smuzhiyun 
mlxsw_sp_port_fids_fini(struct mlxsw_sp_port * mlxsw_sp_port)1112*4882a593Smuzhiyun void mlxsw_sp_port_fids_fini(struct mlxsw_sp_port *mlxsw_sp_port)
1113*4882a593Smuzhiyun {
1114*4882a593Smuzhiyun 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1115*4882a593Smuzhiyun 
1116*4882a593Smuzhiyun 	mlxsw_sp->fid_core->port_fid_mappings[mlxsw_sp_port->local_port] = 0;
1117*4882a593Smuzhiyun }
1118*4882a593Smuzhiyun 
mlxsw_sp_fids_init(struct mlxsw_sp * mlxsw_sp)1119*4882a593Smuzhiyun int mlxsw_sp_fids_init(struct mlxsw_sp *mlxsw_sp)
1120*4882a593Smuzhiyun {
1121*4882a593Smuzhiyun 	unsigned int max_ports = mlxsw_core_max_ports(mlxsw_sp->core);
1122*4882a593Smuzhiyun 	struct mlxsw_sp_fid_core *fid_core;
1123*4882a593Smuzhiyun 	int err, i;
1124*4882a593Smuzhiyun 
1125*4882a593Smuzhiyun 	fid_core = kzalloc(sizeof(*mlxsw_sp->fid_core), GFP_KERNEL);
1126*4882a593Smuzhiyun 	if (!fid_core)
1127*4882a593Smuzhiyun 		return -ENOMEM;
1128*4882a593Smuzhiyun 	mlxsw_sp->fid_core = fid_core;
1129*4882a593Smuzhiyun 
1130*4882a593Smuzhiyun 	err = rhashtable_init(&fid_core->fid_ht, &mlxsw_sp_fid_ht_params);
1131*4882a593Smuzhiyun 	if (err)
1132*4882a593Smuzhiyun 		goto err_rhashtable_fid_init;
1133*4882a593Smuzhiyun 
1134*4882a593Smuzhiyun 	err = rhashtable_init(&fid_core->vni_ht, &mlxsw_sp_fid_vni_ht_params);
1135*4882a593Smuzhiyun 	if (err)
1136*4882a593Smuzhiyun 		goto err_rhashtable_vni_init;
1137*4882a593Smuzhiyun 
1138*4882a593Smuzhiyun 	fid_core->port_fid_mappings = kcalloc(max_ports, sizeof(unsigned int),
1139*4882a593Smuzhiyun 					      GFP_KERNEL);
1140*4882a593Smuzhiyun 	if (!fid_core->port_fid_mappings) {
1141*4882a593Smuzhiyun 		err = -ENOMEM;
1142*4882a593Smuzhiyun 		goto err_alloc_port_fid_mappings;
1143*4882a593Smuzhiyun 	}
1144*4882a593Smuzhiyun 
1145*4882a593Smuzhiyun 	for (i = 0; i < MLXSW_SP_FID_TYPE_MAX; i++) {
1146*4882a593Smuzhiyun 		err = mlxsw_sp_fid_family_register(mlxsw_sp,
1147*4882a593Smuzhiyun 						   mlxsw_sp_fid_family_arr[i]);
1148*4882a593Smuzhiyun 
1149*4882a593Smuzhiyun 		if (err)
1150*4882a593Smuzhiyun 			goto err_fid_ops_register;
1151*4882a593Smuzhiyun 	}
1152*4882a593Smuzhiyun 
1153*4882a593Smuzhiyun 	return 0;
1154*4882a593Smuzhiyun 
1155*4882a593Smuzhiyun err_fid_ops_register:
1156*4882a593Smuzhiyun 	for (i--; i >= 0; i--) {
1157*4882a593Smuzhiyun 		struct mlxsw_sp_fid_family *fid_family;
1158*4882a593Smuzhiyun 
1159*4882a593Smuzhiyun 		fid_family = fid_core->fid_family_arr[i];
1160*4882a593Smuzhiyun 		mlxsw_sp_fid_family_unregister(mlxsw_sp, fid_family);
1161*4882a593Smuzhiyun 	}
1162*4882a593Smuzhiyun 	kfree(fid_core->port_fid_mappings);
1163*4882a593Smuzhiyun err_alloc_port_fid_mappings:
1164*4882a593Smuzhiyun 	rhashtable_destroy(&fid_core->vni_ht);
1165*4882a593Smuzhiyun err_rhashtable_vni_init:
1166*4882a593Smuzhiyun 	rhashtable_destroy(&fid_core->fid_ht);
1167*4882a593Smuzhiyun err_rhashtable_fid_init:
1168*4882a593Smuzhiyun 	kfree(fid_core);
1169*4882a593Smuzhiyun 	return err;
1170*4882a593Smuzhiyun }
1171*4882a593Smuzhiyun 
mlxsw_sp_fids_fini(struct mlxsw_sp * mlxsw_sp)1172*4882a593Smuzhiyun void mlxsw_sp_fids_fini(struct mlxsw_sp *mlxsw_sp)
1173*4882a593Smuzhiyun {
1174*4882a593Smuzhiyun 	struct mlxsw_sp_fid_core *fid_core = mlxsw_sp->fid_core;
1175*4882a593Smuzhiyun 	int i;
1176*4882a593Smuzhiyun 
1177*4882a593Smuzhiyun 	for (i = 0; i < MLXSW_SP_FID_TYPE_MAX; i++)
1178*4882a593Smuzhiyun 		mlxsw_sp_fid_family_unregister(mlxsw_sp,
1179*4882a593Smuzhiyun 					       fid_core->fid_family_arr[i]);
1180*4882a593Smuzhiyun 	kfree(fid_core->port_fid_mappings);
1181*4882a593Smuzhiyun 	rhashtable_destroy(&fid_core->vni_ht);
1182*4882a593Smuzhiyun 	rhashtable_destroy(&fid_core->fid_ht);
1183*4882a593Smuzhiyun 	kfree(fid_core);
1184*4882a593Smuzhiyun }
1185