Merge tag 'asm-generic-6.5' of git://git.kernel.org/pub/scm/linux/kernel/git/arnd...
[linux-block.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 "reg.h"
15
16 struct mlxsw_sp_fid_family;
17
18 struct mlxsw_sp_fid_core {
19         struct rhashtable fid_ht;
20         struct rhashtable vni_ht;
21         struct mlxsw_sp_fid_family *fid_family_arr[MLXSW_SP_FID_TYPE_MAX];
22         unsigned int *port_fid_mappings;
23 };
24
25 struct mlxsw_sp_fid_port_vid {
26         struct list_head list;
27         u16 local_port;
28         u16 vid;
29 };
30
31 struct mlxsw_sp_fid {
32         struct list_head list;
33         struct mlxsw_sp_rif *rif;
34         refcount_t ref_count;
35         u16 fid_index;
36         u16 fid_offset;
37         struct mlxsw_sp_fid_family *fid_family;
38         struct rhash_head ht_node;
39
40         struct rhash_head vni_ht_node;
41         enum mlxsw_sp_nve_type nve_type;
42         __be32 vni;
43         u32 nve_flood_index;
44         int nve_ifindex;
45         u8 vni_valid:1,
46            nve_flood_index_valid:1;
47         struct list_head port_vid_list; /* Ordered by local port. */
48 };
49
50 struct mlxsw_sp_fid_8021q {
51         struct mlxsw_sp_fid common;
52         u16 vid;
53 };
54
55 struct mlxsw_sp_fid_8021d {
56         struct mlxsw_sp_fid common;
57         int br_ifindex;
58 };
59
60 static const struct rhashtable_params mlxsw_sp_fid_ht_params = {
61         .key_len = sizeof_field(struct mlxsw_sp_fid, fid_index),
62         .key_offset = offsetof(struct mlxsw_sp_fid, fid_index),
63         .head_offset = offsetof(struct mlxsw_sp_fid, ht_node),
64 };
65
66 static const struct rhashtable_params mlxsw_sp_fid_vni_ht_params = {
67         .key_len = sizeof_field(struct mlxsw_sp_fid, vni),
68         .key_offset = offsetof(struct mlxsw_sp_fid, vni),
69         .head_offset = offsetof(struct mlxsw_sp_fid, vni_ht_node),
70 };
71
72 struct mlxsw_sp_flood_table {
73         enum mlxsw_sp_flood_type packet_type;
74         enum mlxsw_flood_table_type table_type;
75         int table_index;
76 };
77
78 struct mlxsw_sp_fid_ops {
79         void (*setup)(struct mlxsw_sp_fid *fid, const void *arg);
80         int (*configure)(struct mlxsw_sp_fid *fid);
81         void (*deconfigure)(struct mlxsw_sp_fid *fid);
82         int (*index_alloc)(struct mlxsw_sp_fid *fid, const void *arg,
83                            u16 *p_fid_index);
84         bool (*compare)(const struct mlxsw_sp_fid *fid,
85                         const void *arg);
86         int (*port_vid_map)(struct mlxsw_sp_fid *fid,
87                             struct mlxsw_sp_port *port, u16 vid);
88         void (*port_vid_unmap)(struct mlxsw_sp_fid *fid,
89                                struct mlxsw_sp_port *port, u16 vid);
90         int (*vni_set)(struct mlxsw_sp_fid *fid);
91         void (*vni_clear)(struct mlxsw_sp_fid *fid);
92         int (*nve_flood_index_set)(struct mlxsw_sp_fid *fid);
93         void (*nve_flood_index_clear)(struct mlxsw_sp_fid *fid);
94         void (*fdb_clear_offload)(const struct mlxsw_sp_fid *fid,
95                                   const struct net_device *nve_dev);
96         int (*vid_to_fid_rif_update)(const struct mlxsw_sp_fid *fid,
97                                      const struct mlxsw_sp_rif *rif);
98 };
99
100 struct mlxsw_sp_fid_family {
101         enum mlxsw_sp_fid_type type;
102         size_t fid_size;
103         u16 start_index;
104         u16 end_index;
105         struct list_head fids_list;
106         unsigned long *fids_bitmap;
107         const struct mlxsw_sp_flood_table *flood_tables;
108         int nr_flood_tables;
109         enum mlxsw_sp_rif_type rif_type;
110         const struct mlxsw_sp_fid_ops *ops;
111         struct mlxsw_sp *mlxsw_sp;
112         bool flood_rsp;
113         enum mlxsw_reg_bridge_type bridge_type;
114         u16 pgt_base;
115         bool smpe_index_valid;
116 };
117
118 static const int mlxsw_sp_sfgc_uc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = {
119         [MLXSW_REG_SFGC_TYPE_UNKNOWN_UNICAST]                   = 1,
120 };
121
122 static const int mlxsw_sp_sfgc_bc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = {
123         [MLXSW_REG_SFGC_TYPE_BROADCAST]                         = 1,
124         [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_NON_IP]     = 1,
125         [MLXSW_REG_SFGC_TYPE_IPV4_LINK_LOCAL]                   = 1,
126         [MLXSW_REG_SFGC_TYPE_IPV6_ALL_HOST]                     = 1,
127         [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV6]       = 1,
128 };
129
130 static const int mlxsw_sp_sfgc_mc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = {
131         [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV4]       = 1,
132 };
133
134 static const int *mlxsw_sp_packet_type_sfgc_types[] = {
135         [MLXSW_SP_FLOOD_TYPE_UC]        = mlxsw_sp_sfgc_uc_packet_types,
136         [MLXSW_SP_FLOOD_TYPE_BC]        = mlxsw_sp_sfgc_bc_packet_types,
137         [MLXSW_SP_FLOOD_TYPE_MC]        = mlxsw_sp_sfgc_mc_packet_types,
138 };
139
140 bool mlxsw_sp_fid_is_dummy(struct mlxsw_sp *mlxsw_sp, u16 fid_index)
141 {
142         enum mlxsw_sp_fid_type fid_type = MLXSW_SP_FID_TYPE_DUMMY;
143         struct mlxsw_sp_fid_family *fid_family;
144
145         fid_family = mlxsw_sp->fid_core->fid_family_arr[fid_type];
146
147         return fid_family->start_index == fid_index;
148 }
149
150 struct mlxsw_sp_fid *mlxsw_sp_fid_lookup_by_index(struct mlxsw_sp *mlxsw_sp,
151                                                   u16 fid_index)
152 {
153         struct mlxsw_sp_fid *fid;
154
155         fid = rhashtable_lookup_fast(&mlxsw_sp->fid_core->fid_ht, &fid_index,
156                                      mlxsw_sp_fid_ht_params);
157         if (fid)
158                 refcount_inc(&fid->ref_count);
159
160         return fid;
161 }
162
163 int mlxsw_sp_fid_nve_ifindex(const struct mlxsw_sp_fid *fid, int *nve_ifindex)
164 {
165         if (!fid->vni_valid)
166                 return -EINVAL;
167
168         *nve_ifindex = fid->nve_ifindex;
169
170         return 0;
171 }
172
173 int mlxsw_sp_fid_nve_type(const struct mlxsw_sp_fid *fid,
174                           enum mlxsw_sp_nve_type *p_type)
175 {
176         if (!fid->vni_valid)
177                 return -EINVAL;
178
179         *p_type = fid->nve_type;
180
181         return 0;
182 }
183
184 struct mlxsw_sp_fid *mlxsw_sp_fid_lookup_by_vni(struct mlxsw_sp *mlxsw_sp,
185                                                 __be32 vni)
186 {
187         struct mlxsw_sp_fid *fid;
188
189         fid = rhashtable_lookup_fast(&mlxsw_sp->fid_core->vni_ht, &vni,
190                                      mlxsw_sp_fid_vni_ht_params);
191         if (fid)
192                 refcount_inc(&fid->ref_count);
193
194         return fid;
195 }
196
197 int mlxsw_sp_fid_vni(const struct mlxsw_sp_fid *fid, __be32 *vni)
198 {
199         if (!fid->vni_valid)
200                 return -EINVAL;
201
202         *vni = fid->vni;
203
204         return 0;
205 }
206
207 int mlxsw_sp_fid_nve_flood_index_set(struct mlxsw_sp_fid *fid,
208                                      u32 nve_flood_index)
209 {
210         struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
211         const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
212         int err;
213
214         if (WARN_ON(fid->nve_flood_index_valid))
215                 return -EINVAL;
216
217         fid->nve_flood_index = nve_flood_index;
218         fid->nve_flood_index_valid = true;
219         err = ops->nve_flood_index_set(fid);
220         if (err)
221                 goto err_nve_flood_index_set;
222
223         return 0;
224
225 err_nve_flood_index_set:
226         fid->nve_flood_index_valid = false;
227         return err;
228 }
229
230 void mlxsw_sp_fid_nve_flood_index_clear(struct mlxsw_sp_fid *fid)
231 {
232         struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
233         const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
234
235         if (WARN_ON(!fid->nve_flood_index_valid))
236                 return;
237
238         fid->nve_flood_index_valid = false;
239         ops->nve_flood_index_clear(fid);
240 }
241
242 bool mlxsw_sp_fid_nve_flood_index_is_set(const struct mlxsw_sp_fid *fid)
243 {
244         return fid->nve_flood_index_valid;
245 }
246
247 int mlxsw_sp_fid_vni_set(struct mlxsw_sp_fid *fid, enum mlxsw_sp_nve_type type,
248                          __be32 vni, int nve_ifindex)
249 {
250         struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
251         const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
252         struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
253         int err;
254
255         if (WARN_ON(fid->vni_valid))
256                 return -EINVAL;
257
258         fid->nve_type = type;
259         fid->nve_ifindex = nve_ifindex;
260         fid->vni = vni;
261         err = rhashtable_lookup_insert_fast(&mlxsw_sp->fid_core->vni_ht,
262                                             &fid->vni_ht_node,
263                                             mlxsw_sp_fid_vni_ht_params);
264         if (err)
265                 return err;
266
267         fid->vni_valid = true;
268         err = ops->vni_set(fid);
269         if (err)
270                 goto err_vni_set;
271
272         return 0;
273
274 err_vni_set:
275         fid->vni_valid = false;
276         rhashtable_remove_fast(&mlxsw_sp->fid_core->vni_ht, &fid->vni_ht_node,
277                                mlxsw_sp_fid_vni_ht_params);
278         return err;
279 }
280
281 void mlxsw_sp_fid_vni_clear(struct mlxsw_sp_fid *fid)
282 {
283         struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
284         const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
285         struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
286
287         if (WARN_ON(!fid->vni_valid))
288                 return;
289
290         fid->vni_valid = false;
291         ops->vni_clear(fid);
292         rhashtable_remove_fast(&mlxsw_sp->fid_core->vni_ht, &fid->vni_ht_node,
293                                mlxsw_sp_fid_vni_ht_params);
294 }
295
296 bool mlxsw_sp_fid_vni_is_set(const struct mlxsw_sp_fid *fid)
297 {
298         return fid->vni_valid;
299 }
300
301 void mlxsw_sp_fid_fdb_clear_offload(const struct mlxsw_sp_fid *fid,
302                                     const struct net_device *nve_dev)
303 {
304         struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
305         const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
306
307         if (ops->fdb_clear_offload)
308                 ops->fdb_clear_offload(fid, nve_dev);
309 }
310
311 static const struct mlxsw_sp_flood_table *
312 mlxsw_sp_fid_flood_table_lookup(const struct mlxsw_sp_fid *fid,
313                                 enum mlxsw_sp_flood_type packet_type)
314 {
315         struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
316         int i;
317
318         for (i = 0; i < fid_family->nr_flood_tables; i++) {
319                 if (fid_family->flood_tables[i].packet_type != packet_type)
320                         continue;
321                 return &fid_family->flood_tables[i];
322         }
323
324         return NULL;
325 }
326
327 static u16
328 mlxsw_sp_fid_family_num_fids(const struct mlxsw_sp_fid_family *fid_family)
329 {
330         return fid_family->end_index - fid_family->start_index + 1;
331 }
332
333 static u16
334 mlxsw_sp_fid_flood_table_mid(const struct mlxsw_sp_fid_family *fid_family,
335                              const struct mlxsw_sp_flood_table *flood_table,
336                              u16 fid_offset)
337 {
338         u16 num_fids;
339
340         num_fids = mlxsw_sp_fid_family_num_fids(fid_family);
341         return fid_family->pgt_base + num_fids * flood_table->table_index +
342                fid_offset;
343 }
344
345 int mlxsw_sp_fid_flood_set(struct mlxsw_sp_fid *fid,
346                            enum mlxsw_sp_flood_type packet_type, u16 local_port,
347                            bool member)
348 {
349         struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
350         const struct mlxsw_sp_flood_table *flood_table;
351         u16 mid_index;
352
353         if (WARN_ON(!fid_family->flood_tables))
354                 return -EINVAL;
355
356         flood_table = mlxsw_sp_fid_flood_table_lookup(fid, packet_type);
357         if (!flood_table)
358                 return -ESRCH;
359
360         mid_index = mlxsw_sp_fid_flood_table_mid(fid_family, flood_table,
361                                                  fid->fid_offset);
362         return mlxsw_sp_pgt_entry_port_set(fid_family->mlxsw_sp, mid_index,
363                                            fid->fid_index, local_port, member);
364 }
365
366 int mlxsw_sp_fid_port_vid_map(struct mlxsw_sp_fid *fid,
367                               struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
368 {
369         if (WARN_ON(!fid->fid_family->ops->port_vid_map))
370                 return -EINVAL;
371         return fid->fid_family->ops->port_vid_map(fid, mlxsw_sp_port, vid);
372 }
373
374 void mlxsw_sp_fid_port_vid_unmap(struct mlxsw_sp_fid *fid,
375                                  struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
376 {
377         fid->fid_family->ops->port_vid_unmap(fid, mlxsw_sp_port, vid);
378 }
379
380 u16 mlxsw_sp_fid_index(const struct mlxsw_sp_fid *fid)
381 {
382         return fid->fid_index;
383 }
384
385 enum mlxsw_sp_fid_type mlxsw_sp_fid_type(const struct mlxsw_sp_fid *fid)
386 {
387         return fid->fid_family->type;
388 }
389
390 struct mlxsw_sp_rif *mlxsw_sp_fid_rif(const struct mlxsw_sp_fid *fid)
391 {
392         return fid->rif;
393 }
394
395 enum mlxsw_sp_rif_type
396 mlxsw_sp_fid_type_rif_type(const struct mlxsw_sp *mlxsw_sp,
397                            enum mlxsw_sp_fid_type type)
398 {
399         struct mlxsw_sp_fid_core *fid_core = mlxsw_sp->fid_core;
400
401         return fid_core->fid_family_arr[type]->rif_type;
402 }
403
404 static struct mlxsw_sp_fid_8021q *
405 mlxsw_sp_fid_8021q_fid(const struct mlxsw_sp_fid *fid)
406 {
407         return container_of(fid, struct mlxsw_sp_fid_8021q, common);
408 }
409
410 u16 mlxsw_sp_fid_8021q_vid(const struct mlxsw_sp_fid *fid)
411 {
412         return mlxsw_sp_fid_8021q_fid(fid)->vid;
413 }
414
415 static void mlxsw_sp_fid_8021q_setup(struct mlxsw_sp_fid *fid, const void *arg)
416 {
417         u16 vid = *(u16 *) arg;
418
419         mlxsw_sp_fid_8021q_fid(fid)->vid = vid;
420         fid->fid_offset = fid->fid_index - fid->fid_family->start_index;
421 }
422
423 static enum mlxsw_reg_sfmr_op mlxsw_sp_sfmr_op(bool valid)
424 {
425         return valid ? MLXSW_REG_SFMR_OP_CREATE_FID :
426                        MLXSW_REG_SFMR_OP_DESTROY_FID;
427 }
428
429 static int mlxsw_sp_fid_op(const struct mlxsw_sp_fid *fid, bool valid)
430 {
431         struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
432         char sfmr_pl[MLXSW_REG_SFMR_LEN];
433         u16 smpe;
434
435         smpe = fid->fid_family->smpe_index_valid ? fid->fid_index : 0;
436
437         mlxsw_reg_sfmr_pack(sfmr_pl, mlxsw_sp_sfmr_op(valid), fid->fid_index,
438                             fid->fid_offset, fid->fid_family->flood_rsp,
439                             fid->fid_family->bridge_type,
440                             fid->fid_family->smpe_index_valid, smpe);
441         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl);
442 }
443
444 static int mlxsw_sp_fid_edit_op(const struct mlxsw_sp_fid *fid,
445                                 const struct mlxsw_sp_rif *rif)
446 {
447         struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
448         char sfmr_pl[MLXSW_REG_SFMR_LEN];
449         u16 smpe;
450
451         smpe = fid->fid_family->smpe_index_valid ? fid->fid_index : 0;
452
453         mlxsw_reg_sfmr_pack(sfmr_pl, MLXSW_REG_SFMR_OP_CREATE_FID,
454                             fid->fid_index, fid->fid_offset,
455                             fid->fid_family->flood_rsp,
456                             fid->fid_family->bridge_type,
457                             fid->fid_family->smpe_index_valid, smpe);
458         mlxsw_reg_sfmr_vv_set(sfmr_pl, fid->vni_valid);
459         mlxsw_reg_sfmr_vni_set(sfmr_pl, be32_to_cpu(fid->vni));
460         mlxsw_reg_sfmr_vtfp_set(sfmr_pl, fid->nve_flood_index_valid);
461         mlxsw_reg_sfmr_nve_tunnel_flood_ptr_set(sfmr_pl, fid->nve_flood_index);
462
463         if (rif) {
464                 mlxsw_reg_sfmr_irif_v_set(sfmr_pl, true);
465                 mlxsw_reg_sfmr_irif_set(sfmr_pl, mlxsw_sp_rif_index(rif));
466         }
467
468         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl);
469 }
470
471 static int mlxsw_sp_fid_vni_to_fid_map(const struct mlxsw_sp_fid *fid,
472                                        const struct mlxsw_sp_rif *rif,
473                                        bool valid)
474 {
475         struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
476         char svfa_pl[MLXSW_REG_SVFA_LEN];
477         bool irif_valid;
478         u16 irif_index;
479
480         irif_valid = !!rif;
481         irif_index = rif ? mlxsw_sp_rif_index(rif) : 0;
482
483         mlxsw_reg_svfa_vni_pack(svfa_pl, valid, fid->fid_index,
484                                 be32_to_cpu(fid->vni), irif_valid, irif_index);
485         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl);
486 }
487
488 static int mlxsw_sp_fid_to_fid_rif_update(const struct mlxsw_sp_fid *fid,
489                                           const struct mlxsw_sp_rif *rif)
490 {
491         return mlxsw_sp_fid_edit_op(fid, rif);
492 }
493
494 static int mlxsw_sp_fid_vni_to_fid_rif_update(const struct mlxsw_sp_fid *fid,
495                                               const struct mlxsw_sp_rif *rif)
496 {
497         if (!fid->vni_valid)
498                 return 0;
499
500         return mlxsw_sp_fid_vni_to_fid_map(fid, rif, fid->vni_valid);
501 }
502
503 static int
504 mlxsw_sp_fid_vid_to_fid_map(const struct mlxsw_sp_fid *fid, u16 vid, bool valid,
505                             const struct mlxsw_sp_rif *rif)
506 {
507         struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
508         char svfa_pl[MLXSW_REG_SVFA_LEN];
509         bool irif_valid;
510         u16 irif_index;
511
512         irif_valid = !!rif;
513         irif_index = rif ? mlxsw_sp_rif_index(rif) : 0;
514
515         mlxsw_reg_svfa_vid_pack(svfa_pl, valid, fid->fid_index, vid, irif_valid,
516                                 irif_index);
517         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl);
518 }
519
520 static int
521 mlxsw_sp_fid_8021q_vid_to_fid_rif_update(const struct mlxsw_sp_fid *fid,
522                                          const struct mlxsw_sp_rif *rif)
523 {
524         struct mlxsw_sp_fid_8021q *fid_8021q = mlxsw_sp_fid_8021q_fid(fid);
525
526         /* Update the global VID => FID mapping we created when the FID was
527          * configured.
528          */
529         return mlxsw_sp_fid_vid_to_fid_map(fid, fid_8021q->vid, true, rif);
530 }
531
532 static int
533 mlxsw_sp_fid_port_vid_to_fid_rif_update_one(const struct mlxsw_sp_fid *fid,
534                                             struct mlxsw_sp_fid_port_vid *pv,
535                                             bool irif_valid, u16 irif_index)
536 {
537         struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
538         char svfa_pl[MLXSW_REG_SVFA_LEN];
539
540         mlxsw_reg_svfa_port_vid_pack(svfa_pl, pv->local_port, true,
541                                      fid->fid_index, pv->vid, irif_valid,
542                                      irif_index);
543
544         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl);
545 }
546
547 static int mlxsw_sp_fid_vid_to_fid_rif_set(const struct mlxsw_sp_fid *fid,
548                                            const struct mlxsw_sp_rif *rif)
549 {
550         struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
551         struct mlxsw_sp_fid_port_vid *pv;
552         u16 irif_index;
553         int err;
554
555         err = fid->fid_family->ops->vid_to_fid_rif_update(fid, rif);
556         if (err)
557                 return err;
558
559         irif_index = mlxsw_sp_rif_index(rif);
560
561         list_for_each_entry(pv, &fid->port_vid_list, list) {
562                 /* If port is not in virtual mode, then it does not have any
563                  * {Port, VID}->FID mappings that need to be updated with the
564                  * ingress RIF.
565                  */
566                 if (!mlxsw_sp->fid_core->port_fid_mappings[pv->local_port])
567                         continue;
568
569                 err = mlxsw_sp_fid_port_vid_to_fid_rif_update_one(fid, pv,
570                                                                   true,
571                                                                   irif_index);
572                 if (err)
573                         goto err_port_vid_to_fid_rif_update_one;
574         }
575
576         return 0;
577
578 err_port_vid_to_fid_rif_update_one:
579         list_for_each_entry_continue_reverse(pv, &fid->port_vid_list, list) {
580                 if (!mlxsw_sp->fid_core->port_fid_mappings[pv->local_port])
581                         continue;
582
583                 mlxsw_sp_fid_port_vid_to_fid_rif_update_one(fid, pv, false, 0);
584         }
585
586         fid->fid_family->ops->vid_to_fid_rif_update(fid, NULL);
587         return err;
588 }
589
590 static void mlxsw_sp_fid_vid_to_fid_rif_unset(const struct mlxsw_sp_fid *fid)
591 {
592         struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
593         struct mlxsw_sp_fid_port_vid *pv;
594
595         list_for_each_entry(pv, &fid->port_vid_list, list) {
596                 /* If port is not in virtual mode, then it does not have any
597                  * {Port, VID}->FID mappings that need to be updated.
598                  */
599                 if (!mlxsw_sp->fid_core->port_fid_mappings[pv->local_port])
600                         continue;
601
602                 mlxsw_sp_fid_port_vid_to_fid_rif_update_one(fid, pv, false, 0);
603         }
604
605         fid->fid_family->ops->vid_to_fid_rif_update(fid, NULL);
606 }
607
608 static int mlxsw_sp_fid_reiv_handle(struct mlxsw_sp_fid *fid, u16 rif_index,
609                                     bool valid, u8 port_page)
610 {
611         u16 local_port_end = (port_page + 1) * MLXSW_REG_REIV_REC_MAX_COUNT - 1;
612         u16 local_port_start = port_page * MLXSW_REG_REIV_REC_MAX_COUNT;
613         struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
614         struct mlxsw_sp_fid_port_vid *port_vid;
615         u8 rec_num, entries_num = 0;
616         char *reiv_pl;
617         int err;
618
619         reiv_pl = kmalloc(MLXSW_REG_REIV_LEN, GFP_KERNEL);
620         if (!reiv_pl)
621                 return -ENOMEM;
622
623         mlxsw_reg_reiv_pack(reiv_pl, port_page, rif_index);
624
625         list_for_each_entry(port_vid, &fid->port_vid_list, list) {
626                 /* port_vid_list is sorted by local_port. */
627                 if (port_vid->local_port < local_port_start)
628                         continue;
629
630                 if (port_vid->local_port > local_port_end)
631                         break;
632
633                 rec_num = port_vid->local_port % MLXSW_REG_REIV_REC_MAX_COUNT;
634                 mlxsw_reg_reiv_rec_update_set(reiv_pl, rec_num, true);
635                 mlxsw_reg_reiv_rec_evid_set(reiv_pl, rec_num,
636                                             valid ? port_vid->vid : 0);
637                 entries_num++;
638         }
639
640         if (!entries_num) {
641                 kfree(reiv_pl);
642                 return 0;
643         }
644
645         err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(reiv), reiv_pl);
646         if (err)
647                 goto err_reg_write;
648
649         kfree(reiv_pl);
650         return 0;
651
652 err_reg_write:
653         kfree(reiv_pl);
654         return err;
655 }
656
657 static int mlxsw_sp_fid_erif_eport_to_vid_map(struct mlxsw_sp_fid *fid,
658                                               u16 rif_index, bool valid)
659 {
660         struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
661         u8 num_port_pages;
662         int err, i;
663
664         num_port_pages = mlxsw_core_max_ports(mlxsw_sp->core) /
665                          MLXSW_REG_REIV_REC_MAX_COUNT + 1;
666
667         for (i = 0; i < num_port_pages; i++) {
668                 err = mlxsw_sp_fid_reiv_handle(fid, rif_index, valid, i);
669                 if (err)
670                         goto err_reiv_handle;
671         }
672
673         return 0;
674
675 err_reiv_handle:
676         for (; i >= 0; i--)
677                 mlxsw_sp_fid_reiv_handle(fid, rif_index, !valid, i);
678         return err;
679 }
680
681 int mlxsw_sp_fid_rif_set(struct mlxsw_sp_fid *fid, struct mlxsw_sp_rif *rif)
682 {
683         u16 rif_index = mlxsw_sp_rif_index(rif);
684         int err;
685
686         err = mlxsw_sp_fid_to_fid_rif_update(fid, rif);
687         if (err)
688                 return err;
689
690         err = mlxsw_sp_fid_vni_to_fid_rif_update(fid, rif);
691         if (err)
692                 goto err_vni_to_fid_rif_update;
693
694         err = mlxsw_sp_fid_vid_to_fid_rif_set(fid, rif);
695         if (err)
696                 goto err_vid_to_fid_rif_set;
697
698         err = mlxsw_sp_fid_erif_eport_to_vid_map(fid, rif_index, true);
699         if (err)
700                 goto err_erif_eport_to_vid_map;
701
702         fid->rif = rif;
703         return 0;
704
705 err_erif_eport_to_vid_map:
706         mlxsw_sp_fid_vid_to_fid_rif_unset(fid);
707 err_vid_to_fid_rif_set:
708         mlxsw_sp_fid_vni_to_fid_rif_update(fid, NULL);
709 err_vni_to_fid_rif_update:
710         mlxsw_sp_fid_to_fid_rif_update(fid, NULL);
711         return err;
712 }
713
714 void mlxsw_sp_fid_rif_unset(struct mlxsw_sp_fid *fid)
715 {
716         u16 rif_index;
717
718         if (!fid->rif)
719                 return;
720
721         rif_index = mlxsw_sp_rif_index(fid->rif);
722         fid->rif = NULL;
723
724         mlxsw_sp_fid_erif_eport_to_vid_map(fid, rif_index, false);
725         mlxsw_sp_fid_vid_to_fid_rif_unset(fid);
726         mlxsw_sp_fid_vni_to_fid_rif_update(fid, NULL);
727         mlxsw_sp_fid_to_fid_rif_update(fid, NULL);
728 }
729
730 static int mlxsw_sp_fid_vni_op(const struct mlxsw_sp_fid *fid)
731 {
732         int err;
733
734         err = mlxsw_sp_fid_vni_to_fid_map(fid, fid->rif, fid->vni_valid);
735         if (err)
736                 return err;
737
738         err = mlxsw_sp_fid_edit_op(fid, fid->rif);
739         if (err)
740                 goto err_fid_edit_op;
741
742         return 0;
743
744 err_fid_edit_op:
745         mlxsw_sp_fid_vni_to_fid_map(fid, fid->rif, !fid->vni_valid);
746         return err;
747 }
748
749 static int __mlxsw_sp_fid_port_vid_map(const struct mlxsw_sp_fid *fid,
750                                        u16 local_port, u16 vid, bool valid)
751 {
752         struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
753         char svfa_pl[MLXSW_REG_SVFA_LEN];
754         bool irif_valid = false;
755         u16 irif_index = 0;
756
757         if (fid->rif) {
758                 irif_valid = true;
759                 irif_index = mlxsw_sp_rif_index(fid->rif);
760         }
761
762         mlxsw_reg_svfa_port_vid_pack(svfa_pl, local_port, valid, fid->fid_index,
763                                      vid, irif_valid, irif_index);
764         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl);
765 }
766
767 static struct mlxsw_sp_fid_8021d *
768 mlxsw_sp_fid_8021d_fid(const struct mlxsw_sp_fid *fid)
769 {
770         return container_of(fid, struct mlxsw_sp_fid_8021d, common);
771 }
772
773 static void mlxsw_sp_fid_8021d_setup(struct mlxsw_sp_fid *fid, const void *arg)
774 {
775         int br_ifindex = *(int *) arg;
776
777         mlxsw_sp_fid_8021d_fid(fid)->br_ifindex = br_ifindex;
778         fid->fid_offset = fid->fid_index - fid->fid_family->start_index;
779 }
780
781 static int mlxsw_sp_fid_8021d_configure(struct mlxsw_sp_fid *fid)
782 {
783         return mlxsw_sp_fid_op(fid, true);
784 }
785
786 static void mlxsw_sp_fid_8021d_deconfigure(struct mlxsw_sp_fid *fid)
787 {
788         if (fid->vni_valid)
789                 mlxsw_sp_nve_fid_disable(fid->fid_family->mlxsw_sp, fid);
790         mlxsw_sp_fid_op(fid, false);
791 }
792
793 static int mlxsw_sp_fid_8021d_index_alloc(struct mlxsw_sp_fid *fid,
794                                           const void *arg, u16 *p_fid_index)
795 {
796         struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
797         u16 nr_fids, fid_index;
798
799         nr_fids = fid_family->end_index - fid_family->start_index + 1;
800         fid_index = find_first_zero_bit(fid_family->fids_bitmap, nr_fids);
801         if (fid_index == nr_fids)
802                 return -ENOBUFS;
803         *p_fid_index = fid_family->start_index + fid_index;
804
805         return 0;
806 }
807
808 static bool
809 mlxsw_sp_fid_8021d_compare(const struct mlxsw_sp_fid *fid, const void *arg)
810 {
811         int br_ifindex = *(int *) arg;
812
813         return mlxsw_sp_fid_8021d_fid(fid)->br_ifindex == br_ifindex;
814 }
815
816 static int mlxsw_sp_port_vp_mode_trans(struct mlxsw_sp_port *mlxsw_sp_port)
817 {
818         struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
819         int err;
820
821         list_for_each_entry(mlxsw_sp_port_vlan, &mlxsw_sp_port->vlans_list,
822                             list) {
823                 struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid;
824                 u16 vid = mlxsw_sp_port_vlan->vid;
825
826                 if (!fid)
827                         continue;
828
829                 err = __mlxsw_sp_fid_port_vid_map(fid,
830                                                   mlxsw_sp_port->local_port,
831                                                   vid, true);
832                 if (err)
833                         goto err_fid_port_vid_map;
834         }
835
836         err = mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, true);
837         if (err)
838                 goto err_port_vp_mode_set;
839
840         return 0;
841
842 err_port_vp_mode_set:
843 err_fid_port_vid_map:
844         list_for_each_entry_continue_reverse(mlxsw_sp_port_vlan,
845                                              &mlxsw_sp_port->vlans_list, list) {
846                 struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid;
847                 u16 vid = mlxsw_sp_port_vlan->vid;
848
849                 if (!fid)
850                         continue;
851
852                 __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid,
853                                             false);
854         }
855         return err;
856 }
857
858 static void mlxsw_sp_port_vlan_mode_trans(struct mlxsw_sp_port *mlxsw_sp_port)
859 {
860         struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
861
862         mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, false);
863
864         list_for_each_entry_reverse(mlxsw_sp_port_vlan,
865                                     &mlxsw_sp_port->vlans_list, list) {
866                 struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid;
867                 u16 vid = mlxsw_sp_port_vlan->vid;
868
869                 if (!fid)
870                         continue;
871
872                 __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid,
873                                             false);
874         }
875 }
876
877 static int
878 mlxsw_sp_fid_port_vid_list_add(struct mlxsw_sp_fid *fid, u16 local_port,
879                                u16 vid)
880 {
881         struct mlxsw_sp_fid_port_vid *port_vid, *tmp_port_vid;
882
883         port_vid = kzalloc(sizeof(*port_vid), GFP_KERNEL);
884         if (!port_vid)
885                 return -ENOMEM;
886
887         port_vid->local_port = local_port;
888         port_vid->vid = vid;
889
890         list_for_each_entry(tmp_port_vid, &fid->port_vid_list, list) {
891                 if (tmp_port_vid->local_port > local_port)
892                         break;
893         }
894
895         list_add_tail(&port_vid->list, &tmp_port_vid->list);
896         return 0;
897 }
898
899 static void
900 mlxsw_sp_fid_port_vid_list_del(struct mlxsw_sp_fid *fid, u16 local_port,
901                                u16 vid)
902 {
903         struct mlxsw_sp_fid_port_vid *port_vid, *tmp;
904
905         list_for_each_entry_safe(port_vid, tmp, &fid->port_vid_list, list) {
906                 if (port_vid->local_port != local_port || port_vid->vid != vid)
907                         continue;
908
909                 list_del(&port_vid->list);
910                 kfree(port_vid);
911                 return;
912         }
913 }
914
915 static int
916 mlxsw_sp_fid_mpe_table_map(const struct mlxsw_sp_fid *fid, u16 local_port,
917                            u16 vid, bool valid)
918 {
919         struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
920         char smpe_pl[MLXSW_REG_SMPE_LEN];
921
922         mlxsw_reg_smpe_pack(smpe_pl, local_port, fid->fid_index,
923                             valid ? vid : 0);
924         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(smpe), smpe_pl);
925 }
926
927 static int
928 mlxsw_sp_fid_erif_eport_to_vid_map_one(const struct mlxsw_sp_fid *fid,
929                                        u16 local_port, u16 vid, bool valid)
930 {
931         u8 port_page = local_port / MLXSW_REG_REIV_REC_MAX_COUNT;
932         u8 rec_num = local_port % MLXSW_REG_REIV_REC_MAX_COUNT;
933         struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
934         u16 rif_index = mlxsw_sp_rif_index(fid->rif);
935         char *reiv_pl;
936         int err;
937
938         reiv_pl = kmalloc(MLXSW_REG_REIV_LEN, GFP_KERNEL);
939         if (!reiv_pl)
940                 return -ENOMEM;
941
942         mlxsw_reg_reiv_pack(reiv_pl, port_page, rif_index);
943         mlxsw_reg_reiv_rec_update_set(reiv_pl, rec_num, true);
944         mlxsw_reg_reiv_rec_evid_set(reiv_pl, rec_num, valid ? vid : 0);
945         err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(reiv), reiv_pl);
946         kfree(reiv_pl);
947         return err;
948 }
949
950 static int mlxsw_sp_fid_evid_map(const struct mlxsw_sp_fid *fid, u16 local_port,
951                                  u16 vid, bool valid)
952 {
953         int err;
954
955         err = mlxsw_sp_fid_mpe_table_map(fid, local_port, vid, valid);
956         if (err)
957                 return err;
958
959         if (!fid->rif)
960                 return 0;
961
962         err = mlxsw_sp_fid_erif_eport_to_vid_map_one(fid, local_port, vid,
963                                                      valid);
964         if (err)
965                 goto err_erif_eport_to_vid_map_one;
966
967         return 0;
968
969 err_erif_eport_to_vid_map_one:
970         mlxsw_sp_fid_mpe_table_map(fid, local_port, vid, !valid);
971         return err;
972 }
973
974 static int mlxsw_sp_fid_8021d_port_vid_map(struct mlxsw_sp_fid *fid,
975                                            struct mlxsw_sp_port *mlxsw_sp_port,
976                                            u16 vid)
977 {
978         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
979         u16 local_port = mlxsw_sp_port->local_port;
980         int err;
981
982         err = __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid,
983                                           true);
984         if (err)
985                 return err;
986
987         err = mlxsw_sp_fid_evid_map(fid, local_port, vid, true);
988         if (err)
989                 goto err_fid_evid_map;
990
991         err = mlxsw_sp_fid_port_vid_list_add(fid, mlxsw_sp_port->local_port,
992                                              vid);
993         if (err)
994                 goto err_port_vid_list_add;
995
996         if (mlxsw_sp->fid_core->port_fid_mappings[local_port]++ == 0) {
997                 err = mlxsw_sp_port_vp_mode_trans(mlxsw_sp_port);
998                 if (err)
999                         goto err_port_vp_mode_trans;
1000         }
1001
1002         return 0;
1003
1004 err_port_vp_mode_trans:
1005         mlxsw_sp->fid_core->port_fid_mappings[local_port]--;
1006         mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid);
1007 err_port_vid_list_add:
1008         mlxsw_sp_fid_evid_map(fid, local_port, vid, false);
1009 err_fid_evid_map:
1010         __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, false);
1011         return err;
1012 }
1013
1014 static void
1015 mlxsw_sp_fid_8021d_port_vid_unmap(struct mlxsw_sp_fid *fid,
1016                                   struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
1017 {
1018         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1019         u16 local_port = mlxsw_sp_port->local_port;
1020
1021         if (mlxsw_sp->fid_core->port_fid_mappings[local_port] == 1)
1022                 mlxsw_sp_port_vlan_mode_trans(mlxsw_sp_port);
1023         mlxsw_sp->fid_core->port_fid_mappings[local_port]--;
1024         mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid);
1025         mlxsw_sp_fid_evid_map(fid, local_port, vid, false);
1026         __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, false);
1027 }
1028
1029 static int mlxsw_sp_fid_8021d_vni_set(struct mlxsw_sp_fid *fid)
1030 {
1031         return mlxsw_sp_fid_vni_op(fid);
1032 }
1033
1034 static void mlxsw_sp_fid_8021d_vni_clear(struct mlxsw_sp_fid *fid)
1035 {
1036         mlxsw_sp_fid_vni_op(fid);
1037 }
1038
1039 static int mlxsw_sp_fid_8021d_nve_flood_index_set(struct mlxsw_sp_fid *fid)
1040 {
1041         return mlxsw_sp_fid_edit_op(fid, fid->rif);
1042 }
1043
1044 static void mlxsw_sp_fid_8021d_nve_flood_index_clear(struct mlxsw_sp_fid *fid)
1045 {
1046         mlxsw_sp_fid_edit_op(fid, fid->rif);
1047 }
1048
1049 static void
1050 mlxsw_sp_fid_8021d_fdb_clear_offload(const struct mlxsw_sp_fid *fid,
1051                                      const struct net_device *nve_dev)
1052 {
1053         br_fdb_clear_offload(nve_dev, 0);
1054 }
1055
1056 static int
1057 mlxsw_sp_fid_8021d_vid_to_fid_rif_update(const struct mlxsw_sp_fid *fid,
1058                                          const struct mlxsw_sp_rif *rif)
1059 {
1060         return 0;
1061 }
1062
1063 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021d_ops = {
1064         .setup                  = mlxsw_sp_fid_8021d_setup,
1065         .configure              = mlxsw_sp_fid_8021d_configure,
1066         .deconfigure            = mlxsw_sp_fid_8021d_deconfigure,
1067         .index_alloc            = mlxsw_sp_fid_8021d_index_alloc,
1068         .compare                = mlxsw_sp_fid_8021d_compare,
1069         .port_vid_map           = mlxsw_sp_fid_8021d_port_vid_map,
1070         .port_vid_unmap         = mlxsw_sp_fid_8021d_port_vid_unmap,
1071         .vni_set                = mlxsw_sp_fid_8021d_vni_set,
1072         .vni_clear              = mlxsw_sp_fid_8021d_vni_clear,
1073         .nve_flood_index_set    = mlxsw_sp_fid_8021d_nve_flood_index_set,
1074         .nve_flood_index_clear  = mlxsw_sp_fid_8021d_nve_flood_index_clear,
1075         .fdb_clear_offload      = mlxsw_sp_fid_8021d_fdb_clear_offload,
1076         .vid_to_fid_rif_update  = mlxsw_sp_fid_8021d_vid_to_fid_rif_update,
1077 };
1078
1079 #define MLXSW_SP_FID_8021Q_MAX (VLAN_N_VID - 2)
1080 #define MLXSW_SP_FID_RFID_MAX (11 * 1024)
1081 #define MLXSW_SP_FID_8021Q_PGT_BASE 0
1082 #define MLXSW_SP_FID_8021D_PGT_BASE (3 * MLXSW_SP_FID_8021Q_MAX)
1083
1084 static const struct mlxsw_sp_flood_table mlxsw_sp_fid_8021d_flood_tables[] = {
1085         {
1086                 .packet_type    = MLXSW_SP_FLOOD_TYPE_UC,
1087                 .table_type     = MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFSET,
1088                 .table_index    = 0,
1089         },
1090         {
1091                 .packet_type    = MLXSW_SP_FLOOD_TYPE_MC,
1092                 .table_type     = MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFSET,
1093                 .table_index    = 1,
1094         },
1095         {
1096                 .packet_type    = MLXSW_SP_FLOOD_TYPE_BC,
1097                 .table_type     = MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFSET,
1098                 .table_index    = 2,
1099         },
1100 };
1101
1102 static bool
1103 mlxsw_sp_fid_8021q_compare(const struct mlxsw_sp_fid *fid, const void *arg)
1104 {
1105         u16 vid = *(u16 *) arg;
1106
1107         return mlxsw_sp_fid_8021q_fid(fid)->vid == vid;
1108 }
1109
1110 static void
1111 mlxsw_sp_fid_8021q_fdb_clear_offload(const struct mlxsw_sp_fid *fid,
1112                                      const struct net_device *nve_dev)
1113 {
1114         br_fdb_clear_offload(nve_dev, mlxsw_sp_fid_8021q_vid(fid));
1115 }
1116
1117 static void mlxsw_sp_fid_rfid_setup(struct mlxsw_sp_fid *fid, const void *arg)
1118 {
1119         fid->fid_offset = 0;
1120 }
1121
1122 static int mlxsw_sp_fid_rfid_configure(struct mlxsw_sp_fid *fid)
1123 {
1124         return mlxsw_sp_fid_op(fid, true);
1125 }
1126
1127 static void mlxsw_sp_fid_rfid_deconfigure(struct mlxsw_sp_fid *fid)
1128 {
1129         mlxsw_sp_fid_op(fid, false);
1130 }
1131
1132 static int mlxsw_sp_fid_rfid_index_alloc(struct mlxsw_sp_fid *fid,
1133                                          const void *arg, u16 *p_fid_index)
1134 {
1135         u16 rif_index = *(u16 *) arg;
1136
1137         *p_fid_index = fid->fid_family->start_index + rif_index;
1138
1139         return 0;
1140 }
1141
1142 static bool mlxsw_sp_fid_rfid_compare(const struct mlxsw_sp_fid *fid,
1143                                       const void *arg)
1144 {
1145         u16 rif_index = *(u16 *) arg;
1146
1147         return fid->fid_index == rif_index + fid->fid_family->start_index;
1148 }
1149
1150 static int mlxsw_sp_fid_rfid_port_vid_map(struct mlxsw_sp_fid *fid,
1151                                           struct mlxsw_sp_port *mlxsw_sp_port,
1152                                           u16 vid)
1153 {
1154         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1155         u16 local_port = mlxsw_sp_port->local_port;
1156         int err;
1157
1158         err = mlxsw_sp_fid_port_vid_list_add(fid, mlxsw_sp_port->local_port,
1159                                              vid);
1160         if (err)
1161                 return err;
1162
1163         /* Using legacy bridge model, we only need to transition the port to
1164          * virtual mode since {Port, VID} => FID is done by the firmware upon
1165          * RIF creation. Using unified bridge model, we need to map
1166          * {Port, VID} => FID and map egress VID.
1167          */
1168         err = __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid,
1169                                           true);
1170         if (err)
1171                 goto err_port_vid_map;
1172
1173         if (fid->rif) {
1174                 err = mlxsw_sp_fid_erif_eport_to_vid_map_one(fid, local_port,
1175                                                              vid, true);
1176                 if (err)
1177                         goto err_erif_eport_to_vid_map_one;
1178         }
1179
1180         if (mlxsw_sp->fid_core->port_fid_mappings[local_port]++ == 0) {
1181                 err = mlxsw_sp_port_vp_mode_trans(mlxsw_sp_port);
1182                 if (err)
1183                         goto err_port_vp_mode_trans;
1184         }
1185
1186         return 0;
1187
1188 err_port_vp_mode_trans:
1189         mlxsw_sp->fid_core->port_fid_mappings[local_port]--;
1190         if (fid->rif)
1191                 mlxsw_sp_fid_erif_eport_to_vid_map_one(fid, local_port, vid,
1192                                                        false);
1193 err_erif_eport_to_vid_map_one:
1194         __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, false);
1195 err_port_vid_map:
1196         mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid);
1197         return err;
1198 }
1199
1200 static void
1201 mlxsw_sp_fid_rfid_port_vid_unmap(struct mlxsw_sp_fid *fid,
1202                                  struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
1203 {
1204         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1205         u16 local_port = mlxsw_sp_port->local_port;
1206
1207         if (mlxsw_sp->fid_core->port_fid_mappings[local_port] == 1)
1208                 mlxsw_sp_port_vlan_mode_trans(mlxsw_sp_port);
1209         mlxsw_sp->fid_core->port_fid_mappings[local_port]--;
1210
1211         if (fid->rif)
1212                 mlxsw_sp_fid_erif_eport_to_vid_map_one(fid, local_port, vid,
1213                                                        false);
1214         __mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, false);
1215         mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid);
1216 }
1217
1218 static int mlxsw_sp_fid_rfid_vni_set(struct mlxsw_sp_fid *fid)
1219 {
1220         return -EOPNOTSUPP;
1221 }
1222
1223 static void mlxsw_sp_fid_rfid_vni_clear(struct mlxsw_sp_fid *fid)
1224 {
1225         WARN_ON_ONCE(1);
1226 }
1227
1228 static int mlxsw_sp_fid_rfid_nve_flood_index_set(struct mlxsw_sp_fid *fid)
1229 {
1230         return -EOPNOTSUPP;
1231 }
1232
1233 static void mlxsw_sp_fid_rfid_nve_flood_index_clear(struct mlxsw_sp_fid *fid)
1234 {
1235         WARN_ON_ONCE(1);
1236 }
1237
1238 static int
1239 mlxsw_sp_fid_rfid_vid_to_fid_rif_update(const struct mlxsw_sp_fid *fid,
1240                                         const struct mlxsw_sp_rif *rif)
1241 {
1242         return 0;
1243 }
1244
1245 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_rfid_ops = {
1246         .setup                  = mlxsw_sp_fid_rfid_setup,
1247         .configure              = mlxsw_sp_fid_rfid_configure,
1248         .deconfigure            = mlxsw_sp_fid_rfid_deconfigure,
1249         .index_alloc            = mlxsw_sp_fid_rfid_index_alloc,
1250         .compare                = mlxsw_sp_fid_rfid_compare,
1251         .port_vid_map           = mlxsw_sp_fid_rfid_port_vid_map,
1252         .port_vid_unmap         = mlxsw_sp_fid_rfid_port_vid_unmap,
1253         .vni_set                = mlxsw_sp_fid_rfid_vni_set,
1254         .vni_clear              = mlxsw_sp_fid_rfid_vni_clear,
1255         .nve_flood_index_set    = mlxsw_sp_fid_rfid_nve_flood_index_set,
1256         .nve_flood_index_clear  = mlxsw_sp_fid_rfid_nve_flood_index_clear,
1257         .vid_to_fid_rif_update  = mlxsw_sp_fid_rfid_vid_to_fid_rif_update,
1258 };
1259
1260 static void mlxsw_sp_fid_dummy_setup(struct mlxsw_sp_fid *fid, const void *arg)
1261 {
1262         fid->fid_offset = 0;
1263 }
1264
1265 static int mlxsw_sp_fid_dummy_configure(struct mlxsw_sp_fid *fid)
1266 {
1267         return mlxsw_sp_fid_op(fid, true);
1268 }
1269
1270 static void mlxsw_sp_fid_dummy_deconfigure(struct mlxsw_sp_fid *fid)
1271 {
1272         mlxsw_sp_fid_op(fid, false);
1273 }
1274
1275 static int mlxsw_sp_fid_dummy_index_alloc(struct mlxsw_sp_fid *fid,
1276                                           const void *arg, u16 *p_fid_index)
1277 {
1278         *p_fid_index = fid->fid_family->start_index;
1279
1280         return 0;
1281 }
1282
1283 static bool mlxsw_sp_fid_dummy_compare(const struct mlxsw_sp_fid *fid,
1284                                        const void *arg)
1285 {
1286         return true;
1287 }
1288
1289 static int mlxsw_sp_fid_dummy_vni_set(struct mlxsw_sp_fid *fid)
1290 {
1291         return -EOPNOTSUPP;
1292 }
1293
1294 static void mlxsw_sp_fid_dummy_vni_clear(struct mlxsw_sp_fid *fid)
1295 {
1296         WARN_ON_ONCE(1);
1297 }
1298
1299 static int mlxsw_sp_fid_dummy_nve_flood_index_set(struct mlxsw_sp_fid *fid)
1300 {
1301         return -EOPNOTSUPP;
1302 }
1303
1304 static void mlxsw_sp_fid_dummy_nve_flood_index_clear(struct mlxsw_sp_fid *fid)
1305 {
1306         WARN_ON_ONCE(1);
1307 }
1308
1309 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_dummy_ops = {
1310         .setup                  = mlxsw_sp_fid_dummy_setup,
1311         .configure              = mlxsw_sp_fid_dummy_configure,
1312         .deconfigure            = mlxsw_sp_fid_dummy_deconfigure,
1313         .index_alloc            = mlxsw_sp_fid_dummy_index_alloc,
1314         .compare                = mlxsw_sp_fid_dummy_compare,
1315         .vni_set                = mlxsw_sp_fid_dummy_vni_set,
1316         .vni_clear              = mlxsw_sp_fid_dummy_vni_clear,
1317         .nve_flood_index_set    = mlxsw_sp_fid_dummy_nve_flood_index_set,
1318         .nve_flood_index_clear  = mlxsw_sp_fid_dummy_nve_flood_index_clear,
1319 };
1320
1321 static int mlxsw_sp_fid_8021q_configure(struct mlxsw_sp_fid *fid)
1322 {
1323         struct mlxsw_sp_fid_8021q *fid_8021q = mlxsw_sp_fid_8021q_fid(fid);
1324         int err;
1325
1326         err = mlxsw_sp_fid_op(fid, true);
1327         if (err)
1328                 return err;
1329
1330         err = mlxsw_sp_fid_vid_to_fid_map(fid, fid_8021q->vid, true, fid->rif);
1331         if (err)
1332                 goto err_vid_to_fid_map;
1333
1334         return 0;
1335
1336 err_vid_to_fid_map:
1337         mlxsw_sp_fid_op(fid, false);
1338         return err;
1339 }
1340
1341 static void mlxsw_sp_fid_8021q_deconfigure(struct mlxsw_sp_fid *fid)
1342 {
1343         struct mlxsw_sp_fid_8021q *fid_8021q = mlxsw_sp_fid_8021q_fid(fid);
1344
1345         if (fid->vni_valid)
1346                 mlxsw_sp_nve_fid_disable(fid->fid_family->mlxsw_sp, fid);
1347
1348         mlxsw_sp_fid_vid_to_fid_map(fid, fid_8021q->vid, false, NULL);
1349         mlxsw_sp_fid_op(fid, false);
1350 }
1351
1352 static int mlxsw_sp_fid_8021q_port_vid_map(struct mlxsw_sp_fid *fid,
1353                                            struct mlxsw_sp_port *mlxsw_sp_port,
1354                                            u16 vid)
1355 {
1356         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1357         u16 local_port = mlxsw_sp_port->local_port;
1358         int err;
1359
1360         /* In case there are no {Port, VID} => FID mappings on the port,
1361          * we can use the global VID => FID mapping we created when the
1362          * FID was configured, otherwise, configure new mapping.
1363          */
1364         if (mlxsw_sp->fid_core->port_fid_mappings[local_port]) {
1365                 err =  __mlxsw_sp_fid_port_vid_map(fid, local_port, vid, true);
1366                 if (err)
1367                         return err;
1368         }
1369
1370         err = mlxsw_sp_fid_evid_map(fid, local_port, vid, true);
1371         if (err)
1372                 goto err_fid_evid_map;
1373
1374         err = mlxsw_sp_fid_port_vid_list_add(fid, mlxsw_sp_port->local_port,
1375                                              vid);
1376         if (err)
1377                 goto err_port_vid_list_add;
1378
1379         return 0;
1380
1381 err_port_vid_list_add:
1382          mlxsw_sp_fid_evid_map(fid, local_port, vid, false);
1383 err_fid_evid_map:
1384         if (mlxsw_sp->fid_core->port_fid_mappings[local_port])
1385                 __mlxsw_sp_fid_port_vid_map(fid, local_port, vid, false);
1386         return err;
1387 }
1388
1389 static void
1390 mlxsw_sp_fid_8021q_port_vid_unmap(struct mlxsw_sp_fid *fid,
1391                                   struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
1392 {
1393         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1394         u16 local_port = mlxsw_sp_port->local_port;
1395
1396         mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid);
1397         mlxsw_sp_fid_evid_map(fid, local_port, vid, false);
1398         if (mlxsw_sp->fid_core->port_fid_mappings[local_port])
1399                 __mlxsw_sp_fid_port_vid_map(fid, local_port, vid, false);
1400 }
1401
1402 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021q_ops = {
1403         .setup                  = mlxsw_sp_fid_8021q_setup,
1404         .configure              = mlxsw_sp_fid_8021q_configure,
1405         .deconfigure            = mlxsw_sp_fid_8021q_deconfigure,
1406         .index_alloc            = mlxsw_sp_fid_8021d_index_alloc,
1407         .compare                = mlxsw_sp_fid_8021q_compare,
1408         .port_vid_map           = mlxsw_sp_fid_8021q_port_vid_map,
1409         .port_vid_unmap         = mlxsw_sp_fid_8021q_port_vid_unmap,
1410         .vni_set                = mlxsw_sp_fid_8021d_vni_set,
1411         .vni_clear              = mlxsw_sp_fid_8021d_vni_clear,
1412         .nve_flood_index_set    = mlxsw_sp_fid_8021d_nve_flood_index_set,
1413         .nve_flood_index_clear  = mlxsw_sp_fid_8021d_nve_flood_index_clear,
1414         .fdb_clear_offload      = mlxsw_sp_fid_8021q_fdb_clear_offload,
1415         .vid_to_fid_rif_update  = mlxsw_sp_fid_8021q_vid_to_fid_rif_update,
1416 };
1417
1418 /* There are 4K-2 802.1Q FIDs */
1419 #define MLXSW_SP_FID_8021Q_START        1 /* FID 0 is reserved. */
1420 #define MLXSW_SP_FID_8021Q_END          (MLXSW_SP_FID_8021Q_START + \
1421                                          MLXSW_SP_FID_8021Q_MAX - 1)
1422
1423 /* There are 1K 802.1D FIDs */
1424 #define MLXSW_SP_FID_8021D_START        (MLXSW_SP_FID_8021Q_END + 1)
1425 #define MLXSW_SP_FID_8021D_END          (MLXSW_SP_FID_8021D_START + \
1426                                          MLXSW_SP_FID_8021D_MAX - 1)
1427
1428 /* There is one dummy FID */
1429 #define MLXSW_SP_FID_DUMMY              (MLXSW_SP_FID_8021D_END + 1)
1430
1431 /* There are 11K rFIDs */
1432 #define MLXSW_SP_RFID_START             (MLXSW_SP_FID_DUMMY + 1)
1433 #define MLXSW_SP_RFID_END               (MLXSW_SP_RFID_START + \
1434                                          MLXSW_SP_FID_RFID_MAX - 1)
1435
1436 static const struct mlxsw_sp_fid_family mlxsw_sp1_fid_8021q_family = {
1437         .type                   = MLXSW_SP_FID_TYPE_8021Q,
1438         .fid_size               = sizeof(struct mlxsw_sp_fid_8021q),
1439         .start_index            = MLXSW_SP_FID_8021Q_START,
1440         .end_index              = MLXSW_SP_FID_8021Q_END,
1441         .flood_tables           = mlxsw_sp_fid_8021d_flood_tables,
1442         .nr_flood_tables        = ARRAY_SIZE(mlxsw_sp_fid_8021d_flood_tables),
1443         .rif_type               = MLXSW_SP_RIF_TYPE_VLAN,
1444         .ops                    = &mlxsw_sp_fid_8021q_ops,
1445         .flood_rsp              = false,
1446         .bridge_type            = MLXSW_REG_BRIDGE_TYPE_0,
1447         .pgt_base               = MLXSW_SP_FID_8021Q_PGT_BASE,
1448         .smpe_index_valid       = false,
1449 };
1450
1451 static const struct mlxsw_sp_fid_family mlxsw_sp1_fid_8021d_family = {
1452         .type                   = MLXSW_SP_FID_TYPE_8021D,
1453         .fid_size               = sizeof(struct mlxsw_sp_fid_8021d),
1454         .start_index            = MLXSW_SP_FID_8021D_START,
1455         .end_index              = MLXSW_SP_FID_8021D_END,
1456         .flood_tables           = mlxsw_sp_fid_8021d_flood_tables,
1457         .nr_flood_tables        = ARRAY_SIZE(mlxsw_sp_fid_8021d_flood_tables),
1458         .rif_type               = MLXSW_SP_RIF_TYPE_FID,
1459         .ops                    = &mlxsw_sp_fid_8021d_ops,
1460         .bridge_type            = MLXSW_REG_BRIDGE_TYPE_1,
1461         .pgt_base               = MLXSW_SP_FID_8021D_PGT_BASE,
1462         .smpe_index_valid       = false,
1463 };
1464
1465 static const struct mlxsw_sp_fid_family mlxsw_sp1_fid_dummy_family = {
1466         .type                   = MLXSW_SP_FID_TYPE_DUMMY,
1467         .fid_size               = sizeof(struct mlxsw_sp_fid),
1468         .start_index            = MLXSW_SP_FID_DUMMY,
1469         .end_index              = MLXSW_SP_FID_DUMMY,
1470         .ops                    = &mlxsw_sp_fid_dummy_ops,
1471         .smpe_index_valid       = false,
1472 };
1473
1474 static const struct mlxsw_sp_fid_family mlxsw_sp_fid_rfid_family = {
1475         .type                   = MLXSW_SP_FID_TYPE_RFID,
1476         .fid_size               = sizeof(struct mlxsw_sp_fid),
1477         .start_index            = MLXSW_SP_RFID_START,
1478         .end_index              = MLXSW_SP_RFID_END,
1479         .rif_type               = MLXSW_SP_RIF_TYPE_SUBPORT,
1480         .ops                    = &mlxsw_sp_fid_rfid_ops,
1481         .flood_rsp              = true,
1482         .smpe_index_valid       = false,
1483 };
1484
1485 const struct mlxsw_sp_fid_family *mlxsw_sp1_fid_family_arr[] = {
1486         [MLXSW_SP_FID_TYPE_8021Q]       = &mlxsw_sp1_fid_8021q_family,
1487         [MLXSW_SP_FID_TYPE_8021D]       = &mlxsw_sp1_fid_8021d_family,
1488         [MLXSW_SP_FID_TYPE_DUMMY]       = &mlxsw_sp1_fid_dummy_family,
1489         [MLXSW_SP_FID_TYPE_RFID]        = &mlxsw_sp_fid_rfid_family,
1490 };
1491
1492 static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_8021q_family = {
1493         .type                   = MLXSW_SP_FID_TYPE_8021Q,
1494         .fid_size               = sizeof(struct mlxsw_sp_fid_8021q),
1495         .start_index            = MLXSW_SP_FID_8021Q_START,
1496         .end_index              = MLXSW_SP_FID_8021Q_END,
1497         .flood_tables           = mlxsw_sp_fid_8021d_flood_tables,
1498         .nr_flood_tables        = ARRAY_SIZE(mlxsw_sp_fid_8021d_flood_tables),
1499         .rif_type               = MLXSW_SP_RIF_TYPE_VLAN,
1500         .ops                    = &mlxsw_sp_fid_8021q_ops,
1501         .flood_rsp              = false,
1502         .bridge_type            = MLXSW_REG_BRIDGE_TYPE_0,
1503         .pgt_base               = MLXSW_SP_FID_8021Q_PGT_BASE,
1504         .smpe_index_valid       = true,
1505 };
1506
1507 static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_8021d_family = {
1508         .type                   = MLXSW_SP_FID_TYPE_8021D,
1509         .fid_size               = sizeof(struct mlxsw_sp_fid_8021d),
1510         .start_index            = MLXSW_SP_FID_8021D_START,
1511         .end_index              = MLXSW_SP_FID_8021D_END,
1512         .flood_tables           = mlxsw_sp_fid_8021d_flood_tables,
1513         .nr_flood_tables        = ARRAY_SIZE(mlxsw_sp_fid_8021d_flood_tables),
1514         .rif_type               = MLXSW_SP_RIF_TYPE_FID,
1515         .ops                    = &mlxsw_sp_fid_8021d_ops,
1516         .bridge_type            = MLXSW_REG_BRIDGE_TYPE_1,
1517         .pgt_base               = MLXSW_SP_FID_8021D_PGT_BASE,
1518         .smpe_index_valid       = true,
1519 };
1520
1521 static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_dummy_family = {
1522         .type                   = MLXSW_SP_FID_TYPE_DUMMY,
1523         .fid_size               = sizeof(struct mlxsw_sp_fid),
1524         .start_index            = MLXSW_SP_FID_DUMMY,
1525         .end_index              = MLXSW_SP_FID_DUMMY,
1526         .ops                    = &mlxsw_sp_fid_dummy_ops,
1527         .smpe_index_valid       = false,
1528 };
1529
1530 const struct mlxsw_sp_fid_family *mlxsw_sp2_fid_family_arr[] = {
1531         [MLXSW_SP_FID_TYPE_8021Q]       = &mlxsw_sp2_fid_8021q_family,
1532         [MLXSW_SP_FID_TYPE_8021D]       = &mlxsw_sp2_fid_8021d_family,
1533         [MLXSW_SP_FID_TYPE_DUMMY]       = &mlxsw_sp2_fid_dummy_family,
1534         [MLXSW_SP_FID_TYPE_RFID]        = &mlxsw_sp_fid_rfid_family,
1535 };
1536
1537 static struct mlxsw_sp_fid *mlxsw_sp_fid_lookup(struct mlxsw_sp *mlxsw_sp,
1538                                                 enum mlxsw_sp_fid_type type,
1539                                                 const void *arg)
1540 {
1541         struct mlxsw_sp_fid_family *fid_family;
1542         struct mlxsw_sp_fid *fid;
1543
1544         fid_family = mlxsw_sp->fid_core->fid_family_arr[type];
1545         list_for_each_entry(fid, &fid_family->fids_list, list) {
1546                 if (!fid->fid_family->ops->compare(fid, arg))
1547                         continue;
1548                 refcount_inc(&fid->ref_count);
1549                 return fid;
1550         }
1551
1552         return NULL;
1553 }
1554
1555 static struct mlxsw_sp_fid *mlxsw_sp_fid_get(struct mlxsw_sp *mlxsw_sp,
1556                                              enum mlxsw_sp_fid_type type,
1557                                              const void *arg)
1558 {
1559         struct mlxsw_sp_fid_family *fid_family;
1560         struct mlxsw_sp_fid *fid;
1561         u16 fid_index;
1562         int err;
1563
1564         fid = mlxsw_sp_fid_lookup(mlxsw_sp, type, arg);
1565         if (fid)
1566                 return fid;
1567
1568         fid_family = mlxsw_sp->fid_core->fid_family_arr[type];
1569         fid = kzalloc(fid_family->fid_size, GFP_KERNEL);
1570         if (!fid)
1571                 return ERR_PTR(-ENOMEM);
1572
1573         INIT_LIST_HEAD(&fid->port_vid_list);
1574         fid->fid_family = fid_family;
1575
1576         err = fid->fid_family->ops->index_alloc(fid, arg, &fid_index);
1577         if (err)
1578                 goto err_index_alloc;
1579         fid->fid_index = fid_index;
1580         __set_bit(fid_index - fid_family->start_index, fid_family->fids_bitmap);
1581
1582         fid->fid_family->ops->setup(fid, arg);
1583
1584         err = fid->fid_family->ops->configure(fid);
1585         if (err)
1586                 goto err_configure;
1587
1588         err = rhashtable_insert_fast(&mlxsw_sp->fid_core->fid_ht, &fid->ht_node,
1589                                      mlxsw_sp_fid_ht_params);
1590         if (err)
1591                 goto err_rhashtable_insert;
1592
1593         list_add(&fid->list, &fid_family->fids_list);
1594         refcount_set(&fid->ref_count, 1);
1595         return fid;
1596
1597 err_rhashtable_insert:
1598         fid->fid_family->ops->deconfigure(fid);
1599 err_configure:
1600         __clear_bit(fid_index - fid_family->start_index,
1601                     fid_family->fids_bitmap);
1602 err_index_alloc:
1603         kfree(fid);
1604         return ERR_PTR(err);
1605 }
1606
1607 void mlxsw_sp_fid_put(struct mlxsw_sp_fid *fid)
1608 {
1609         struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
1610         struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
1611
1612         if (!refcount_dec_and_test(&fid->ref_count))
1613                 return;
1614
1615         list_del(&fid->list);
1616         rhashtable_remove_fast(&mlxsw_sp->fid_core->fid_ht,
1617                                &fid->ht_node, mlxsw_sp_fid_ht_params);
1618         fid->fid_family->ops->deconfigure(fid);
1619         __clear_bit(fid->fid_index - fid_family->start_index,
1620                     fid_family->fids_bitmap);
1621         WARN_ON_ONCE(!list_empty(&fid->port_vid_list));
1622         kfree(fid);
1623 }
1624
1625 struct mlxsw_sp_fid *mlxsw_sp_fid_8021q_get(struct mlxsw_sp *mlxsw_sp, u16 vid)
1626 {
1627         return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_8021Q, &vid);
1628 }
1629
1630 struct mlxsw_sp_fid *mlxsw_sp_fid_8021d_get(struct mlxsw_sp *mlxsw_sp,
1631                                             int br_ifindex)
1632 {
1633         return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_8021D, &br_ifindex);
1634 }
1635
1636 struct mlxsw_sp_fid *mlxsw_sp_fid_8021q_lookup(struct mlxsw_sp *mlxsw_sp,
1637                                                u16 vid)
1638 {
1639         return mlxsw_sp_fid_lookup(mlxsw_sp, MLXSW_SP_FID_TYPE_8021Q, &vid);
1640 }
1641
1642 struct mlxsw_sp_fid *mlxsw_sp_fid_8021d_lookup(struct mlxsw_sp *mlxsw_sp,
1643                                                int br_ifindex)
1644 {
1645         return mlxsw_sp_fid_lookup(mlxsw_sp, MLXSW_SP_FID_TYPE_8021D,
1646                                    &br_ifindex);
1647 }
1648
1649 struct mlxsw_sp_fid *mlxsw_sp_fid_rfid_get(struct mlxsw_sp *mlxsw_sp,
1650                                            u16 rif_index)
1651 {
1652         return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_RFID, &rif_index);
1653 }
1654
1655 struct mlxsw_sp_fid *mlxsw_sp_fid_dummy_get(struct mlxsw_sp *mlxsw_sp)
1656 {
1657         return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_DUMMY, NULL);
1658 }
1659
1660 static int
1661 mlxsw_sp_fid_flood_table_init(struct mlxsw_sp_fid_family *fid_family,
1662                               const struct mlxsw_sp_flood_table *flood_table)
1663 {
1664         enum mlxsw_sp_flood_type packet_type = flood_table->packet_type;
1665         struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
1666         const int *sfgc_packet_types;
1667         u16 num_fids, mid_base;
1668         int err, i;
1669
1670         mid_base = mlxsw_sp_fid_flood_table_mid(fid_family, flood_table, 0);
1671         num_fids = mlxsw_sp_fid_family_num_fids(fid_family);
1672         err = mlxsw_sp_pgt_mid_alloc_range(mlxsw_sp, mid_base, num_fids);
1673         if (err)
1674                 return err;
1675
1676         sfgc_packet_types = mlxsw_sp_packet_type_sfgc_types[packet_type];
1677         for (i = 0; i < MLXSW_REG_SFGC_TYPE_MAX; i++) {
1678                 char sfgc_pl[MLXSW_REG_SFGC_LEN];
1679
1680                 if (!sfgc_packet_types[i])
1681                         continue;
1682
1683                 mlxsw_reg_sfgc_pack(sfgc_pl, i, fid_family->bridge_type,
1684                                     flood_table->table_type, 0, mid_base);
1685
1686                 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfgc), sfgc_pl);
1687                 if (err)
1688                         goto err_reg_write;
1689         }
1690
1691         return 0;
1692
1693 err_reg_write:
1694         mlxsw_sp_pgt_mid_free_range(mlxsw_sp, mid_base, num_fids);
1695         return err;
1696 }
1697
1698 static void
1699 mlxsw_sp_fid_flood_table_fini(struct mlxsw_sp_fid_family *fid_family,
1700                               const struct mlxsw_sp_flood_table *flood_table)
1701 {
1702         struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
1703         u16 num_fids, mid_base;
1704
1705         mid_base = mlxsw_sp_fid_flood_table_mid(fid_family, flood_table, 0);
1706         num_fids = mlxsw_sp_fid_family_num_fids(fid_family);
1707         mlxsw_sp_pgt_mid_free_range(mlxsw_sp, mid_base, num_fids);
1708 }
1709
1710 static int
1711 mlxsw_sp_fid_flood_tables_init(struct mlxsw_sp_fid_family *fid_family)
1712 {
1713         int i;
1714
1715         for (i = 0; i < fid_family->nr_flood_tables; i++) {
1716                 const struct mlxsw_sp_flood_table *flood_table;
1717                 int err;
1718
1719                 flood_table = &fid_family->flood_tables[i];
1720                 err = mlxsw_sp_fid_flood_table_init(fid_family, flood_table);
1721                 if (err)
1722                         return err;
1723         }
1724
1725         return 0;
1726 }
1727
1728 static void
1729 mlxsw_sp_fid_flood_tables_fini(struct mlxsw_sp_fid_family *fid_family)
1730 {
1731         int i;
1732
1733         for (i = 0; i < fid_family->nr_flood_tables; i++) {
1734                 const struct mlxsw_sp_flood_table *flood_table;
1735
1736                 flood_table = &fid_family->flood_tables[i];
1737                 mlxsw_sp_fid_flood_table_fini(fid_family, flood_table);
1738         }
1739 }
1740
1741 static int mlxsw_sp_fid_family_register(struct mlxsw_sp *mlxsw_sp,
1742                                         const struct mlxsw_sp_fid_family *tmpl)
1743 {
1744         u16 nr_fids = tmpl->end_index - tmpl->start_index + 1;
1745         struct mlxsw_sp_fid_family *fid_family;
1746         int err;
1747
1748         fid_family = kmemdup(tmpl, sizeof(*fid_family), GFP_KERNEL);
1749         if (!fid_family)
1750                 return -ENOMEM;
1751
1752         fid_family->mlxsw_sp = mlxsw_sp;
1753         INIT_LIST_HEAD(&fid_family->fids_list);
1754         fid_family->fids_bitmap = bitmap_zalloc(nr_fids, GFP_KERNEL);
1755         if (!fid_family->fids_bitmap) {
1756                 err = -ENOMEM;
1757                 goto err_alloc_fids_bitmap;
1758         }
1759
1760         if (fid_family->flood_tables) {
1761                 err = mlxsw_sp_fid_flood_tables_init(fid_family);
1762                 if (err)
1763                         goto err_fid_flood_tables_init;
1764         }
1765
1766         mlxsw_sp->fid_core->fid_family_arr[tmpl->type] = fid_family;
1767
1768         return 0;
1769
1770 err_fid_flood_tables_init:
1771         bitmap_free(fid_family->fids_bitmap);
1772 err_alloc_fids_bitmap:
1773         kfree(fid_family);
1774         return err;
1775 }
1776
1777 static void
1778 mlxsw_sp_fid_family_unregister(struct mlxsw_sp *mlxsw_sp,
1779                                struct mlxsw_sp_fid_family *fid_family)
1780 {
1781         mlxsw_sp->fid_core->fid_family_arr[fid_family->type] = NULL;
1782
1783         if (fid_family->flood_tables)
1784                 mlxsw_sp_fid_flood_tables_fini(fid_family);
1785
1786         bitmap_free(fid_family->fids_bitmap);
1787         WARN_ON_ONCE(!list_empty(&fid_family->fids_list));
1788         kfree(fid_family);
1789 }
1790
1791 int mlxsw_sp_port_fids_init(struct mlxsw_sp_port *mlxsw_sp_port)
1792 {
1793         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1794
1795         /* Track number of FIDs configured on the port with mapping type
1796          * PORT_VID_TO_FID, so that we know when to transition the port
1797          * back to non-virtual (VLAN) mode.
1798          */
1799         mlxsw_sp->fid_core->port_fid_mappings[mlxsw_sp_port->local_port] = 0;
1800
1801         return mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, false);
1802 }
1803
1804 void mlxsw_sp_port_fids_fini(struct mlxsw_sp_port *mlxsw_sp_port)
1805 {
1806         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1807
1808         mlxsw_sp->fid_core->port_fid_mappings[mlxsw_sp_port->local_port] = 0;
1809 }
1810
1811 int mlxsw_sp_fids_init(struct mlxsw_sp *mlxsw_sp)
1812 {
1813         unsigned int max_ports = mlxsw_core_max_ports(mlxsw_sp->core);
1814         struct mlxsw_sp_fid_core *fid_core;
1815         int err, i;
1816
1817         fid_core = kzalloc(sizeof(*mlxsw_sp->fid_core), GFP_KERNEL);
1818         if (!fid_core)
1819                 return -ENOMEM;
1820         mlxsw_sp->fid_core = fid_core;
1821
1822         err = rhashtable_init(&fid_core->fid_ht, &mlxsw_sp_fid_ht_params);
1823         if (err)
1824                 goto err_rhashtable_fid_init;
1825
1826         err = rhashtable_init(&fid_core->vni_ht, &mlxsw_sp_fid_vni_ht_params);
1827         if (err)
1828                 goto err_rhashtable_vni_init;
1829
1830         fid_core->port_fid_mappings = kcalloc(max_ports, sizeof(unsigned int),
1831                                               GFP_KERNEL);
1832         if (!fid_core->port_fid_mappings) {
1833                 err = -ENOMEM;
1834                 goto err_alloc_port_fid_mappings;
1835         }
1836
1837         for (i = 0; i < MLXSW_SP_FID_TYPE_MAX; i++) {
1838                 err = mlxsw_sp_fid_family_register(mlxsw_sp,
1839                                                    mlxsw_sp->fid_family_arr[i]);
1840
1841                 if (err)
1842                         goto err_fid_ops_register;
1843         }
1844
1845         return 0;
1846
1847 err_fid_ops_register:
1848         for (i--; i >= 0; i--) {
1849                 struct mlxsw_sp_fid_family *fid_family;
1850
1851                 fid_family = fid_core->fid_family_arr[i];
1852                 mlxsw_sp_fid_family_unregister(mlxsw_sp, fid_family);
1853         }
1854         kfree(fid_core->port_fid_mappings);
1855 err_alloc_port_fid_mappings:
1856         rhashtable_destroy(&fid_core->vni_ht);
1857 err_rhashtable_vni_init:
1858         rhashtable_destroy(&fid_core->fid_ht);
1859 err_rhashtable_fid_init:
1860         kfree(fid_core);
1861         return err;
1862 }
1863
1864 void mlxsw_sp_fids_fini(struct mlxsw_sp *mlxsw_sp)
1865 {
1866         struct mlxsw_sp_fid_core *fid_core = mlxsw_sp->fid_core;
1867         int i;
1868
1869         for (i = 0; i < MLXSW_SP_FID_TYPE_MAX; i++)
1870                 mlxsw_sp_fid_family_unregister(mlxsw_sp,
1871                                                fid_core->fid_family_arr[i]);
1872         kfree(fid_core->port_fid_mappings);
1873         rhashtable_destroy(&fid_core->vni_ht);
1874         rhashtable_destroy(&fid_core->fid_ht);
1875         kfree(fid_core);
1876 }