hc
2024-01-03 2f7c68cb55ecb7331f2381deb497c27155f32faf
kernel/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c
....@@ -6,7 +6,9 @@
66 #include <linux/if_vlan.h>
77 #include <linux/if_bridge.h>
88 #include <linux/netdevice.h>
9
+#include <linux/rhashtable.h>
910 #include <linux/rtnetlink.h>
11
+#include <linux/refcount.h>
1012
1113 #include "spectrum.h"
1214 #include "reg.h"
....@@ -14,6 +16,8 @@
1416 struct mlxsw_sp_fid_family;
1517
1618 struct mlxsw_sp_fid_core {
19
+ struct rhashtable fid_ht;
20
+ struct rhashtable vni_ht;
1721 struct mlxsw_sp_fid_family *fid_family_arr[MLXSW_SP_FID_TYPE_MAX];
1822 unsigned int *port_fid_mappings;
1923 };
....@@ -21,9 +25,18 @@
2125 struct mlxsw_sp_fid {
2226 struct list_head list;
2327 struct mlxsw_sp_rif *rif;
24
- unsigned int ref_count;
28
+ refcount_t ref_count;
2529 u16 fid_index;
2630 struct mlxsw_sp_fid_family *fid_family;
31
+ struct rhash_head ht_node;
32
+
33
+ struct rhash_head vni_ht_node;
34
+ enum mlxsw_sp_nve_type nve_type;
35
+ __be32 vni;
36
+ u32 nve_flood_index;
37
+ int nve_ifindex;
38
+ u8 vni_valid:1,
39
+ nve_flood_index_valid:1;
2740 };
2841
2942 struct mlxsw_sp_fid_8021q {
....@@ -34,6 +47,18 @@
3447 struct mlxsw_sp_fid_8021d {
3548 struct mlxsw_sp_fid common;
3649 int br_ifindex;
50
+};
51
+
52
+static const struct rhashtable_params mlxsw_sp_fid_ht_params = {
53
+ .key_len = sizeof_field(struct mlxsw_sp_fid, fid_index),
54
+ .key_offset = offsetof(struct mlxsw_sp_fid, fid_index),
55
+ .head_offset = offsetof(struct mlxsw_sp_fid, ht_node),
56
+};
57
+
58
+static const struct rhashtable_params mlxsw_sp_fid_vni_ht_params = {
59
+ .key_len = sizeof_field(struct mlxsw_sp_fid, vni),
60
+ .key_offset = offsetof(struct mlxsw_sp_fid, vni),
61
+ .head_offset = offsetof(struct mlxsw_sp_fid, vni_ht_node),
3762 };
3863
3964 struct mlxsw_sp_flood_table {
....@@ -56,6 +81,13 @@
5681 struct mlxsw_sp_port *port, u16 vid);
5782 void (*port_vid_unmap)(struct mlxsw_sp_fid *fid,
5883 struct mlxsw_sp_port *port, u16 vid);
84
+ int (*vni_set)(struct mlxsw_sp_fid *fid, __be32 vni);
85
+ void (*vni_clear)(struct mlxsw_sp_fid *fid);
86
+ int (*nve_flood_index_set)(struct mlxsw_sp_fid *fid,
87
+ u32 nve_flood_index);
88
+ void (*nve_flood_index_clear)(struct mlxsw_sp_fid *fid);
89
+ void (*fdb_clear_offload)(const struct mlxsw_sp_fid *fid,
90
+ const struct net_device *nve_dev);
5991 };
6092
6193 struct mlxsw_sp_fid_family {
....@@ -70,6 +102,7 @@
70102 enum mlxsw_sp_rif_type rif_type;
71103 const struct mlxsw_sp_fid_ops *ops;
72104 struct mlxsw_sp *mlxsw_sp;
105
+ u8 lag_vid_valid:1;
73106 };
74107
75108 static const int mlxsw_sp_sfgc_uc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = {
....@@ -93,6 +126,179 @@
93126 [MLXSW_SP_FLOOD_TYPE_BC] = mlxsw_sp_sfgc_bc_packet_types,
94127 [MLXSW_SP_FLOOD_TYPE_MC] = mlxsw_sp_sfgc_mc_packet_types,
95128 };
129
+
130
+bool mlxsw_sp_fid_is_dummy(struct mlxsw_sp *mlxsw_sp, u16 fid_index)
131
+{
132
+ enum mlxsw_sp_fid_type fid_type = MLXSW_SP_FID_TYPE_DUMMY;
133
+ struct mlxsw_sp_fid_family *fid_family;
134
+
135
+ fid_family = mlxsw_sp->fid_core->fid_family_arr[fid_type];
136
+
137
+ return fid_family->start_index == fid_index;
138
+}
139
+
140
+bool mlxsw_sp_fid_lag_vid_valid(const struct mlxsw_sp_fid *fid)
141
+{
142
+ return fid->fid_family->lag_vid_valid;
143
+}
144
+
145
+struct mlxsw_sp_fid *mlxsw_sp_fid_lookup_by_index(struct mlxsw_sp *mlxsw_sp,
146
+ u16 fid_index)
147
+{
148
+ struct mlxsw_sp_fid *fid;
149
+
150
+ fid = rhashtable_lookup_fast(&mlxsw_sp->fid_core->fid_ht, &fid_index,
151
+ mlxsw_sp_fid_ht_params);
152
+ if (fid)
153
+ refcount_inc(&fid->ref_count);
154
+
155
+ return fid;
156
+}
157
+
158
+int mlxsw_sp_fid_nve_ifindex(const struct mlxsw_sp_fid *fid, int *nve_ifindex)
159
+{
160
+ if (!fid->vni_valid)
161
+ return -EINVAL;
162
+
163
+ *nve_ifindex = fid->nve_ifindex;
164
+
165
+ return 0;
166
+}
167
+
168
+int mlxsw_sp_fid_nve_type(const struct mlxsw_sp_fid *fid,
169
+ enum mlxsw_sp_nve_type *p_type)
170
+{
171
+ if (!fid->vni_valid)
172
+ return -EINVAL;
173
+
174
+ *p_type = fid->nve_type;
175
+
176
+ return 0;
177
+}
178
+
179
+struct mlxsw_sp_fid *mlxsw_sp_fid_lookup_by_vni(struct mlxsw_sp *mlxsw_sp,
180
+ __be32 vni)
181
+{
182
+ struct mlxsw_sp_fid *fid;
183
+
184
+ fid = rhashtable_lookup_fast(&mlxsw_sp->fid_core->vni_ht, &vni,
185
+ mlxsw_sp_fid_vni_ht_params);
186
+ if (fid)
187
+ refcount_inc(&fid->ref_count);
188
+
189
+ return fid;
190
+}
191
+
192
+int mlxsw_sp_fid_vni(const struct mlxsw_sp_fid *fid, __be32 *vni)
193
+{
194
+ if (!fid->vni_valid)
195
+ return -EINVAL;
196
+
197
+ *vni = fid->vni;
198
+
199
+ return 0;
200
+}
201
+
202
+int mlxsw_sp_fid_nve_flood_index_set(struct mlxsw_sp_fid *fid,
203
+ u32 nve_flood_index)
204
+{
205
+ struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
206
+ const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
207
+ int err;
208
+
209
+ if (WARN_ON(!ops->nve_flood_index_set || fid->nve_flood_index_valid))
210
+ return -EINVAL;
211
+
212
+ err = ops->nve_flood_index_set(fid, nve_flood_index);
213
+ if (err)
214
+ return err;
215
+
216
+ fid->nve_flood_index = nve_flood_index;
217
+ fid->nve_flood_index_valid = true;
218
+
219
+ return 0;
220
+}
221
+
222
+void mlxsw_sp_fid_nve_flood_index_clear(struct mlxsw_sp_fid *fid)
223
+{
224
+ struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
225
+ const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
226
+
227
+ if (WARN_ON(!ops->nve_flood_index_clear || !fid->nve_flood_index_valid))
228
+ return;
229
+
230
+ fid->nve_flood_index_valid = false;
231
+ ops->nve_flood_index_clear(fid);
232
+}
233
+
234
+bool mlxsw_sp_fid_nve_flood_index_is_set(const struct mlxsw_sp_fid *fid)
235
+{
236
+ return fid->nve_flood_index_valid;
237
+}
238
+
239
+int mlxsw_sp_fid_vni_set(struct mlxsw_sp_fid *fid, enum mlxsw_sp_nve_type type,
240
+ __be32 vni, int nve_ifindex)
241
+{
242
+ struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
243
+ const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
244
+ struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
245
+ int err;
246
+
247
+ if (WARN_ON(!ops->vni_set || fid->vni_valid))
248
+ return -EINVAL;
249
+
250
+ fid->nve_type = type;
251
+ fid->nve_ifindex = nve_ifindex;
252
+ fid->vni = vni;
253
+ err = rhashtable_lookup_insert_fast(&mlxsw_sp->fid_core->vni_ht,
254
+ &fid->vni_ht_node,
255
+ mlxsw_sp_fid_vni_ht_params);
256
+ if (err)
257
+ return err;
258
+
259
+ err = ops->vni_set(fid, vni);
260
+ if (err)
261
+ goto err_vni_set;
262
+
263
+ fid->vni_valid = true;
264
+
265
+ return 0;
266
+
267
+err_vni_set:
268
+ rhashtable_remove_fast(&mlxsw_sp->fid_core->vni_ht, &fid->vni_ht_node,
269
+ mlxsw_sp_fid_vni_ht_params);
270
+ return err;
271
+}
272
+
273
+void mlxsw_sp_fid_vni_clear(struct mlxsw_sp_fid *fid)
274
+{
275
+ struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
276
+ const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
277
+ struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
278
+
279
+ if (WARN_ON(!ops->vni_clear || !fid->vni_valid))
280
+ return;
281
+
282
+ fid->vni_valid = false;
283
+ ops->vni_clear(fid);
284
+ rhashtable_remove_fast(&mlxsw_sp->fid_core->vni_ht, &fid->vni_ht_node,
285
+ mlxsw_sp_fid_vni_ht_params);
286
+}
287
+
288
+bool mlxsw_sp_fid_vni_is_set(const struct mlxsw_sp_fid *fid)
289
+{
290
+ return fid->vni_valid;
291
+}
292
+
293
+void mlxsw_sp_fid_fdb_clear_offload(const struct mlxsw_sp_fid *fid,
294
+ const struct net_device *nve_dev)
295
+{
296
+ struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
297
+ const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
298
+
299
+ if (ops->fdb_clear_offload)
300
+ ops->fdb_clear_offload(fid, nve_dev);
301
+}
96302
97303 static const struct mlxsw_sp_flood_table *
98304 mlxsw_sp_fid_flood_table_lookup(const struct mlxsw_sp_fid *fid,
....@@ -154,11 +360,6 @@
154360 fid->fid_family->ops->port_vid_unmap(fid, mlxsw_sp_port, vid);
155361 }
156362
157
-enum mlxsw_sp_rif_type mlxsw_sp_fid_rif_type(const struct mlxsw_sp_fid *fid)
158
-{
159
- return fid->fid_family->rif_type;
160
-}
161
-
162363 u16 mlxsw_sp_fid_index(const struct mlxsw_sp_fid *fid)
163364 {
164365 return fid->fid_index;
....@@ -172,6 +373,11 @@
172373 void mlxsw_sp_fid_rif_set(struct mlxsw_sp_fid *fid, struct mlxsw_sp_rif *rif)
173374 {
174375 fid->rif = rif;
376
+}
377
+
378
+struct mlxsw_sp_rif *mlxsw_sp_fid_rif(const struct mlxsw_sp_fid *fid)
379
+{
380
+ return fid->rif;
175381 }
176382
177383 enum mlxsw_sp_rif_type
....@@ -217,14 +423,19 @@
217423 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl);
218424 }
219425
220
-static int mlxsw_sp_fid_vid_map(struct mlxsw_sp *mlxsw_sp, u16 fid_index,
221
- u16 vid, bool valid)
426
+static int mlxsw_sp_fid_vni_op(struct mlxsw_sp *mlxsw_sp, u16 fid_index,
427
+ __be32 vni, bool vni_valid, u32 nve_flood_index,
428
+ bool nve_flood_index_valid)
222429 {
223
- enum mlxsw_reg_svfa_mt mt = MLXSW_REG_SVFA_MT_VID_TO_FID;
224
- char svfa_pl[MLXSW_REG_SVFA_LEN];
430
+ char sfmr_pl[MLXSW_REG_SFMR_LEN];
225431
226
- mlxsw_reg_svfa_pack(svfa_pl, 0, mt, valid, fid_index, vid);
227
- return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl);
432
+ mlxsw_reg_sfmr_pack(sfmr_pl, MLXSW_REG_SFMR_OP_CREATE_FID, fid_index,
433
+ 0);
434
+ mlxsw_reg_sfmr_vv_set(sfmr_pl, vni_valid);
435
+ mlxsw_reg_sfmr_vni_set(sfmr_pl, be32_to_cpu(vni));
436
+ mlxsw_reg_sfmr_vtfp_set(sfmr_pl, nve_flood_index_valid);
437
+ mlxsw_reg_sfmr_nve_tunnel_flood_ptr_set(sfmr_pl, nve_flood_index);
438
+ return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl);
228439 }
229440
230441 static int __mlxsw_sp_fid_port_vid_map(struct mlxsw_sp *mlxsw_sp, u16 fid_index,
....@@ -236,140 +447,6 @@
236447 mlxsw_reg_svfa_pack(svfa_pl, local_port, mt, valid, fid_index, vid);
237448 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl);
238449 }
239
-
240
-static int mlxsw_sp_fid_8021q_configure(struct mlxsw_sp_fid *fid)
241
-{
242
- struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
243
- struct mlxsw_sp_fid_8021q *fid_8021q;
244
- int err;
245
-
246
- err = mlxsw_sp_fid_op(mlxsw_sp, fid->fid_index, fid->fid_index, true);
247
- if (err)
248
- return err;
249
-
250
- fid_8021q = mlxsw_sp_fid_8021q_fid(fid);
251
- err = mlxsw_sp_fid_vid_map(mlxsw_sp, fid->fid_index, fid_8021q->vid,
252
- true);
253
- if (err)
254
- goto err_fid_map;
255
-
256
- return 0;
257
-
258
-err_fid_map:
259
- mlxsw_sp_fid_op(mlxsw_sp, fid->fid_index, 0, false);
260
- return err;
261
-}
262
-
263
-static void mlxsw_sp_fid_8021q_deconfigure(struct mlxsw_sp_fid *fid)
264
-{
265
- struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
266
- struct mlxsw_sp_fid_8021q *fid_8021q;
267
-
268
- fid_8021q = mlxsw_sp_fid_8021q_fid(fid);
269
- mlxsw_sp_fid_vid_map(mlxsw_sp, fid->fid_index, fid_8021q->vid, false);
270
- mlxsw_sp_fid_op(mlxsw_sp, fid->fid_index, 0, false);
271
-}
272
-
273
-static int mlxsw_sp_fid_8021q_index_alloc(struct mlxsw_sp_fid *fid,
274
- const void *arg, u16 *p_fid_index)
275
-{
276
- struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
277
- u16 vid = *(u16 *) arg;
278
-
279
- /* Use 1:1 mapping for simplicity although not a must */
280
- if (vid < fid_family->start_index || vid > fid_family->end_index)
281
- return -EINVAL;
282
- *p_fid_index = vid;
283
-
284
- return 0;
285
-}
286
-
287
-static bool
288
-mlxsw_sp_fid_8021q_compare(const struct mlxsw_sp_fid *fid, const void *arg)
289
-{
290
- u16 vid = *(u16 *) arg;
291
-
292
- return mlxsw_sp_fid_8021q_fid(fid)->vid == vid;
293
-}
294
-
295
-static u16 mlxsw_sp_fid_8021q_flood_index(const struct mlxsw_sp_fid *fid)
296
-{
297
- return fid->fid_index;
298
-}
299
-
300
-static int mlxsw_sp_fid_8021q_port_vid_map(struct mlxsw_sp_fid *fid,
301
- struct mlxsw_sp_port *mlxsw_sp_port,
302
- u16 vid)
303
-{
304
- struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
305
- u8 local_port = mlxsw_sp_port->local_port;
306
-
307
- /* In case there are no {Port, VID} => FID mappings on the port,
308
- * we can use the global VID => FID mapping we created when the
309
- * FID was configured.
310
- */
311
- if (mlxsw_sp->fid_core->port_fid_mappings[local_port] == 0)
312
- return 0;
313
- return __mlxsw_sp_fid_port_vid_map(mlxsw_sp, fid->fid_index, local_port,
314
- vid, true);
315
-}
316
-
317
-static void
318
-mlxsw_sp_fid_8021q_port_vid_unmap(struct mlxsw_sp_fid *fid,
319
- struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
320
-{
321
- struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
322
- u8 local_port = mlxsw_sp_port->local_port;
323
-
324
- if (mlxsw_sp->fid_core->port_fid_mappings[local_port] == 0)
325
- return;
326
- __mlxsw_sp_fid_port_vid_map(mlxsw_sp, fid->fid_index, local_port, vid,
327
- false);
328
-}
329
-
330
-static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021q_ops = {
331
- .setup = mlxsw_sp_fid_8021q_setup,
332
- .configure = mlxsw_sp_fid_8021q_configure,
333
- .deconfigure = mlxsw_sp_fid_8021q_deconfigure,
334
- .index_alloc = mlxsw_sp_fid_8021q_index_alloc,
335
- .compare = mlxsw_sp_fid_8021q_compare,
336
- .flood_index = mlxsw_sp_fid_8021q_flood_index,
337
- .port_vid_map = mlxsw_sp_fid_8021q_port_vid_map,
338
- .port_vid_unmap = mlxsw_sp_fid_8021q_port_vid_unmap,
339
-};
340
-
341
-static const struct mlxsw_sp_flood_table mlxsw_sp_fid_8021q_flood_tables[] = {
342
- {
343
- .packet_type = MLXSW_SP_FLOOD_TYPE_UC,
344
- .bridge_type = MLXSW_REG_SFGC_BRIDGE_TYPE_1Q_FID,
345
- .table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFSET,
346
- .table_index = 0,
347
- },
348
- {
349
- .packet_type = MLXSW_SP_FLOOD_TYPE_MC,
350
- .bridge_type = MLXSW_REG_SFGC_BRIDGE_TYPE_1Q_FID,
351
- .table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFSET,
352
- .table_index = 1,
353
- },
354
- {
355
- .packet_type = MLXSW_SP_FLOOD_TYPE_BC,
356
- .bridge_type = MLXSW_REG_SFGC_BRIDGE_TYPE_1Q_FID,
357
- .table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFSET,
358
- .table_index = 2,
359
- },
360
-};
361
-
362
-/* Range and flood configuration must match mlxsw_config_profile */
363
-static const struct mlxsw_sp_fid_family mlxsw_sp_fid_8021q_family = {
364
- .type = MLXSW_SP_FID_TYPE_8021Q,
365
- .fid_size = sizeof(struct mlxsw_sp_fid_8021q),
366
- .start_index = 1,
367
- .end_index = VLAN_VID_MASK,
368
- .flood_tables = mlxsw_sp_fid_8021q_flood_tables,
369
- .nr_flood_tables = ARRAY_SIZE(mlxsw_sp_fid_8021q_flood_tables),
370
- .rif_type = MLXSW_SP_RIF_TYPE_VLAN,
371
- .ops = &mlxsw_sp_fid_8021q_ops,
372
-};
373450
374451 static struct mlxsw_sp_fid_8021d *
375452 mlxsw_sp_fid_8021d_fid(const struct mlxsw_sp_fid *fid)
....@@ -393,6 +470,8 @@
393470
394471 static void mlxsw_sp_fid_8021d_deconfigure(struct mlxsw_sp_fid *fid)
395472 {
473
+ if (fid->vni_valid)
474
+ mlxsw_sp_nve_fid_disable(fid->fid_family->mlxsw_sp, fid);
396475 mlxsw_sp_fid_op(fid->fid_family->mlxsw_sp, fid->fid_index, 0, false);
397476 }
398477
....@@ -421,7 +500,7 @@
421500
422501 static u16 mlxsw_sp_fid_8021d_flood_index(const struct mlxsw_sp_fid *fid)
423502 {
424
- return fid->fid_index - fid->fid_family->start_index;
503
+ return fid->fid_index - VLAN_N_VID;
425504 }
426505
427506 static int mlxsw_sp_port_vp_mode_trans(struct mlxsw_sp_port *mlxsw_sp_port)
....@@ -531,6 +610,48 @@
531610 mlxsw_sp_port->local_port, vid, false);
532611 }
533612
613
+static int mlxsw_sp_fid_8021d_vni_set(struct mlxsw_sp_fid *fid, __be32 vni)
614
+{
615
+ struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
616
+
617
+ return mlxsw_sp_fid_vni_op(fid_family->mlxsw_sp, fid->fid_index, vni,
618
+ true, fid->nve_flood_index,
619
+ fid->nve_flood_index_valid);
620
+}
621
+
622
+static void mlxsw_sp_fid_8021d_vni_clear(struct mlxsw_sp_fid *fid)
623
+{
624
+ struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
625
+
626
+ mlxsw_sp_fid_vni_op(fid_family->mlxsw_sp, fid->fid_index, 0, false,
627
+ fid->nve_flood_index, fid->nve_flood_index_valid);
628
+}
629
+
630
+static int mlxsw_sp_fid_8021d_nve_flood_index_set(struct mlxsw_sp_fid *fid,
631
+ u32 nve_flood_index)
632
+{
633
+ struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
634
+
635
+ return mlxsw_sp_fid_vni_op(fid_family->mlxsw_sp, fid->fid_index,
636
+ fid->vni, fid->vni_valid, nve_flood_index,
637
+ true);
638
+}
639
+
640
+static void mlxsw_sp_fid_8021d_nve_flood_index_clear(struct mlxsw_sp_fid *fid)
641
+{
642
+ struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
643
+
644
+ mlxsw_sp_fid_vni_op(fid_family->mlxsw_sp, fid->fid_index, fid->vni,
645
+ fid->vni_valid, 0, false);
646
+}
647
+
648
+static void
649
+mlxsw_sp_fid_8021d_fdb_clear_offload(const struct mlxsw_sp_fid *fid,
650
+ const struct net_device *nve_dev)
651
+{
652
+ br_fdb_clear_offload(nve_dev, 0);
653
+}
654
+
534655 static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021d_ops = {
535656 .setup = mlxsw_sp_fid_8021d_setup,
536657 .configure = mlxsw_sp_fid_8021d_configure,
....@@ -540,6 +661,11 @@
540661 .flood_index = mlxsw_sp_fid_8021d_flood_index,
541662 .port_vid_map = mlxsw_sp_fid_8021d_port_vid_map,
542663 .port_vid_unmap = mlxsw_sp_fid_8021d_port_vid_unmap,
664
+ .vni_set = mlxsw_sp_fid_8021d_vni_set,
665
+ .vni_clear = mlxsw_sp_fid_8021d_vni_clear,
666
+ .nve_flood_index_set = mlxsw_sp_fid_8021d_nve_flood_index_set,
667
+ .nve_flood_index_clear = mlxsw_sp_fid_8021d_nve_flood_index_clear,
668
+ .fdb_clear_offload = mlxsw_sp_fid_8021d_fdb_clear_offload,
543669 };
544670
545671 static const struct mlxsw_sp_flood_table mlxsw_sp_fid_8021d_flood_tables[] = {
....@@ -573,6 +699,56 @@
573699 .nr_flood_tables = ARRAY_SIZE(mlxsw_sp_fid_8021d_flood_tables),
574700 .rif_type = MLXSW_SP_RIF_TYPE_FID,
575701 .ops = &mlxsw_sp_fid_8021d_ops,
702
+ .lag_vid_valid = 1,
703
+};
704
+
705
+static bool
706
+mlxsw_sp_fid_8021q_compare(const struct mlxsw_sp_fid *fid, const void *arg)
707
+{
708
+ u16 vid = *(u16 *) arg;
709
+
710
+ return mlxsw_sp_fid_8021q_fid(fid)->vid == vid;
711
+}
712
+
713
+static void
714
+mlxsw_sp_fid_8021q_fdb_clear_offload(const struct mlxsw_sp_fid *fid,
715
+ const struct net_device *nve_dev)
716
+{
717
+ br_fdb_clear_offload(nve_dev, mlxsw_sp_fid_8021q_vid(fid));
718
+}
719
+
720
+static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021q_emu_ops = {
721
+ .setup = mlxsw_sp_fid_8021q_setup,
722
+ .configure = mlxsw_sp_fid_8021d_configure,
723
+ .deconfigure = mlxsw_sp_fid_8021d_deconfigure,
724
+ .index_alloc = mlxsw_sp_fid_8021d_index_alloc,
725
+ .compare = mlxsw_sp_fid_8021q_compare,
726
+ .flood_index = mlxsw_sp_fid_8021d_flood_index,
727
+ .port_vid_map = mlxsw_sp_fid_8021d_port_vid_map,
728
+ .port_vid_unmap = mlxsw_sp_fid_8021d_port_vid_unmap,
729
+ .vni_set = mlxsw_sp_fid_8021d_vni_set,
730
+ .vni_clear = mlxsw_sp_fid_8021d_vni_clear,
731
+ .nve_flood_index_set = mlxsw_sp_fid_8021d_nve_flood_index_set,
732
+ .nve_flood_index_clear = mlxsw_sp_fid_8021d_nve_flood_index_clear,
733
+ .fdb_clear_offload = mlxsw_sp_fid_8021q_fdb_clear_offload,
734
+};
735
+
736
+/* There are 4K-2 emulated 802.1Q FIDs, starting right after the 802.1D FIDs */
737
+#define MLXSW_SP_FID_8021Q_EMU_START (VLAN_N_VID + MLXSW_SP_FID_8021D_MAX)
738
+#define MLXSW_SP_FID_8021Q_EMU_END (MLXSW_SP_FID_8021Q_EMU_START + \
739
+ VLAN_VID_MASK - 2)
740
+
741
+/* Range and flood configuration must match mlxsw_config_profile */
742
+static const struct mlxsw_sp_fid_family mlxsw_sp_fid_8021q_emu_family = {
743
+ .type = MLXSW_SP_FID_TYPE_8021Q,
744
+ .fid_size = sizeof(struct mlxsw_sp_fid_8021q),
745
+ .start_index = MLXSW_SP_FID_8021Q_EMU_START,
746
+ .end_index = MLXSW_SP_FID_8021Q_EMU_END,
747
+ .flood_tables = mlxsw_sp_fid_8021d_flood_tables,
748
+ .nr_flood_tables = ARRAY_SIZE(mlxsw_sp_fid_8021d_flood_tables),
749
+ .rif_type = MLXSW_SP_RIF_TYPE_VLAN,
750
+ .ops = &mlxsw_sp_fid_8021q_emu_ops,
751
+ .lag_vid_valid = 1,
576752 };
577753
578754 static int mlxsw_sp_fid_rfid_configure(struct mlxsw_sp_fid *fid)
....@@ -702,11 +878,29 @@
702878 };
703879
704880 static const struct mlxsw_sp_fid_family *mlxsw_sp_fid_family_arr[] = {
705
- [MLXSW_SP_FID_TYPE_8021Q] = &mlxsw_sp_fid_8021q_family,
881
+ [MLXSW_SP_FID_TYPE_8021Q] = &mlxsw_sp_fid_8021q_emu_family,
706882 [MLXSW_SP_FID_TYPE_8021D] = &mlxsw_sp_fid_8021d_family,
707883 [MLXSW_SP_FID_TYPE_RFID] = &mlxsw_sp_fid_rfid_family,
708884 [MLXSW_SP_FID_TYPE_DUMMY] = &mlxsw_sp_fid_dummy_family,
709885 };
886
+
887
+static struct mlxsw_sp_fid *mlxsw_sp_fid_lookup(struct mlxsw_sp *mlxsw_sp,
888
+ enum mlxsw_sp_fid_type type,
889
+ const void *arg)
890
+{
891
+ struct mlxsw_sp_fid_family *fid_family;
892
+ struct mlxsw_sp_fid *fid;
893
+
894
+ fid_family = mlxsw_sp->fid_core->fid_family_arr[type];
895
+ list_for_each_entry(fid, &fid_family->fids_list, list) {
896
+ if (!fid->fid_family->ops->compare(fid, arg))
897
+ continue;
898
+ refcount_inc(&fid->ref_count);
899
+ return fid;
900
+ }
901
+
902
+ return NULL;
903
+}
710904
711905 static struct mlxsw_sp_fid *mlxsw_sp_fid_get(struct mlxsw_sp *mlxsw_sp,
712906 enum mlxsw_sp_fid_type type,
....@@ -717,14 +911,11 @@
717911 u16 fid_index;
718912 int err;
719913
720
- fid_family = mlxsw_sp->fid_core->fid_family_arr[type];
721
- list_for_each_entry(fid, &fid_family->fids_list, list) {
722
- if (!fid->fid_family->ops->compare(fid, arg))
723
- continue;
724
- fid->ref_count++;
914
+ fid = mlxsw_sp_fid_lookup(mlxsw_sp, type, arg);
915
+ if (fid)
725916 return fid;
726
- }
727917
918
+ fid_family = mlxsw_sp->fid_core->fid_family_arr[type];
728919 fid = kzalloc(fid_family->fid_size, GFP_KERNEL);
729920 if (!fid)
730921 return ERR_PTR(-ENOMEM);
....@@ -743,10 +934,17 @@
743934 if (err)
744935 goto err_configure;
745936
937
+ err = rhashtable_insert_fast(&mlxsw_sp->fid_core->fid_ht, &fid->ht_node,
938
+ mlxsw_sp_fid_ht_params);
939
+ if (err)
940
+ goto err_rhashtable_insert;
941
+
746942 list_add(&fid->list, &fid_family->fids_list);
747
- fid->ref_count++;
943
+ refcount_set(&fid->ref_count, 1);
748944 return fid;
749945
946
+err_rhashtable_insert:
947
+ fid->fid_family->ops->deconfigure(fid);
750948 err_configure:
751949 __clear_bit(fid_index - fid_family->start_index,
752950 fid_family->fids_bitmap);
....@@ -758,19 +956,18 @@
758956 void mlxsw_sp_fid_put(struct mlxsw_sp_fid *fid)
759957 {
760958 struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
959
+ struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
761960
762
- if (--fid->ref_count == 1 && fid->rif) {
763
- /* Destroy the associated RIF and let it drop the last
764
- * reference on the FID.
765
- */
766
- return mlxsw_sp_rif_destroy(fid->rif);
767
- } else if (fid->ref_count == 0) {
768
- list_del(&fid->list);
769
- fid->fid_family->ops->deconfigure(fid);
770
- __clear_bit(fid->fid_index - fid_family->start_index,
771
- fid_family->fids_bitmap);
772
- kfree(fid);
773
- }
961
+ if (!refcount_dec_and_test(&fid->ref_count))
962
+ return;
963
+
964
+ list_del(&fid->list);
965
+ rhashtable_remove_fast(&mlxsw_sp->fid_core->fid_ht,
966
+ &fid->ht_node, mlxsw_sp_fid_ht_params);
967
+ fid->fid_family->ops->deconfigure(fid);
968
+ __clear_bit(fid->fid_index - fid_family->start_index,
969
+ fid_family->fids_bitmap);
970
+ kfree(fid);
774971 }
775972
776973 struct mlxsw_sp_fid *mlxsw_sp_fid_8021q_get(struct mlxsw_sp *mlxsw_sp, u16 vid)
....@@ -782,6 +979,19 @@
782979 int br_ifindex)
783980 {
784981 return mlxsw_sp_fid_get(mlxsw_sp, MLXSW_SP_FID_TYPE_8021D, &br_ifindex);
982
+}
983
+
984
+struct mlxsw_sp_fid *mlxsw_sp_fid_8021q_lookup(struct mlxsw_sp *mlxsw_sp,
985
+ u16 vid)
986
+{
987
+ return mlxsw_sp_fid_lookup(mlxsw_sp, MLXSW_SP_FID_TYPE_8021Q, &vid);
988
+}
989
+
990
+struct mlxsw_sp_fid *mlxsw_sp_fid_8021d_lookup(struct mlxsw_sp *mlxsw_sp,
991
+ int br_ifindex)
992
+{
993
+ return mlxsw_sp_fid_lookup(mlxsw_sp, MLXSW_SP_FID_TYPE_8021D,
994
+ &br_ifindex);
785995 }
786996
787997 struct mlxsw_sp_fid *mlxsw_sp_fid_rfid_get(struct mlxsw_sp *mlxsw_sp,
....@@ -853,8 +1063,7 @@
8531063
8541064 fid_family->mlxsw_sp = mlxsw_sp;
8551065 INIT_LIST_HEAD(&fid_family->fids_list);
856
- fid_family->fids_bitmap = kcalloc(BITS_TO_LONGS(nr_fids),
857
- sizeof(unsigned long), GFP_KERNEL);
1066
+ fid_family->fids_bitmap = bitmap_zalloc(nr_fids, GFP_KERNEL);
8581067 if (!fid_family->fids_bitmap) {
8591068 err = -ENOMEM;
8601069 goto err_alloc_fids_bitmap;
....@@ -871,7 +1080,7 @@
8711080 return 0;
8721081
8731082 err_fid_flood_tables_init:
874
- kfree(fid_family->fids_bitmap);
1083
+ bitmap_free(fid_family->fids_bitmap);
8751084 err_alloc_fids_bitmap:
8761085 kfree(fid_family);
8771086 return err;
....@@ -882,7 +1091,7 @@
8821091 struct mlxsw_sp_fid_family *fid_family)
8831092 {
8841093 mlxsw_sp->fid_core->fid_family_arr[fid_family->type] = NULL;
885
- kfree(fid_family->fids_bitmap);
1094
+ bitmap_free(fid_family->fids_bitmap);
8861095 WARN_ON_ONCE(!list_empty(&fid_family->fids_list));
8871096 kfree(fid_family);
8881097 }
....@@ -918,6 +1127,14 @@
9181127 return -ENOMEM;
9191128 mlxsw_sp->fid_core = fid_core;
9201129
1130
+ err = rhashtable_init(&fid_core->fid_ht, &mlxsw_sp_fid_ht_params);
1131
+ if (err)
1132
+ goto err_rhashtable_fid_init;
1133
+
1134
+ err = rhashtable_init(&fid_core->vni_ht, &mlxsw_sp_fid_vni_ht_params);
1135
+ if (err)
1136
+ goto err_rhashtable_vni_init;
1137
+
9211138 fid_core->port_fid_mappings = kcalloc(max_ports, sizeof(unsigned int),
9221139 GFP_KERNEL);
9231140 if (!fid_core->port_fid_mappings) {
....@@ -944,6 +1161,10 @@
9441161 }
9451162 kfree(fid_core->port_fid_mappings);
9461163 err_alloc_port_fid_mappings:
1164
+ rhashtable_destroy(&fid_core->vni_ht);
1165
+err_rhashtable_vni_init:
1166
+ rhashtable_destroy(&fid_core->fid_ht);
1167
+err_rhashtable_fid_init:
9471168 kfree(fid_core);
9481169 return err;
9491170 }
....@@ -957,5 +1178,7 @@
9571178 mlxsw_sp_fid_family_unregister(mlxsw_sp,
9581179 fid_core->fid_family_arr[i]);
9591180 kfree(fid_core->port_fid_mappings);
1181
+ rhashtable_destroy(&fid_core->vni_ht);
1182
+ rhashtable_destroy(&fid_core->fid_ht);
9601183 kfree(fid_core);
9611184 }