clk: Drop the rate range on clk_put()
[linux-2.6-microblaze.git] / drivers / net / ethernet / mellanox / mlx5 / core / esw / bridge.c
1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 /* Copyright (c) 2021 Mellanox Technologies. */
3
4 #include <linux/list.h>
5 #include <linux/notifier.h>
6 #include <net/netevent.h>
7 #include <net/switchdev.h>
8 #include "lib/devcom.h"
9 #include "bridge.h"
10 #include "eswitch.h"
11 #include "bridge_priv.h"
12 #define CREATE_TRACE_POINTS
13 #include "diag/bridge_tracepoint.h"
14
15 #define MLX5_ESW_BRIDGE_INGRESS_TABLE_SIZE 64000
16 #define MLX5_ESW_BRIDGE_INGRESS_TABLE_VLAN_GRP_IDX_FROM 0
17 #define MLX5_ESW_BRIDGE_INGRESS_TABLE_VLAN_GRP_IDX_TO (MLX5_ESW_BRIDGE_INGRESS_TABLE_SIZE / 4 - 1)
18 #define MLX5_ESW_BRIDGE_INGRESS_TABLE_FILTER_GRP_IDX_FROM \
19         (MLX5_ESW_BRIDGE_INGRESS_TABLE_VLAN_GRP_IDX_TO + 1)
20 #define MLX5_ESW_BRIDGE_INGRESS_TABLE_FILTER_GRP_IDX_TO \
21         (MLX5_ESW_BRIDGE_INGRESS_TABLE_SIZE / 2 - 1)
22 #define MLX5_ESW_BRIDGE_INGRESS_TABLE_MAC_GRP_IDX_FROM \
23         (MLX5_ESW_BRIDGE_INGRESS_TABLE_FILTER_GRP_IDX_TO + 1)
24 #define MLX5_ESW_BRIDGE_INGRESS_TABLE_MAC_GRP_IDX_TO (MLX5_ESW_BRIDGE_INGRESS_TABLE_SIZE - 1)
25
26 #define MLX5_ESW_BRIDGE_EGRESS_TABLE_SIZE 64000
27 #define MLX5_ESW_BRIDGE_EGRESS_TABLE_VLAN_GRP_IDX_FROM 0
28 #define MLX5_ESW_BRIDGE_EGRESS_TABLE_VLAN_GRP_IDX_TO (MLX5_ESW_BRIDGE_EGRESS_TABLE_SIZE / 2 - 1)
29 #define MLX5_ESW_BRIDGE_EGRESS_TABLE_MAC_GRP_IDX_FROM \
30         (MLX5_ESW_BRIDGE_EGRESS_TABLE_VLAN_GRP_IDX_TO + 1)
31 #define MLX5_ESW_BRIDGE_EGRESS_TABLE_MAC_GRP_IDX_TO (MLX5_ESW_BRIDGE_EGRESS_TABLE_SIZE - 2)
32 #define MLX5_ESW_BRIDGE_EGRESS_TABLE_MISS_GRP_IDX_FROM \
33         (MLX5_ESW_BRIDGE_EGRESS_TABLE_MAC_GRP_IDX_TO + 1)
34 #define MLX5_ESW_BRIDGE_EGRESS_TABLE_MISS_GRP_IDX_TO (MLX5_ESW_BRIDGE_EGRESS_TABLE_SIZE - 1)
35
36 #define MLX5_ESW_BRIDGE_SKIP_TABLE_SIZE 0
37
38 enum {
39         MLX5_ESW_BRIDGE_LEVEL_INGRESS_TABLE,
40         MLX5_ESW_BRIDGE_LEVEL_EGRESS_TABLE,
41         MLX5_ESW_BRIDGE_LEVEL_SKIP_TABLE,
42 };
43
44 static const struct rhashtable_params fdb_ht_params = {
45         .key_offset = offsetof(struct mlx5_esw_bridge_fdb_entry, key),
46         .key_len = sizeof(struct mlx5_esw_bridge_fdb_key),
47         .head_offset = offsetof(struct mlx5_esw_bridge_fdb_entry, ht_node),
48         .automatic_shrinking = true,
49 };
50
51 enum {
52         MLX5_ESW_BRIDGE_VLAN_FILTERING_FLAG = BIT(0),
53 };
54
55 struct mlx5_esw_bridge {
56         int ifindex;
57         int refcnt;
58         struct list_head list;
59         struct mlx5_esw_bridge_offloads *br_offloads;
60
61         struct list_head fdb_list;
62         struct rhashtable fdb_ht;
63
64         struct mlx5_flow_table *egress_ft;
65         struct mlx5_flow_group *egress_vlan_fg;
66         struct mlx5_flow_group *egress_mac_fg;
67         struct mlx5_flow_group *egress_miss_fg;
68         struct mlx5_pkt_reformat *egress_miss_pkt_reformat;
69         struct mlx5_flow_handle *egress_miss_handle;
70         unsigned long ageing_time;
71         u32 flags;
72 };
73
74 static void
75 mlx5_esw_bridge_fdb_offload_notify(struct net_device *dev, const unsigned char *addr, u16 vid,
76                                    unsigned long val)
77 {
78         struct switchdev_notifier_fdb_info send_info = {};
79
80         send_info.addr = addr;
81         send_info.vid = vid;
82         send_info.offloaded = true;
83         call_switchdev_notifiers(val, dev, &send_info.info, NULL);
84 }
85
86 static void
87 mlx5_esw_bridge_fdb_del_notify(struct mlx5_esw_bridge_fdb_entry *entry)
88 {
89         if (!(entry->flags & (MLX5_ESW_BRIDGE_FLAG_ADDED_BY_USER | MLX5_ESW_BRIDGE_FLAG_PEER)))
90                 mlx5_esw_bridge_fdb_offload_notify(entry->dev, entry->key.addr,
91                                                    entry->key.vid,
92                                                    SWITCHDEV_FDB_DEL_TO_BRIDGE);
93 }
94
95 static bool mlx5_esw_bridge_pkt_reformat_vlan_pop_supported(struct mlx5_eswitch *esw)
96 {
97         return BIT(MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, reformat_remove)) &&
98                 MLX5_CAP_GEN_2(esw->dev, max_reformat_remove_size) >= sizeof(struct vlan_hdr) &&
99                 MLX5_CAP_GEN_2(esw->dev, max_reformat_remove_offset) >=
100                 offsetof(struct vlan_ethhdr, h_vlan_proto);
101 }
102
103 static struct mlx5_pkt_reformat *
104 mlx5_esw_bridge_pkt_reformat_vlan_pop_create(struct mlx5_eswitch *esw)
105 {
106         struct mlx5_pkt_reformat_params reformat_params = {};
107
108         reformat_params.type = MLX5_REFORMAT_TYPE_REMOVE_HDR;
109         reformat_params.param_0 = MLX5_REFORMAT_CONTEXT_ANCHOR_MAC_START;
110         reformat_params.param_1 = offsetof(struct vlan_ethhdr, h_vlan_proto);
111         reformat_params.size = sizeof(struct vlan_hdr);
112         return mlx5_packet_reformat_alloc(esw->dev, &reformat_params, MLX5_FLOW_NAMESPACE_FDB);
113 }
114
115 static struct mlx5_flow_table *
116 mlx5_esw_bridge_table_create(int max_fte, u32 level, struct mlx5_eswitch *esw)
117 {
118         struct mlx5_flow_table_attr ft_attr = {};
119         struct mlx5_core_dev *dev = esw->dev;
120         struct mlx5_flow_namespace *ns;
121         struct mlx5_flow_table *fdb;
122
123         ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_FDB);
124         if (!ns) {
125                 esw_warn(dev, "Failed to get FDB namespace\n");
126                 return ERR_PTR(-ENOENT);
127         }
128
129         ft_attr.flags = MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT;
130         ft_attr.max_fte = max_fte;
131         ft_attr.level = level;
132         ft_attr.prio = FDB_BR_OFFLOAD;
133         fdb = mlx5_create_flow_table(ns, &ft_attr);
134         if (IS_ERR(fdb))
135                 esw_warn(dev, "Failed to create bridge FDB Table (err=%ld)\n", PTR_ERR(fdb));
136
137         return fdb;
138 }
139
140 static struct mlx5_flow_group *
141 mlx5_esw_bridge_ingress_vlan_fg_create(struct mlx5_eswitch *esw, struct mlx5_flow_table *ingress_ft)
142 {
143         int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
144         struct mlx5_flow_group *fg;
145         u32 *in, *match;
146
147         in = kvzalloc(inlen, GFP_KERNEL);
148         if (!in)
149                 return ERR_PTR(-ENOMEM);
150
151         MLX5_SET(create_flow_group_in, in, match_criteria_enable,
152                  MLX5_MATCH_OUTER_HEADERS | MLX5_MATCH_MISC_PARAMETERS_2);
153         match = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria);
154
155         MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.smac_47_16);
156         MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.smac_15_0);
157         MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.cvlan_tag);
158         MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.first_vid);
159
160         MLX5_SET(fte_match_param, match, misc_parameters_2.metadata_reg_c_0,
161                  mlx5_eswitch_get_vport_metadata_mask());
162
163         MLX5_SET(create_flow_group_in, in, start_flow_index,
164                  MLX5_ESW_BRIDGE_INGRESS_TABLE_VLAN_GRP_IDX_FROM);
165         MLX5_SET(create_flow_group_in, in, end_flow_index,
166                  MLX5_ESW_BRIDGE_INGRESS_TABLE_VLAN_GRP_IDX_TO);
167
168         fg = mlx5_create_flow_group(ingress_ft, in);
169         kvfree(in);
170         if (IS_ERR(fg))
171                 esw_warn(esw->dev,
172                          "Failed to create VLAN flow group for bridge ingress table (err=%ld)\n",
173                          PTR_ERR(fg));
174
175         return fg;
176 }
177
178 static struct mlx5_flow_group *
179 mlx5_esw_bridge_ingress_filter_fg_create(struct mlx5_eswitch *esw,
180                                          struct mlx5_flow_table *ingress_ft)
181 {
182         int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
183         struct mlx5_flow_group *fg;
184         u32 *in, *match;
185
186         in = kvzalloc(inlen, GFP_KERNEL);
187         if (!in)
188                 return ERR_PTR(-ENOMEM);
189
190         MLX5_SET(create_flow_group_in, in, match_criteria_enable,
191                  MLX5_MATCH_OUTER_HEADERS | MLX5_MATCH_MISC_PARAMETERS_2);
192         match = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria);
193
194         MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.smac_47_16);
195         MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.smac_15_0);
196         MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.cvlan_tag);
197
198         MLX5_SET(fte_match_param, match, misc_parameters_2.metadata_reg_c_0,
199                  mlx5_eswitch_get_vport_metadata_mask());
200
201         MLX5_SET(create_flow_group_in, in, start_flow_index,
202                  MLX5_ESW_BRIDGE_INGRESS_TABLE_FILTER_GRP_IDX_FROM);
203         MLX5_SET(create_flow_group_in, in, end_flow_index,
204                  MLX5_ESW_BRIDGE_INGRESS_TABLE_FILTER_GRP_IDX_TO);
205
206         fg = mlx5_create_flow_group(ingress_ft, in);
207         if (IS_ERR(fg))
208                 esw_warn(esw->dev,
209                          "Failed to create bridge ingress table VLAN filter flow group (err=%ld)\n",
210                          PTR_ERR(fg));
211
212         kvfree(in);
213         return fg;
214 }
215
216 static struct mlx5_flow_group *
217 mlx5_esw_bridge_ingress_mac_fg_create(struct mlx5_eswitch *esw, struct mlx5_flow_table *ingress_ft)
218 {
219         int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
220         struct mlx5_flow_group *fg;
221         u32 *in, *match;
222
223         in = kvzalloc(inlen, GFP_KERNEL);
224         if (!in)
225                 return ERR_PTR(-ENOMEM);
226
227         MLX5_SET(create_flow_group_in, in, match_criteria_enable,
228                  MLX5_MATCH_OUTER_HEADERS | MLX5_MATCH_MISC_PARAMETERS_2);
229         match = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria);
230
231         MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.smac_47_16);
232         MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.smac_15_0);
233
234         MLX5_SET(fte_match_param, match, misc_parameters_2.metadata_reg_c_0,
235                  mlx5_eswitch_get_vport_metadata_mask());
236
237         MLX5_SET(create_flow_group_in, in, start_flow_index,
238                  MLX5_ESW_BRIDGE_INGRESS_TABLE_MAC_GRP_IDX_FROM);
239         MLX5_SET(create_flow_group_in, in, end_flow_index,
240                  MLX5_ESW_BRIDGE_INGRESS_TABLE_MAC_GRP_IDX_TO);
241
242         fg = mlx5_create_flow_group(ingress_ft, in);
243         if (IS_ERR(fg))
244                 esw_warn(esw->dev,
245                          "Failed to create MAC flow group for bridge ingress table (err=%ld)\n",
246                          PTR_ERR(fg));
247
248         kvfree(in);
249         return fg;
250 }
251
252 static struct mlx5_flow_group *
253 mlx5_esw_bridge_egress_vlan_fg_create(struct mlx5_eswitch *esw, struct mlx5_flow_table *egress_ft)
254 {
255         int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
256         struct mlx5_flow_group *fg;
257         u32 *in, *match;
258
259         in = kvzalloc(inlen, GFP_KERNEL);
260         if (!in)
261                 return ERR_PTR(-ENOMEM);
262
263         MLX5_SET(create_flow_group_in, in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
264         match = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria);
265
266         MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.dmac_47_16);
267         MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.dmac_15_0);
268         MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.cvlan_tag);
269         MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.first_vid);
270
271         MLX5_SET(create_flow_group_in, in, start_flow_index,
272                  MLX5_ESW_BRIDGE_EGRESS_TABLE_VLAN_GRP_IDX_FROM);
273         MLX5_SET(create_flow_group_in, in, end_flow_index,
274                  MLX5_ESW_BRIDGE_EGRESS_TABLE_VLAN_GRP_IDX_TO);
275
276         fg = mlx5_create_flow_group(egress_ft, in);
277         if (IS_ERR(fg))
278                 esw_warn(esw->dev,
279                          "Failed to create VLAN flow group for bridge egress table (err=%ld)\n",
280                          PTR_ERR(fg));
281         kvfree(in);
282         return fg;
283 }
284
285 static struct mlx5_flow_group *
286 mlx5_esw_bridge_egress_mac_fg_create(struct mlx5_eswitch *esw, struct mlx5_flow_table *egress_ft)
287 {
288         int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
289         struct mlx5_flow_group *fg;
290         u32 *in, *match;
291
292         in = kvzalloc(inlen, GFP_KERNEL);
293         if (!in)
294                 return ERR_PTR(-ENOMEM);
295
296         MLX5_SET(create_flow_group_in, in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
297         match = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria);
298
299         MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.dmac_47_16);
300         MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.dmac_15_0);
301
302         MLX5_SET(create_flow_group_in, in, start_flow_index,
303                  MLX5_ESW_BRIDGE_EGRESS_TABLE_MAC_GRP_IDX_FROM);
304         MLX5_SET(create_flow_group_in, in, end_flow_index,
305                  MLX5_ESW_BRIDGE_EGRESS_TABLE_MAC_GRP_IDX_TO);
306
307         fg = mlx5_create_flow_group(egress_ft, in);
308         if (IS_ERR(fg))
309                 esw_warn(esw->dev,
310                          "Failed to create bridge egress table MAC flow group (err=%ld)\n",
311                          PTR_ERR(fg));
312         kvfree(in);
313         return fg;
314 }
315
316 static struct mlx5_flow_group *
317 mlx5_esw_bridge_egress_miss_fg_create(struct mlx5_eswitch *esw, struct mlx5_flow_table *egress_ft)
318 {
319         int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
320         struct mlx5_flow_group *fg;
321         u32 *in, *match;
322
323         in = kvzalloc(inlen, GFP_KERNEL);
324         if (!in)
325                 return ERR_PTR(-ENOMEM);
326
327         MLX5_SET(create_flow_group_in, in, match_criteria_enable, MLX5_MATCH_MISC_PARAMETERS_2);
328         match = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria);
329
330         MLX5_SET(fte_match_param, match, misc_parameters_2.metadata_reg_c_1, ESW_TUN_MASK);
331
332         MLX5_SET(create_flow_group_in, in, start_flow_index,
333                  MLX5_ESW_BRIDGE_EGRESS_TABLE_MISS_GRP_IDX_FROM);
334         MLX5_SET(create_flow_group_in, in, end_flow_index,
335                  MLX5_ESW_BRIDGE_EGRESS_TABLE_MISS_GRP_IDX_TO);
336
337         fg = mlx5_create_flow_group(egress_ft, in);
338         if (IS_ERR(fg))
339                 esw_warn(esw->dev,
340                          "Failed to create bridge egress table miss flow group (err=%ld)\n",
341                          PTR_ERR(fg));
342         kvfree(in);
343         return fg;
344 }
345
346 static int
347 mlx5_esw_bridge_ingress_table_init(struct mlx5_esw_bridge_offloads *br_offloads)
348 {
349         struct mlx5_flow_group *mac_fg, *filter_fg, *vlan_fg;
350         struct mlx5_flow_table *ingress_ft, *skip_ft;
351         struct mlx5_eswitch *esw = br_offloads->esw;
352         int err;
353
354         if (!mlx5_eswitch_vport_match_metadata_enabled(esw))
355                 return -EOPNOTSUPP;
356
357         ingress_ft = mlx5_esw_bridge_table_create(MLX5_ESW_BRIDGE_INGRESS_TABLE_SIZE,
358                                                   MLX5_ESW_BRIDGE_LEVEL_INGRESS_TABLE,
359                                                   esw);
360         if (IS_ERR(ingress_ft))
361                 return PTR_ERR(ingress_ft);
362
363         skip_ft = mlx5_esw_bridge_table_create(MLX5_ESW_BRIDGE_SKIP_TABLE_SIZE,
364                                                MLX5_ESW_BRIDGE_LEVEL_SKIP_TABLE,
365                                                esw);
366         if (IS_ERR(skip_ft)) {
367                 err = PTR_ERR(skip_ft);
368                 goto err_skip_tbl;
369         }
370
371         vlan_fg = mlx5_esw_bridge_ingress_vlan_fg_create(esw, ingress_ft);
372         if (IS_ERR(vlan_fg)) {
373                 err = PTR_ERR(vlan_fg);
374                 goto err_vlan_fg;
375         }
376
377         filter_fg = mlx5_esw_bridge_ingress_filter_fg_create(esw, ingress_ft);
378         if (IS_ERR(filter_fg)) {
379                 err = PTR_ERR(filter_fg);
380                 goto err_filter_fg;
381         }
382
383         mac_fg = mlx5_esw_bridge_ingress_mac_fg_create(esw, ingress_ft);
384         if (IS_ERR(mac_fg)) {
385                 err = PTR_ERR(mac_fg);
386                 goto err_mac_fg;
387         }
388
389         br_offloads->ingress_ft = ingress_ft;
390         br_offloads->skip_ft = skip_ft;
391         br_offloads->ingress_vlan_fg = vlan_fg;
392         br_offloads->ingress_filter_fg = filter_fg;
393         br_offloads->ingress_mac_fg = mac_fg;
394         return 0;
395
396 err_mac_fg:
397         mlx5_destroy_flow_group(filter_fg);
398 err_filter_fg:
399         mlx5_destroy_flow_group(vlan_fg);
400 err_vlan_fg:
401         mlx5_destroy_flow_table(skip_ft);
402 err_skip_tbl:
403         mlx5_destroy_flow_table(ingress_ft);
404         return err;
405 }
406
407 static void
408 mlx5_esw_bridge_ingress_table_cleanup(struct mlx5_esw_bridge_offloads *br_offloads)
409 {
410         mlx5_destroy_flow_group(br_offloads->ingress_mac_fg);
411         br_offloads->ingress_mac_fg = NULL;
412         mlx5_destroy_flow_group(br_offloads->ingress_filter_fg);
413         br_offloads->ingress_filter_fg = NULL;
414         mlx5_destroy_flow_group(br_offloads->ingress_vlan_fg);
415         br_offloads->ingress_vlan_fg = NULL;
416         mlx5_destroy_flow_table(br_offloads->skip_ft);
417         br_offloads->skip_ft = NULL;
418         mlx5_destroy_flow_table(br_offloads->ingress_ft);
419         br_offloads->ingress_ft = NULL;
420 }
421
422 static struct mlx5_flow_handle *
423 mlx5_esw_bridge_egress_miss_flow_create(struct mlx5_flow_table *egress_ft,
424                                         struct mlx5_flow_table *skip_ft,
425                                         struct mlx5_pkt_reformat *pkt_reformat);
426
427 static int
428 mlx5_esw_bridge_egress_table_init(struct mlx5_esw_bridge_offloads *br_offloads,
429                                   struct mlx5_esw_bridge *bridge)
430 {
431         struct mlx5_flow_group *miss_fg = NULL, *mac_fg, *vlan_fg;
432         struct mlx5_pkt_reformat *miss_pkt_reformat = NULL;
433         struct mlx5_flow_handle *miss_handle = NULL;
434         struct mlx5_eswitch *esw = br_offloads->esw;
435         struct mlx5_flow_table *egress_ft;
436         int err;
437
438         egress_ft = mlx5_esw_bridge_table_create(MLX5_ESW_BRIDGE_EGRESS_TABLE_SIZE,
439                                                  MLX5_ESW_BRIDGE_LEVEL_EGRESS_TABLE,
440                                                  esw);
441         if (IS_ERR(egress_ft))
442                 return PTR_ERR(egress_ft);
443
444         vlan_fg = mlx5_esw_bridge_egress_vlan_fg_create(esw, egress_ft);
445         if (IS_ERR(vlan_fg)) {
446                 err = PTR_ERR(vlan_fg);
447                 goto err_vlan_fg;
448         }
449
450         mac_fg = mlx5_esw_bridge_egress_mac_fg_create(esw, egress_ft);
451         if (IS_ERR(mac_fg)) {
452                 err = PTR_ERR(mac_fg);
453                 goto err_mac_fg;
454         }
455
456         if (mlx5_esw_bridge_pkt_reformat_vlan_pop_supported(esw)) {
457                 miss_fg = mlx5_esw_bridge_egress_miss_fg_create(esw, egress_ft);
458                 if (IS_ERR(miss_fg)) {
459                         esw_warn(esw->dev, "Failed to create miss flow group (err=%ld)\n",
460                                  PTR_ERR(miss_fg));
461                         miss_fg = NULL;
462                         goto skip_miss_flow;
463                 }
464
465                 miss_pkt_reformat = mlx5_esw_bridge_pkt_reformat_vlan_pop_create(esw);
466                 if (IS_ERR(miss_pkt_reformat)) {
467                         esw_warn(esw->dev,
468                                  "Failed to alloc packet reformat REMOVE_HEADER (err=%ld)\n",
469                                  PTR_ERR(miss_pkt_reformat));
470                         miss_pkt_reformat = NULL;
471                         mlx5_destroy_flow_group(miss_fg);
472                         miss_fg = NULL;
473                         goto skip_miss_flow;
474                 }
475
476                 miss_handle = mlx5_esw_bridge_egress_miss_flow_create(egress_ft,
477                                                                       br_offloads->skip_ft,
478                                                                       miss_pkt_reformat);
479                 if (IS_ERR(miss_handle)) {
480                         esw_warn(esw->dev, "Failed to create miss flow (err=%ld)\n",
481                                  PTR_ERR(miss_handle));
482                         miss_handle = NULL;
483                         mlx5_packet_reformat_dealloc(esw->dev, miss_pkt_reformat);
484                         miss_pkt_reformat = NULL;
485                         mlx5_destroy_flow_group(miss_fg);
486                         miss_fg = NULL;
487                         goto skip_miss_flow;
488                 }
489         }
490 skip_miss_flow:
491
492         bridge->egress_ft = egress_ft;
493         bridge->egress_vlan_fg = vlan_fg;
494         bridge->egress_mac_fg = mac_fg;
495         bridge->egress_miss_fg = miss_fg;
496         bridge->egress_miss_pkt_reformat = miss_pkt_reformat;
497         bridge->egress_miss_handle = miss_handle;
498         return 0;
499
500 err_mac_fg:
501         mlx5_destroy_flow_group(vlan_fg);
502 err_vlan_fg:
503         mlx5_destroy_flow_table(egress_ft);
504         return err;
505 }
506
507 static void
508 mlx5_esw_bridge_egress_table_cleanup(struct mlx5_esw_bridge *bridge)
509 {
510         if (bridge->egress_miss_handle)
511                 mlx5_del_flow_rules(bridge->egress_miss_handle);
512         if (bridge->egress_miss_pkt_reformat)
513                 mlx5_packet_reformat_dealloc(bridge->br_offloads->esw->dev,
514                                              bridge->egress_miss_pkt_reformat);
515         if (bridge->egress_miss_fg)
516                 mlx5_destroy_flow_group(bridge->egress_miss_fg);
517         mlx5_destroy_flow_group(bridge->egress_mac_fg);
518         mlx5_destroy_flow_group(bridge->egress_vlan_fg);
519         mlx5_destroy_flow_table(bridge->egress_ft);
520 }
521
522 static struct mlx5_flow_handle *
523 mlx5_esw_bridge_ingress_flow_with_esw_create(u16 vport_num, const unsigned char *addr,
524                                              struct mlx5_esw_bridge_vlan *vlan, u32 counter_id,
525                                              struct mlx5_esw_bridge *bridge,
526                                              struct mlx5_eswitch *esw)
527 {
528         struct mlx5_esw_bridge_offloads *br_offloads = bridge->br_offloads;
529         struct mlx5_flow_act flow_act = {
530                 .action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | MLX5_FLOW_CONTEXT_ACTION_COUNT,
531                 .flags = FLOW_ACT_NO_APPEND,
532         };
533         struct mlx5_flow_destination dests[2] = {};
534         struct mlx5_flow_spec *rule_spec;
535         struct mlx5_flow_handle *handle;
536         u8 *smac_v, *smac_c;
537
538         rule_spec = kvzalloc(sizeof(*rule_spec), GFP_KERNEL);
539         if (!rule_spec)
540                 return ERR_PTR(-ENOMEM);
541
542         rule_spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS | MLX5_MATCH_MISC_PARAMETERS_2;
543
544         smac_v = MLX5_ADDR_OF(fte_match_param, rule_spec->match_value,
545                               outer_headers.smac_47_16);
546         ether_addr_copy(smac_v, addr);
547         smac_c = MLX5_ADDR_OF(fte_match_param, rule_spec->match_criteria,
548                               outer_headers.smac_47_16);
549         eth_broadcast_addr(smac_c);
550
551         MLX5_SET(fte_match_param, rule_spec->match_criteria,
552                  misc_parameters_2.metadata_reg_c_0, mlx5_eswitch_get_vport_metadata_mask());
553         MLX5_SET(fte_match_param, rule_spec->match_value, misc_parameters_2.metadata_reg_c_0,
554                  mlx5_eswitch_get_vport_metadata_for_match(esw, vport_num));
555
556         if (vlan && vlan->pkt_reformat_push) {
557                 flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT |
558                         MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
559                 flow_act.pkt_reformat = vlan->pkt_reformat_push;
560                 flow_act.modify_hdr = vlan->pkt_mod_hdr_push_mark;
561         } else if (vlan) {
562                 MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_criteria,
563                                  outer_headers.cvlan_tag);
564                 MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_value,
565                                  outer_headers.cvlan_tag);
566                 MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_criteria,
567                                  outer_headers.first_vid);
568                 MLX5_SET(fte_match_param, rule_spec->match_value, outer_headers.first_vid,
569                          vlan->vid);
570         }
571
572         dests[0].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
573         dests[0].ft = bridge->egress_ft;
574         dests[1].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
575         dests[1].counter_id = counter_id;
576
577         handle = mlx5_add_flow_rules(br_offloads->ingress_ft, rule_spec, &flow_act, dests,
578                                      ARRAY_SIZE(dests));
579
580         kvfree(rule_spec);
581         return handle;
582 }
583
584 static struct mlx5_flow_handle *
585 mlx5_esw_bridge_ingress_flow_create(u16 vport_num, const unsigned char *addr,
586                                     struct mlx5_esw_bridge_vlan *vlan, u32 counter_id,
587                                     struct mlx5_esw_bridge *bridge)
588 {
589         return mlx5_esw_bridge_ingress_flow_with_esw_create(vport_num, addr, vlan, counter_id,
590                                                             bridge, bridge->br_offloads->esw);
591 }
592
593 static struct mlx5_flow_handle *
594 mlx5_esw_bridge_ingress_flow_peer_create(u16 vport_num, const unsigned char *addr,
595                                          struct mlx5_esw_bridge_vlan *vlan, u32 counter_id,
596                                          struct mlx5_esw_bridge *bridge)
597 {
598         struct mlx5_devcom *devcom = bridge->br_offloads->esw->dev->priv.devcom;
599         static struct mlx5_flow_handle *handle;
600         struct mlx5_eswitch *peer_esw;
601
602         peer_esw = mlx5_devcom_get_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
603         if (!peer_esw)
604                 return ERR_PTR(-ENODEV);
605
606         handle = mlx5_esw_bridge_ingress_flow_with_esw_create(vport_num, addr, vlan, counter_id,
607                                                               bridge, peer_esw);
608
609         mlx5_devcom_release_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
610         return handle;
611 }
612
613 static struct mlx5_flow_handle *
614 mlx5_esw_bridge_ingress_filter_flow_create(u16 vport_num, const unsigned char *addr,
615                                            struct mlx5_esw_bridge *bridge)
616 {
617         struct mlx5_esw_bridge_offloads *br_offloads = bridge->br_offloads;
618         struct mlx5_flow_destination dest = {
619                 .type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE,
620                 .ft = br_offloads->skip_ft,
621         };
622         struct mlx5_flow_act flow_act = {
623                 .action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
624                 .flags = FLOW_ACT_NO_APPEND,
625         };
626         struct mlx5_flow_spec *rule_spec;
627         struct mlx5_flow_handle *handle;
628         u8 *smac_v, *smac_c;
629
630         rule_spec = kvzalloc(sizeof(*rule_spec), GFP_KERNEL);
631         if (!rule_spec)
632                 return ERR_PTR(-ENOMEM);
633
634         rule_spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS | MLX5_MATCH_MISC_PARAMETERS_2;
635
636         smac_v = MLX5_ADDR_OF(fte_match_param, rule_spec->match_value,
637                               outer_headers.smac_47_16);
638         ether_addr_copy(smac_v, addr);
639         smac_c = MLX5_ADDR_OF(fte_match_param, rule_spec->match_criteria,
640                               outer_headers.smac_47_16);
641         eth_broadcast_addr(smac_c);
642
643         MLX5_SET(fte_match_param, rule_spec->match_criteria,
644                  misc_parameters_2.metadata_reg_c_0, mlx5_eswitch_get_vport_metadata_mask());
645         MLX5_SET(fte_match_param, rule_spec->match_value, misc_parameters_2.metadata_reg_c_0,
646                  mlx5_eswitch_get_vport_metadata_for_match(br_offloads->esw, vport_num));
647
648         MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_criteria,
649                          outer_headers.cvlan_tag);
650         MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_value,
651                          outer_headers.cvlan_tag);
652
653         handle = mlx5_add_flow_rules(br_offloads->ingress_ft, rule_spec, &flow_act, &dest, 1);
654
655         kvfree(rule_spec);
656         return handle;
657 }
658
659 static struct mlx5_flow_handle *
660 mlx5_esw_bridge_egress_flow_create(u16 vport_num, u16 esw_owner_vhca_id, const unsigned char *addr,
661                                    struct mlx5_esw_bridge_vlan *vlan,
662                                    struct mlx5_esw_bridge *bridge)
663 {
664         struct mlx5_flow_destination dest = {
665                 .type = MLX5_FLOW_DESTINATION_TYPE_VPORT,
666                 .vport.num = vport_num,
667         };
668         struct mlx5_flow_act flow_act = {
669                 .action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
670                 .flags = FLOW_ACT_NO_APPEND,
671         };
672         struct mlx5_flow_spec *rule_spec;
673         struct mlx5_flow_handle *handle;
674         u8 *dmac_v, *dmac_c;
675
676         rule_spec = kvzalloc(sizeof(*rule_spec), GFP_KERNEL);
677         if (!rule_spec)
678                 return ERR_PTR(-ENOMEM);
679
680         if (MLX5_CAP_ESW_FLOWTABLE(bridge->br_offloads->esw->dev, flow_source) &&
681             vport_num == MLX5_VPORT_UPLINK)
682                 rule_spec->flow_context.flow_source =
683                         MLX5_FLOW_CONTEXT_FLOW_SOURCE_LOCAL_VPORT;
684         rule_spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
685
686         dmac_v = MLX5_ADDR_OF(fte_match_param, rule_spec->match_value,
687                               outer_headers.dmac_47_16);
688         ether_addr_copy(dmac_v, addr);
689         dmac_c = MLX5_ADDR_OF(fte_match_param, rule_spec->match_criteria,
690                               outer_headers.dmac_47_16);
691         eth_broadcast_addr(dmac_c);
692
693         if (vlan) {
694                 if (vlan->pkt_reformat_pop) {
695                         flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT;
696                         flow_act.pkt_reformat = vlan->pkt_reformat_pop;
697                 }
698
699                 MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_criteria,
700                                  outer_headers.cvlan_tag);
701                 MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_value,
702                                  outer_headers.cvlan_tag);
703                 MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_criteria,
704                                  outer_headers.first_vid);
705                 MLX5_SET(fte_match_param, rule_spec->match_value, outer_headers.first_vid,
706                          vlan->vid);
707         }
708
709         if (MLX5_CAP_ESW(bridge->br_offloads->esw->dev, merged_eswitch)) {
710                 dest.vport.flags = MLX5_FLOW_DEST_VPORT_VHCA_ID;
711                 dest.vport.vhca_id = esw_owner_vhca_id;
712         }
713         handle = mlx5_add_flow_rules(bridge->egress_ft, rule_spec, &flow_act, &dest, 1);
714
715         kvfree(rule_spec);
716         return handle;
717 }
718
719 static struct mlx5_flow_handle *
720 mlx5_esw_bridge_egress_miss_flow_create(struct mlx5_flow_table *egress_ft,
721                                         struct mlx5_flow_table *skip_ft,
722                                         struct mlx5_pkt_reformat *pkt_reformat)
723 {
724         struct mlx5_flow_destination dest = {
725                 .type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE,
726                 .ft = skip_ft,
727         };
728         struct mlx5_flow_act flow_act = {
729                 .action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
730                 MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT,
731                 .flags = FLOW_ACT_NO_APPEND,
732                 .pkt_reformat = pkt_reformat,
733         };
734         struct mlx5_flow_spec *rule_spec;
735         struct mlx5_flow_handle *handle;
736
737         rule_spec = kvzalloc(sizeof(*rule_spec), GFP_KERNEL);
738         if (!rule_spec)
739                 return ERR_PTR(-ENOMEM);
740
741         rule_spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS_2;
742
743         MLX5_SET(fte_match_param, rule_spec->match_criteria,
744                  misc_parameters_2.metadata_reg_c_1, ESW_TUN_MASK);
745         MLX5_SET(fte_match_param, rule_spec->match_value, misc_parameters_2.metadata_reg_c_1,
746                  ESW_TUN_BRIDGE_INGRESS_PUSH_VLAN_MARK);
747
748         handle = mlx5_add_flow_rules(egress_ft, rule_spec, &flow_act, &dest, 1);
749
750         kvfree(rule_spec);
751         return handle;
752 }
753
754 static struct mlx5_esw_bridge *mlx5_esw_bridge_create(int ifindex,
755                                                       struct mlx5_esw_bridge_offloads *br_offloads)
756 {
757         struct mlx5_esw_bridge *bridge;
758         int err;
759
760         bridge = kvzalloc(sizeof(*bridge), GFP_KERNEL);
761         if (!bridge)
762                 return ERR_PTR(-ENOMEM);
763
764         bridge->br_offloads = br_offloads;
765         err = mlx5_esw_bridge_egress_table_init(br_offloads, bridge);
766         if (err)
767                 goto err_egress_tbl;
768
769         err = rhashtable_init(&bridge->fdb_ht, &fdb_ht_params);
770         if (err)
771                 goto err_fdb_ht;
772
773         INIT_LIST_HEAD(&bridge->fdb_list);
774         bridge->ifindex = ifindex;
775         bridge->refcnt = 1;
776         bridge->ageing_time = clock_t_to_jiffies(BR_DEFAULT_AGEING_TIME);
777         list_add(&bridge->list, &br_offloads->bridges);
778
779         return bridge;
780
781 err_fdb_ht:
782         mlx5_esw_bridge_egress_table_cleanup(bridge);
783 err_egress_tbl:
784         kvfree(bridge);
785         return ERR_PTR(err);
786 }
787
788 static void mlx5_esw_bridge_get(struct mlx5_esw_bridge *bridge)
789 {
790         bridge->refcnt++;
791 }
792
793 static void mlx5_esw_bridge_put(struct mlx5_esw_bridge_offloads *br_offloads,
794                                 struct mlx5_esw_bridge *bridge)
795 {
796         if (--bridge->refcnt)
797                 return;
798
799         mlx5_esw_bridge_egress_table_cleanup(bridge);
800         list_del(&bridge->list);
801         rhashtable_destroy(&bridge->fdb_ht);
802         kvfree(bridge);
803
804         if (list_empty(&br_offloads->bridges))
805                 mlx5_esw_bridge_ingress_table_cleanup(br_offloads);
806 }
807
808 static struct mlx5_esw_bridge *
809 mlx5_esw_bridge_lookup(int ifindex, struct mlx5_esw_bridge_offloads *br_offloads)
810 {
811         struct mlx5_esw_bridge *bridge;
812
813         ASSERT_RTNL();
814
815         list_for_each_entry(bridge, &br_offloads->bridges, list) {
816                 if (bridge->ifindex == ifindex) {
817                         mlx5_esw_bridge_get(bridge);
818                         return bridge;
819                 }
820         }
821
822         if (!br_offloads->ingress_ft) {
823                 int err = mlx5_esw_bridge_ingress_table_init(br_offloads);
824
825                 if (err)
826                         return ERR_PTR(err);
827         }
828
829         bridge = mlx5_esw_bridge_create(ifindex, br_offloads);
830         if (IS_ERR(bridge) && list_empty(&br_offloads->bridges))
831                 mlx5_esw_bridge_ingress_table_cleanup(br_offloads);
832         return bridge;
833 }
834
835 static unsigned long mlx5_esw_bridge_port_key_from_data(u16 vport_num, u16 esw_owner_vhca_id)
836 {
837         return vport_num | (unsigned long)esw_owner_vhca_id << sizeof(vport_num) * BITS_PER_BYTE;
838 }
839
840 static unsigned long mlx5_esw_bridge_port_key(struct mlx5_esw_bridge_port *port)
841 {
842         return mlx5_esw_bridge_port_key_from_data(port->vport_num, port->esw_owner_vhca_id);
843 }
844
845 static int mlx5_esw_bridge_port_insert(struct mlx5_esw_bridge_port *port,
846                                        struct mlx5_esw_bridge_offloads *br_offloads)
847 {
848         return xa_insert(&br_offloads->ports, mlx5_esw_bridge_port_key(port), port, GFP_KERNEL);
849 }
850
851 static struct mlx5_esw_bridge_port *
852 mlx5_esw_bridge_port_lookup(u16 vport_num, u16 esw_owner_vhca_id,
853                             struct mlx5_esw_bridge_offloads *br_offloads)
854 {
855         return xa_load(&br_offloads->ports, mlx5_esw_bridge_port_key_from_data(vport_num,
856                                                                                esw_owner_vhca_id));
857 }
858
859 static void mlx5_esw_bridge_port_erase(struct mlx5_esw_bridge_port *port,
860                                        struct mlx5_esw_bridge_offloads *br_offloads)
861 {
862         xa_erase(&br_offloads->ports, mlx5_esw_bridge_port_key(port));
863 }
864
865 static void mlx5_esw_bridge_fdb_entry_refresh(struct mlx5_esw_bridge_fdb_entry *entry)
866 {
867         trace_mlx5_esw_bridge_fdb_entry_refresh(entry);
868
869         mlx5_esw_bridge_fdb_offload_notify(entry->dev, entry->key.addr,
870                                            entry->key.vid,
871                                            SWITCHDEV_FDB_ADD_TO_BRIDGE);
872 }
873
874 static void
875 mlx5_esw_bridge_fdb_entry_cleanup(struct mlx5_esw_bridge_fdb_entry *entry,
876                                   struct mlx5_esw_bridge *bridge)
877 {
878         trace_mlx5_esw_bridge_fdb_entry_cleanup(entry);
879
880         rhashtable_remove_fast(&bridge->fdb_ht, &entry->ht_node, fdb_ht_params);
881         mlx5_del_flow_rules(entry->egress_handle);
882         if (entry->filter_handle)
883                 mlx5_del_flow_rules(entry->filter_handle);
884         mlx5_del_flow_rules(entry->ingress_handle);
885         mlx5_fc_destroy(bridge->br_offloads->esw->dev, entry->ingress_counter);
886         list_del(&entry->vlan_list);
887         list_del(&entry->list);
888         kvfree(entry);
889 }
890
891 static void
892 mlx5_esw_bridge_fdb_entry_notify_and_cleanup(struct mlx5_esw_bridge_fdb_entry *entry,
893                                              struct mlx5_esw_bridge *bridge)
894 {
895         mlx5_esw_bridge_fdb_del_notify(entry);
896         mlx5_esw_bridge_fdb_entry_cleanup(entry, bridge);
897 }
898
899 static void mlx5_esw_bridge_fdb_flush(struct mlx5_esw_bridge *bridge)
900 {
901         struct mlx5_esw_bridge_fdb_entry *entry, *tmp;
902
903         list_for_each_entry_safe(entry, tmp, &bridge->fdb_list, list)
904                 mlx5_esw_bridge_fdb_entry_notify_and_cleanup(entry, bridge);
905 }
906
907 static struct mlx5_esw_bridge_vlan *
908 mlx5_esw_bridge_vlan_lookup(u16 vid, struct mlx5_esw_bridge_port *port)
909 {
910         return xa_load(&port->vlans, vid);
911 }
912
913 static int
914 mlx5_esw_bridge_vlan_push_create(struct mlx5_esw_bridge_vlan *vlan, struct mlx5_eswitch *esw)
915 {
916         struct {
917                 __be16  h_vlan_proto;
918                 __be16  h_vlan_TCI;
919         } vlan_hdr = { htons(ETH_P_8021Q), htons(vlan->vid) };
920         struct mlx5_pkt_reformat_params reformat_params = {};
921         struct mlx5_pkt_reformat *pkt_reformat;
922
923         if (!BIT(MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, reformat_insert)) ||
924             MLX5_CAP_GEN_2(esw->dev, max_reformat_insert_size) < sizeof(vlan_hdr) ||
925             MLX5_CAP_GEN_2(esw->dev, max_reformat_insert_offset) <
926             offsetof(struct vlan_ethhdr, h_vlan_proto)) {
927                 esw_warn(esw->dev, "Packet reformat INSERT_HEADER is not supported\n");
928                 return -EOPNOTSUPP;
929         }
930
931         reformat_params.type = MLX5_REFORMAT_TYPE_INSERT_HDR;
932         reformat_params.param_0 = MLX5_REFORMAT_CONTEXT_ANCHOR_MAC_START;
933         reformat_params.param_1 = offsetof(struct vlan_ethhdr, h_vlan_proto);
934         reformat_params.size = sizeof(vlan_hdr);
935         reformat_params.data = &vlan_hdr;
936         pkt_reformat = mlx5_packet_reformat_alloc(esw->dev,
937                                                   &reformat_params,
938                                                   MLX5_FLOW_NAMESPACE_FDB);
939         if (IS_ERR(pkt_reformat)) {
940                 esw_warn(esw->dev, "Failed to alloc packet reformat INSERT_HEADER (err=%ld)\n",
941                          PTR_ERR(pkt_reformat));
942                 return PTR_ERR(pkt_reformat);
943         }
944
945         vlan->pkt_reformat_push = pkt_reformat;
946         return 0;
947 }
948
949 static void
950 mlx5_esw_bridge_vlan_push_cleanup(struct mlx5_esw_bridge_vlan *vlan, struct mlx5_eswitch *esw)
951 {
952         mlx5_packet_reformat_dealloc(esw->dev, vlan->pkt_reformat_push);
953         vlan->pkt_reformat_push = NULL;
954 }
955
956 static int
957 mlx5_esw_bridge_vlan_pop_create(struct mlx5_esw_bridge_vlan *vlan, struct mlx5_eswitch *esw)
958 {
959         struct mlx5_pkt_reformat *pkt_reformat;
960
961         if (!mlx5_esw_bridge_pkt_reformat_vlan_pop_supported(esw)) {
962                 esw_warn(esw->dev, "Packet reformat REMOVE_HEADER is not supported\n");
963                 return -EOPNOTSUPP;
964         }
965
966         pkt_reformat = mlx5_esw_bridge_pkt_reformat_vlan_pop_create(esw);
967         if (IS_ERR(pkt_reformat)) {
968                 esw_warn(esw->dev, "Failed to alloc packet reformat REMOVE_HEADER (err=%ld)\n",
969                          PTR_ERR(pkt_reformat));
970                 return PTR_ERR(pkt_reformat);
971         }
972
973         vlan->pkt_reformat_pop = pkt_reformat;
974         return 0;
975 }
976
977 static void
978 mlx5_esw_bridge_vlan_pop_cleanup(struct mlx5_esw_bridge_vlan *vlan, struct mlx5_eswitch *esw)
979 {
980         mlx5_packet_reformat_dealloc(esw->dev, vlan->pkt_reformat_pop);
981         vlan->pkt_reformat_pop = NULL;
982 }
983
984 static int
985 mlx5_esw_bridge_vlan_push_mark_create(struct mlx5_esw_bridge_vlan *vlan, struct mlx5_eswitch *esw)
986 {
987         u8 action[MLX5_UN_SZ_BYTES(set_add_copy_action_in_auto)] = {};
988         struct mlx5_modify_hdr *pkt_mod_hdr;
989
990         MLX5_SET(set_action_in, action, action_type, MLX5_ACTION_TYPE_SET);
991         MLX5_SET(set_action_in, action, field, MLX5_ACTION_IN_FIELD_METADATA_REG_C_1);
992         MLX5_SET(set_action_in, action, offset, 8);
993         MLX5_SET(set_action_in, action, length, ESW_TUN_OPTS_BITS + ESW_TUN_ID_BITS);
994         MLX5_SET(set_action_in, action, data, ESW_TUN_BRIDGE_INGRESS_PUSH_VLAN);
995
996         pkt_mod_hdr = mlx5_modify_header_alloc(esw->dev, MLX5_FLOW_NAMESPACE_FDB, 1, action);
997         if (IS_ERR(pkt_mod_hdr))
998                 return PTR_ERR(pkt_mod_hdr);
999
1000         vlan->pkt_mod_hdr_push_mark = pkt_mod_hdr;
1001         return 0;
1002 }
1003
1004 static void
1005 mlx5_esw_bridge_vlan_push_mark_cleanup(struct mlx5_esw_bridge_vlan *vlan, struct mlx5_eswitch *esw)
1006 {
1007         mlx5_modify_header_dealloc(esw->dev, vlan->pkt_mod_hdr_push_mark);
1008         vlan->pkt_mod_hdr_push_mark = NULL;
1009 }
1010
1011 static struct mlx5_esw_bridge_vlan *
1012 mlx5_esw_bridge_vlan_create(u16 vid, u16 flags, struct mlx5_esw_bridge_port *port,
1013                             struct mlx5_eswitch *esw)
1014 {
1015         struct mlx5_esw_bridge_vlan *vlan;
1016         int err;
1017
1018         vlan = kvzalloc(sizeof(*vlan), GFP_KERNEL);
1019         if (!vlan)
1020                 return ERR_PTR(-ENOMEM);
1021
1022         vlan->vid = vid;
1023         vlan->flags = flags;
1024         INIT_LIST_HEAD(&vlan->fdb_list);
1025
1026         if (flags & BRIDGE_VLAN_INFO_PVID) {
1027                 err = mlx5_esw_bridge_vlan_push_create(vlan, esw);
1028                 if (err)
1029                         goto err_vlan_push;
1030
1031                 err = mlx5_esw_bridge_vlan_push_mark_create(vlan, esw);
1032                 if (err)
1033                         goto err_vlan_push_mark;
1034         }
1035         if (flags & BRIDGE_VLAN_INFO_UNTAGGED) {
1036                 err = mlx5_esw_bridge_vlan_pop_create(vlan, esw);
1037                 if (err)
1038                         goto err_vlan_pop;
1039         }
1040
1041         err = xa_insert(&port->vlans, vid, vlan, GFP_KERNEL);
1042         if (err)
1043                 goto err_xa_insert;
1044
1045         trace_mlx5_esw_bridge_vlan_create(vlan);
1046         return vlan;
1047
1048 err_xa_insert:
1049         if (vlan->pkt_reformat_pop)
1050                 mlx5_esw_bridge_vlan_pop_cleanup(vlan, esw);
1051 err_vlan_pop:
1052         if (vlan->pkt_mod_hdr_push_mark)
1053                 mlx5_esw_bridge_vlan_push_mark_cleanup(vlan, esw);
1054 err_vlan_push_mark:
1055         if (vlan->pkt_reformat_push)
1056                 mlx5_esw_bridge_vlan_push_cleanup(vlan, esw);
1057 err_vlan_push:
1058         kvfree(vlan);
1059         return ERR_PTR(err);
1060 }
1061
1062 static void mlx5_esw_bridge_vlan_erase(struct mlx5_esw_bridge_port *port,
1063                                        struct mlx5_esw_bridge_vlan *vlan)
1064 {
1065         xa_erase(&port->vlans, vlan->vid);
1066 }
1067
1068 static void mlx5_esw_bridge_vlan_flush(struct mlx5_esw_bridge_vlan *vlan,
1069                                        struct mlx5_esw_bridge *bridge)
1070 {
1071         struct mlx5_eswitch *esw = bridge->br_offloads->esw;
1072         struct mlx5_esw_bridge_fdb_entry *entry, *tmp;
1073
1074         list_for_each_entry_safe(entry, tmp, &vlan->fdb_list, vlan_list)
1075                 mlx5_esw_bridge_fdb_entry_notify_and_cleanup(entry, bridge);
1076
1077         if (vlan->pkt_reformat_pop)
1078                 mlx5_esw_bridge_vlan_pop_cleanup(vlan, esw);
1079         if (vlan->pkt_mod_hdr_push_mark)
1080                 mlx5_esw_bridge_vlan_push_mark_cleanup(vlan, esw);
1081         if (vlan->pkt_reformat_push)
1082                 mlx5_esw_bridge_vlan_push_cleanup(vlan, esw);
1083 }
1084
1085 static void mlx5_esw_bridge_vlan_cleanup(struct mlx5_esw_bridge_port *port,
1086                                          struct mlx5_esw_bridge_vlan *vlan,
1087                                          struct mlx5_esw_bridge *bridge)
1088 {
1089         trace_mlx5_esw_bridge_vlan_cleanup(vlan);
1090         mlx5_esw_bridge_vlan_flush(vlan, bridge);
1091         mlx5_esw_bridge_vlan_erase(port, vlan);
1092         kvfree(vlan);
1093 }
1094
1095 static void mlx5_esw_bridge_port_vlans_flush(struct mlx5_esw_bridge_port *port,
1096                                              struct mlx5_esw_bridge *bridge)
1097 {
1098         struct mlx5_esw_bridge_vlan *vlan;
1099         unsigned long index;
1100
1101         xa_for_each(&port->vlans, index, vlan)
1102                 mlx5_esw_bridge_vlan_cleanup(port, vlan, bridge);
1103 }
1104
1105 static struct mlx5_esw_bridge_vlan *
1106 mlx5_esw_bridge_port_vlan_lookup(u16 vid, u16 vport_num, u16 esw_owner_vhca_id,
1107                                  struct mlx5_esw_bridge *bridge, struct mlx5_eswitch *esw)
1108 {
1109         struct mlx5_esw_bridge_port *port;
1110         struct mlx5_esw_bridge_vlan *vlan;
1111
1112         port = mlx5_esw_bridge_port_lookup(vport_num, esw_owner_vhca_id, bridge->br_offloads);
1113         if (!port) {
1114                 /* FDB is added asynchronously on wq while port might have been deleted
1115                  * concurrently. Report on 'info' logging level and skip the FDB offload.
1116                  */
1117                 esw_info(esw->dev, "Failed to lookup bridge port (vport=%u)\n", vport_num);
1118                 return ERR_PTR(-EINVAL);
1119         }
1120
1121         vlan = mlx5_esw_bridge_vlan_lookup(vid, port);
1122         if (!vlan) {
1123                 /* FDB is added asynchronously on wq while vlan might have been deleted
1124                  * concurrently. Report on 'info' logging level and skip the FDB offload.
1125                  */
1126                 esw_info(esw->dev, "Failed to lookup bridge port vlan metadata (vport=%u)\n",
1127                          vport_num);
1128                 return ERR_PTR(-EINVAL);
1129         }
1130
1131         return vlan;
1132 }
1133
1134 static struct mlx5_esw_bridge_fdb_entry *
1135 mlx5_esw_bridge_fdb_lookup(struct mlx5_esw_bridge *bridge,
1136                            const unsigned char *addr, u16 vid)
1137 {
1138         struct mlx5_esw_bridge_fdb_key key = {};
1139
1140         ether_addr_copy(key.addr, addr);
1141         key.vid = vid;
1142         return rhashtable_lookup_fast(&bridge->fdb_ht, &key, fdb_ht_params);
1143 }
1144
1145 static struct mlx5_esw_bridge_fdb_entry *
1146 mlx5_esw_bridge_fdb_entry_init(struct net_device *dev, u16 vport_num, u16 esw_owner_vhca_id,
1147                                const unsigned char *addr, u16 vid, bool added_by_user, bool peer,
1148                                struct mlx5_eswitch *esw, struct mlx5_esw_bridge *bridge)
1149 {
1150         struct mlx5_esw_bridge_vlan *vlan = NULL;
1151         struct mlx5_esw_bridge_fdb_entry *entry;
1152         struct mlx5_flow_handle *handle;
1153         struct mlx5_fc *counter;
1154         int err;
1155
1156         if (bridge->flags & MLX5_ESW_BRIDGE_VLAN_FILTERING_FLAG && vid) {
1157                 vlan = mlx5_esw_bridge_port_vlan_lookup(vid, vport_num, esw_owner_vhca_id, bridge,
1158                                                         esw);
1159                 if (IS_ERR(vlan))
1160                         return ERR_CAST(vlan);
1161         }
1162
1163         entry = mlx5_esw_bridge_fdb_lookup(bridge, addr, vid);
1164         if (entry)
1165                 mlx5_esw_bridge_fdb_entry_notify_and_cleanup(entry, bridge);
1166
1167         entry = kvzalloc(sizeof(*entry), GFP_KERNEL);
1168         if (!entry)
1169                 return ERR_PTR(-ENOMEM);
1170
1171         ether_addr_copy(entry->key.addr, addr);
1172         entry->key.vid = vid;
1173         entry->dev = dev;
1174         entry->vport_num = vport_num;
1175         entry->esw_owner_vhca_id = esw_owner_vhca_id;
1176         entry->lastuse = jiffies;
1177         if (added_by_user)
1178                 entry->flags |= MLX5_ESW_BRIDGE_FLAG_ADDED_BY_USER;
1179         if (peer)
1180                 entry->flags |= MLX5_ESW_BRIDGE_FLAG_PEER;
1181
1182         counter = mlx5_fc_create(esw->dev, true);
1183         if (IS_ERR(counter)) {
1184                 err = PTR_ERR(counter);
1185                 goto err_ingress_fc_create;
1186         }
1187         entry->ingress_counter = counter;
1188
1189         handle = peer ?
1190                 mlx5_esw_bridge_ingress_flow_peer_create(vport_num, addr, vlan,
1191                                                          mlx5_fc_id(counter), bridge) :
1192                 mlx5_esw_bridge_ingress_flow_create(vport_num, addr, vlan,
1193                                                     mlx5_fc_id(counter), bridge);
1194         if (IS_ERR(handle)) {
1195                 err = PTR_ERR(handle);
1196                 esw_warn(esw->dev, "Failed to create ingress flow(vport=%u,err=%d)\n",
1197                          vport_num, err);
1198                 goto err_ingress_flow_create;
1199         }
1200         entry->ingress_handle = handle;
1201
1202         if (bridge->flags & MLX5_ESW_BRIDGE_VLAN_FILTERING_FLAG) {
1203                 handle = mlx5_esw_bridge_ingress_filter_flow_create(vport_num, addr, bridge);
1204                 if (IS_ERR(handle)) {
1205                         err = PTR_ERR(handle);
1206                         esw_warn(esw->dev, "Failed to create ingress filter(vport=%u,err=%d)\n",
1207                                  vport_num, err);
1208                         goto err_ingress_filter_flow_create;
1209                 }
1210                 entry->filter_handle = handle;
1211         }
1212
1213         handle = mlx5_esw_bridge_egress_flow_create(vport_num, esw_owner_vhca_id, addr, vlan,
1214                                                     bridge);
1215         if (IS_ERR(handle)) {
1216                 err = PTR_ERR(handle);
1217                 esw_warn(esw->dev, "Failed to create egress flow(vport=%u,err=%d)\n",
1218                          vport_num, err);
1219                 goto err_egress_flow_create;
1220         }
1221         entry->egress_handle = handle;
1222
1223         err = rhashtable_insert_fast(&bridge->fdb_ht, &entry->ht_node, fdb_ht_params);
1224         if (err) {
1225                 esw_warn(esw->dev, "Failed to insert FDB flow(vport=%u,err=%d)\n", vport_num, err);
1226                 goto err_ht_init;
1227         }
1228
1229         if (vlan)
1230                 list_add(&entry->vlan_list, &vlan->fdb_list);
1231         else
1232                 INIT_LIST_HEAD(&entry->vlan_list);
1233         list_add(&entry->list, &bridge->fdb_list);
1234
1235         trace_mlx5_esw_bridge_fdb_entry_init(entry);
1236         return entry;
1237
1238 err_ht_init:
1239         mlx5_del_flow_rules(entry->egress_handle);
1240 err_egress_flow_create:
1241         if (entry->filter_handle)
1242                 mlx5_del_flow_rules(entry->filter_handle);
1243 err_ingress_filter_flow_create:
1244         mlx5_del_flow_rules(entry->ingress_handle);
1245 err_ingress_flow_create:
1246         mlx5_fc_destroy(esw->dev, entry->ingress_counter);
1247 err_ingress_fc_create:
1248         kvfree(entry);
1249         return ERR_PTR(err);
1250 }
1251
1252 int mlx5_esw_bridge_ageing_time_set(u16 vport_num, u16 esw_owner_vhca_id, unsigned long ageing_time,
1253                                     struct mlx5_esw_bridge_offloads *br_offloads)
1254 {
1255         struct mlx5_esw_bridge_port *port;
1256
1257         port = mlx5_esw_bridge_port_lookup(vport_num, esw_owner_vhca_id, br_offloads);
1258         if (!port)
1259                 return -EINVAL;
1260
1261         port->bridge->ageing_time = clock_t_to_jiffies(ageing_time);
1262         return 0;
1263 }
1264
1265 int mlx5_esw_bridge_vlan_filtering_set(u16 vport_num, u16 esw_owner_vhca_id, bool enable,
1266                                        struct mlx5_esw_bridge_offloads *br_offloads)
1267 {
1268         struct mlx5_esw_bridge_port *port;
1269         struct mlx5_esw_bridge *bridge;
1270         bool filtering;
1271
1272         port = mlx5_esw_bridge_port_lookup(vport_num, esw_owner_vhca_id, br_offloads);
1273         if (!port)
1274                 return -EINVAL;
1275
1276         bridge = port->bridge;
1277         filtering = bridge->flags & MLX5_ESW_BRIDGE_VLAN_FILTERING_FLAG;
1278         if (filtering == enable)
1279                 return 0;
1280
1281         mlx5_esw_bridge_fdb_flush(bridge);
1282         if (enable)
1283                 bridge->flags |= MLX5_ESW_BRIDGE_VLAN_FILTERING_FLAG;
1284         else
1285                 bridge->flags &= ~MLX5_ESW_BRIDGE_VLAN_FILTERING_FLAG;
1286
1287         return 0;
1288 }
1289
1290 static int mlx5_esw_bridge_vport_init(u16 vport_num, u16 esw_owner_vhca_id, u16 flags,
1291                                       struct mlx5_esw_bridge_offloads *br_offloads,
1292                                       struct mlx5_esw_bridge *bridge)
1293 {
1294         struct mlx5_eswitch *esw = br_offloads->esw;
1295         struct mlx5_esw_bridge_port *port;
1296         int err;
1297
1298         port = kvzalloc(sizeof(*port), GFP_KERNEL);
1299         if (!port)
1300                 return -ENOMEM;
1301
1302         port->vport_num = vport_num;
1303         port->esw_owner_vhca_id = esw_owner_vhca_id;
1304         port->bridge = bridge;
1305         port->flags |= flags;
1306         xa_init(&port->vlans);
1307         err = mlx5_esw_bridge_port_insert(port, br_offloads);
1308         if (err) {
1309                 esw_warn(esw->dev,
1310                          "Failed to insert port metadata (vport=%u,esw_owner_vhca_id=%u,err=%d)\n",
1311                          port->vport_num, port->esw_owner_vhca_id, err);
1312                 goto err_port_insert;
1313         }
1314         trace_mlx5_esw_bridge_vport_init(port);
1315
1316         return 0;
1317
1318 err_port_insert:
1319         kvfree(port);
1320         return err;
1321 }
1322
1323 static int mlx5_esw_bridge_vport_cleanup(struct mlx5_esw_bridge_offloads *br_offloads,
1324                                          struct mlx5_esw_bridge_port *port)
1325 {
1326         u16 vport_num = port->vport_num, esw_owner_vhca_id = port->esw_owner_vhca_id;
1327         struct mlx5_esw_bridge *bridge = port->bridge;
1328         struct mlx5_esw_bridge_fdb_entry *entry, *tmp;
1329
1330         list_for_each_entry_safe(entry, tmp, &bridge->fdb_list, list)
1331                 if (entry->vport_num == vport_num && entry->esw_owner_vhca_id == esw_owner_vhca_id)
1332                         mlx5_esw_bridge_fdb_entry_cleanup(entry, bridge);
1333
1334         trace_mlx5_esw_bridge_vport_cleanup(port);
1335         mlx5_esw_bridge_port_vlans_flush(port, bridge);
1336         mlx5_esw_bridge_port_erase(port, br_offloads);
1337         kvfree(port);
1338         mlx5_esw_bridge_put(br_offloads, bridge);
1339         return 0;
1340 }
1341
1342 static int mlx5_esw_bridge_vport_link_with_flags(int ifindex, u16 vport_num, u16 esw_owner_vhca_id,
1343                                                  u16 flags,
1344                                                  struct mlx5_esw_bridge_offloads *br_offloads,
1345                                                  struct netlink_ext_ack *extack)
1346 {
1347         struct mlx5_esw_bridge *bridge;
1348         int err;
1349
1350         bridge = mlx5_esw_bridge_lookup(ifindex, br_offloads);
1351         if (IS_ERR(bridge)) {
1352                 NL_SET_ERR_MSG_MOD(extack, "Error checking for existing bridge with same ifindex");
1353                 return PTR_ERR(bridge);
1354         }
1355
1356         err = mlx5_esw_bridge_vport_init(vport_num, esw_owner_vhca_id, flags, br_offloads, bridge);
1357         if (err) {
1358                 NL_SET_ERR_MSG_MOD(extack, "Error initializing port");
1359                 goto err_vport;
1360         }
1361         return 0;
1362
1363 err_vport:
1364         mlx5_esw_bridge_put(br_offloads, bridge);
1365         return err;
1366 }
1367
1368 int mlx5_esw_bridge_vport_link(int ifindex, u16 vport_num, u16 esw_owner_vhca_id,
1369                                struct mlx5_esw_bridge_offloads *br_offloads,
1370                                struct netlink_ext_ack *extack)
1371 {
1372         return mlx5_esw_bridge_vport_link_with_flags(ifindex, vport_num, esw_owner_vhca_id, 0,
1373                                                      br_offloads, extack);
1374 }
1375
1376 int mlx5_esw_bridge_vport_unlink(int ifindex, u16 vport_num, u16 esw_owner_vhca_id,
1377                                  struct mlx5_esw_bridge_offloads *br_offloads,
1378                                  struct netlink_ext_ack *extack)
1379 {
1380         struct mlx5_esw_bridge_port *port;
1381         int err;
1382
1383         port = mlx5_esw_bridge_port_lookup(vport_num, esw_owner_vhca_id, br_offloads);
1384         if (!port) {
1385                 NL_SET_ERR_MSG_MOD(extack, "Port is not attached to any bridge");
1386                 return -EINVAL;
1387         }
1388         if (port->bridge->ifindex != ifindex) {
1389                 NL_SET_ERR_MSG_MOD(extack, "Port is attached to another bridge");
1390                 return -EINVAL;
1391         }
1392
1393         err = mlx5_esw_bridge_vport_cleanup(br_offloads, port);
1394         if (err)
1395                 NL_SET_ERR_MSG_MOD(extack, "Port cleanup failed");
1396         return err;
1397 }
1398
1399 int mlx5_esw_bridge_vport_peer_link(int ifindex, u16 vport_num, u16 esw_owner_vhca_id,
1400                                     struct mlx5_esw_bridge_offloads *br_offloads,
1401                                     struct netlink_ext_ack *extack)
1402 {
1403         if (!MLX5_CAP_ESW(br_offloads->esw->dev, merged_eswitch))
1404                 return 0;
1405
1406         return mlx5_esw_bridge_vport_link_with_flags(ifindex, vport_num, esw_owner_vhca_id,
1407                                                      MLX5_ESW_BRIDGE_PORT_FLAG_PEER,
1408                                                      br_offloads, extack);
1409 }
1410
1411 int mlx5_esw_bridge_vport_peer_unlink(int ifindex, u16 vport_num, u16 esw_owner_vhca_id,
1412                                       struct mlx5_esw_bridge_offloads *br_offloads,
1413                                       struct netlink_ext_ack *extack)
1414 {
1415         return mlx5_esw_bridge_vport_unlink(ifindex, vport_num, esw_owner_vhca_id, br_offloads,
1416                                             extack);
1417 }
1418
1419 int mlx5_esw_bridge_port_vlan_add(u16 vport_num, u16 esw_owner_vhca_id, u16 vid, u16 flags,
1420                                   struct mlx5_esw_bridge_offloads *br_offloads,
1421                                   struct netlink_ext_ack *extack)
1422 {
1423         struct mlx5_esw_bridge_port *port;
1424         struct mlx5_esw_bridge_vlan *vlan;
1425
1426         port = mlx5_esw_bridge_port_lookup(vport_num, esw_owner_vhca_id, br_offloads);
1427         if (!port)
1428                 return -EINVAL;
1429
1430         vlan = mlx5_esw_bridge_vlan_lookup(vid, port);
1431         if (vlan) {
1432                 if (vlan->flags == flags)
1433                         return 0;
1434                 mlx5_esw_bridge_vlan_cleanup(port, vlan, port->bridge);
1435         }
1436
1437         vlan = mlx5_esw_bridge_vlan_create(vid, flags, port, br_offloads->esw);
1438         if (IS_ERR(vlan)) {
1439                 NL_SET_ERR_MSG_MOD(extack, "Failed to create VLAN entry");
1440                 return PTR_ERR(vlan);
1441         }
1442         return 0;
1443 }
1444
1445 void mlx5_esw_bridge_port_vlan_del(u16 vport_num, u16 esw_owner_vhca_id, u16 vid,
1446                                    struct mlx5_esw_bridge_offloads *br_offloads)
1447 {
1448         struct mlx5_esw_bridge_port *port;
1449         struct mlx5_esw_bridge_vlan *vlan;
1450
1451         port = mlx5_esw_bridge_port_lookup(vport_num, esw_owner_vhca_id, br_offloads);
1452         if (!port)
1453                 return;
1454
1455         vlan = mlx5_esw_bridge_vlan_lookup(vid, port);
1456         if (!vlan)
1457                 return;
1458         mlx5_esw_bridge_vlan_cleanup(port, vlan, port->bridge);
1459 }
1460
1461 void mlx5_esw_bridge_fdb_update_used(struct net_device *dev, u16 vport_num, u16 esw_owner_vhca_id,
1462                                      struct mlx5_esw_bridge_offloads *br_offloads,
1463                                      struct switchdev_notifier_fdb_info *fdb_info)
1464 {
1465         struct mlx5_esw_bridge_fdb_entry *entry;
1466         struct mlx5_esw_bridge_port *port;
1467         struct mlx5_esw_bridge *bridge;
1468
1469         port = mlx5_esw_bridge_port_lookup(vport_num, esw_owner_vhca_id, br_offloads);
1470         if (!port || port->flags & MLX5_ESW_BRIDGE_PORT_FLAG_PEER)
1471                 return;
1472
1473         bridge = port->bridge;
1474         entry = mlx5_esw_bridge_fdb_lookup(bridge, fdb_info->addr, fdb_info->vid);
1475         if (!entry) {
1476                 esw_debug(br_offloads->esw->dev,
1477                           "FDB entry with specified key not found (MAC=%pM,vid=%u,vport=%u)\n",
1478                           fdb_info->addr, fdb_info->vid, vport_num);
1479                 return;
1480         }
1481
1482         entry->lastuse = jiffies;
1483 }
1484
1485 void mlx5_esw_bridge_fdb_create(struct net_device *dev, u16 vport_num, u16 esw_owner_vhca_id,
1486                                 struct mlx5_esw_bridge_offloads *br_offloads,
1487                                 struct switchdev_notifier_fdb_info *fdb_info)
1488 {
1489         struct mlx5_esw_bridge_fdb_entry *entry;
1490         struct mlx5_esw_bridge_port *port;
1491         struct mlx5_esw_bridge *bridge;
1492
1493         port = mlx5_esw_bridge_port_lookup(vport_num, esw_owner_vhca_id, br_offloads);
1494         if (!port)
1495                 return;
1496
1497         bridge = port->bridge;
1498         entry = mlx5_esw_bridge_fdb_entry_init(dev, vport_num, esw_owner_vhca_id, fdb_info->addr,
1499                                                fdb_info->vid, fdb_info->added_by_user,
1500                                                port->flags & MLX5_ESW_BRIDGE_PORT_FLAG_PEER,
1501                                                br_offloads->esw, bridge);
1502         if (IS_ERR(entry))
1503                 return;
1504
1505         if (entry->flags & MLX5_ESW_BRIDGE_FLAG_ADDED_BY_USER)
1506                 mlx5_esw_bridge_fdb_offload_notify(dev, entry->key.addr, entry->key.vid,
1507                                                    SWITCHDEV_FDB_OFFLOADED);
1508         else if (!(entry->flags & MLX5_ESW_BRIDGE_FLAG_PEER))
1509                 /* Take over dynamic entries to prevent kernel bridge from aging them out. */
1510                 mlx5_esw_bridge_fdb_offload_notify(dev, entry->key.addr, entry->key.vid,
1511                                                    SWITCHDEV_FDB_ADD_TO_BRIDGE);
1512 }
1513
1514 void mlx5_esw_bridge_fdb_remove(struct net_device *dev, u16 vport_num, u16 esw_owner_vhca_id,
1515                                 struct mlx5_esw_bridge_offloads *br_offloads,
1516                                 struct switchdev_notifier_fdb_info *fdb_info)
1517 {
1518         struct mlx5_eswitch *esw = br_offloads->esw;
1519         struct mlx5_esw_bridge_fdb_entry *entry;
1520         struct mlx5_esw_bridge_port *port;
1521         struct mlx5_esw_bridge *bridge;
1522
1523         port = mlx5_esw_bridge_port_lookup(vport_num, esw_owner_vhca_id, br_offloads);
1524         if (!port)
1525                 return;
1526
1527         bridge = port->bridge;
1528         entry = mlx5_esw_bridge_fdb_lookup(bridge, fdb_info->addr, fdb_info->vid);
1529         if (!entry) {
1530                 esw_warn(esw->dev,
1531                          "FDB entry with specified key not found (MAC=%pM,vid=%u,vport=%u)\n",
1532                          fdb_info->addr, fdb_info->vid, vport_num);
1533                 return;
1534         }
1535
1536         mlx5_esw_bridge_fdb_entry_notify_and_cleanup(entry, bridge);
1537 }
1538
1539 void mlx5_esw_bridge_update(struct mlx5_esw_bridge_offloads *br_offloads)
1540 {
1541         struct mlx5_esw_bridge_fdb_entry *entry, *tmp;
1542         struct mlx5_esw_bridge *bridge;
1543
1544         list_for_each_entry(bridge, &br_offloads->bridges, list) {
1545                 list_for_each_entry_safe(entry, tmp, &bridge->fdb_list, list) {
1546                         unsigned long lastuse =
1547                                 (unsigned long)mlx5_fc_query_lastuse(entry->ingress_counter);
1548
1549                         if (entry->flags & MLX5_ESW_BRIDGE_FLAG_ADDED_BY_USER)
1550                                 continue;
1551
1552                         if (time_after(lastuse, entry->lastuse))
1553                                 mlx5_esw_bridge_fdb_entry_refresh(entry);
1554                         else if (!(entry->flags & MLX5_ESW_BRIDGE_FLAG_PEER) &&
1555                                  time_is_before_jiffies(entry->lastuse + bridge->ageing_time))
1556                                 mlx5_esw_bridge_fdb_entry_notify_and_cleanup(entry, bridge);
1557                 }
1558         }
1559 }
1560
1561 static void mlx5_esw_bridge_flush(struct mlx5_esw_bridge_offloads *br_offloads)
1562 {
1563         struct mlx5_esw_bridge_port *port;
1564         unsigned long i;
1565
1566         xa_for_each(&br_offloads->ports, i, port)
1567                 mlx5_esw_bridge_vport_cleanup(br_offloads, port);
1568
1569         WARN_ONCE(!list_empty(&br_offloads->bridges),
1570                   "Cleaning up bridge offloads while still having bridges attached\n");
1571 }
1572
1573 struct mlx5_esw_bridge_offloads *mlx5_esw_bridge_init(struct mlx5_eswitch *esw)
1574 {
1575         struct mlx5_esw_bridge_offloads *br_offloads;
1576
1577         br_offloads = kvzalloc(sizeof(*br_offloads), GFP_KERNEL);
1578         if (!br_offloads)
1579                 return ERR_PTR(-ENOMEM);
1580
1581         INIT_LIST_HEAD(&br_offloads->bridges);
1582         xa_init(&br_offloads->ports);
1583         br_offloads->esw = esw;
1584         esw->br_offloads = br_offloads;
1585
1586         return br_offloads;
1587 }
1588
1589 void mlx5_esw_bridge_cleanup(struct mlx5_eswitch *esw)
1590 {
1591         struct mlx5_esw_bridge_offloads *br_offloads = esw->br_offloads;
1592
1593         if (!br_offloads)
1594                 return;
1595
1596         mlx5_esw_bridge_flush(br_offloads);
1597         WARN_ON(!xa_empty(&br_offloads->ports));
1598
1599         esw->br_offloads = NULL;
1600         kvfree(br_offloads);
1601 }