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