]> asedeno.scripts.mit.edu Git - linux.git/blob - drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
net: hns: add phy_attached_info() to the hns driver
[linux.git] / drivers / net / ethernet / mellanox / mlx5 / core / eswitch_offloads.c
1 /*
2  * Copyright (c) 2016, Mellanox Technologies. All rights reserved.
3  *
4  * This software is available to you under a choice of one of two
5  * licenses.  You may choose to be licensed under the terms of the GNU
6  * General Public License (GPL) Version 2, available from the file
7  * COPYING in the main directory of this source tree, or the
8  * OpenIB.org BSD license below:
9  *
10  *     Redistribution and use in source and binary forms, with or
11  *     without modification, are permitted provided that the following
12  *     conditions are met:
13  *
14  *      - Redistributions of source code must retain the above
15  *        copyright notice, this list of conditions and the following
16  *        disclaimer.
17  *
18  *      - Redistributions in binary form must reproduce the above
19  *        copyright notice, this list of conditions and the following
20  *        disclaimer in the documentation and/or other materials
21  *        provided with the distribution.
22  *
23  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30  * SOFTWARE.
31  */
32
33 #include <linux/etherdevice.h>
34 #include <linux/mlx5/driver.h>
35 #include <linux/mlx5/mlx5_ifc.h>
36 #include <linux/mlx5/vport.h>
37 #include <linux/mlx5/fs.h>
38 #include "mlx5_core.h"
39 #include "eswitch.h"
40 #include "rdma.h"
41 #include "en.h"
42 #include "fs_core.h"
43 #include "lib/devcom.h"
44 #include "lib/eq.h"
45
46 /* There are two match-all miss flows, one for unicast dst mac and
47  * one for multicast.
48  */
49 #define MLX5_ESW_MISS_FLOWS (2)
50
51 #define fdb_prio_table(esw, chain, prio, level) \
52         (esw)->fdb_table.offloads.fdb_prio[(chain)][(prio)][(level)]
53
54 #define UPLINK_REP_INDEX 0
55
56 static struct mlx5_eswitch_rep *mlx5_eswitch_get_rep(struct mlx5_eswitch *esw,
57                                                      u16 vport_num)
58 {
59         int idx = mlx5_eswitch_vport_num_to_index(esw, vport_num);
60
61         WARN_ON(idx > esw->total_vports - 1);
62         return &esw->offloads.vport_reps[idx];
63 }
64
65 static struct mlx5_flow_table *
66 esw_get_prio_table(struct mlx5_eswitch *esw, u32 chain, u16 prio, int level);
67 static void
68 esw_put_prio_table(struct mlx5_eswitch *esw, u32 chain, u16 prio, int level);
69
70 bool mlx5_eswitch_prios_supported(struct mlx5_eswitch *esw)
71 {
72         return (!!(esw->fdb_table.flags & ESW_FDB_CHAINS_AND_PRIOS_SUPPORTED));
73 }
74
75 u32 mlx5_eswitch_get_chain_range(struct mlx5_eswitch *esw)
76 {
77         if (esw->fdb_table.flags & ESW_FDB_CHAINS_AND_PRIOS_SUPPORTED)
78                 return FDB_MAX_CHAIN;
79
80         return 0;
81 }
82
83 u16 mlx5_eswitch_get_prio_range(struct mlx5_eswitch *esw)
84 {
85         if (esw->fdb_table.flags & ESW_FDB_CHAINS_AND_PRIOS_SUPPORTED)
86                 return FDB_MAX_PRIO;
87
88         return 1;
89 }
90
91 static void
92 mlx5_eswitch_set_rule_source_port(struct mlx5_eswitch *esw,
93                                   struct mlx5_flow_spec *spec,
94                                   struct mlx5_esw_flow_attr *attr)
95 {
96         void *misc2;
97         void *misc;
98
99         /* Use metadata matching because vport is not represented by single
100          * VHCA in dual-port RoCE mode, and matching on source vport may fail.
101          */
102         if (mlx5_eswitch_vport_match_metadata_enabled(esw)) {
103                 misc2 = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters_2);
104                 MLX5_SET(fte_match_set_misc2, misc2, metadata_reg_c_0,
105                          mlx5_eswitch_get_vport_metadata_for_match(attr->in_mdev->priv.eswitch,
106                                                                    attr->in_rep->vport));
107
108                 misc2 = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters_2);
109                 MLX5_SET_TO_ONES(fte_match_set_misc2, misc2, metadata_reg_c_0);
110
111                 spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS_2;
112                 misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters);
113                 if (memchr_inv(misc, 0, MLX5_ST_SZ_BYTES(fte_match_set_misc)))
114                         spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS;
115         } else {
116                 misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters);
117                 MLX5_SET(fte_match_set_misc, misc, source_port, attr->in_rep->vport);
118
119                 if (MLX5_CAP_ESW(esw->dev, merged_eswitch))
120                         MLX5_SET(fte_match_set_misc, misc,
121                                  source_eswitch_owner_vhca_id,
122                                  MLX5_CAP_GEN(attr->in_mdev, vhca_id));
123
124                 misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters);
125                 MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port);
126                 if (MLX5_CAP_ESW(esw->dev, merged_eswitch))
127                         MLX5_SET_TO_ONES(fte_match_set_misc, misc,
128                                          source_eswitch_owner_vhca_id);
129
130                 spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS;
131         }
132
133         if (MLX5_CAP_ESW_FLOWTABLE(esw->dev, flow_source) &&
134             attr->in_rep->vport == MLX5_VPORT_UPLINK)
135                 spec->flow_context.flow_source = MLX5_FLOW_CONTEXT_FLOW_SOURCE_UPLINK;
136 }
137
138 struct mlx5_flow_handle *
139 mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw,
140                                 struct mlx5_flow_spec *spec,
141                                 struct mlx5_esw_flow_attr *attr)
142 {
143         struct mlx5_flow_destination dest[MLX5_MAX_FLOW_FWD_VPORTS + 1] = {};
144         struct mlx5_flow_act flow_act = { .flags = FLOW_ACT_NO_APPEND, };
145         bool split = !!(attr->split_count);
146         struct mlx5_flow_handle *rule;
147         struct mlx5_flow_table *fdb;
148         int j, i = 0;
149
150         if (esw->mode != MLX5_ESWITCH_OFFLOADS)
151                 return ERR_PTR(-EOPNOTSUPP);
152
153         flow_act.action = attr->action;
154         /* if per flow vlan pop/push is emulated, don't set that into the firmware */
155         if (!mlx5_eswitch_vlan_actions_supported(esw->dev, 1))
156                 flow_act.action &= ~(MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH |
157                                      MLX5_FLOW_CONTEXT_ACTION_VLAN_POP);
158         else if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH) {
159                 flow_act.vlan[0].ethtype = ntohs(attr->vlan_proto[0]);
160                 flow_act.vlan[0].vid = attr->vlan_vid[0];
161                 flow_act.vlan[0].prio = attr->vlan_prio[0];
162                 if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH_2) {
163                         flow_act.vlan[1].ethtype = ntohs(attr->vlan_proto[1]);
164                         flow_act.vlan[1].vid = attr->vlan_vid[1];
165                         flow_act.vlan[1].prio = attr->vlan_prio[1];
166                 }
167         }
168
169         if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) {
170                 if (attr->dest_chain) {
171                         struct mlx5_flow_table *ft;
172
173                         ft = esw_get_prio_table(esw, attr->dest_chain, 1, 0);
174                         if (IS_ERR(ft)) {
175                                 rule = ERR_CAST(ft);
176                                 goto err_create_goto_table;
177                         }
178
179                         dest[i].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
180                         dest[i].ft = ft;
181                         i++;
182                 } else {
183                         for (j = attr->split_count; j < attr->out_count; j++) {
184                                 dest[i].type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
185                                 dest[i].vport.num = attr->dests[j].rep->vport;
186                                 dest[i].vport.vhca_id =
187                                         MLX5_CAP_GEN(attr->dests[j].mdev, vhca_id);
188                                 if (MLX5_CAP_ESW(esw->dev, merged_eswitch))
189                                         dest[i].vport.flags |=
190                                                 MLX5_FLOW_DEST_VPORT_VHCA_ID;
191                                 if (attr->dests[j].flags & MLX5_ESW_DEST_ENCAP) {
192                                         flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT;
193                                         flow_act.reformat_id = attr->dests[j].encap_id;
194                                         dest[i].vport.flags |= MLX5_FLOW_DEST_VPORT_REFORMAT_ID;
195                                         dest[i].vport.reformat_id =
196                                                 attr->dests[j].encap_id;
197                                 }
198                                 i++;
199                         }
200                 }
201         }
202         if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_COUNT) {
203                 dest[i].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
204                 dest[i].counter_id = mlx5_fc_id(attr->counter);
205                 i++;
206         }
207
208         mlx5_eswitch_set_rule_source_port(esw, spec, attr);
209
210         if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_DECAP) {
211                 if (attr->tunnel_match_level != MLX5_MATCH_NONE)
212                         spec->match_criteria_enable |= MLX5_MATCH_OUTER_HEADERS;
213                 if (attr->match_level != MLX5_MATCH_NONE)
214                         spec->match_criteria_enable |= MLX5_MATCH_INNER_HEADERS;
215         } else if (attr->match_level != MLX5_MATCH_NONE) {
216                 spec->match_criteria_enable |= MLX5_MATCH_OUTER_HEADERS;
217         }
218
219         if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
220                 flow_act.modify_id = attr->mod_hdr_id;
221
222         fdb = esw_get_prio_table(esw, attr->chain, attr->prio, !!split);
223         if (IS_ERR(fdb)) {
224                 rule = ERR_CAST(fdb);
225                 goto err_esw_get;
226         }
227
228         if (mlx5_eswitch_termtbl_required(esw, &flow_act, spec))
229                 rule = mlx5_eswitch_add_termtbl_rule(esw, fdb, spec, attr,
230                                                      &flow_act, dest, i);
231         else
232                 rule = mlx5_add_flow_rules(fdb, spec, &flow_act, dest, i);
233         if (IS_ERR(rule))
234                 goto err_add_rule;
235         else
236                 atomic64_inc(&esw->offloads.num_flows);
237
238         return rule;
239
240 err_add_rule:
241         esw_put_prio_table(esw, attr->chain, attr->prio, !!split);
242 err_esw_get:
243         if (attr->dest_chain)
244                 esw_put_prio_table(esw, attr->dest_chain, 1, 0);
245 err_create_goto_table:
246         return rule;
247 }
248
249 struct mlx5_flow_handle *
250 mlx5_eswitch_add_fwd_rule(struct mlx5_eswitch *esw,
251                           struct mlx5_flow_spec *spec,
252                           struct mlx5_esw_flow_attr *attr)
253 {
254         struct mlx5_flow_destination dest[MLX5_MAX_FLOW_FWD_VPORTS + 1] = {};
255         struct mlx5_flow_act flow_act = { .flags = FLOW_ACT_NO_APPEND, };
256         struct mlx5_flow_table *fast_fdb;
257         struct mlx5_flow_table *fwd_fdb;
258         struct mlx5_flow_handle *rule;
259         int i;
260
261         fast_fdb = esw_get_prio_table(esw, attr->chain, attr->prio, 0);
262         if (IS_ERR(fast_fdb)) {
263                 rule = ERR_CAST(fast_fdb);
264                 goto err_get_fast;
265         }
266
267         fwd_fdb = esw_get_prio_table(esw, attr->chain, attr->prio, 1);
268         if (IS_ERR(fwd_fdb)) {
269                 rule = ERR_CAST(fwd_fdb);
270                 goto err_get_fwd;
271         }
272
273         flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
274         for (i = 0; i < attr->split_count; i++) {
275                 dest[i].type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
276                 dest[i].vport.num = attr->dests[i].rep->vport;
277                 dest[i].vport.vhca_id =
278                         MLX5_CAP_GEN(attr->dests[i].mdev, vhca_id);
279                 if (MLX5_CAP_ESW(esw->dev, merged_eswitch))
280                         dest[i].vport.flags |= MLX5_FLOW_DEST_VPORT_VHCA_ID;
281                 if (attr->dests[i].flags & MLX5_ESW_DEST_ENCAP) {
282                         dest[i].vport.flags |= MLX5_FLOW_DEST_VPORT_REFORMAT_ID;
283                         dest[i].vport.reformat_id = attr->dests[i].encap_id;
284                 }
285         }
286         dest[i].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
287         dest[i].ft = fwd_fdb,
288         i++;
289
290         mlx5_eswitch_set_rule_source_port(esw, spec, attr);
291
292         spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS;
293         if (attr->match_level != MLX5_MATCH_NONE)
294                 spec->match_criteria_enable |= MLX5_MATCH_OUTER_HEADERS;
295
296         rule = mlx5_add_flow_rules(fast_fdb, spec, &flow_act, dest, i);
297
298         if (IS_ERR(rule))
299                 goto add_err;
300
301         atomic64_inc(&esw->offloads.num_flows);
302
303         return rule;
304 add_err:
305         esw_put_prio_table(esw, attr->chain, attr->prio, 1);
306 err_get_fwd:
307         esw_put_prio_table(esw, attr->chain, attr->prio, 0);
308 err_get_fast:
309         return rule;
310 }
311
312 static void
313 __mlx5_eswitch_del_rule(struct mlx5_eswitch *esw,
314                         struct mlx5_flow_handle *rule,
315                         struct mlx5_esw_flow_attr *attr,
316                         bool fwd_rule)
317 {
318         bool split = (attr->split_count > 0);
319         int i;
320
321         mlx5_del_flow_rules(rule);
322
323         /* unref the term table */
324         for (i = 0; i < MLX5_MAX_FLOW_FWD_VPORTS; i++) {
325                 if (attr->dests[i].termtbl)
326                         mlx5_eswitch_termtbl_put(esw, attr->dests[i].termtbl);
327         }
328
329         atomic64_dec(&esw->offloads.num_flows);
330
331         if (fwd_rule)  {
332                 esw_put_prio_table(esw, attr->chain, attr->prio, 1);
333                 esw_put_prio_table(esw, attr->chain, attr->prio, 0);
334         } else {
335                 esw_put_prio_table(esw, attr->chain, attr->prio, !!split);
336                 if (attr->dest_chain)
337                         esw_put_prio_table(esw, attr->dest_chain, 1, 0);
338         }
339 }
340
341 void
342 mlx5_eswitch_del_offloaded_rule(struct mlx5_eswitch *esw,
343                                 struct mlx5_flow_handle *rule,
344                                 struct mlx5_esw_flow_attr *attr)
345 {
346         __mlx5_eswitch_del_rule(esw, rule, attr, false);
347 }
348
349 void
350 mlx5_eswitch_del_fwd_rule(struct mlx5_eswitch *esw,
351                           struct mlx5_flow_handle *rule,
352                           struct mlx5_esw_flow_attr *attr)
353 {
354         __mlx5_eswitch_del_rule(esw, rule, attr, true);
355 }
356
357 static int esw_set_global_vlan_pop(struct mlx5_eswitch *esw, u8 val)
358 {
359         struct mlx5_eswitch_rep *rep;
360         int i, err = 0;
361
362         esw_debug(esw->dev, "%s applying global %s policy\n", __func__, val ? "pop" : "none");
363         mlx5_esw_for_each_host_func_rep(esw, i, rep, esw->esw_funcs.num_vfs) {
364                 if (atomic_read(&rep->rep_data[REP_ETH].state) != REP_LOADED)
365                         continue;
366
367                 err = __mlx5_eswitch_set_vport_vlan(esw, rep->vport, 0, 0, val);
368                 if (err)
369                         goto out;
370         }
371
372 out:
373         return err;
374 }
375
376 static struct mlx5_eswitch_rep *
377 esw_vlan_action_get_vport(struct mlx5_esw_flow_attr *attr, bool push, bool pop)
378 {
379         struct mlx5_eswitch_rep *in_rep, *out_rep, *vport = NULL;
380
381         in_rep  = attr->in_rep;
382         out_rep = attr->dests[0].rep;
383
384         if (push)
385                 vport = in_rep;
386         else if (pop)
387                 vport = out_rep;
388         else
389                 vport = in_rep;
390
391         return vport;
392 }
393
394 static int esw_add_vlan_action_check(struct mlx5_esw_flow_attr *attr,
395                                      bool push, bool pop, bool fwd)
396 {
397         struct mlx5_eswitch_rep *in_rep, *out_rep;
398
399         if ((push || pop) && !fwd)
400                 goto out_notsupp;
401
402         in_rep  = attr->in_rep;
403         out_rep = attr->dests[0].rep;
404
405         if (push && in_rep->vport == MLX5_VPORT_UPLINK)
406                 goto out_notsupp;
407
408         if (pop && out_rep->vport == MLX5_VPORT_UPLINK)
409                 goto out_notsupp;
410
411         /* vport has vlan push configured, can't offload VF --> wire rules w.o it */
412         if (!push && !pop && fwd)
413                 if (in_rep->vlan && out_rep->vport == MLX5_VPORT_UPLINK)
414                         goto out_notsupp;
415
416         /* protects against (1) setting rules with different vlans to push and
417          * (2) setting rules w.o vlans (attr->vlan = 0) && w. vlans to push (!= 0)
418          */
419         if (push && in_rep->vlan_refcount && (in_rep->vlan != attr->vlan_vid[0]))
420                 goto out_notsupp;
421
422         return 0;
423
424 out_notsupp:
425         return -EOPNOTSUPP;
426 }
427
428 int mlx5_eswitch_add_vlan_action(struct mlx5_eswitch *esw,
429                                  struct mlx5_esw_flow_attr *attr)
430 {
431         struct offloads_fdb *offloads = &esw->fdb_table.offloads;
432         struct mlx5_eswitch_rep *vport = NULL;
433         bool push, pop, fwd;
434         int err = 0;
435
436         /* nop if we're on the vlan push/pop non emulation mode */
437         if (mlx5_eswitch_vlan_actions_supported(esw->dev, 1))
438                 return 0;
439
440         push = !!(attr->action & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH);
441         pop  = !!(attr->action & MLX5_FLOW_CONTEXT_ACTION_VLAN_POP);
442         fwd  = !!((attr->action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) &&
443                    !attr->dest_chain);
444
445         mutex_lock(&esw->state_lock);
446
447         err = esw_add_vlan_action_check(attr, push, pop, fwd);
448         if (err)
449                 goto unlock;
450
451         attr->vlan_handled = false;
452
453         vport = esw_vlan_action_get_vport(attr, push, pop);
454
455         if (!push && !pop && fwd) {
456                 /* tracks VF --> wire rules without vlan push action */
457                 if (attr->dests[0].rep->vport == MLX5_VPORT_UPLINK) {
458                         vport->vlan_refcount++;
459                         attr->vlan_handled = true;
460                 }
461
462                 goto unlock;
463         }
464
465         if (!push && !pop)
466                 goto unlock;
467
468         if (!(offloads->vlan_push_pop_refcount)) {
469                 /* it's the 1st vlan rule, apply global vlan pop policy */
470                 err = esw_set_global_vlan_pop(esw, SET_VLAN_STRIP);
471                 if (err)
472                         goto out;
473         }
474         offloads->vlan_push_pop_refcount++;
475
476         if (push) {
477                 if (vport->vlan_refcount)
478                         goto skip_set_push;
479
480                 err = __mlx5_eswitch_set_vport_vlan(esw, vport->vport, attr->vlan_vid[0], 0,
481                                                     SET_VLAN_INSERT | SET_VLAN_STRIP);
482                 if (err)
483                         goto out;
484                 vport->vlan = attr->vlan_vid[0];
485 skip_set_push:
486                 vport->vlan_refcount++;
487         }
488 out:
489         if (!err)
490                 attr->vlan_handled = true;
491 unlock:
492         mutex_unlock(&esw->state_lock);
493         return err;
494 }
495
496 int mlx5_eswitch_del_vlan_action(struct mlx5_eswitch *esw,
497                                  struct mlx5_esw_flow_attr *attr)
498 {
499         struct offloads_fdb *offloads = &esw->fdb_table.offloads;
500         struct mlx5_eswitch_rep *vport = NULL;
501         bool push, pop, fwd;
502         int err = 0;
503
504         /* nop if we're on the vlan push/pop non emulation mode */
505         if (mlx5_eswitch_vlan_actions_supported(esw->dev, 1))
506                 return 0;
507
508         if (!attr->vlan_handled)
509                 return 0;
510
511         push = !!(attr->action & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH);
512         pop  = !!(attr->action & MLX5_FLOW_CONTEXT_ACTION_VLAN_POP);
513         fwd  = !!(attr->action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST);
514
515         mutex_lock(&esw->state_lock);
516
517         vport = esw_vlan_action_get_vport(attr, push, pop);
518
519         if (!push && !pop && fwd) {
520                 /* tracks VF --> wire rules without vlan push action */
521                 if (attr->dests[0].rep->vport == MLX5_VPORT_UPLINK)
522                         vport->vlan_refcount--;
523
524                 goto out;
525         }
526
527         if (push) {
528                 vport->vlan_refcount--;
529                 if (vport->vlan_refcount)
530                         goto skip_unset_push;
531
532                 vport->vlan = 0;
533                 err = __mlx5_eswitch_set_vport_vlan(esw, vport->vport,
534                                                     0, 0, SET_VLAN_STRIP);
535                 if (err)
536                         goto out;
537         }
538
539 skip_unset_push:
540         offloads->vlan_push_pop_refcount--;
541         if (offloads->vlan_push_pop_refcount)
542                 goto out;
543
544         /* no more vlan rules, stop global vlan pop policy */
545         err = esw_set_global_vlan_pop(esw, 0);
546
547 out:
548         mutex_unlock(&esw->state_lock);
549         return err;
550 }
551
552 struct mlx5_flow_handle *
553 mlx5_eswitch_add_send_to_vport_rule(struct mlx5_eswitch *esw, u16 vport,
554                                     u32 sqn)
555 {
556         struct mlx5_flow_act flow_act = {0};
557         struct mlx5_flow_destination dest = {};
558         struct mlx5_flow_handle *flow_rule;
559         struct mlx5_flow_spec *spec;
560         void *misc;
561
562         spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
563         if (!spec) {
564                 flow_rule = ERR_PTR(-ENOMEM);
565                 goto out;
566         }
567
568         misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters);
569         MLX5_SET(fte_match_set_misc, misc, source_sqn, sqn);
570         /* source vport is the esw manager */
571         MLX5_SET(fte_match_set_misc, misc, source_port, esw->manager_vport);
572
573         misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters);
574         MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_sqn);
575         MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port);
576
577         spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS;
578         dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
579         dest.vport.num = vport;
580         flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
581
582         flow_rule = mlx5_add_flow_rules(esw->fdb_table.offloads.slow_fdb, spec,
583                                         &flow_act, &dest, 1);
584         if (IS_ERR(flow_rule))
585                 esw_warn(esw->dev, "FDB: Failed to add send to vport rule err %ld\n", PTR_ERR(flow_rule));
586 out:
587         kvfree(spec);
588         return flow_rule;
589 }
590 EXPORT_SYMBOL(mlx5_eswitch_add_send_to_vport_rule);
591
592 void mlx5_eswitch_del_send_to_vport_rule(struct mlx5_flow_handle *rule)
593 {
594         mlx5_del_flow_rules(rule);
595 }
596
597 static int esw_set_passing_vport_metadata(struct mlx5_eswitch *esw, bool enable)
598 {
599         u32 out[MLX5_ST_SZ_DW(query_esw_vport_context_out)] = {};
600         u32 in[MLX5_ST_SZ_DW(modify_esw_vport_context_in)] = {};
601         u8 fdb_to_vport_reg_c_id;
602         int err;
603
604         if (!mlx5_eswitch_vport_match_metadata_enabled(esw))
605                 return 0;
606
607         err = mlx5_eswitch_query_esw_vport_context(esw, esw->manager_vport,
608                                                    out, sizeof(out));
609         if (err)
610                 return err;
611
612         fdb_to_vport_reg_c_id = MLX5_GET(query_esw_vport_context_out, out,
613                                          esw_vport_context.fdb_to_vport_reg_c_id);
614
615         if (enable)
616                 fdb_to_vport_reg_c_id |= MLX5_FDB_TO_VPORT_REG_C_0;
617         else
618                 fdb_to_vport_reg_c_id &= ~MLX5_FDB_TO_VPORT_REG_C_0;
619
620         MLX5_SET(modify_esw_vport_context_in, in,
621                  esw_vport_context.fdb_to_vport_reg_c_id, fdb_to_vport_reg_c_id);
622
623         MLX5_SET(modify_esw_vport_context_in, in,
624                  field_select.fdb_to_vport_reg_c_id, 1);
625
626         return mlx5_eswitch_modify_esw_vport_context(esw, esw->manager_vport,
627                                                      in, sizeof(in));
628 }
629
630 static void peer_miss_rules_setup(struct mlx5_eswitch *esw,
631                                   struct mlx5_core_dev *peer_dev,
632                                   struct mlx5_flow_spec *spec,
633                                   struct mlx5_flow_destination *dest)
634 {
635         void *misc;
636
637         if (mlx5_eswitch_vport_match_metadata_enabled(esw)) {
638                 misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
639                                     misc_parameters_2);
640                 MLX5_SET_TO_ONES(fte_match_set_misc2, misc, metadata_reg_c_0);
641
642                 spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS_2;
643         } else {
644                 misc = MLX5_ADDR_OF(fte_match_param, spec->match_value,
645                                     misc_parameters);
646
647                 MLX5_SET(fte_match_set_misc, misc, source_eswitch_owner_vhca_id,
648                          MLX5_CAP_GEN(peer_dev, vhca_id));
649
650                 spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS;
651
652                 misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
653                                     misc_parameters);
654                 MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port);
655                 MLX5_SET_TO_ONES(fte_match_set_misc, misc,
656                                  source_eswitch_owner_vhca_id);
657         }
658
659         dest->type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
660         dest->vport.num = peer_dev->priv.eswitch->manager_vport;
661         dest->vport.vhca_id = MLX5_CAP_GEN(peer_dev, vhca_id);
662         dest->vport.flags |= MLX5_FLOW_DEST_VPORT_VHCA_ID;
663 }
664
665 static void esw_set_peer_miss_rule_source_port(struct mlx5_eswitch *esw,
666                                                struct mlx5_eswitch *peer_esw,
667                                                struct mlx5_flow_spec *spec,
668                                                u16 vport)
669 {
670         void *misc;
671
672         if (mlx5_eswitch_vport_match_metadata_enabled(esw)) {
673                 misc = MLX5_ADDR_OF(fte_match_param, spec->match_value,
674                                     misc_parameters_2);
675                 MLX5_SET(fte_match_set_misc2, misc, metadata_reg_c_0,
676                          mlx5_eswitch_get_vport_metadata_for_match(peer_esw,
677                                                                    vport));
678         } else {
679                 misc = MLX5_ADDR_OF(fte_match_param, spec->match_value,
680                                     misc_parameters);
681                 MLX5_SET(fte_match_set_misc, misc, source_port, vport);
682         }
683 }
684
685 static int esw_add_fdb_peer_miss_rules(struct mlx5_eswitch *esw,
686                                        struct mlx5_core_dev *peer_dev)
687 {
688         struct mlx5_flow_destination dest = {};
689         struct mlx5_flow_act flow_act = {0};
690         struct mlx5_flow_handle **flows;
691         struct mlx5_flow_handle *flow;
692         struct mlx5_flow_spec *spec;
693         /* total vports is the same for both e-switches */
694         int nvports = esw->total_vports;
695         void *misc;
696         int err, i;
697
698         spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
699         if (!spec)
700                 return -ENOMEM;
701
702         peer_miss_rules_setup(esw, peer_dev, spec, &dest);
703
704         flows = kvzalloc(nvports * sizeof(*flows), GFP_KERNEL);
705         if (!flows) {
706                 err = -ENOMEM;
707                 goto alloc_flows_err;
708         }
709
710         flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
711         misc = MLX5_ADDR_OF(fte_match_param, spec->match_value,
712                             misc_parameters);
713
714         if (mlx5_core_is_ecpf_esw_manager(esw->dev)) {
715                 esw_set_peer_miss_rule_source_port(esw, peer_dev->priv.eswitch,
716                                                    spec, MLX5_VPORT_PF);
717
718                 flow = mlx5_add_flow_rules(esw->fdb_table.offloads.slow_fdb,
719                                            spec, &flow_act, &dest, 1);
720                 if (IS_ERR(flow)) {
721                         err = PTR_ERR(flow);
722                         goto add_pf_flow_err;
723                 }
724                 flows[MLX5_VPORT_PF] = flow;
725         }
726
727         if (mlx5_ecpf_vport_exists(esw->dev)) {
728                 MLX5_SET(fte_match_set_misc, misc, source_port, MLX5_VPORT_ECPF);
729                 flow = mlx5_add_flow_rules(esw->fdb_table.offloads.slow_fdb,
730                                            spec, &flow_act, &dest, 1);
731                 if (IS_ERR(flow)) {
732                         err = PTR_ERR(flow);
733                         goto add_ecpf_flow_err;
734                 }
735                 flows[mlx5_eswitch_ecpf_idx(esw)] = flow;
736         }
737
738         mlx5_esw_for_each_vf_vport_num(esw, i, mlx5_core_max_vfs(esw->dev)) {
739                 esw_set_peer_miss_rule_source_port(esw,
740                                                    peer_dev->priv.eswitch,
741                                                    spec, i);
742
743                 flow = mlx5_add_flow_rules(esw->fdb_table.offloads.slow_fdb,
744                                            spec, &flow_act, &dest, 1);
745                 if (IS_ERR(flow)) {
746                         err = PTR_ERR(flow);
747                         goto add_vf_flow_err;
748                 }
749                 flows[i] = flow;
750         }
751
752         esw->fdb_table.offloads.peer_miss_rules = flows;
753
754         kvfree(spec);
755         return 0;
756
757 add_vf_flow_err:
758         nvports = --i;
759         mlx5_esw_for_each_vf_vport_num_reverse(esw, i, nvports)
760                 mlx5_del_flow_rules(flows[i]);
761
762         if (mlx5_ecpf_vport_exists(esw->dev))
763                 mlx5_del_flow_rules(flows[mlx5_eswitch_ecpf_idx(esw)]);
764 add_ecpf_flow_err:
765         if (mlx5_core_is_ecpf_esw_manager(esw->dev))
766                 mlx5_del_flow_rules(flows[MLX5_VPORT_PF]);
767 add_pf_flow_err:
768         esw_warn(esw->dev, "FDB: Failed to add peer miss flow rule err %d\n", err);
769         kvfree(flows);
770 alloc_flows_err:
771         kvfree(spec);
772         return err;
773 }
774
775 static void esw_del_fdb_peer_miss_rules(struct mlx5_eswitch *esw)
776 {
777         struct mlx5_flow_handle **flows;
778         int i;
779
780         flows = esw->fdb_table.offloads.peer_miss_rules;
781
782         mlx5_esw_for_each_vf_vport_num_reverse(esw, i,
783                                                mlx5_core_max_vfs(esw->dev))
784                 mlx5_del_flow_rules(flows[i]);
785
786         if (mlx5_ecpf_vport_exists(esw->dev))
787                 mlx5_del_flow_rules(flows[mlx5_eswitch_ecpf_idx(esw)]);
788
789         if (mlx5_core_is_ecpf_esw_manager(esw->dev))
790                 mlx5_del_flow_rules(flows[MLX5_VPORT_PF]);
791
792         kvfree(flows);
793 }
794
795 static int esw_add_fdb_miss_rule(struct mlx5_eswitch *esw)
796 {
797         struct mlx5_flow_act flow_act = {0};
798         struct mlx5_flow_destination dest = {};
799         struct mlx5_flow_handle *flow_rule = NULL;
800         struct mlx5_flow_spec *spec;
801         void *headers_c;
802         void *headers_v;
803         int err = 0;
804         u8 *dmac_c;
805         u8 *dmac_v;
806
807         spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
808         if (!spec) {
809                 err = -ENOMEM;
810                 goto out;
811         }
812
813         spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
814         headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
815                                  outer_headers);
816         dmac_c = MLX5_ADDR_OF(fte_match_param, headers_c,
817                               outer_headers.dmac_47_16);
818         dmac_c[0] = 0x01;
819
820         dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
821         dest.vport.num = esw->manager_vport;
822         flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
823
824         flow_rule = mlx5_add_flow_rules(esw->fdb_table.offloads.slow_fdb, spec,
825                                         &flow_act, &dest, 1);
826         if (IS_ERR(flow_rule)) {
827                 err = PTR_ERR(flow_rule);
828                 esw_warn(esw->dev,  "FDB: Failed to add unicast miss flow rule err %d\n", err);
829                 goto out;
830         }
831
832         esw->fdb_table.offloads.miss_rule_uni = flow_rule;
833
834         headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value,
835                                  outer_headers);
836         dmac_v = MLX5_ADDR_OF(fte_match_param, headers_v,
837                               outer_headers.dmac_47_16);
838         dmac_v[0] = 0x01;
839         flow_rule = mlx5_add_flow_rules(esw->fdb_table.offloads.slow_fdb, spec,
840                                         &flow_act, &dest, 1);
841         if (IS_ERR(flow_rule)) {
842                 err = PTR_ERR(flow_rule);
843                 esw_warn(esw->dev, "FDB: Failed to add multicast miss flow rule err %d\n", err);
844                 mlx5_del_flow_rules(esw->fdb_table.offloads.miss_rule_uni);
845                 goto out;
846         }
847
848         esw->fdb_table.offloads.miss_rule_multi = flow_rule;
849
850 out:
851         kvfree(spec);
852         return err;
853 }
854
855 #define ESW_OFFLOADS_NUM_GROUPS  4
856
857 /* Firmware currently has 4 pool of 4 sizes that it supports (ESW_POOLS),
858  * and a virtual memory region of 16M (ESW_SIZE), this region is duplicated
859  * for each flow table pool. We can allocate up to 16M of each pool,
860  * and we keep track of how much we used via put/get_sz_to_pool.
861  * Firmware doesn't report any of this for now.
862  * ESW_POOL is expected to be sorted from large to small
863  */
864 #define ESW_SIZE (16 * 1024 * 1024)
865 const unsigned int ESW_POOLS[4] = { 4 * 1024 * 1024, 1 * 1024 * 1024,
866                                     64 * 1024, 4 * 1024 };
867
868 static int
869 get_sz_from_pool(struct mlx5_eswitch *esw)
870 {
871         int sz = 0, i;
872
873         for (i = 0; i < ARRAY_SIZE(ESW_POOLS); i++) {
874                 if (esw->fdb_table.offloads.fdb_left[i]) {
875                         --esw->fdb_table.offloads.fdb_left[i];
876                         sz = ESW_POOLS[i];
877                         break;
878                 }
879         }
880
881         return sz;
882 }
883
884 static void
885 put_sz_to_pool(struct mlx5_eswitch *esw, int sz)
886 {
887         int i;
888
889         for (i = 0; i < ARRAY_SIZE(ESW_POOLS); i++) {
890                 if (sz >= ESW_POOLS[i]) {
891                         ++esw->fdb_table.offloads.fdb_left[i];
892                         break;
893                 }
894         }
895 }
896
897 static struct mlx5_flow_table *
898 create_next_size_table(struct mlx5_eswitch *esw,
899                        struct mlx5_flow_namespace *ns,
900                        u16 table_prio,
901                        int level,
902                        u32 flags)
903 {
904         struct mlx5_flow_table *fdb;
905         int sz;
906
907         sz = get_sz_from_pool(esw);
908         if (!sz)
909                 return ERR_PTR(-ENOSPC);
910
911         fdb = mlx5_create_auto_grouped_flow_table(ns,
912                                                   table_prio,
913                                                   sz,
914                                                   ESW_OFFLOADS_NUM_GROUPS,
915                                                   level,
916                                                   flags);
917         if (IS_ERR(fdb)) {
918                 esw_warn(esw->dev, "Failed to create FDB Table err %d (table prio: %d, level: %d, size: %d)\n",
919                          (int)PTR_ERR(fdb), table_prio, level, sz);
920                 put_sz_to_pool(esw, sz);
921         }
922
923         return fdb;
924 }
925
926 static struct mlx5_flow_table *
927 esw_get_prio_table(struct mlx5_eswitch *esw, u32 chain, u16 prio, int level)
928 {
929         struct mlx5_core_dev *dev = esw->dev;
930         struct mlx5_flow_table *fdb = NULL;
931         struct mlx5_flow_namespace *ns;
932         int table_prio, l = 0;
933         u32 flags = 0;
934
935         if (chain == FDB_SLOW_PATH_CHAIN)
936                 return esw->fdb_table.offloads.slow_fdb;
937
938         mutex_lock(&esw->fdb_table.offloads.fdb_prio_lock);
939
940         fdb = fdb_prio_table(esw, chain, prio, level).fdb;
941         if (fdb) {
942                 /* take ref on earlier levels as well */
943                 while (level >= 0)
944                         fdb_prio_table(esw, chain, prio, level--).num_rules++;
945                 mutex_unlock(&esw->fdb_table.offloads.fdb_prio_lock);
946                 return fdb;
947         }
948
949         ns = mlx5_get_fdb_sub_ns(dev, chain);
950         if (!ns) {
951                 esw_warn(dev, "Failed to get FDB sub namespace\n");
952                 mutex_unlock(&esw->fdb_table.offloads.fdb_prio_lock);
953                 return ERR_PTR(-EOPNOTSUPP);
954         }
955
956         if (esw->offloads.encap != DEVLINK_ESWITCH_ENCAP_MODE_NONE)
957                 flags |= (MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT |
958                           MLX5_FLOW_TABLE_TUNNEL_EN_DECAP);
959
960         table_prio = (chain * FDB_MAX_PRIO) + prio - 1;
961
962         /* create earlier levels for correct fs_core lookup when
963          * connecting tables
964          */
965         for (l = 0; l <= level; l++) {
966                 if (fdb_prio_table(esw, chain, prio, l).fdb) {
967                         fdb_prio_table(esw, chain, prio, l).num_rules++;
968                         continue;
969                 }
970
971                 fdb = create_next_size_table(esw, ns, table_prio, l, flags);
972                 if (IS_ERR(fdb)) {
973                         l--;
974                         goto err_create_fdb;
975                 }
976
977                 fdb_prio_table(esw, chain, prio, l).fdb = fdb;
978                 fdb_prio_table(esw, chain, prio, l).num_rules = 1;
979         }
980
981         mutex_unlock(&esw->fdb_table.offloads.fdb_prio_lock);
982         return fdb;
983
984 err_create_fdb:
985         mutex_unlock(&esw->fdb_table.offloads.fdb_prio_lock);
986         if (l >= 0)
987                 esw_put_prio_table(esw, chain, prio, l);
988
989         return fdb;
990 }
991
992 static void
993 esw_put_prio_table(struct mlx5_eswitch *esw, u32 chain, u16 prio, int level)
994 {
995         int l;
996
997         if (chain == FDB_SLOW_PATH_CHAIN)
998                 return;
999
1000         mutex_lock(&esw->fdb_table.offloads.fdb_prio_lock);
1001
1002         for (l = level; l >= 0; l--) {
1003                 if (--(fdb_prio_table(esw, chain, prio, l).num_rules) > 0)
1004                         continue;
1005
1006                 put_sz_to_pool(esw, fdb_prio_table(esw, chain, prio, l).fdb->max_fte);
1007                 mlx5_destroy_flow_table(fdb_prio_table(esw, chain, prio, l).fdb);
1008                 fdb_prio_table(esw, chain, prio, l).fdb = NULL;
1009         }
1010
1011         mutex_unlock(&esw->fdb_table.offloads.fdb_prio_lock);
1012 }
1013
1014 static void esw_destroy_offloads_fast_fdb_tables(struct mlx5_eswitch *esw)
1015 {
1016         /* If lazy creation isn't supported, deref the fast path tables */
1017         if (!(esw->fdb_table.flags & ESW_FDB_CHAINS_AND_PRIOS_SUPPORTED)) {
1018                 esw_put_prio_table(esw, 0, 1, 1);
1019                 esw_put_prio_table(esw, 0, 1, 0);
1020         }
1021 }
1022
1023 #define MAX_PF_SQ 256
1024 #define MAX_SQ_NVPORTS 32
1025
1026 static void esw_set_flow_group_source_port(struct mlx5_eswitch *esw,
1027                                            u32 *flow_group_in)
1028 {
1029         void *match_criteria = MLX5_ADDR_OF(create_flow_group_in,
1030                                             flow_group_in,
1031                                             match_criteria);
1032
1033         if (mlx5_eswitch_vport_match_metadata_enabled(esw)) {
1034                 MLX5_SET(create_flow_group_in, flow_group_in,
1035                          match_criteria_enable,
1036                          MLX5_MATCH_MISC_PARAMETERS_2);
1037
1038                 MLX5_SET_TO_ONES(fte_match_param, match_criteria,
1039                                  misc_parameters_2.metadata_reg_c_0);
1040         } else {
1041                 MLX5_SET(create_flow_group_in, flow_group_in,
1042                          match_criteria_enable,
1043                          MLX5_MATCH_MISC_PARAMETERS);
1044
1045                 MLX5_SET_TO_ONES(fte_match_param, match_criteria,
1046                                  misc_parameters.source_port);
1047         }
1048 }
1049
1050 static int esw_create_offloads_fdb_tables(struct mlx5_eswitch *esw, int nvports)
1051 {
1052         int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
1053         struct mlx5_flow_table_attr ft_attr = {};
1054         struct mlx5_core_dev *dev = esw->dev;
1055         u32 *flow_group_in, max_flow_counter;
1056         struct mlx5_flow_namespace *root_ns;
1057         struct mlx5_flow_table *fdb = NULL;
1058         int table_size, ix, err = 0, i;
1059         struct mlx5_flow_group *g;
1060         u32 flags = 0, fdb_max;
1061         void *match_criteria;
1062         u8 *dmac;
1063
1064         esw_debug(esw->dev, "Create offloads FDB Tables\n");
1065         flow_group_in = kvzalloc(inlen, GFP_KERNEL);
1066         if (!flow_group_in)
1067                 return -ENOMEM;
1068
1069         root_ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_FDB);
1070         if (!root_ns) {
1071                 esw_warn(dev, "Failed to get FDB flow namespace\n");
1072                 err = -EOPNOTSUPP;
1073                 goto ns_err;
1074         }
1075
1076         max_flow_counter = (MLX5_CAP_GEN(dev, max_flow_counter_31_16) << 16) |
1077                             MLX5_CAP_GEN(dev, max_flow_counter_15_0);
1078         fdb_max = 1 << MLX5_CAP_ESW_FLOWTABLE_FDB(dev, log_max_ft_size);
1079
1080         esw_debug(dev, "Create offloads FDB table, min (max esw size(2^%d), max counters(%d), groups(%d), max flow table size(2^%d))\n",
1081                   MLX5_CAP_ESW_FLOWTABLE_FDB(dev, log_max_ft_size),
1082                   max_flow_counter, ESW_OFFLOADS_NUM_GROUPS,
1083                   fdb_max);
1084
1085         for (i = 0; i < ARRAY_SIZE(ESW_POOLS); i++)
1086                 esw->fdb_table.offloads.fdb_left[i] =
1087                         ESW_POOLS[i] <= fdb_max ? ESW_SIZE / ESW_POOLS[i] : 0;
1088
1089         table_size = nvports * MAX_SQ_NVPORTS + MAX_PF_SQ +
1090                 MLX5_ESW_MISS_FLOWS + esw->total_vports;
1091
1092         /* create the slow path fdb with encap set, so further table instances
1093          * can be created at run time while VFs are probed if the FW allows that.
1094          */
1095         if (esw->offloads.encap != DEVLINK_ESWITCH_ENCAP_MODE_NONE)
1096                 flags |= (MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT |
1097                           MLX5_FLOW_TABLE_TUNNEL_EN_DECAP);
1098
1099         ft_attr.flags = flags;
1100         ft_attr.max_fte = table_size;
1101         ft_attr.prio = FDB_SLOW_PATH;
1102
1103         fdb = mlx5_create_flow_table(root_ns, &ft_attr);
1104         if (IS_ERR(fdb)) {
1105                 err = PTR_ERR(fdb);
1106                 esw_warn(dev, "Failed to create slow path FDB Table err %d\n", err);
1107                 goto slow_fdb_err;
1108         }
1109         esw->fdb_table.offloads.slow_fdb = fdb;
1110
1111         /* If lazy creation isn't supported, open the fast path tables now */
1112         if (!MLX5_CAP_ESW_FLOWTABLE(esw->dev, multi_fdb_encap) &&
1113             esw->offloads.encap != DEVLINK_ESWITCH_ENCAP_MODE_NONE) {
1114                 esw->fdb_table.flags &= ~ESW_FDB_CHAINS_AND_PRIOS_SUPPORTED;
1115                 esw_warn(dev, "Lazy creation of flow tables isn't supported, ignoring priorities\n");
1116                 esw_get_prio_table(esw, 0, 1, 0);
1117                 esw_get_prio_table(esw, 0, 1, 1);
1118         } else {
1119                 esw_debug(dev, "Lazy creation of flow tables supported, deferring table opening\n");
1120                 esw->fdb_table.flags |= ESW_FDB_CHAINS_AND_PRIOS_SUPPORTED;
1121         }
1122
1123         /* create send-to-vport group */
1124         MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
1125                  MLX5_MATCH_MISC_PARAMETERS);
1126
1127         match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in, match_criteria);
1128
1129         MLX5_SET_TO_ONES(fte_match_param, match_criteria, misc_parameters.source_sqn);
1130         MLX5_SET_TO_ONES(fte_match_param, match_criteria, misc_parameters.source_port);
1131
1132         ix = nvports * MAX_SQ_NVPORTS + MAX_PF_SQ;
1133         MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 0);
1134         MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, ix - 1);
1135
1136         g = mlx5_create_flow_group(fdb, flow_group_in);
1137         if (IS_ERR(g)) {
1138                 err = PTR_ERR(g);
1139                 esw_warn(dev, "Failed to create send-to-vport flow group err(%d)\n", err);
1140                 goto send_vport_err;
1141         }
1142         esw->fdb_table.offloads.send_to_vport_grp = g;
1143
1144         /* create peer esw miss group */
1145         memset(flow_group_in, 0, inlen);
1146
1147         esw_set_flow_group_source_port(esw, flow_group_in);
1148
1149         if (!mlx5_eswitch_vport_match_metadata_enabled(esw)) {
1150                 match_criteria = MLX5_ADDR_OF(create_flow_group_in,
1151                                               flow_group_in,
1152                                               match_criteria);
1153
1154                 MLX5_SET_TO_ONES(fte_match_param, match_criteria,
1155                                  misc_parameters.source_eswitch_owner_vhca_id);
1156
1157                 MLX5_SET(create_flow_group_in, flow_group_in,
1158                          source_eswitch_owner_vhca_id_valid, 1);
1159         }
1160
1161         MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, ix);
1162         MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index,
1163                  ix + esw->total_vports - 1);
1164         ix += esw->total_vports;
1165
1166         g = mlx5_create_flow_group(fdb, flow_group_in);
1167         if (IS_ERR(g)) {
1168                 err = PTR_ERR(g);
1169                 esw_warn(dev, "Failed to create peer miss flow group err(%d)\n", err);
1170                 goto peer_miss_err;
1171         }
1172         esw->fdb_table.offloads.peer_miss_grp = g;
1173
1174         /* create miss group */
1175         memset(flow_group_in, 0, inlen);
1176         MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
1177                  MLX5_MATCH_OUTER_HEADERS);
1178         match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in,
1179                                       match_criteria);
1180         dmac = MLX5_ADDR_OF(fte_match_param, match_criteria,
1181                             outer_headers.dmac_47_16);
1182         dmac[0] = 0x01;
1183
1184         MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, ix);
1185         MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index,
1186                  ix + MLX5_ESW_MISS_FLOWS);
1187
1188         g = mlx5_create_flow_group(fdb, flow_group_in);
1189         if (IS_ERR(g)) {
1190                 err = PTR_ERR(g);
1191                 esw_warn(dev, "Failed to create miss flow group err(%d)\n", err);
1192                 goto miss_err;
1193         }
1194         esw->fdb_table.offloads.miss_grp = g;
1195
1196         err = esw_add_fdb_miss_rule(esw);
1197         if (err)
1198                 goto miss_rule_err;
1199
1200         esw->nvports = nvports;
1201         kvfree(flow_group_in);
1202         return 0;
1203
1204 miss_rule_err:
1205         mlx5_destroy_flow_group(esw->fdb_table.offloads.miss_grp);
1206 miss_err:
1207         mlx5_destroy_flow_group(esw->fdb_table.offloads.peer_miss_grp);
1208 peer_miss_err:
1209         mlx5_destroy_flow_group(esw->fdb_table.offloads.send_to_vport_grp);
1210 send_vport_err:
1211         esw_destroy_offloads_fast_fdb_tables(esw);
1212         mlx5_destroy_flow_table(esw->fdb_table.offloads.slow_fdb);
1213 slow_fdb_err:
1214 ns_err:
1215         kvfree(flow_group_in);
1216         return err;
1217 }
1218
1219 static void esw_destroy_offloads_fdb_tables(struct mlx5_eswitch *esw)
1220 {
1221         if (!esw->fdb_table.offloads.slow_fdb)
1222                 return;
1223
1224         esw_debug(esw->dev, "Destroy offloads FDB Tables\n");
1225         mlx5_del_flow_rules(esw->fdb_table.offloads.miss_rule_multi);
1226         mlx5_del_flow_rules(esw->fdb_table.offloads.miss_rule_uni);
1227         mlx5_destroy_flow_group(esw->fdb_table.offloads.send_to_vport_grp);
1228         mlx5_destroy_flow_group(esw->fdb_table.offloads.peer_miss_grp);
1229         mlx5_destroy_flow_group(esw->fdb_table.offloads.miss_grp);
1230
1231         mlx5_destroy_flow_table(esw->fdb_table.offloads.slow_fdb);
1232         esw_destroy_offloads_fast_fdb_tables(esw);
1233 }
1234
1235 static int esw_create_offloads_table(struct mlx5_eswitch *esw, int nvports)
1236 {
1237         struct mlx5_flow_table_attr ft_attr = {};
1238         struct mlx5_core_dev *dev = esw->dev;
1239         struct mlx5_flow_table *ft_offloads;
1240         struct mlx5_flow_namespace *ns;
1241         int err = 0;
1242
1243         ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_OFFLOADS);
1244         if (!ns) {
1245                 esw_warn(esw->dev, "Failed to get offloads flow namespace\n");
1246                 return -EOPNOTSUPP;
1247         }
1248
1249         ft_attr.max_fte = nvports + MLX5_ESW_MISS_FLOWS;
1250
1251         ft_offloads = mlx5_create_flow_table(ns, &ft_attr);
1252         if (IS_ERR(ft_offloads)) {
1253                 err = PTR_ERR(ft_offloads);
1254                 esw_warn(esw->dev, "Failed to create offloads table, err %d\n", err);
1255                 return err;
1256         }
1257
1258         esw->offloads.ft_offloads = ft_offloads;
1259         return 0;
1260 }
1261
1262 static void esw_destroy_offloads_table(struct mlx5_eswitch *esw)
1263 {
1264         struct mlx5_esw_offload *offloads = &esw->offloads;
1265
1266         mlx5_destroy_flow_table(offloads->ft_offloads);
1267 }
1268
1269 static int esw_create_vport_rx_group(struct mlx5_eswitch *esw, int nvports)
1270 {
1271         int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
1272         struct mlx5_flow_group *g;
1273         u32 *flow_group_in;
1274         int err = 0;
1275
1276         nvports = nvports + MLX5_ESW_MISS_FLOWS;
1277         flow_group_in = kvzalloc(inlen, GFP_KERNEL);
1278         if (!flow_group_in)
1279                 return -ENOMEM;
1280
1281         /* create vport rx group */
1282         esw_set_flow_group_source_port(esw, flow_group_in);
1283
1284         MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 0);
1285         MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, nvports - 1);
1286
1287         g = mlx5_create_flow_group(esw->offloads.ft_offloads, flow_group_in);
1288
1289         if (IS_ERR(g)) {
1290                 err = PTR_ERR(g);
1291                 mlx5_core_warn(esw->dev, "Failed to create vport rx group err %d\n", err);
1292                 goto out;
1293         }
1294
1295         esw->offloads.vport_rx_group = g;
1296 out:
1297         kvfree(flow_group_in);
1298         return err;
1299 }
1300
1301 static void esw_destroy_vport_rx_group(struct mlx5_eswitch *esw)
1302 {
1303         mlx5_destroy_flow_group(esw->offloads.vport_rx_group);
1304 }
1305
1306 struct mlx5_flow_handle *
1307 mlx5_eswitch_create_vport_rx_rule(struct mlx5_eswitch *esw, u16 vport,
1308                                   struct mlx5_flow_destination *dest)
1309 {
1310         struct mlx5_flow_act flow_act = {0};
1311         struct mlx5_flow_handle *flow_rule;
1312         struct mlx5_flow_spec *spec;
1313         void *misc;
1314
1315         spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
1316         if (!spec) {
1317                 flow_rule = ERR_PTR(-ENOMEM);
1318                 goto out;
1319         }
1320
1321         if (mlx5_eswitch_vport_match_metadata_enabled(esw)) {
1322                 misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters_2);
1323                 MLX5_SET(fte_match_set_misc2, misc, metadata_reg_c_0,
1324                          mlx5_eswitch_get_vport_metadata_for_match(esw, vport));
1325
1326                 misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters_2);
1327                 MLX5_SET_TO_ONES(fte_match_set_misc2, misc, metadata_reg_c_0);
1328
1329                 spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS_2;
1330         } else {
1331                 misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters);
1332                 MLX5_SET(fte_match_set_misc, misc, source_port, vport);
1333
1334                 misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters);
1335                 MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port);
1336
1337                 spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS;
1338         }
1339
1340         flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
1341         flow_rule = mlx5_add_flow_rules(esw->offloads.ft_offloads, spec,
1342                                         &flow_act, dest, 1);
1343         if (IS_ERR(flow_rule)) {
1344                 esw_warn(esw->dev, "fs offloads: Failed to add vport rx rule err %ld\n", PTR_ERR(flow_rule));
1345                 goto out;
1346         }
1347
1348 out:
1349         kvfree(spec);
1350         return flow_rule;
1351 }
1352
1353 static int esw_offloads_start(struct mlx5_eswitch *esw,
1354                               struct netlink_ext_ack *extack)
1355 {
1356         int err, err1;
1357
1358         if (esw->mode != MLX5_ESWITCH_LEGACY &&
1359             !mlx5_core_is_ecpf_esw_manager(esw->dev)) {
1360                 NL_SET_ERR_MSG_MOD(extack,
1361                                    "Can't set offloads mode, SRIOV legacy not enabled");
1362                 return -EINVAL;
1363         }
1364
1365         mlx5_eswitch_disable(esw);
1366         mlx5_eswitch_update_num_of_vfs(esw, esw->dev->priv.sriov.num_vfs);
1367         err = mlx5_eswitch_enable(esw, MLX5_ESWITCH_OFFLOADS);
1368         if (err) {
1369                 NL_SET_ERR_MSG_MOD(extack,
1370                                    "Failed setting eswitch to offloads");
1371                 err1 = mlx5_eswitch_enable(esw, MLX5_ESWITCH_LEGACY);
1372                 if (err1) {
1373                         NL_SET_ERR_MSG_MOD(extack,
1374                                            "Failed setting eswitch back to legacy");
1375                 }
1376         }
1377         if (esw->offloads.inline_mode == MLX5_INLINE_MODE_NONE) {
1378                 if (mlx5_eswitch_inline_mode_get(esw,
1379                                                  &esw->offloads.inline_mode)) {
1380                         esw->offloads.inline_mode = MLX5_INLINE_MODE_L2;
1381                         NL_SET_ERR_MSG_MOD(extack,
1382                                            "Inline mode is different between vports");
1383                 }
1384         }
1385         return err;
1386 }
1387
1388 void esw_offloads_cleanup_reps(struct mlx5_eswitch *esw)
1389 {
1390         kfree(esw->offloads.vport_reps);
1391 }
1392
1393 int esw_offloads_init_reps(struct mlx5_eswitch *esw)
1394 {
1395         int total_vports = esw->total_vports;
1396         struct mlx5_eswitch_rep *rep;
1397         int vport_index;
1398         u8 rep_type;
1399
1400         esw->offloads.vport_reps = kcalloc(total_vports,
1401                                            sizeof(struct mlx5_eswitch_rep),
1402                                            GFP_KERNEL);
1403         if (!esw->offloads.vport_reps)
1404                 return -ENOMEM;
1405
1406         mlx5_esw_for_all_reps(esw, vport_index, rep) {
1407                 rep->vport = mlx5_eswitch_index_to_vport_num(esw, vport_index);
1408                 rep->vport_index = vport_index;
1409
1410                 for (rep_type = 0; rep_type < NUM_REP_TYPES; rep_type++)
1411                         atomic_set(&rep->rep_data[rep_type].state,
1412                                    REP_UNREGISTERED);
1413         }
1414
1415         return 0;
1416 }
1417
1418 static void __esw_offloads_unload_rep(struct mlx5_eswitch *esw,
1419                                       struct mlx5_eswitch_rep *rep, u8 rep_type)
1420 {
1421         if (atomic_cmpxchg(&rep->rep_data[rep_type].state,
1422                            REP_LOADED, REP_REGISTERED) == REP_LOADED)
1423                 esw->offloads.rep_ops[rep_type]->unload(rep);
1424 }
1425
1426 static void __unload_reps_special_vport(struct mlx5_eswitch *esw, u8 rep_type)
1427 {
1428         struct mlx5_eswitch_rep *rep;
1429
1430         if (mlx5_ecpf_vport_exists(esw->dev)) {
1431                 rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_ECPF);
1432                 __esw_offloads_unload_rep(esw, rep, rep_type);
1433         }
1434
1435         if (mlx5_core_is_ecpf_esw_manager(esw->dev)) {
1436                 rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_PF);
1437                 __esw_offloads_unload_rep(esw, rep, rep_type);
1438         }
1439
1440         rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_UPLINK);
1441         __esw_offloads_unload_rep(esw, rep, rep_type);
1442 }
1443
1444 static void __unload_reps_vf_vport(struct mlx5_eswitch *esw, int nvports,
1445                                    u8 rep_type)
1446 {
1447         struct mlx5_eswitch_rep *rep;
1448         int i;
1449
1450         mlx5_esw_for_each_vf_rep_reverse(esw, i, rep, nvports)
1451                 __esw_offloads_unload_rep(esw, rep, rep_type);
1452 }
1453
1454 static void esw_offloads_unload_vf_reps(struct mlx5_eswitch *esw, int nvports)
1455 {
1456         u8 rep_type = NUM_REP_TYPES;
1457
1458         while (rep_type-- > 0)
1459                 __unload_reps_vf_vport(esw, nvports, rep_type);
1460 }
1461
1462 static void __unload_reps_all_vport(struct mlx5_eswitch *esw, u8 rep_type)
1463 {
1464         __unload_reps_vf_vport(esw, esw->esw_funcs.num_vfs, rep_type);
1465
1466         /* Special vports must be the last to unload. */
1467         __unload_reps_special_vport(esw, rep_type);
1468 }
1469
1470 static void esw_offloads_unload_all_reps(struct mlx5_eswitch *esw)
1471 {
1472         u8 rep_type = NUM_REP_TYPES;
1473
1474         while (rep_type-- > 0)
1475                 __unload_reps_all_vport(esw, rep_type);
1476 }
1477
1478 static int __esw_offloads_load_rep(struct mlx5_eswitch *esw,
1479                                    struct mlx5_eswitch_rep *rep, u8 rep_type)
1480 {
1481         int err = 0;
1482
1483         if (atomic_cmpxchg(&rep->rep_data[rep_type].state,
1484                            REP_REGISTERED, REP_LOADED) == REP_REGISTERED) {
1485                 err = esw->offloads.rep_ops[rep_type]->load(esw->dev, rep);
1486                 if (err)
1487                         atomic_set(&rep->rep_data[rep_type].state,
1488                                    REP_REGISTERED);
1489         }
1490
1491         return err;
1492 }
1493
1494 static int __load_reps_special_vport(struct mlx5_eswitch *esw, u8 rep_type)
1495 {
1496         struct mlx5_eswitch_rep *rep;
1497         int err;
1498
1499         rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_UPLINK);
1500         err = __esw_offloads_load_rep(esw, rep, rep_type);
1501         if (err)
1502                 return err;
1503
1504         if (mlx5_core_is_ecpf_esw_manager(esw->dev)) {
1505                 rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_PF);
1506                 err = __esw_offloads_load_rep(esw, rep, rep_type);
1507                 if (err)
1508                         goto err_pf;
1509         }
1510
1511         if (mlx5_ecpf_vport_exists(esw->dev)) {
1512                 rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_ECPF);
1513                 err = __esw_offloads_load_rep(esw, rep, rep_type);
1514                 if (err)
1515                         goto err_ecpf;
1516         }
1517
1518         return 0;
1519
1520 err_ecpf:
1521         if (mlx5_core_is_ecpf_esw_manager(esw->dev)) {
1522                 rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_PF);
1523                 __esw_offloads_unload_rep(esw, rep, rep_type);
1524         }
1525
1526 err_pf:
1527         rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_UPLINK);
1528         __esw_offloads_unload_rep(esw, rep, rep_type);
1529         return err;
1530 }
1531
1532 static int __load_reps_vf_vport(struct mlx5_eswitch *esw, int nvports,
1533                                 u8 rep_type)
1534 {
1535         struct mlx5_eswitch_rep *rep;
1536         int err, i;
1537
1538         mlx5_esw_for_each_vf_rep(esw, i, rep, nvports) {
1539                 err = __esw_offloads_load_rep(esw, rep, rep_type);
1540                 if (err)
1541                         goto err_vf;
1542         }
1543
1544         return 0;
1545
1546 err_vf:
1547         __unload_reps_vf_vport(esw, --i, rep_type);
1548         return err;
1549 }
1550
1551 static int __load_reps_all_vport(struct mlx5_eswitch *esw, u8 rep_type)
1552 {
1553         int err;
1554
1555         /* Special vports must be loaded first, uplink rep creates mdev resource. */
1556         err = __load_reps_special_vport(esw, rep_type);
1557         if (err)
1558                 return err;
1559
1560         err = __load_reps_vf_vport(esw, esw->esw_funcs.num_vfs, rep_type);
1561         if (err)
1562                 goto err_vfs;
1563
1564         return 0;
1565
1566 err_vfs:
1567         __unload_reps_special_vport(esw, rep_type);
1568         return err;
1569 }
1570
1571 static int esw_offloads_load_vf_reps(struct mlx5_eswitch *esw, int nvports)
1572 {
1573         u8 rep_type = 0;
1574         int err;
1575
1576         for (rep_type = 0; rep_type < NUM_REP_TYPES; rep_type++) {
1577                 err = __load_reps_vf_vport(esw, nvports, rep_type);
1578                 if (err)
1579                         goto err_reps;
1580         }
1581
1582         return err;
1583
1584 err_reps:
1585         while (rep_type-- > 0)
1586                 __unload_reps_vf_vport(esw, nvports, rep_type);
1587         return err;
1588 }
1589
1590 static int esw_offloads_load_all_reps(struct mlx5_eswitch *esw)
1591 {
1592         u8 rep_type = 0;
1593         int err;
1594
1595         for (rep_type = 0; rep_type < NUM_REP_TYPES; rep_type++) {
1596                 err = __load_reps_all_vport(esw, rep_type);
1597                 if (err)
1598                         goto err_reps;
1599         }
1600
1601         return err;
1602
1603 err_reps:
1604         while (rep_type-- > 0)
1605                 __unload_reps_all_vport(esw, rep_type);
1606         return err;
1607 }
1608
1609 #define ESW_OFFLOADS_DEVCOM_PAIR        (0)
1610 #define ESW_OFFLOADS_DEVCOM_UNPAIR      (1)
1611
1612 static int mlx5_esw_offloads_pair(struct mlx5_eswitch *esw,
1613                                   struct mlx5_eswitch *peer_esw)
1614 {
1615         int err;
1616
1617         err = esw_add_fdb_peer_miss_rules(esw, peer_esw->dev);
1618         if (err)
1619                 return err;
1620
1621         return 0;
1622 }
1623
1624 static void mlx5_esw_offloads_unpair(struct mlx5_eswitch *esw)
1625 {
1626         mlx5e_tc_clean_fdb_peer_flows(esw);
1627         esw_del_fdb_peer_miss_rules(esw);
1628 }
1629
1630 static int mlx5_esw_offloads_devcom_event(int event,
1631                                           void *my_data,
1632                                           void *event_data)
1633 {
1634         struct mlx5_eswitch *esw = my_data;
1635         struct mlx5_eswitch *peer_esw = event_data;
1636         struct mlx5_devcom *devcom = esw->dev->priv.devcom;
1637         int err;
1638
1639         switch (event) {
1640         case ESW_OFFLOADS_DEVCOM_PAIR:
1641                 if (mlx5_eswitch_vport_match_metadata_enabled(esw) !=
1642                     mlx5_eswitch_vport_match_metadata_enabled(peer_esw))
1643                         break;
1644
1645                 err = mlx5_esw_offloads_pair(esw, peer_esw);
1646                 if (err)
1647                         goto err_out;
1648
1649                 err = mlx5_esw_offloads_pair(peer_esw, esw);
1650                 if (err)
1651                         goto err_pair;
1652
1653                 mlx5_devcom_set_paired(devcom, MLX5_DEVCOM_ESW_OFFLOADS, true);
1654                 break;
1655
1656         case ESW_OFFLOADS_DEVCOM_UNPAIR:
1657                 if (!mlx5_devcom_is_paired(devcom, MLX5_DEVCOM_ESW_OFFLOADS))
1658                         break;
1659
1660                 mlx5_devcom_set_paired(devcom, MLX5_DEVCOM_ESW_OFFLOADS, false);
1661                 mlx5_esw_offloads_unpair(peer_esw);
1662                 mlx5_esw_offloads_unpair(esw);
1663                 break;
1664         }
1665
1666         return 0;
1667
1668 err_pair:
1669         mlx5_esw_offloads_unpair(esw);
1670
1671 err_out:
1672         mlx5_core_err(esw->dev, "esw offloads devcom event failure, event %u err %d",
1673                       event, err);
1674         return err;
1675 }
1676
1677 static void esw_offloads_devcom_init(struct mlx5_eswitch *esw)
1678 {
1679         struct mlx5_devcom *devcom = esw->dev->priv.devcom;
1680
1681         INIT_LIST_HEAD(&esw->offloads.peer_flows);
1682         mutex_init(&esw->offloads.peer_mutex);
1683
1684         if (!MLX5_CAP_ESW(esw->dev, merged_eswitch))
1685                 return;
1686
1687         mlx5_devcom_register_component(devcom,
1688                                        MLX5_DEVCOM_ESW_OFFLOADS,
1689                                        mlx5_esw_offloads_devcom_event,
1690                                        esw);
1691
1692         mlx5_devcom_send_event(devcom,
1693                                MLX5_DEVCOM_ESW_OFFLOADS,
1694                                ESW_OFFLOADS_DEVCOM_PAIR, esw);
1695 }
1696
1697 static void esw_offloads_devcom_cleanup(struct mlx5_eswitch *esw)
1698 {
1699         struct mlx5_devcom *devcom = esw->dev->priv.devcom;
1700
1701         if (!MLX5_CAP_ESW(esw->dev, merged_eswitch))
1702                 return;
1703
1704         mlx5_devcom_send_event(devcom, MLX5_DEVCOM_ESW_OFFLOADS,
1705                                ESW_OFFLOADS_DEVCOM_UNPAIR, esw);
1706
1707         mlx5_devcom_unregister_component(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
1708 }
1709
1710 static int esw_vport_ingress_prio_tag_config(struct mlx5_eswitch *esw,
1711                                              struct mlx5_vport *vport)
1712 {
1713         struct mlx5_flow_act flow_act = {0};
1714         struct mlx5_flow_spec *spec;
1715         int err = 0;
1716
1717         /* For prio tag mode, there is only 1 FTEs:
1718          * 1) Untagged packets - push prio tag VLAN and modify metadata if
1719          * required, allow
1720          * Unmatched traffic is allowed by default
1721          */
1722
1723         spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
1724         if (!spec) {
1725                 err = -ENOMEM;
1726                 goto out_no_mem;
1727         }
1728
1729         /* Untagged packets - push prio tag VLAN, allow */
1730         MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.cvlan_tag);
1731         MLX5_SET(fte_match_param, spec->match_value, outer_headers.cvlan_tag, 0);
1732         spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
1733         flow_act.action = MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH |
1734                           MLX5_FLOW_CONTEXT_ACTION_ALLOW;
1735         flow_act.vlan[0].ethtype = ETH_P_8021Q;
1736         flow_act.vlan[0].vid = 0;
1737         flow_act.vlan[0].prio = 0;
1738
1739         if (vport->ingress.modify_metadata_rule) {
1740                 flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
1741                 flow_act.modify_id = vport->ingress.modify_metadata_id;
1742         }
1743
1744         vport->ingress.allow_rule =
1745                 mlx5_add_flow_rules(vport->ingress.acl, spec,
1746                                     &flow_act, NULL, 0);
1747         if (IS_ERR(vport->ingress.allow_rule)) {
1748                 err = PTR_ERR(vport->ingress.allow_rule);
1749                 esw_warn(esw->dev,
1750                          "vport[%d] configure ingress untagged allow rule, err(%d)\n",
1751                          vport->vport, err);
1752                 vport->ingress.allow_rule = NULL;
1753                 goto out;
1754         }
1755
1756 out:
1757         kvfree(spec);
1758 out_no_mem:
1759         if (err)
1760                 esw_vport_cleanup_ingress_rules(esw, vport);
1761         return err;
1762 }
1763
1764 static int esw_vport_add_ingress_acl_modify_metadata(struct mlx5_eswitch *esw,
1765                                                      struct mlx5_vport *vport)
1766 {
1767         u8 action[MLX5_UN_SZ_BYTES(set_action_in_add_action_in_auto)] = {};
1768         static const struct mlx5_flow_spec spec = {};
1769         struct mlx5_flow_act flow_act = {};
1770         int err = 0;
1771
1772         MLX5_SET(set_action_in, action, action_type, MLX5_ACTION_TYPE_SET);
1773         MLX5_SET(set_action_in, action, field, MLX5_ACTION_IN_FIELD_METADATA_REG_C_0);
1774         MLX5_SET(set_action_in, action, data,
1775                  mlx5_eswitch_get_vport_metadata_for_match(esw, vport->vport));
1776
1777         err = mlx5_modify_header_alloc(esw->dev, MLX5_FLOW_NAMESPACE_ESW_INGRESS,
1778                                        1, action, &vport->ingress.modify_metadata_id);
1779         if (err) {
1780                 esw_warn(esw->dev,
1781                          "failed to alloc modify header for vport %d ingress acl (%d)\n",
1782                          vport->vport, err);
1783                 return err;
1784         }
1785
1786         flow_act.action = MLX5_FLOW_CONTEXT_ACTION_MOD_HDR | MLX5_FLOW_CONTEXT_ACTION_ALLOW;
1787         flow_act.modify_id = vport->ingress.modify_metadata_id;
1788         vport->ingress.modify_metadata_rule = mlx5_add_flow_rules(vport->ingress.acl,
1789                                                                   &spec, &flow_act, NULL, 0);
1790         if (IS_ERR(vport->ingress.modify_metadata_rule)) {
1791                 err = PTR_ERR(vport->ingress.modify_metadata_rule);
1792                 esw_warn(esw->dev,
1793                          "failed to add setting metadata rule for vport %d ingress acl, err(%d)\n",
1794                          vport->vport, err);
1795                 vport->ingress.modify_metadata_rule = NULL;
1796                 goto out;
1797         }
1798
1799 out:
1800         if (err)
1801                 mlx5_modify_header_dealloc(esw->dev, vport->ingress.modify_metadata_id);
1802         return err;
1803 }
1804
1805 void esw_vport_del_ingress_acl_modify_metadata(struct mlx5_eswitch *esw,
1806                                                struct mlx5_vport *vport)
1807 {
1808         if (vport->ingress.modify_metadata_rule) {
1809                 mlx5_del_flow_rules(vport->ingress.modify_metadata_rule);
1810                 mlx5_modify_header_dealloc(esw->dev, vport->ingress.modify_metadata_id);
1811
1812                 vport->ingress.modify_metadata_rule = NULL;
1813         }
1814 }
1815
1816 static int esw_vport_egress_prio_tag_config(struct mlx5_eswitch *esw,
1817                                             struct mlx5_vport *vport)
1818 {
1819         struct mlx5_flow_act flow_act = {0};
1820         struct mlx5_flow_spec *spec;
1821         int err = 0;
1822
1823         if (!MLX5_CAP_GEN(esw->dev, prio_tag_required))
1824                 return 0;
1825
1826         /* For prio tag mode, there is only 1 FTEs:
1827          * 1) prio tag packets - pop the prio tag VLAN, allow
1828          * Unmatched traffic is allowed by default
1829          */
1830
1831         esw_vport_cleanup_egress_rules(esw, vport);
1832
1833         err = esw_vport_enable_egress_acl(esw, vport);
1834         if (err) {
1835                 mlx5_core_warn(esw->dev,
1836                                "failed to enable egress acl (%d) on vport[%d]\n",
1837                                err, vport->vport);
1838                 return err;
1839         }
1840
1841         esw_debug(esw->dev,
1842                   "vport[%d] configure prio tag egress rules\n", vport->vport);
1843
1844         spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
1845         if (!spec) {
1846                 err = -ENOMEM;
1847                 goto out_no_mem;
1848         }
1849
1850         /* prio tag vlan rule - pop it so VF receives untagged packets */
1851         MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.cvlan_tag);
1852         MLX5_SET_TO_ONES(fte_match_param, spec->match_value, outer_headers.cvlan_tag);
1853         MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.first_vid);
1854         MLX5_SET(fte_match_param, spec->match_value, outer_headers.first_vid, 0);
1855
1856         spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
1857         flow_act.action = MLX5_FLOW_CONTEXT_ACTION_VLAN_POP |
1858                           MLX5_FLOW_CONTEXT_ACTION_ALLOW;
1859         vport->egress.allowed_vlan =
1860                 mlx5_add_flow_rules(vport->egress.acl, spec,
1861                                     &flow_act, NULL, 0);
1862         if (IS_ERR(vport->egress.allowed_vlan)) {
1863                 err = PTR_ERR(vport->egress.allowed_vlan);
1864                 esw_warn(esw->dev,
1865                          "vport[%d] configure egress pop prio tag vlan rule failed, err(%d)\n",
1866                          vport->vport, err);
1867                 vport->egress.allowed_vlan = NULL;
1868                 goto out;
1869         }
1870
1871 out:
1872         kvfree(spec);
1873 out_no_mem:
1874         if (err)
1875                 esw_vport_cleanup_egress_rules(esw, vport);
1876         return err;
1877 }
1878
1879 static int esw_vport_ingress_common_config(struct mlx5_eswitch *esw,
1880                                            struct mlx5_vport *vport)
1881 {
1882         int err;
1883
1884         if (!mlx5_eswitch_vport_match_metadata_enabled(esw) &&
1885             !MLX5_CAP_GEN(esw->dev, prio_tag_required))
1886                 return 0;
1887
1888         esw_vport_cleanup_ingress_rules(esw, vport);
1889
1890         err = esw_vport_enable_ingress_acl(esw, vport);
1891         if (err) {
1892                 esw_warn(esw->dev,
1893                          "failed to enable ingress acl (%d) on vport[%d]\n",
1894                          err, vport->vport);
1895                 return err;
1896         }
1897
1898         esw_debug(esw->dev,
1899                   "vport[%d] configure ingress rules\n", vport->vport);
1900
1901         if (mlx5_eswitch_vport_match_metadata_enabled(esw)) {
1902                 err = esw_vport_add_ingress_acl_modify_metadata(esw, vport);
1903                 if (err)
1904                         goto out;
1905         }
1906
1907         if (MLX5_CAP_GEN(esw->dev, prio_tag_required) &&
1908             mlx5_eswitch_is_vf_vport(esw, vport->vport)) {
1909                 err = esw_vport_ingress_prio_tag_config(esw, vport);
1910                 if (err)
1911                         goto out;
1912         }
1913
1914 out:
1915         if (err)
1916                 esw_vport_disable_ingress_acl(esw, vport);
1917         return err;
1918 }
1919
1920 static bool
1921 esw_check_vport_match_metadata_supported(const struct mlx5_eswitch *esw)
1922 {
1923         if (!MLX5_CAP_ESW(esw->dev, esw_uplink_ingress_acl))
1924                 return false;
1925
1926         if (!(MLX5_CAP_ESW_FLOWTABLE(esw->dev, fdb_to_vport_reg_c_id) &
1927               MLX5_FDB_TO_VPORT_REG_C_0))
1928                 return false;
1929
1930         if (!MLX5_CAP_ESW_FLOWTABLE(esw->dev, flow_source))
1931                 return false;
1932
1933         if (mlx5_core_is_ecpf_esw_manager(esw->dev) ||
1934             mlx5_ecpf_vport_exists(esw->dev))
1935                 return false;
1936
1937         return true;
1938 }
1939
1940 static int esw_create_offloads_acl_tables(struct mlx5_eswitch *esw)
1941 {
1942         struct mlx5_vport *vport;
1943         int i, j;
1944         int err;
1945
1946         if (esw_check_vport_match_metadata_supported(esw))
1947                 esw->flags |= MLX5_ESWITCH_VPORT_MATCH_METADATA;
1948
1949         mlx5_esw_for_all_vports(esw, i, vport) {
1950                 err = esw_vport_ingress_common_config(esw, vport);
1951                 if (err)
1952                         goto err_ingress;
1953
1954                 if (mlx5_eswitch_is_vf_vport(esw, vport->vport)) {
1955                         err = esw_vport_egress_prio_tag_config(esw, vport);
1956                         if (err)
1957                                 goto err_egress;
1958                 }
1959         }
1960
1961         if (mlx5_eswitch_vport_match_metadata_enabled(esw))
1962                 esw_info(esw->dev, "Use metadata reg_c as source vport to match\n");
1963
1964         return 0;
1965
1966 err_egress:
1967         esw_vport_disable_ingress_acl(esw, vport);
1968 err_ingress:
1969         for (j = MLX5_VPORT_PF; j < i; j++) {
1970                 vport = &esw->vports[j];
1971                 esw_vport_disable_egress_acl(esw, vport);
1972                 esw_vport_disable_ingress_acl(esw, vport);
1973         }
1974
1975         return err;
1976 }
1977
1978 static void esw_destroy_offloads_acl_tables(struct mlx5_eswitch *esw)
1979 {
1980         struct mlx5_vport *vport;
1981         int i;
1982
1983         mlx5_esw_for_all_vports(esw, i, vport) {
1984                 esw_vport_disable_egress_acl(esw, vport);
1985                 esw_vport_disable_ingress_acl(esw, vport);
1986         }
1987
1988         esw->flags &= ~MLX5_ESWITCH_VPORT_MATCH_METADATA;
1989 }
1990
1991 static int esw_offloads_steering_init(struct mlx5_eswitch *esw)
1992 {
1993         int num_vfs = esw->esw_funcs.num_vfs;
1994         int total_vports;
1995         int err;
1996
1997         if (mlx5_core_is_ecpf_esw_manager(esw->dev))
1998                 total_vports = esw->total_vports;
1999         else
2000                 total_vports = num_vfs + MLX5_SPECIAL_VPORTS(esw->dev);
2001
2002         memset(&esw->fdb_table.offloads, 0, sizeof(struct offloads_fdb));
2003         mutex_init(&esw->fdb_table.offloads.fdb_prio_lock);
2004
2005         err = esw_create_offloads_acl_tables(esw);
2006         if (err)
2007                 return err;
2008
2009         err = esw_create_offloads_fdb_tables(esw, total_vports);
2010         if (err)
2011                 goto create_fdb_err;
2012
2013         err = esw_create_offloads_table(esw, total_vports);
2014         if (err)
2015                 goto create_ft_err;
2016
2017         err = esw_create_vport_rx_group(esw, total_vports);
2018         if (err)
2019                 goto create_fg_err;
2020
2021         return 0;
2022
2023 create_fg_err:
2024         esw_destroy_offloads_table(esw);
2025
2026 create_ft_err:
2027         esw_destroy_offloads_fdb_tables(esw);
2028
2029 create_fdb_err:
2030         esw_destroy_offloads_acl_tables(esw);
2031
2032         return err;
2033 }
2034
2035 static void esw_offloads_steering_cleanup(struct mlx5_eswitch *esw)
2036 {
2037         esw_destroy_vport_rx_group(esw);
2038         esw_destroy_offloads_table(esw);
2039         esw_destroy_offloads_fdb_tables(esw);
2040         esw_destroy_offloads_acl_tables(esw);
2041 }
2042
2043 static void
2044 esw_vfs_changed_event_handler(struct mlx5_eswitch *esw, const u32 *out)
2045 {
2046         bool host_pf_disabled;
2047         u16 new_num_vfs;
2048
2049         new_num_vfs = MLX5_GET(query_esw_functions_out, out,
2050                                host_params_context.host_num_of_vfs);
2051         host_pf_disabled = MLX5_GET(query_esw_functions_out, out,
2052                                     host_params_context.host_pf_disabled);
2053
2054         if (new_num_vfs == esw->esw_funcs.num_vfs || host_pf_disabled)
2055                 return;
2056
2057         /* Number of VFs can only change from "0 to x" or "x to 0". */
2058         if (esw->esw_funcs.num_vfs > 0) {
2059                 esw_offloads_unload_vf_reps(esw, esw->esw_funcs.num_vfs);
2060         } else {
2061                 int err;
2062
2063                 err = esw_offloads_load_vf_reps(esw, new_num_vfs);
2064                 if (err)
2065                         return;
2066         }
2067         esw->esw_funcs.num_vfs = new_num_vfs;
2068 }
2069
2070 static void esw_functions_changed_event_handler(struct work_struct *work)
2071 {
2072         struct mlx5_host_work *host_work;
2073         struct mlx5_eswitch *esw;
2074         const u32 *out;
2075
2076         host_work = container_of(work, struct mlx5_host_work, work);
2077         esw = host_work->esw;
2078
2079         out = mlx5_esw_query_functions(esw->dev);
2080         if (IS_ERR(out))
2081                 goto out;
2082
2083         esw_vfs_changed_event_handler(esw, out);
2084         kvfree(out);
2085 out:
2086         kfree(host_work);
2087 }
2088
2089 int mlx5_esw_funcs_changed_handler(struct notifier_block *nb, unsigned long type, void *data)
2090 {
2091         struct mlx5_esw_functions *esw_funcs;
2092         struct mlx5_host_work *host_work;
2093         struct mlx5_eswitch *esw;
2094
2095         host_work = kzalloc(sizeof(*host_work), GFP_ATOMIC);
2096         if (!host_work)
2097                 return NOTIFY_DONE;
2098
2099         esw_funcs = mlx5_nb_cof(nb, struct mlx5_esw_functions, nb);
2100         esw = container_of(esw_funcs, struct mlx5_eswitch, esw_funcs);
2101
2102         host_work->esw = esw;
2103
2104         INIT_WORK(&host_work->work, esw_functions_changed_event_handler);
2105         queue_work(esw->work_queue, &host_work->work);
2106
2107         return NOTIFY_OK;
2108 }
2109
2110 int esw_offloads_enable(struct mlx5_eswitch *esw)
2111 {
2112         int err;
2113
2114         if (MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, reformat) &&
2115             MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, decap))
2116                 esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_BASIC;
2117         else
2118                 esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_NONE;
2119
2120         err = esw_offloads_steering_init(esw);
2121         if (err)
2122                 return err;
2123
2124         err = esw_set_passing_vport_metadata(esw, true);
2125         if (err)
2126                 goto err_vport_metadata;
2127
2128         mlx5_eswitch_enable_pf_vf_vports(esw, MLX5_VPORT_UC_ADDR_CHANGE);
2129
2130         err = esw_offloads_load_all_reps(esw);
2131         if (err)
2132                 goto err_reps;
2133
2134         esw_offloads_devcom_init(esw);
2135         mutex_init(&esw->offloads.termtbl_mutex);
2136
2137         mlx5_rdma_enable_roce(esw->dev);
2138
2139         return 0;
2140
2141 err_reps:
2142         mlx5_eswitch_disable_pf_vf_vports(esw);
2143         esw_set_passing_vport_metadata(esw, false);
2144 err_vport_metadata:
2145         esw_offloads_steering_cleanup(esw);
2146         return err;
2147 }
2148
2149 static int esw_offloads_stop(struct mlx5_eswitch *esw,
2150                              struct netlink_ext_ack *extack)
2151 {
2152         int err, err1;
2153
2154         mlx5_eswitch_disable(esw);
2155         err = mlx5_eswitch_enable(esw, MLX5_ESWITCH_LEGACY);
2156         if (err) {
2157                 NL_SET_ERR_MSG_MOD(extack, "Failed setting eswitch to legacy");
2158                 err1 = mlx5_eswitch_enable(esw, MLX5_ESWITCH_OFFLOADS);
2159                 if (err1) {
2160                         NL_SET_ERR_MSG_MOD(extack,
2161                                            "Failed setting eswitch back to offloads");
2162                 }
2163         }
2164
2165         return err;
2166 }
2167
2168 void esw_offloads_disable(struct mlx5_eswitch *esw)
2169 {
2170         mlx5_rdma_disable_roce(esw->dev);
2171         esw_offloads_devcom_cleanup(esw);
2172         esw_offloads_unload_all_reps(esw);
2173         mlx5_eswitch_disable_pf_vf_vports(esw);
2174         esw_set_passing_vport_metadata(esw, false);
2175         esw_offloads_steering_cleanup(esw);
2176         esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_NONE;
2177 }
2178
2179 static int esw_mode_from_devlink(u16 mode, u16 *mlx5_mode)
2180 {
2181         switch (mode) {
2182         case DEVLINK_ESWITCH_MODE_LEGACY:
2183                 *mlx5_mode = MLX5_ESWITCH_LEGACY;
2184                 break;
2185         case DEVLINK_ESWITCH_MODE_SWITCHDEV:
2186                 *mlx5_mode = MLX5_ESWITCH_OFFLOADS;
2187                 break;
2188         default:
2189                 return -EINVAL;
2190         }
2191
2192         return 0;
2193 }
2194
2195 static int esw_mode_to_devlink(u16 mlx5_mode, u16 *mode)
2196 {
2197         switch (mlx5_mode) {
2198         case MLX5_ESWITCH_LEGACY:
2199                 *mode = DEVLINK_ESWITCH_MODE_LEGACY;
2200                 break;
2201         case MLX5_ESWITCH_OFFLOADS:
2202                 *mode = DEVLINK_ESWITCH_MODE_SWITCHDEV;
2203                 break;
2204         default:
2205                 return -EINVAL;
2206         }
2207
2208         return 0;
2209 }
2210
2211 static int esw_inline_mode_from_devlink(u8 mode, u8 *mlx5_mode)
2212 {
2213         switch (mode) {
2214         case DEVLINK_ESWITCH_INLINE_MODE_NONE:
2215                 *mlx5_mode = MLX5_INLINE_MODE_NONE;
2216                 break;
2217         case DEVLINK_ESWITCH_INLINE_MODE_LINK:
2218                 *mlx5_mode = MLX5_INLINE_MODE_L2;
2219                 break;
2220         case DEVLINK_ESWITCH_INLINE_MODE_NETWORK:
2221                 *mlx5_mode = MLX5_INLINE_MODE_IP;
2222                 break;
2223         case DEVLINK_ESWITCH_INLINE_MODE_TRANSPORT:
2224                 *mlx5_mode = MLX5_INLINE_MODE_TCP_UDP;
2225                 break;
2226         default:
2227                 return -EINVAL;
2228         }
2229
2230         return 0;
2231 }
2232
2233 static int esw_inline_mode_to_devlink(u8 mlx5_mode, u8 *mode)
2234 {
2235         switch (mlx5_mode) {
2236         case MLX5_INLINE_MODE_NONE:
2237                 *mode = DEVLINK_ESWITCH_INLINE_MODE_NONE;
2238                 break;
2239         case MLX5_INLINE_MODE_L2:
2240                 *mode = DEVLINK_ESWITCH_INLINE_MODE_LINK;
2241                 break;
2242         case MLX5_INLINE_MODE_IP:
2243                 *mode = DEVLINK_ESWITCH_INLINE_MODE_NETWORK;
2244                 break;
2245         case MLX5_INLINE_MODE_TCP_UDP:
2246                 *mode = DEVLINK_ESWITCH_INLINE_MODE_TRANSPORT;
2247                 break;
2248         default:
2249                 return -EINVAL;
2250         }
2251
2252         return 0;
2253 }
2254
2255 static int mlx5_devlink_eswitch_check(struct devlink *devlink)
2256 {
2257         struct mlx5_core_dev *dev = devlink_priv(devlink);
2258
2259         if (MLX5_CAP_GEN(dev, port_type) != MLX5_CAP_PORT_TYPE_ETH)
2260                 return -EOPNOTSUPP;
2261
2262         if(!MLX5_ESWITCH_MANAGER(dev))
2263                 return -EPERM;
2264
2265         if (dev->priv.eswitch->mode == MLX5_ESWITCH_NONE &&
2266             !mlx5_core_is_ecpf_esw_manager(dev))
2267                 return -EOPNOTSUPP;
2268
2269         return 0;
2270 }
2271
2272 int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode,
2273                                   struct netlink_ext_ack *extack)
2274 {
2275         struct mlx5_core_dev *dev = devlink_priv(devlink);
2276         u16 cur_mlx5_mode, mlx5_mode = 0;
2277         int err;
2278
2279         err = mlx5_devlink_eswitch_check(devlink);
2280         if (err)
2281                 return err;
2282
2283         cur_mlx5_mode = dev->priv.eswitch->mode;
2284
2285         if (esw_mode_from_devlink(mode, &mlx5_mode))
2286                 return -EINVAL;
2287
2288         if (cur_mlx5_mode == mlx5_mode)
2289                 return 0;
2290
2291         if (mode == DEVLINK_ESWITCH_MODE_SWITCHDEV)
2292                 return esw_offloads_start(dev->priv.eswitch, extack);
2293         else if (mode == DEVLINK_ESWITCH_MODE_LEGACY)
2294                 return esw_offloads_stop(dev->priv.eswitch, extack);
2295         else
2296                 return -EINVAL;
2297 }
2298
2299 int mlx5_devlink_eswitch_mode_get(struct devlink *devlink, u16 *mode)
2300 {
2301         struct mlx5_core_dev *dev = devlink_priv(devlink);
2302         int err;
2303
2304         err = mlx5_devlink_eswitch_check(devlink);
2305         if (err)
2306                 return err;
2307
2308         return esw_mode_to_devlink(dev->priv.eswitch->mode, mode);
2309 }
2310
2311 int mlx5_devlink_eswitch_inline_mode_set(struct devlink *devlink, u8 mode,
2312                                          struct netlink_ext_ack *extack)
2313 {
2314         struct mlx5_core_dev *dev = devlink_priv(devlink);
2315         struct mlx5_eswitch *esw = dev->priv.eswitch;
2316         int err, vport, num_vport;
2317         u8 mlx5_mode;
2318
2319         err = mlx5_devlink_eswitch_check(devlink);
2320         if (err)
2321                 return err;
2322
2323         switch (MLX5_CAP_ETH(dev, wqe_inline_mode)) {
2324         case MLX5_CAP_INLINE_MODE_NOT_REQUIRED:
2325                 if (mode == DEVLINK_ESWITCH_INLINE_MODE_NONE)
2326                         return 0;
2327                 /* fall through */
2328         case MLX5_CAP_INLINE_MODE_L2:
2329                 NL_SET_ERR_MSG_MOD(extack, "Inline mode can't be set");
2330                 return -EOPNOTSUPP;
2331         case MLX5_CAP_INLINE_MODE_VPORT_CONTEXT:
2332                 break;
2333         }
2334
2335         if (atomic64_read(&esw->offloads.num_flows) > 0) {
2336                 NL_SET_ERR_MSG_MOD(extack,
2337                                    "Can't set inline mode when flows are configured");
2338                 return -EOPNOTSUPP;
2339         }
2340
2341         err = esw_inline_mode_from_devlink(mode, &mlx5_mode);
2342         if (err)
2343                 goto out;
2344
2345         mlx5_esw_for_each_host_func_vport(esw, vport, esw->esw_funcs.num_vfs) {
2346                 err = mlx5_modify_nic_vport_min_inline(dev, vport, mlx5_mode);
2347                 if (err) {
2348                         NL_SET_ERR_MSG_MOD(extack,
2349                                            "Failed to set min inline on vport");
2350                         goto revert_inline_mode;
2351                 }
2352         }
2353
2354         esw->offloads.inline_mode = mlx5_mode;
2355         return 0;
2356
2357 revert_inline_mode:
2358         num_vport = --vport;
2359         mlx5_esw_for_each_host_func_vport_reverse(esw, vport, num_vport)
2360                 mlx5_modify_nic_vport_min_inline(dev,
2361                                                  vport,
2362                                                  esw->offloads.inline_mode);
2363 out:
2364         return err;
2365 }
2366
2367 int mlx5_devlink_eswitch_inline_mode_get(struct devlink *devlink, u8 *mode)
2368 {
2369         struct mlx5_core_dev *dev = devlink_priv(devlink);
2370         struct mlx5_eswitch *esw = dev->priv.eswitch;
2371         int err;
2372
2373         err = mlx5_devlink_eswitch_check(devlink);
2374         if (err)
2375                 return err;
2376
2377         return esw_inline_mode_to_devlink(esw->offloads.inline_mode, mode);
2378 }
2379
2380 int mlx5_eswitch_inline_mode_get(struct mlx5_eswitch *esw, u8 *mode)
2381 {
2382         u8 prev_mlx5_mode, mlx5_mode = MLX5_INLINE_MODE_L2;
2383         struct mlx5_core_dev *dev = esw->dev;
2384         int vport;
2385
2386         if (!MLX5_CAP_GEN(dev, vport_group_manager))
2387                 return -EOPNOTSUPP;
2388
2389         if (esw->mode == MLX5_ESWITCH_NONE)
2390                 return -EOPNOTSUPP;
2391
2392         switch (MLX5_CAP_ETH(dev, wqe_inline_mode)) {
2393         case MLX5_CAP_INLINE_MODE_NOT_REQUIRED:
2394                 mlx5_mode = MLX5_INLINE_MODE_NONE;
2395                 goto out;
2396         case MLX5_CAP_INLINE_MODE_L2:
2397                 mlx5_mode = MLX5_INLINE_MODE_L2;
2398                 goto out;
2399         case MLX5_CAP_INLINE_MODE_VPORT_CONTEXT:
2400                 goto query_vports;
2401         }
2402
2403 query_vports:
2404         mlx5_query_nic_vport_min_inline(dev, esw->first_host_vport, &prev_mlx5_mode);
2405         mlx5_esw_for_each_host_func_vport(esw, vport, esw->esw_funcs.num_vfs) {
2406                 mlx5_query_nic_vport_min_inline(dev, vport, &mlx5_mode);
2407                 if (prev_mlx5_mode != mlx5_mode)
2408                         return -EINVAL;
2409                 prev_mlx5_mode = mlx5_mode;
2410         }
2411
2412 out:
2413         *mode = mlx5_mode;
2414         return 0;
2415 }
2416
2417 int mlx5_devlink_eswitch_encap_mode_set(struct devlink *devlink,
2418                                         enum devlink_eswitch_encap_mode encap,
2419                                         struct netlink_ext_ack *extack)
2420 {
2421         struct mlx5_core_dev *dev = devlink_priv(devlink);
2422         struct mlx5_eswitch *esw = dev->priv.eswitch;
2423         int err;
2424
2425         err = mlx5_devlink_eswitch_check(devlink);
2426         if (err)
2427                 return err;
2428
2429         if (encap != DEVLINK_ESWITCH_ENCAP_MODE_NONE &&
2430             (!MLX5_CAP_ESW_FLOWTABLE_FDB(dev, reformat) ||
2431              !MLX5_CAP_ESW_FLOWTABLE_FDB(dev, decap)))
2432                 return -EOPNOTSUPP;
2433
2434         if (encap && encap != DEVLINK_ESWITCH_ENCAP_MODE_BASIC)
2435                 return -EOPNOTSUPP;
2436
2437         if (esw->mode == MLX5_ESWITCH_LEGACY) {
2438                 esw->offloads.encap = encap;
2439                 return 0;
2440         }
2441
2442         if (esw->offloads.encap == encap)
2443                 return 0;
2444
2445         if (atomic64_read(&esw->offloads.num_flows) > 0) {
2446                 NL_SET_ERR_MSG_MOD(extack,
2447                                    "Can't set encapsulation when flows are configured");
2448                 return -EOPNOTSUPP;
2449         }
2450
2451         esw_destroy_offloads_fdb_tables(esw);
2452
2453         esw->offloads.encap = encap;
2454
2455         err = esw_create_offloads_fdb_tables(esw, esw->nvports);
2456
2457         if (err) {
2458                 NL_SET_ERR_MSG_MOD(extack,
2459                                    "Failed re-creating fast FDB table");
2460                 esw->offloads.encap = !encap;
2461                 (void)esw_create_offloads_fdb_tables(esw, esw->nvports);
2462         }
2463
2464         return err;
2465 }
2466
2467 int mlx5_devlink_eswitch_encap_mode_get(struct devlink *devlink,
2468                                         enum devlink_eswitch_encap_mode *encap)
2469 {
2470         struct mlx5_core_dev *dev = devlink_priv(devlink);
2471         struct mlx5_eswitch *esw = dev->priv.eswitch;
2472         int err;
2473
2474         err = mlx5_devlink_eswitch_check(devlink);
2475         if (err)
2476                 return err;
2477
2478         *encap = esw->offloads.encap;
2479         return 0;
2480 }
2481
2482 void mlx5_eswitch_register_vport_reps(struct mlx5_eswitch *esw,
2483                                       const struct mlx5_eswitch_rep_ops *ops,
2484                                       u8 rep_type)
2485 {
2486         struct mlx5_eswitch_rep_data *rep_data;
2487         struct mlx5_eswitch_rep *rep;
2488         int i;
2489
2490         esw->offloads.rep_ops[rep_type] = ops;
2491         mlx5_esw_for_all_reps(esw, i, rep) {
2492                 rep_data = &rep->rep_data[rep_type];
2493                 atomic_set(&rep_data->state, REP_REGISTERED);
2494         }
2495 }
2496 EXPORT_SYMBOL(mlx5_eswitch_register_vport_reps);
2497
2498 void mlx5_eswitch_unregister_vport_reps(struct mlx5_eswitch *esw, u8 rep_type)
2499 {
2500         struct mlx5_eswitch_rep *rep;
2501         int i;
2502
2503         if (esw->mode == MLX5_ESWITCH_OFFLOADS)
2504                 __unload_reps_all_vport(esw, rep_type);
2505
2506         mlx5_esw_for_all_reps(esw, i, rep)
2507                 atomic_set(&rep->rep_data[rep_type].state, REP_UNREGISTERED);
2508 }
2509 EXPORT_SYMBOL(mlx5_eswitch_unregister_vport_reps);
2510
2511 void *mlx5_eswitch_get_uplink_priv(struct mlx5_eswitch *esw, u8 rep_type)
2512 {
2513         struct mlx5_eswitch_rep *rep;
2514
2515         rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_UPLINK);
2516         return rep->rep_data[rep_type].priv;
2517 }
2518
2519 void *mlx5_eswitch_get_proto_dev(struct mlx5_eswitch *esw,
2520                                  u16 vport,
2521                                  u8 rep_type)
2522 {
2523         struct mlx5_eswitch_rep *rep;
2524
2525         rep = mlx5_eswitch_get_rep(esw, vport);
2526
2527         if (atomic_read(&rep->rep_data[rep_type].state) == REP_LOADED &&
2528             esw->offloads.rep_ops[rep_type]->get_proto_dev)
2529                 return esw->offloads.rep_ops[rep_type]->get_proto_dev(rep);
2530         return NULL;
2531 }
2532 EXPORT_SYMBOL(mlx5_eswitch_get_proto_dev);
2533
2534 void *mlx5_eswitch_uplink_get_proto_dev(struct mlx5_eswitch *esw, u8 rep_type)
2535 {
2536         return mlx5_eswitch_get_proto_dev(esw, MLX5_VPORT_UPLINK, rep_type);
2537 }
2538 EXPORT_SYMBOL(mlx5_eswitch_uplink_get_proto_dev);
2539
2540 struct mlx5_eswitch_rep *mlx5_eswitch_vport_rep(struct mlx5_eswitch *esw,
2541                                                 u16 vport)
2542 {
2543         return mlx5_eswitch_get_rep(esw, vport);
2544 }
2545 EXPORT_SYMBOL(mlx5_eswitch_vport_rep);
2546
2547 bool mlx5_eswitch_is_vf_vport(const struct mlx5_eswitch *esw, u16 vport_num)
2548 {
2549         return vport_num >= MLX5_VPORT_FIRST_VF &&
2550                vport_num <= esw->dev->priv.sriov.max_vfs;
2551 }
2552
2553 bool mlx5_eswitch_vport_match_metadata_enabled(const struct mlx5_eswitch *esw)
2554 {
2555         return !!(esw->flags & MLX5_ESWITCH_VPORT_MATCH_METADATA);
2556 }
2557 EXPORT_SYMBOL(mlx5_eswitch_vport_match_metadata_enabled);
2558
2559 u32 mlx5_eswitch_get_vport_metadata_for_match(const struct mlx5_eswitch *esw,
2560                                               u16 vport_num)
2561 {
2562         return ((MLX5_CAP_GEN(esw->dev, vhca_id) & 0xffff) << 16) | vport_num;
2563 }
2564 EXPORT_SYMBOL(mlx5_eswitch_get_vport_metadata_for_match);