GNU Linux-libre 6.8.9-gnu
[releases.git] / drivers / net / ethernet / mellanox / mlxsw / spectrum_fid.c
1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /* Copyright (c) 2017-2018 Mellanox Technologies. All rights reserved */
3
4 #include <linux/kernel.h>
5 #include <linux/bitops.h>
6 #include <linux/if_vlan.h>
7 #include <linux/if_bridge.h>
8 #include <linux/netdevice.h>
9 #include <linux/rhashtable.h>
10 #include <linux/rtnetlink.h>
11 #include <linux/refcount.h>
12
13 #include "spectrum.h"
14 #include "spectrum_router.h"
15 #include "reg.h"
16
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
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
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
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
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
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
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
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
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
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
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
335 bool mlxsw_sp_fid_vni_is_set(const struct mlxsw_sp_fid *fid)
336 {
337         return fid->vni_valid;
338 }
339
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 *
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
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
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
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
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
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
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
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
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
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
467 u16 mlxsw_sp_fid_index(const struct mlxsw_sp_fid *fid)
468 {
469         return fid->fid_index;
470 }
471
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
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
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 *
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 *
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
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
923 static int mlxsw_sp_fid_8021d_configure(struct mlxsw_sp_fid *fid)
924 {
925         return mlxsw_sp_fid_op(fid, true);
926 }
927
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
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
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
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
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
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
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
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
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
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
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
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
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
1176 static void mlxsw_sp_fid_8021d_vni_clear(struct mlxsw_sp_fid *fid)
1177 {
1178         mlxsw_sp_fid_vni_op(fid);
1179 }
1180
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
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
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
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
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
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
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
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
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
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
1387 static int mlxsw_sp_fid_rfid_configure(struct mlxsw_sp_fid *fid)
1388 {
1389         return mlxsw_sp_fid_op(fid, true);
1390 }
1391
1392 static void mlxsw_sp_fid_rfid_deconfigure(struct mlxsw_sp_fid *fid)
1393 {
1394         mlxsw_sp_fid_op(fid, false);
1395 }
1396
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
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
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
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
1483 static int mlxsw_sp_fid_rfid_vni_set(struct mlxsw_sp_fid *fid)
1484 {
1485         return -EOPNOTSUPP;
1486 }
1487
1488 static void mlxsw_sp_fid_rfid_vni_clear(struct mlxsw_sp_fid *fid)
1489 {
1490         WARN_ON_ONCE(1);
1491 }
1492
1493 static int mlxsw_sp_fid_rfid_nve_flood_index_set(struct mlxsw_sp_fid *fid)
1494 {
1495         return -EOPNOTSUPP;
1496 }
1497
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
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
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
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
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
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
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
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
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
1665 static int mlxsw_sp_fid_dummy_configure(struct mlxsw_sp_fid *fid)
1666 {
1667         return mlxsw_sp_fid_op(fid, true);
1668 }
1669
1670 static void mlxsw_sp_fid_dummy_deconfigure(struct mlxsw_sp_fid *fid)
1671 {
1672         mlxsw_sp_fid_op(fid, false);
1673 }
1674
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
1683 static bool mlxsw_sp_fid_dummy_compare(const struct mlxsw_sp_fid *fid,
1684                                        const void *arg)
1685 {
1686         return true;
1687 }
1688
1689 static int mlxsw_sp_fid_dummy_vni_set(struct mlxsw_sp_fid *fid)
1690 {
1691         return -EOPNOTSUPP;
1692 }
1693
1694 static void mlxsw_sp_fid_dummy_vni_clear(struct mlxsw_sp_fid *fid)
1695 {
1696         WARN_ON_ONCE(1);
1697 }
1698
1699 static int mlxsw_sp_fid_dummy_nve_flood_index_set(struct mlxsw_sp_fid *fid)
1700 {
1701         return -EOPNOTSUPP;
1702 }
1703
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 };