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