net/mlx5: E-Switch, return error if encap isn't supported
[sfrench/cifs-2.6.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/idr.h>
35 #include <linux/mlx5/driver.h>
36 #include <linux/mlx5/mlx5_ifc.h>
37 #include <linux/mlx5/vport.h>
38 #include <linux/mlx5/fs.h>
39 #include "mlx5_core.h"
40 #include "eswitch.h"
41 #include "esw/indir_table.h"
42 #include "esw/acl/ofld.h"
43 #include "rdma.h"
44 #include "en.h"
45 #include "fs_core.h"
46 #include "lib/devcom.h"
47 #include "lib/eq.h"
48 #include "lib/fs_chains.h"
49 #include "en_tc.h"
50 #include "en/mapping.h"
51 #include "devlink.h"
52
53 #define mlx5_esw_for_each_rep(esw, i, rep) \
54         xa_for_each(&((esw)->offloads.vport_reps), i, rep)
55
56 #define mlx5_esw_for_each_sf_rep(esw, i, rep) \
57         xa_for_each_marked(&((esw)->offloads.vport_reps), i, rep, MLX5_ESW_VPT_SF)
58
59 #define mlx5_esw_for_each_vf_rep(esw, index, rep)       \
60         mlx5_esw_for_each_entry_marked(&((esw)->offloads.vport_reps), index, \
61                                        rep, (esw)->esw_funcs.num_vfs, MLX5_ESW_VPT_VF)
62
63 /* There are two match-all miss flows, one for unicast dst mac and
64  * one for multicast.
65  */
66 #define MLX5_ESW_MISS_FLOWS (2)
67 #define UPLINK_REP_INDEX 0
68
69 #define MLX5_ESW_VPORT_TBL_SIZE 128
70 #define MLX5_ESW_VPORT_TBL_NUM_GROUPS  4
71
72 static const struct esw_vport_tbl_namespace mlx5_esw_vport_tbl_mirror_ns = {
73         .max_fte = MLX5_ESW_VPORT_TBL_SIZE,
74         .max_num_groups = MLX5_ESW_VPORT_TBL_NUM_GROUPS,
75         .flags = 0,
76 };
77
78 static struct mlx5_eswitch_rep *mlx5_eswitch_get_rep(struct mlx5_eswitch *esw,
79                                                      u16 vport_num)
80 {
81         return xa_load(&esw->offloads.vport_reps, vport_num);
82 }
83
84 static void
85 mlx5_eswitch_set_rule_flow_source(struct mlx5_eswitch *esw,
86                                   struct mlx5_flow_spec *spec,
87                                   struct mlx5_esw_flow_attr *attr)
88 {
89         if (!MLX5_CAP_ESW_FLOWTABLE(esw->dev, flow_source) || !attr || !attr->in_rep)
90                 return;
91
92         if (attr->int_port) {
93                 spec->flow_context.flow_source = mlx5e_tc_int_port_get_flow_source(attr->int_port);
94
95                 return;
96         }
97
98         spec->flow_context.flow_source = (attr->in_rep->vport == MLX5_VPORT_UPLINK) ?
99                                          MLX5_FLOW_CONTEXT_FLOW_SOURCE_UPLINK :
100                                          MLX5_FLOW_CONTEXT_FLOW_SOURCE_LOCAL_VPORT;
101 }
102
103 /* Actually only the upper 16 bits of reg c0 need to be cleared, but the lower 16 bits
104  * are not needed as well in the following process. So clear them all for simplicity.
105  */
106 void
107 mlx5_eswitch_clear_rule_source_port(struct mlx5_eswitch *esw, struct mlx5_flow_spec *spec)
108 {
109         if (mlx5_eswitch_vport_match_metadata_enabled(esw)) {
110                 void *misc2;
111
112                 misc2 = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters_2);
113                 MLX5_SET(fte_match_set_misc2, misc2, metadata_reg_c_0, 0);
114
115                 misc2 = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters_2);
116                 MLX5_SET(fte_match_set_misc2, misc2, metadata_reg_c_0, 0);
117
118                 if (!memchr_inv(misc2, 0, MLX5_ST_SZ_BYTES(fte_match_set_misc2)))
119                         spec->match_criteria_enable &= ~MLX5_MATCH_MISC_PARAMETERS_2;
120         }
121 }
122
123 static void
124 mlx5_eswitch_set_rule_source_port(struct mlx5_eswitch *esw,
125                                   struct mlx5_flow_spec *spec,
126                                   struct mlx5_flow_attr *attr,
127                                   struct mlx5_eswitch *src_esw,
128                                   u16 vport)
129 {
130         struct mlx5_esw_flow_attr *esw_attr = attr->esw_attr;
131         u32 metadata;
132         void *misc2;
133         void *misc;
134
135         /* Use metadata matching because vport is not represented by single
136          * VHCA in dual-port RoCE mode, and matching on source vport may fail.
137          */
138         if (mlx5_eswitch_vport_match_metadata_enabled(esw)) {
139                 if (mlx5_esw_indir_table_decap_vport(attr))
140                         vport = mlx5_esw_indir_table_decap_vport(attr);
141
142                 if (esw_attr->int_port)
143                         metadata =
144                                 mlx5e_tc_int_port_get_metadata_for_match(esw_attr->int_port);
145                 else
146                         metadata =
147                                 mlx5_eswitch_get_vport_metadata_for_match(src_esw, vport);
148
149                 misc2 = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters_2);
150                 MLX5_SET(fte_match_set_misc2, misc2, metadata_reg_c_0, metadata);
151
152                 misc2 = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters_2);
153                 MLX5_SET(fte_match_set_misc2, misc2, metadata_reg_c_0,
154                          mlx5_eswitch_get_vport_metadata_mask());
155
156                 spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS_2;
157         } else {
158                 misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters);
159                 MLX5_SET(fte_match_set_misc, misc, source_port, vport);
160
161                 if (MLX5_CAP_ESW(esw->dev, merged_eswitch))
162                         MLX5_SET(fte_match_set_misc, misc,
163                                  source_eswitch_owner_vhca_id,
164                                  MLX5_CAP_GEN(src_esw->dev, vhca_id));
165
166                 misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters);
167                 MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port);
168                 if (MLX5_CAP_ESW(esw->dev, merged_eswitch))
169                         MLX5_SET_TO_ONES(fte_match_set_misc, misc,
170                                          source_eswitch_owner_vhca_id);
171
172                 spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS;
173         }
174 }
175
176 static int
177 esw_setup_decap_indir(struct mlx5_eswitch *esw,
178                       struct mlx5_flow_attr *attr,
179                       struct mlx5_flow_spec *spec)
180 {
181         struct mlx5_flow_table *ft;
182
183         if (!(attr->flags & MLX5_ESW_ATTR_FLAG_SRC_REWRITE))
184                 return -EOPNOTSUPP;
185
186         ft = mlx5_esw_indir_table_get(esw, attr, spec,
187                                       mlx5_esw_indir_table_decap_vport(attr), true);
188         return PTR_ERR_OR_ZERO(ft);
189 }
190
191 static void
192 esw_cleanup_decap_indir(struct mlx5_eswitch *esw,
193                         struct mlx5_flow_attr *attr)
194 {
195         if (mlx5_esw_indir_table_decap_vport(attr))
196                 mlx5_esw_indir_table_put(esw, attr,
197                                          mlx5_esw_indir_table_decap_vport(attr),
198                                          true);
199 }
200
201 static int
202 esw_setup_sampler_dest(struct mlx5_flow_destination *dest,
203                        struct mlx5_flow_act *flow_act,
204                        struct mlx5_flow_attr *attr,
205                        int i)
206 {
207         flow_act->flags |= FLOW_ACT_IGNORE_FLOW_LEVEL;
208         dest[i].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_SAMPLER;
209         dest[i].sampler_id = attr->sample_attr->sampler_id;
210
211         return 0;
212 }
213
214 static int
215 esw_setup_ft_dest(struct mlx5_flow_destination *dest,
216                   struct mlx5_flow_act *flow_act,
217                   struct mlx5_eswitch *esw,
218                   struct mlx5_flow_attr *attr,
219                   struct mlx5_flow_spec *spec,
220                   int i)
221 {
222         flow_act->flags |= FLOW_ACT_IGNORE_FLOW_LEVEL;
223         dest[i].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
224         dest[i].ft = attr->dest_ft;
225
226         if (mlx5_esw_indir_table_decap_vport(attr))
227                 return esw_setup_decap_indir(esw, attr, spec);
228         return 0;
229 }
230
231 static void
232 esw_setup_slow_path_dest(struct mlx5_flow_destination *dest,
233                          struct mlx5_flow_act *flow_act,
234                          struct mlx5_fs_chains *chains,
235                          int i)
236 {
237         if (mlx5_chains_ignore_flow_level_supported(chains))
238                 flow_act->flags |= FLOW_ACT_IGNORE_FLOW_LEVEL;
239         dest[i].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
240         dest[i].ft = mlx5_chains_get_tc_end_ft(chains);
241 }
242
243 static int
244 esw_setup_chain_dest(struct mlx5_flow_destination *dest,
245                      struct mlx5_flow_act *flow_act,
246                      struct mlx5_fs_chains *chains,
247                      u32 chain, u32 prio, u32 level,
248                      int i)
249 {
250         struct mlx5_flow_table *ft;
251
252         flow_act->flags |= FLOW_ACT_IGNORE_FLOW_LEVEL;
253         ft = mlx5_chains_get_table(chains, chain, prio, level);
254         if (IS_ERR(ft))
255                 return PTR_ERR(ft);
256
257         dest[i].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
258         dest[i].ft = ft;
259         return  0;
260 }
261
262 static void esw_put_dest_tables_loop(struct mlx5_eswitch *esw, struct mlx5_flow_attr *attr,
263                                      int from, int to)
264 {
265         struct mlx5_esw_flow_attr *esw_attr = attr->esw_attr;
266         struct mlx5_fs_chains *chains = esw_chains(esw);
267         int i;
268
269         for (i = from; i < to; i++)
270                 if (esw_attr->dests[i].flags & MLX5_ESW_DEST_CHAIN_WITH_SRC_PORT_CHANGE)
271                         mlx5_chains_put_table(chains, 0, 1, 0);
272                 else if (mlx5_esw_indir_table_needed(esw, attr, esw_attr->dests[i].rep->vport,
273                                                      esw_attr->dests[i].mdev))
274                         mlx5_esw_indir_table_put(esw, attr, esw_attr->dests[i].rep->vport,
275                                                  false);
276 }
277
278 static bool
279 esw_is_chain_src_port_rewrite(struct mlx5_eswitch *esw, struct mlx5_esw_flow_attr *esw_attr)
280 {
281         int i;
282
283         for (i = esw_attr->split_count; i < esw_attr->out_count; i++)
284                 if (esw_attr->dests[i].flags & MLX5_ESW_DEST_CHAIN_WITH_SRC_PORT_CHANGE)
285                         return true;
286         return false;
287 }
288
289 static int
290 esw_setup_chain_src_port_rewrite(struct mlx5_flow_destination *dest,
291                                  struct mlx5_flow_act *flow_act,
292                                  struct mlx5_eswitch *esw,
293                                  struct mlx5_fs_chains *chains,
294                                  struct mlx5_flow_attr *attr,
295                                  int *i)
296 {
297         struct mlx5_esw_flow_attr *esw_attr = attr->esw_attr;
298         int j, err;
299
300         if (!(attr->flags & MLX5_ESW_ATTR_FLAG_SRC_REWRITE))
301                 return -EOPNOTSUPP;
302
303         for (j = esw_attr->split_count; j < esw_attr->out_count; j++, (*i)++) {
304                 err = esw_setup_chain_dest(dest, flow_act, chains, attr->dest_chain, 1, 0, *i);
305                 if (err)
306                         goto err_setup_chain;
307
308                 if (esw_attr->dests[j].pkt_reformat) {
309                         flow_act->action |= MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT;
310                         flow_act->pkt_reformat = esw_attr->dests[j].pkt_reformat;
311                 }
312         }
313         return 0;
314
315 err_setup_chain:
316         esw_put_dest_tables_loop(esw, attr, esw_attr->split_count, j);
317         return err;
318 }
319
320 static void esw_cleanup_chain_src_port_rewrite(struct mlx5_eswitch *esw,
321                                                struct mlx5_flow_attr *attr)
322 {
323         struct mlx5_esw_flow_attr *esw_attr = attr->esw_attr;
324
325         esw_put_dest_tables_loop(esw, attr, esw_attr->split_count, esw_attr->out_count);
326 }
327
328 static bool
329 esw_is_indir_table(struct mlx5_eswitch *esw, struct mlx5_flow_attr *attr)
330 {
331         struct mlx5_esw_flow_attr *esw_attr = attr->esw_attr;
332         int i;
333
334         for (i = esw_attr->split_count; i < esw_attr->out_count; i++)
335                 if (esw_attr->dests[i].rep &&
336                     mlx5_esw_indir_table_needed(esw, attr, esw_attr->dests[i].rep->vport,
337                                                 esw_attr->dests[i].mdev))
338                         return true;
339         return false;
340 }
341
342 static int
343 esw_setup_indir_table(struct mlx5_flow_destination *dest,
344                       struct mlx5_flow_act *flow_act,
345                       struct mlx5_eswitch *esw,
346                       struct mlx5_flow_attr *attr,
347                       struct mlx5_flow_spec *spec,
348                       bool ignore_flow_lvl,
349                       int *i)
350 {
351         struct mlx5_esw_flow_attr *esw_attr = attr->esw_attr;
352         int j, err;
353
354         if (!(attr->flags & MLX5_ESW_ATTR_FLAG_SRC_REWRITE))
355                 return -EOPNOTSUPP;
356
357         for (j = esw_attr->split_count; j < esw_attr->out_count; j++, (*i)++) {
358                 if (ignore_flow_lvl)
359                         flow_act->flags |= FLOW_ACT_IGNORE_FLOW_LEVEL;
360                 dest[*i].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
361
362                 dest[*i].ft = mlx5_esw_indir_table_get(esw, attr, spec,
363                                                        esw_attr->dests[j].rep->vport, false);
364                 if (IS_ERR(dest[*i].ft)) {
365                         err = PTR_ERR(dest[*i].ft);
366                         goto err_indir_tbl_get;
367                 }
368         }
369
370         if (mlx5_esw_indir_table_decap_vport(attr)) {
371                 err = esw_setup_decap_indir(esw, attr, spec);
372                 if (err)
373                         goto err_indir_tbl_get;
374         }
375
376         return 0;
377
378 err_indir_tbl_get:
379         esw_put_dest_tables_loop(esw, attr, esw_attr->split_count, j);
380         return err;
381 }
382
383 static void esw_cleanup_indir_table(struct mlx5_eswitch *esw, struct mlx5_flow_attr *attr)
384 {
385         struct mlx5_esw_flow_attr *esw_attr = attr->esw_attr;
386
387         esw_put_dest_tables_loop(esw, attr, esw_attr->split_count, esw_attr->out_count);
388         esw_cleanup_decap_indir(esw, attr);
389 }
390
391 static void
392 esw_cleanup_chain_dest(struct mlx5_fs_chains *chains, u32 chain, u32 prio, u32 level)
393 {
394         mlx5_chains_put_table(chains, chain, prio, level);
395 }
396
397 static void
398 esw_setup_vport_dest(struct mlx5_flow_destination *dest, struct mlx5_flow_act *flow_act,
399                      struct mlx5_eswitch *esw, struct mlx5_esw_flow_attr *esw_attr,
400                      int attr_idx, int dest_idx, bool pkt_reformat)
401 {
402         dest[dest_idx].type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
403         dest[dest_idx].vport.num = esw_attr->dests[attr_idx].rep->vport;
404         if (MLX5_CAP_ESW(esw->dev, merged_eswitch)) {
405                 dest[dest_idx].vport.vhca_id =
406                         MLX5_CAP_GEN(esw_attr->dests[attr_idx].mdev, vhca_id);
407                 dest[dest_idx].vport.flags |= MLX5_FLOW_DEST_VPORT_VHCA_ID;
408         }
409         if (esw_attr->dests[attr_idx].flags & MLX5_ESW_DEST_ENCAP) {
410                 if (pkt_reformat) {
411                         flow_act->action |= MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT;
412                         flow_act->pkt_reformat = esw_attr->dests[attr_idx].pkt_reformat;
413                 }
414                 dest[dest_idx].vport.flags |= MLX5_FLOW_DEST_VPORT_REFORMAT_ID;
415                 dest[dest_idx].vport.pkt_reformat = esw_attr->dests[attr_idx].pkt_reformat;
416         }
417 }
418
419 static int
420 esw_setup_vport_dests(struct mlx5_flow_destination *dest, struct mlx5_flow_act *flow_act,
421                       struct mlx5_eswitch *esw, struct mlx5_esw_flow_attr *esw_attr,
422                       int i)
423 {
424         int j;
425
426         for (j = esw_attr->split_count; j < esw_attr->out_count; j++, i++)
427                 esw_setup_vport_dest(dest, flow_act, esw, esw_attr, j, i, true);
428         return i;
429 }
430
431 static bool
432 esw_src_port_rewrite_supported(struct mlx5_eswitch *esw)
433 {
434         return MLX5_CAP_GEN(esw->dev, reg_c_preserve) &&
435                mlx5_eswitch_vport_match_metadata_enabled(esw) &&
436                MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, ignore_flow_level);
437 }
438
439 static int
440 esw_setup_dests(struct mlx5_flow_destination *dest,
441                 struct mlx5_flow_act *flow_act,
442                 struct mlx5_eswitch *esw,
443                 struct mlx5_flow_attr *attr,
444                 struct mlx5_flow_spec *spec,
445                 int *i)
446 {
447         struct mlx5_esw_flow_attr *esw_attr = attr->esw_attr;
448         struct mlx5_fs_chains *chains = esw_chains(esw);
449         int err = 0;
450
451         if (!mlx5_eswitch_termtbl_required(esw, attr, flow_act, spec) &&
452             esw_src_port_rewrite_supported(esw))
453                 attr->flags |= MLX5_ESW_ATTR_FLAG_SRC_REWRITE;
454
455         if (attr->flags & MLX5_ESW_ATTR_FLAG_SAMPLE) {
456                 esw_setup_sampler_dest(dest, flow_act, attr, *i);
457                 (*i)++;
458         } else if (attr->dest_ft) {
459                 esw_setup_ft_dest(dest, flow_act, esw, attr, spec, *i);
460                 (*i)++;
461         } else if (mlx5_esw_attr_flags_skip(attr->flags)) {
462                 esw_setup_slow_path_dest(dest, flow_act, chains, *i);
463                 (*i)++;
464         } else if (attr->dest_chain) {
465                 err = esw_setup_chain_dest(dest, flow_act, chains, attr->dest_chain,
466                                            1, 0, *i);
467                 (*i)++;
468         } else if (esw_is_indir_table(esw, attr)) {
469                 err = esw_setup_indir_table(dest, flow_act, esw, attr, spec, true, i);
470         } else if (esw_is_chain_src_port_rewrite(esw, esw_attr)) {
471                 err = esw_setup_chain_src_port_rewrite(dest, flow_act, esw, chains, attr, i);
472         } else {
473                 *i = esw_setup_vport_dests(dest, flow_act, esw, esw_attr, *i);
474         }
475
476         return err;
477 }
478
479 static void
480 esw_cleanup_dests(struct mlx5_eswitch *esw,
481                   struct mlx5_flow_attr *attr)
482 {
483         struct mlx5_esw_flow_attr *esw_attr = attr->esw_attr;
484         struct mlx5_fs_chains *chains = esw_chains(esw);
485
486         if (attr->dest_ft) {
487                 esw_cleanup_decap_indir(esw, attr);
488         } else if (!mlx5_esw_attr_flags_skip(attr->flags)) {
489                 if (attr->dest_chain)
490                         esw_cleanup_chain_dest(chains, attr->dest_chain, 1, 0);
491                 else if (esw_is_indir_table(esw, attr))
492                         esw_cleanup_indir_table(esw, attr);
493                 else if (esw_is_chain_src_port_rewrite(esw, esw_attr))
494                         esw_cleanup_chain_src_port_rewrite(esw, attr);
495         }
496 }
497
498 struct mlx5_flow_handle *
499 mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw,
500                                 struct mlx5_flow_spec *spec,
501                                 struct mlx5_flow_attr *attr)
502 {
503         struct mlx5_flow_act flow_act = { .flags = FLOW_ACT_NO_APPEND, };
504         struct mlx5_esw_flow_attr *esw_attr = attr->esw_attr;
505         struct mlx5_fs_chains *chains = esw_chains(esw);
506         bool split = !!(esw_attr->split_count);
507         struct mlx5_vport_tbl_attr fwd_attr;
508         struct mlx5_flow_destination *dest;
509         struct mlx5_flow_handle *rule;
510         struct mlx5_flow_table *fdb;
511         int i = 0;
512
513         if (esw->mode != MLX5_ESWITCH_OFFLOADS)
514                 return ERR_PTR(-EOPNOTSUPP);
515
516         dest = kcalloc(MLX5_MAX_FLOW_FWD_VPORTS + 1, sizeof(*dest), GFP_KERNEL);
517         if (!dest)
518                 return ERR_PTR(-ENOMEM);
519
520         flow_act.action = attr->action;
521         /* if per flow vlan pop/push is emulated, don't set that into the firmware */
522         if (!mlx5_eswitch_vlan_actions_supported(esw->dev, 1))
523                 flow_act.action &= ~(MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH |
524                                      MLX5_FLOW_CONTEXT_ACTION_VLAN_POP);
525         else if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH) {
526                 flow_act.vlan[0].ethtype = ntohs(esw_attr->vlan_proto[0]);
527                 flow_act.vlan[0].vid = esw_attr->vlan_vid[0];
528                 flow_act.vlan[0].prio = esw_attr->vlan_prio[0];
529                 if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH_2) {
530                         flow_act.vlan[1].ethtype = ntohs(esw_attr->vlan_proto[1]);
531                         flow_act.vlan[1].vid = esw_attr->vlan_vid[1];
532                         flow_act.vlan[1].prio = esw_attr->vlan_prio[1];
533                 }
534         }
535
536         mlx5_eswitch_set_rule_flow_source(esw, spec, esw_attr);
537
538         if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) {
539                 int err;
540
541                 err = esw_setup_dests(dest, &flow_act, esw, attr, spec, &i);
542                 if (err) {
543                         rule = ERR_PTR(err);
544                         goto err_create_goto_table;
545                 }
546         }
547
548         if (esw_attr->decap_pkt_reformat)
549                 flow_act.pkt_reformat = esw_attr->decap_pkt_reformat;
550
551         if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_COUNT) {
552                 dest[i].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
553                 dest[i].counter_id = mlx5_fc_id(attr->counter);
554                 i++;
555         }
556
557         if (attr->outer_match_level != MLX5_MATCH_NONE)
558                 spec->match_criteria_enable |= MLX5_MATCH_OUTER_HEADERS;
559         if (attr->inner_match_level != MLX5_MATCH_NONE)
560                 spec->match_criteria_enable |= MLX5_MATCH_INNER_HEADERS;
561
562         if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
563                 flow_act.modify_hdr = attr->modify_hdr;
564
565         if (split) {
566                 fwd_attr.chain = attr->chain;
567                 fwd_attr.prio = attr->prio;
568                 fwd_attr.vport = esw_attr->in_rep->vport;
569                 fwd_attr.vport_ns = &mlx5_esw_vport_tbl_mirror_ns;
570
571                 fdb = mlx5_esw_vporttbl_get(esw, &fwd_attr);
572         } else {
573                 if (attr->chain || attr->prio)
574                         fdb = mlx5_chains_get_table(chains, attr->chain,
575                                                     attr->prio, 0);
576                 else
577                         fdb = attr->ft;
578
579                 if (!(attr->flags & MLX5_ESW_ATTR_FLAG_NO_IN_PORT))
580                         mlx5_eswitch_set_rule_source_port(esw, spec, attr,
581                                                           esw_attr->in_mdev->priv.eswitch,
582                                                           esw_attr->in_rep->vport);
583         }
584         if (IS_ERR(fdb)) {
585                 rule = ERR_CAST(fdb);
586                 goto err_esw_get;
587         }
588
589         if (mlx5_eswitch_termtbl_required(esw, attr, &flow_act, spec))
590                 rule = mlx5_eswitch_add_termtbl_rule(esw, fdb, spec, esw_attr,
591                                                      &flow_act, dest, i);
592         else
593                 rule = mlx5_add_flow_rules(fdb, spec, &flow_act, dest, i);
594         if (IS_ERR(rule))
595                 goto err_add_rule;
596         else
597                 atomic64_inc(&esw->offloads.num_flows);
598
599         kfree(dest);
600         return rule;
601
602 err_add_rule:
603         if (split)
604                 mlx5_esw_vporttbl_put(esw, &fwd_attr);
605         else if (attr->chain || attr->prio)
606                 mlx5_chains_put_table(chains, attr->chain, attr->prio, 0);
607 err_esw_get:
608         esw_cleanup_dests(esw, attr);
609 err_create_goto_table:
610         kfree(dest);
611         return rule;
612 }
613
614 struct mlx5_flow_handle *
615 mlx5_eswitch_add_fwd_rule(struct mlx5_eswitch *esw,
616                           struct mlx5_flow_spec *spec,
617                           struct mlx5_flow_attr *attr)
618 {
619         struct mlx5_flow_act flow_act = { .flags = FLOW_ACT_NO_APPEND, };
620         struct mlx5_esw_flow_attr *esw_attr = attr->esw_attr;
621         struct mlx5_fs_chains *chains = esw_chains(esw);
622         struct mlx5_vport_tbl_attr fwd_attr;
623         struct mlx5_flow_destination *dest;
624         struct mlx5_flow_table *fast_fdb;
625         struct mlx5_flow_table *fwd_fdb;
626         struct mlx5_flow_handle *rule;
627         int i, err = 0;
628
629         dest = kcalloc(MLX5_MAX_FLOW_FWD_VPORTS + 1, sizeof(*dest), GFP_KERNEL);
630         if (!dest)
631                 return ERR_PTR(-ENOMEM);
632
633         fast_fdb = mlx5_chains_get_table(chains, attr->chain, attr->prio, 0);
634         if (IS_ERR(fast_fdb)) {
635                 rule = ERR_CAST(fast_fdb);
636                 goto err_get_fast;
637         }
638
639         fwd_attr.chain = attr->chain;
640         fwd_attr.prio = attr->prio;
641         fwd_attr.vport = esw_attr->in_rep->vport;
642         fwd_attr.vport_ns = &mlx5_esw_vport_tbl_mirror_ns;
643         fwd_fdb = mlx5_esw_vporttbl_get(esw, &fwd_attr);
644         if (IS_ERR(fwd_fdb)) {
645                 rule = ERR_CAST(fwd_fdb);
646                 goto err_get_fwd;
647         }
648
649         flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
650         for (i = 0; i < esw_attr->split_count; i++) {
651                 if (esw_is_indir_table(esw, attr))
652                         err = esw_setup_indir_table(dest, &flow_act, esw, attr, spec, false, &i);
653                 else if (esw_is_chain_src_port_rewrite(esw, esw_attr))
654                         err = esw_setup_chain_src_port_rewrite(dest, &flow_act, esw, chains, attr,
655                                                                &i);
656                 else
657                         esw_setup_vport_dest(dest, &flow_act, esw, esw_attr, i, i, false);
658
659                 if (err) {
660                         rule = ERR_PTR(err);
661                         goto err_chain_src_rewrite;
662                 }
663         }
664         dest[i].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
665         dest[i].ft = fwd_fdb;
666         i++;
667
668         mlx5_eswitch_set_rule_source_port(esw, spec, attr,
669                                           esw_attr->in_mdev->priv.eswitch,
670                                           esw_attr->in_rep->vport);
671
672         if (attr->outer_match_level != MLX5_MATCH_NONE)
673                 spec->match_criteria_enable |= MLX5_MATCH_OUTER_HEADERS;
674
675         flow_act.flags |= FLOW_ACT_IGNORE_FLOW_LEVEL;
676         rule = mlx5_add_flow_rules(fast_fdb, spec, &flow_act, dest, i);
677
678         if (IS_ERR(rule)) {
679                 i = esw_attr->split_count;
680                 goto err_chain_src_rewrite;
681         }
682
683         atomic64_inc(&esw->offloads.num_flows);
684
685         kfree(dest);
686         return rule;
687 err_chain_src_rewrite:
688         esw_put_dest_tables_loop(esw, attr, 0, i);
689         mlx5_esw_vporttbl_put(esw, &fwd_attr);
690 err_get_fwd:
691         mlx5_chains_put_table(chains, attr->chain, attr->prio, 0);
692 err_get_fast:
693         kfree(dest);
694         return rule;
695 }
696
697 static void
698 __mlx5_eswitch_del_rule(struct mlx5_eswitch *esw,
699                         struct mlx5_flow_handle *rule,
700                         struct mlx5_flow_attr *attr,
701                         bool fwd_rule)
702 {
703         struct mlx5_esw_flow_attr *esw_attr = attr->esw_attr;
704         struct mlx5_fs_chains *chains = esw_chains(esw);
705         bool split = (esw_attr->split_count > 0);
706         struct mlx5_vport_tbl_attr fwd_attr;
707         int i;
708
709         mlx5_del_flow_rules(rule);
710
711         if (!mlx5_esw_attr_flags_skip(attr->flags)) {
712                 /* unref the term table */
713                 for (i = 0; i < MLX5_MAX_FLOW_FWD_VPORTS; i++) {
714                         if (esw_attr->dests[i].termtbl)
715                                 mlx5_eswitch_termtbl_put(esw, esw_attr->dests[i].termtbl);
716                 }
717         }
718
719         atomic64_dec(&esw->offloads.num_flows);
720
721         if (fwd_rule || split) {
722                 fwd_attr.chain = attr->chain;
723                 fwd_attr.prio = attr->prio;
724                 fwd_attr.vport = esw_attr->in_rep->vport;
725                 fwd_attr.vport_ns = &mlx5_esw_vport_tbl_mirror_ns;
726         }
727
728         if (fwd_rule)  {
729                 mlx5_esw_vporttbl_put(esw, &fwd_attr);
730                 mlx5_chains_put_table(chains, attr->chain, attr->prio, 0);
731                 esw_put_dest_tables_loop(esw, attr, 0, esw_attr->split_count);
732         } else {
733                 if (split)
734                         mlx5_esw_vporttbl_put(esw, &fwd_attr);
735                 else if (attr->chain || attr->prio)
736                         mlx5_chains_put_table(chains, attr->chain, attr->prio, 0);
737                 esw_cleanup_dests(esw, attr);
738         }
739 }
740
741 void
742 mlx5_eswitch_del_offloaded_rule(struct mlx5_eswitch *esw,
743                                 struct mlx5_flow_handle *rule,
744                                 struct mlx5_flow_attr *attr)
745 {
746         __mlx5_eswitch_del_rule(esw, rule, attr, false);
747 }
748
749 void
750 mlx5_eswitch_del_fwd_rule(struct mlx5_eswitch *esw,
751                           struct mlx5_flow_handle *rule,
752                           struct mlx5_flow_attr *attr)
753 {
754         __mlx5_eswitch_del_rule(esw, rule, attr, true);
755 }
756
757 static int esw_set_global_vlan_pop(struct mlx5_eswitch *esw, u8 val)
758 {
759         struct mlx5_eswitch_rep *rep;
760         unsigned long i;
761         int err = 0;
762
763         esw_debug(esw->dev, "%s applying global %s policy\n", __func__, val ? "pop" : "none");
764         mlx5_esw_for_each_host_func_vport(esw, i, rep, esw->esw_funcs.num_vfs) {
765                 if (atomic_read(&rep->rep_data[REP_ETH].state) != REP_LOADED)
766                         continue;
767
768                 err = __mlx5_eswitch_set_vport_vlan(esw, rep->vport, 0, 0, val);
769                 if (err)
770                         goto out;
771         }
772
773 out:
774         return err;
775 }
776
777 static struct mlx5_eswitch_rep *
778 esw_vlan_action_get_vport(struct mlx5_esw_flow_attr *attr, bool push, bool pop)
779 {
780         struct mlx5_eswitch_rep *in_rep, *out_rep, *vport = NULL;
781
782         in_rep  = attr->in_rep;
783         out_rep = attr->dests[0].rep;
784
785         if (push)
786                 vport = in_rep;
787         else if (pop)
788                 vport = out_rep;
789         else
790                 vport = in_rep;
791
792         return vport;
793 }
794
795 static int esw_add_vlan_action_check(struct mlx5_esw_flow_attr *attr,
796                                      bool push, bool pop, bool fwd)
797 {
798         struct mlx5_eswitch_rep *in_rep, *out_rep;
799
800         if ((push || pop) && !fwd)
801                 goto out_notsupp;
802
803         in_rep  = attr->in_rep;
804         out_rep = attr->dests[0].rep;
805
806         if (push && in_rep->vport == MLX5_VPORT_UPLINK)
807                 goto out_notsupp;
808
809         if (pop && out_rep->vport == MLX5_VPORT_UPLINK)
810                 goto out_notsupp;
811
812         /* vport has vlan push configured, can't offload VF --> wire rules w.o it */
813         if (!push && !pop && fwd)
814                 if (in_rep->vlan && out_rep->vport == MLX5_VPORT_UPLINK)
815                         goto out_notsupp;
816
817         /* protects against (1) setting rules with different vlans to push and
818          * (2) setting rules w.o vlans (attr->vlan = 0) && w. vlans to push (!= 0)
819          */
820         if (push && in_rep->vlan_refcount && (in_rep->vlan != attr->vlan_vid[0]))
821                 goto out_notsupp;
822
823         return 0;
824
825 out_notsupp:
826         return -EOPNOTSUPP;
827 }
828
829 int mlx5_eswitch_add_vlan_action(struct mlx5_eswitch *esw,
830                                  struct mlx5_flow_attr *attr)
831 {
832         struct offloads_fdb *offloads = &esw->fdb_table.offloads;
833         struct mlx5_esw_flow_attr *esw_attr = attr->esw_attr;
834         struct mlx5_eswitch_rep *vport = NULL;
835         bool push, pop, fwd;
836         int err = 0;
837
838         /* nop if we're on the vlan push/pop non emulation mode */
839         if (mlx5_eswitch_vlan_actions_supported(esw->dev, 1))
840                 return 0;
841
842         push = !!(attr->action & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH);
843         pop  = !!(attr->action & MLX5_FLOW_CONTEXT_ACTION_VLAN_POP);
844         fwd  = !!((attr->action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) &&
845                    !attr->dest_chain);
846
847         mutex_lock(&esw->state_lock);
848
849         err = esw_add_vlan_action_check(esw_attr, push, pop, fwd);
850         if (err)
851                 goto unlock;
852
853         attr->flags &= ~MLX5_ESW_ATTR_FLAG_VLAN_HANDLED;
854
855         vport = esw_vlan_action_get_vport(esw_attr, push, pop);
856
857         if (!push && !pop && fwd) {
858                 /* tracks VF --> wire rules without vlan push action */
859                 if (esw_attr->dests[0].rep->vport == MLX5_VPORT_UPLINK) {
860                         vport->vlan_refcount++;
861                         attr->flags |= MLX5_ESW_ATTR_FLAG_VLAN_HANDLED;
862                 }
863
864                 goto unlock;
865         }
866
867         if (!push && !pop)
868                 goto unlock;
869
870         if (!(offloads->vlan_push_pop_refcount)) {
871                 /* it's the 1st vlan rule, apply global vlan pop policy */
872                 err = esw_set_global_vlan_pop(esw, SET_VLAN_STRIP);
873                 if (err)
874                         goto out;
875         }
876         offloads->vlan_push_pop_refcount++;
877
878         if (push) {
879                 if (vport->vlan_refcount)
880                         goto skip_set_push;
881
882                 err = __mlx5_eswitch_set_vport_vlan(esw, vport->vport, esw_attr->vlan_vid[0],
883                                                     0, SET_VLAN_INSERT | SET_VLAN_STRIP);
884                 if (err)
885                         goto out;
886                 vport->vlan = esw_attr->vlan_vid[0];
887 skip_set_push:
888                 vport->vlan_refcount++;
889         }
890 out:
891         if (!err)
892                 attr->flags |= MLX5_ESW_ATTR_FLAG_VLAN_HANDLED;
893 unlock:
894         mutex_unlock(&esw->state_lock);
895         return err;
896 }
897
898 int mlx5_eswitch_del_vlan_action(struct mlx5_eswitch *esw,
899                                  struct mlx5_flow_attr *attr)
900 {
901         struct offloads_fdb *offloads = &esw->fdb_table.offloads;
902         struct mlx5_esw_flow_attr *esw_attr = attr->esw_attr;
903         struct mlx5_eswitch_rep *vport = NULL;
904         bool push, pop, fwd;
905         int err = 0;
906
907         /* nop if we're on the vlan push/pop non emulation mode */
908         if (mlx5_eswitch_vlan_actions_supported(esw->dev, 1))
909                 return 0;
910
911         if (!(attr->flags & MLX5_ESW_ATTR_FLAG_VLAN_HANDLED))
912                 return 0;
913
914         push = !!(attr->action & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH);
915         pop  = !!(attr->action & MLX5_FLOW_CONTEXT_ACTION_VLAN_POP);
916         fwd  = !!(attr->action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST);
917
918         mutex_lock(&esw->state_lock);
919
920         vport = esw_vlan_action_get_vport(esw_attr, push, pop);
921
922         if (!push && !pop && fwd) {
923                 /* tracks VF --> wire rules without vlan push action */
924                 if (esw_attr->dests[0].rep->vport == MLX5_VPORT_UPLINK)
925                         vport->vlan_refcount--;
926
927                 goto out;
928         }
929
930         if (push) {
931                 vport->vlan_refcount--;
932                 if (vport->vlan_refcount)
933                         goto skip_unset_push;
934
935                 vport->vlan = 0;
936                 err = __mlx5_eswitch_set_vport_vlan(esw, vport->vport,
937                                                     0, 0, SET_VLAN_STRIP);
938                 if (err)
939                         goto out;
940         }
941
942 skip_unset_push:
943         offloads->vlan_push_pop_refcount--;
944         if (offloads->vlan_push_pop_refcount)
945                 goto out;
946
947         /* no more vlan rules, stop global vlan pop policy */
948         err = esw_set_global_vlan_pop(esw, 0);
949
950 out:
951         mutex_unlock(&esw->state_lock);
952         return err;
953 }
954
955 struct mlx5_flow_handle *
956 mlx5_eswitch_add_send_to_vport_rule(struct mlx5_eswitch *on_esw,
957                                     struct mlx5_eswitch *from_esw,
958                                     struct mlx5_eswitch_rep *rep,
959                                     u32 sqn)
960 {
961         struct mlx5_flow_act flow_act = {0};
962         struct mlx5_flow_destination dest = {};
963         struct mlx5_flow_handle *flow_rule;
964         struct mlx5_flow_spec *spec;
965         void *misc;
966
967         spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
968         if (!spec) {
969                 flow_rule = ERR_PTR(-ENOMEM);
970                 goto out;
971         }
972
973         misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters);
974         MLX5_SET(fte_match_set_misc, misc, source_sqn, sqn);
975         /* source vport is the esw manager */
976         MLX5_SET(fte_match_set_misc, misc, source_port, from_esw->manager_vport);
977         if (MLX5_CAP_ESW(on_esw->dev, merged_eswitch))
978                 MLX5_SET(fte_match_set_misc, misc, source_eswitch_owner_vhca_id,
979                          MLX5_CAP_GEN(from_esw->dev, vhca_id));
980
981         misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters);
982         MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_sqn);
983         MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port);
984         if (MLX5_CAP_ESW(on_esw->dev, merged_eswitch))
985                 MLX5_SET_TO_ONES(fte_match_set_misc, misc,
986                                  source_eswitch_owner_vhca_id);
987
988         spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS;
989         dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
990         dest.vport.num = rep->vport;
991         dest.vport.vhca_id = MLX5_CAP_GEN(rep->esw->dev, vhca_id);
992         dest.vport.flags |= MLX5_FLOW_DEST_VPORT_VHCA_ID;
993         flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
994
995         if (rep->vport == MLX5_VPORT_UPLINK)
996                 spec->flow_context.flow_source = MLX5_FLOW_CONTEXT_FLOW_SOURCE_LOCAL_VPORT;
997
998         flow_rule = mlx5_add_flow_rules(on_esw->fdb_table.offloads.slow_fdb,
999                                         spec, &flow_act, &dest, 1);
1000         if (IS_ERR(flow_rule))
1001                 esw_warn(on_esw->dev, "FDB: Failed to add send to vport rule err %ld\n",
1002                          PTR_ERR(flow_rule));
1003 out:
1004         kvfree(spec);
1005         return flow_rule;
1006 }
1007 EXPORT_SYMBOL(mlx5_eswitch_add_send_to_vport_rule);
1008
1009 void mlx5_eswitch_del_send_to_vport_rule(struct mlx5_flow_handle *rule)
1010 {
1011         mlx5_del_flow_rules(rule);
1012 }
1013
1014 static void mlx5_eswitch_del_send_to_vport_meta_rules(struct mlx5_eswitch *esw)
1015 {
1016         struct mlx5_flow_handle **flows = esw->fdb_table.offloads.send_to_vport_meta_rules;
1017         int i = 0, num_vfs = esw->esw_funcs.num_vfs;
1018
1019         if (!num_vfs || !flows)
1020                 return;
1021
1022         for (i = 0; i < num_vfs; i++)
1023                 mlx5_del_flow_rules(flows[i]);
1024
1025         kvfree(flows);
1026 }
1027
1028 static int
1029 mlx5_eswitch_add_send_to_vport_meta_rules(struct mlx5_eswitch *esw)
1030 {
1031         struct mlx5_flow_destination dest = {};
1032         struct mlx5_flow_act flow_act = {0};
1033         int num_vfs, rule_idx = 0, err = 0;
1034         struct mlx5_flow_handle *flow_rule;
1035         struct mlx5_flow_handle **flows;
1036         struct mlx5_flow_spec *spec;
1037         struct mlx5_vport *vport;
1038         unsigned long i;
1039         u16 vport_num;
1040
1041         num_vfs = esw->esw_funcs.num_vfs;
1042         flows = kvcalloc(num_vfs, sizeof(*flows), GFP_KERNEL);
1043         if (!flows)
1044                 return -ENOMEM;
1045
1046         spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
1047         if (!spec) {
1048                 err = -ENOMEM;
1049                 goto alloc_err;
1050         }
1051
1052         MLX5_SET(fte_match_param, spec->match_criteria,
1053                  misc_parameters_2.metadata_reg_c_0, mlx5_eswitch_get_vport_metadata_mask());
1054         MLX5_SET(fte_match_param, spec->match_criteria,
1055                  misc_parameters_2.metadata_reg_c_1, ESW_TUN_MASK);
1056         MLX5_SET(fte_match_param, spec->match_value, misc_parameters_2.metadata_reg_c_1,
1057                  ESW_TUN_SLOW_TABLE_GOTO_VPORT_MARK);
1058
1059         spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS_2;
1060         dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
1061         flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
1062
1063         mlx5_esw_for_each_vf_vport(esw, i, vport, num_vfs) {
1064                 vport_num = vport->vport;
1065                 MLX5_SET(fte_match_param, spec->match_value, misc_parameters_2.metadata_reg_c_0,
1066                          mlx5_eswitch_get_vport_metadata_for_match(esw, vport_num));
1067                 dest.vport.num = vport_num;
1068
1069                 flow_rule = mlx5_add_flow_rules(esw->fdb_table.offloads.slow_fdb,
1070                                                 spec, &flow_act, &dest, 1);
1071                 if (IS_ERR(flow_rule)) {
1072                         err = PTR_ERR(flow_rule);
1073                         esw_warn(esw->dev, "FDB: Failed to add send to vport meta rule idx %d, err %ld\n",
1074                                  rule_idx, PTR_ERR(flow_rule));
1075                         goto rule_err;
1076                 }
1077                 flows[rule_idx++] = flow_rule;
1078         }
1079
1080         esw->fdb_table.offloads.send_to_vport_meta_rules = flows;
1081         kvfree(spec);
1082         return 0;
1083
1084 rule_err:
1085         while (--rule_idx >= 0)
1086                 mlx5_del_flow_rules(flows[rule_idx]);
1087         kvfree(spec);
1088 alloc_err:
1089         kvfree(flows);
1090         return err;
1091 }
1092
1093 static bool mlx5_eswitch_reg_c1_loopback_supported(struct mlx5_eswitch *esw)
1094 {
1095         return MLX5_CAP_ESW_FLOWTABLE(esw->dev, fdb_to_vport_reg_c_id) &
1096                MLX5_FDB_TO_VPORT_REG_C_1;
1097 }
1098
1099 static int esw_set_passing_vport_metadata(struct mlx5_eswitch *esw, bool enable)
1100 {
1101         u32 out[MLX5_ST_SZ_DW(query_esw_vport_context_out)] = {};
1102         u32 min[MLX5_ST_SZ_DW(modify_esw_vport_context_in)] = {};
1103         u32 in[MLX5_ST_SZ_DW(query_esw_vport_context_in)] = {};
1104         u8 curr, wanted;
1105         int err;
1106
1107         if (!mlx5_eswitch_reg_c1_loopback_supported(esw) &&
1108             !mlx5_eswitch_vport_match_metadata_enabled(esw))
1109                 return 0;
1110
1111         MLX5_SET(query_esw_vport_context_in, in, opcode,
1112                  MLX5_CMD_OP_QUERY_ESW_VPORT_CONTEXT);
1113         err = mlx5_cmd_exec_inout(esw->dev, query_esw_vport_context, in, out);
1114         if (err)
1115                 return err;
1116
1117         curr = MLX5_GET(query_esw_vport_context_out, out,
1118                         esw_vport_context.fdb_to_vport_reg_c_id);
1119         wanted = MLX5_FDB_TO_VPORT_REG_C_0;
1120         if (mlx5_eswitch_reg_c1_loopback_supported(esw))
1121                 wanted |= MLX5_FDB_TO_VPORT_REG_C_1;
1122
1123         if (enable)
1124                 curr |= wanted;
1125         else
1126                 curr &= ~wanted;
1127
1128         MLX5_SET(modify_esw_vport_context_in, min,
1129                  esw_vport_context.fdb_to_vport_reg_c_id, curr);
1130         MLX5_SET(modify_esw_vport_context_in, min,
1131                  field_select.fdb_to_vport_reg_c_id, 1);
1132
1133         err = mlx5_eswitch_modify_esw_vport_context(esw->dev, 0, false, min);
1134         if (!err) {
1135                 if (enable && (curr & MLX5_FDB_TO_VPORT_REG_C_1))
1136                         esw->flags |= MLX5_ESWITCH_REG_C1_LOOPBACK_ENABLED;
1137                 else
1138                         esw->flags &= ~MLX5_ESWITCH_REG_C1_LOOPBACK_ENABLED;
1139         }
1140
1141         return err;
1142 }
1143
1144 static void peer_miss_rules_setup(struct mlx5_eswitch *esw,
1145                                   struct mlx5_core_dev *peer_dev,
1146                                   struct mlx5_flow_spec *spec,
1147                                   struct mlx5_flow_destination *dest)
1148 {
1149         void *misc;
1150
1151         if (mlx5_eswitch_vport_match_metadata_enabled(esw)) {
1152                 misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
1153                                     misc_parameters_2);
1154                 MLX5_SET(fte_match_set_misc2, misc, metadata_reg_c_0,
1155                          mlx5_eswitch_get_vport_metadata_mask());
1156
1157                 spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS_2;
1158         } else {
1159                 misc = MLX5_ADDR_OF(fte_match_param, spec->match_value,
1160                                     misc_parameters);
1161
1162                 MLX5_SET(fte_match_set_misc, misc, source_eswitch_owner_vhca_id,
1163                          MLX5_CAP_GEN(peer_dev, vhca_id));
1164
1165                 spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS;
1166
1167                 misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
1168                                     misc_parameters);
1169                 MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port);
1170                 MLX5_SET_TO_ONES(fte_match_set_misc, misc,
1171                                  source_eswitch_owner_vhca_id);
1172         }
1173
1174         dest->type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
1175         dest->vport.num = peer_dev->priv.eswitch->manager_vport;
1176         dest->vport.vhca_id = MLX5_CAP_GEN(peer_dev, vhca_id);
1177         dest->vport.flags |= MLX5_FLOW_DEST_VPORT_VHCA_ID;
1178 }
1179
1180 static void esw_set_peer_miss_rule_source_port(struct mlx5_eswitch *esw,
1181                                                struct mlx5_eswitch *peer_esw,
1182                                                struct mlx5_flow_spec *spec,
1183                                                u16 vport)
1184 {
1185         void *misc;
1186
1187         if (mlx5_eswitch_vport_match_metadata_enabled(esw)) {
1188                 misc = MLX5_ADDR_OF(fte_match_param, spec->match_value,
1189                                     misc_parameters_2);
1190                 MLX5_SET(fte_match_set_misc2, misc, metadata_reg_c_0,
1191                          mlx5_eswitch_get_vport_metadata_for_match(peer_esw,
1192                                                                    vport));
1193         } else {
1194                 misc = MLX5_ADDR_OF(fte_match_param, spec->match_value,
1195                                     misc_parameters);
1196                 MLX5_SET(fte_match_set_misc, misc, source_port, vport);
1197         }
1198 }
1199
1200 static int esw_add_fdb_peer_miss_rules(struct mlx5_eswitch *esw,
1201                                        struct mlx5_core_dev *peer_dev)
1202 {
1203         struct mlx5_flow_destination dest = {};
1204         struct mlx5_flow_act flow_act = {0};
1205         struct mlx5_flow_handle **flows;
1206         /* total vports is the same for both e-switches */
1207         int nvports = esw->total_vports;
1208         struct mlx5_flow_handle *flow;
1209         struct mlx5_flow_spec *spec;
1210         struct mlx5_vport *vport;
1211         unsigned long i;
1212         void *misc;
1213         int err;
1214
1215         spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
1216         if (!spec)
1217                 return -ENOMEM;
1218
1219         peer_miss_rules_setup(esw, peer_dev, spec, &dest);
1220
1221         flows = kvcalloc(nvports, sizeof(*flows), GFP_KERNEL);
1222         if (!flows) {
1223                 err = -ENOMEM;
1224                 goto alloc_flows_err;
1225         }
1226
1227         flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
1228         misc = MLX5_ADDR_OF(fte_match_param, spec->match_value,
1229                             misc_parameters);
1230
1231         if (mlx5_core_is_ecpf_esw_manager(esw->dev)) {
1232                 vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_PF);
1233                 esw_set_peer_miss_rule_source_port(esw, peer_dev->priv.eswitch,
1234                                                    spec, MLX5_VPORT_PF);
1235
1236                 flow = mlx5_add_flow_rules(esw->fdb_table.offloads.slow_fdb,
1237                                            spec, &flow_act, &dest, 1);
1238                 if (IS_ERR(flow)) {
1239                         err = PTR_ERR(flow);
1240                         goto add_pf_flow_err;
1241                 }
1242                 flows[vport->index] = flow;
1243         }
1244
1245         if (mlx5_ecpf_vport_exists(esw->dev)) {
1246                 vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_ECPF);
1247                 MLX5_SET(fte_match_set_misc, misc, source_port, MLX5_VPORT_ECPF);
1248                 flow = mlx5_add_flow_rules(esw->fdb_table.offloads.slow_fdb,
1249                                            spec, &flow_act, &dest, 1);
1250                 if (IS_ERR(flow)) {
1251                         err = PTR_ERR(flow);
1252                         goto add_ecpf_flow_err;
1253                 }
1254                 flows[vport->index] = flow;
1255         }
1256
1257         mlx5_esw_for_each_vf_vport(esw, i, vport, mlx5_core_max_vfs(esw->dev)) {
1258                 esw_set_peer_miss_rule_source_port(esw,
1259                                                    peer_dev->priv.eswitch,
1260                                                    spec, vport->vport);
1261
1262                 flow = mlx5_add_flow_rules(esw->fdb_table.offloads.slow_fdb,
1263                                            spec, &flow_act, &dest, 1);
1264                 if (IS_ERR(flow)) {
1265                         err = PTR_ERR(flow);
1266                         goto add_vf_flow_err;
1267                 }
1268                 flows[vport->index] = flow;
1269         }
1270
1271         esw->fdb_table.offloads.peer_miss_rules = flows;
1272
1273         kvfree(spec);
1274         return 0;
1275
1276 add_vf_flow_err:
1277         mlx5_esw_for_each_vf_vport(esw, i, vport, mlx5_core_max_vfs(esw->dev)) {
1278                 if (!flows[vport->index])
1279                         continue;
1280                 mlx5_del_flow_rules(flows[vport->index]);
1281         }
1282         if (mlx5_ecpf_vport_exists(esw->dev)) {
1283                 vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_ECPF);
1284                 mlx5_del_flow_rules(flows[vport->index]);
1285         }
1286 add_ecpf_flow_err:
1287         if (mlx5_core_is_ecpf_esw_manager(esw->dev)) {
1288                 vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_PF);
1289                 mlx5_del_flow_rules(flows[vport->index]);
1290         }
1291 add_pf_flow_err:
1292         esw_warn(esw->dev, "FDB: Failed to add peer miss flow rule err %d\n", err);
1293         kvfree(flows);
1294 alloc_flows_err:
1295         kvfree(spec);
1296         return err;
1297 }
1298
1299 static void esw_del_fdb_peer_miss_rules(struct mlx5_eswitch *esw)
1300 {
1301         struct mlx5_flow_handle **flows;
1302         struct mlx5_vport *vport;
1303         unsigned long i;
1304
1305         flows = esw->fdb_table.offloads.peer_miss_rules;
1306
1307         mlx5_esw_for_each_vf_vport(esw, i, vport, mlx5_core_max_vfs(esw->dev))
1308                 mlx5_del_flow_rules(flows[vport->index]);
1309
1310         if (mlx5_ecpf_vport_exists(esw->dev)) {
1311                 vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_ECPF);
1312                 mlx5_del_flow_rules(flows[vport->index]);
1313         }
1314
1315         if (mlx5_core_is_ecpf_esw_manager(esw->dev)) {
1316                 vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_PF);
1317                 mlx5_del_flow_rules(flows[vport->index]);
1318         }
1319         kvfree(flows);
1320 }
1321
1322 static int esw_add_fdb_miss_rule(struct mlx5_eswitch *esw)
1323 {
1324         struct mlx5_flow_act flow_act = {0};
1325         struct mlx5_flow_destination dest = {};
1326         struct mlx5_flow_handle *flow_rule = NULL;
1327         struct mlx5_flow_spec *spec;
1328         void *headers_c;
1329         void *headers_v;
1330         int err = 0;
1331         u8 *dmac_c;
1332         u8 *dmac_v;
1333
1334         spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
1335         if (!spec) {
1336                 err = -ENOMEM;
1337                 goto out;
1338         }
1339
1340         spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
1341         headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
1342                                  outer_headers);
1343         dmac_c = MLX5_ADDR_OF(fte_match_param, headers_c,
1344                               outer_headers.dmac_47_16);
1345         dmac_c[0] = 0x01;
1346
1347         dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
1348         dest.vport.num = esw->manager_vport;
1349         flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
1350
1351         flow_rule = mlx5_add_flow_rules(esw->fdb_table.offloads.slow_fdb,
1352                                         spec, &flow_act, &dest, 1);
1353         if (IS_ERR(flow_rule)) {
1354                 err = PTR_ERR(flow_rule);
1355                 esw_warn(esw->dev,  "FDB: Failed to add unicast miss flow rule err %d\n", err);
1356                 goto out;
1357         }
1358
1359         esw->fdb_table.offloads.miss_rule_uni = flow_rule;
1360
1361         headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value,
1362                                  outer_headers);
1363         dmac_v = MLX5_ADDR_OF(fte_match_param, headers_v,
1364                               outer_headers.dmac_47_16);
1365         dmac_v[0] = 0x01;
1366         flow_rule = mlx5_add_flow_rules(esw->fdb_table.offloads.slow_fdb,
1367                                         spec, &flow_act, &dest, 1);
1368         if (IS_ERR(flow_rule)) {
1369                 err = PTR_ERR(flow_rule);
1370                 esw_warn(esw->dev, "FDB: Failed to add multicast miss flow rule err %d\n", err);
1371                 mlx5_del_flow_rules(esw->fdb_table.offloads.miss_rule_uni);
1372                 goto out;
1373         }
1374
1375         esw->fdb_table.offloads.miss_rule_multi = flow_rule;
1376
1377 out:
1378         kvfree(spec);
1379         return err;
1380 }
1381
1382 struct mlx5_flow_handle *
1383 esw_add_restore_rule(struct mlx5_eswitch *esw, u32 tag)
1384 {
1385         struct mlx5_flow_act flow_act = { .flags = FLOW_ACT_NO_APPEND, };
1386         struct mlx5_flow_table *ft = esw->offloads.ft_offloads_restore;
1387         struct mlx5_flow_context *flow_context;
1388         struct mlx5_flow_handle *flow_rule;
1389         struct mlx5_flow_destination dest;
1390         struct mlx5_flow_spec *spec;
1391         void *misc;
1392
1393         if (!mlx5_eswitch_reg_c1_loopback_supported(esw))
1394                 return ERR_PTR(-EOPNOTSUPP);
1395
1396         spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
1397         if (!spec)
1398                 return ERR_PTR(-ENOMEM);
1399
1400         misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
1401                             misc_parameters_2);
1402         MLX5_SET(fte_match_set_misc2, misc, metadata_reg_c_0,
1403                  ESW_REG_C0_USER_DATA_METADATA_MASK);
1404         misc = MLX5_ADDR_OF(fte_match_param, spec->match_value,
1405                             misc_parameters_2);
1406         MLX5_SET(fte_match_set_misc2, misc, metadata_reg_c_0, tag);
1407         spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS_2;
1408         flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
1409                           MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
1410         flow_act.modify_hdr = esw->offloads.restore_copy_hdr_id;
1411
1412         flow_context = &spec->flow_context;
1413         flow_context->flags |= FLOW_CONTEXT_HAS_TAG;
1414         flow_context->flow_tag = tag;
1415         dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
1416         dest.ft = esw->offloads.ft_offloads;
1417
1418         flow_rule = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
1419         kvfree(spec);
1420
1421         if (IS_ERR(flow_rule))
1422                 esw_warn(esw->dev,
1423                          "Failed to create restore rule for tag: %d, err(%d)\n",
1424                          tag, (int)PTR_ERR(flow_rule));
1425
1426         return flow_rule;
1427 }
1428
1429 #define MAX_PF_SQ 256
1430 #define MAX_SQ_NVPORTS 32
1431
1432 static void esw_set_flow_group_source_port(struct mlx5_eswitch *esw,
1433                                            u32 *flow_group_in)
1434 {
1435         void *match_criteria = MLX5_ADDR_OF(create_flow_group_in,
1436                                             flow_group_in,
1437                                             match_criteria);
1438
1439         if (mlx5_eswitch_vport_match_metadata_enabled(esw)) {
1440                 MLX5_SET(create_flow_group_in, flow_group_in,
1441                          match_criteria_enable,
1442                          MLX5_MATCH_MISC_PARAMETERS_2);
1443
1444                 MLX5_SET(fte_match_param, match_criteria,
1445                          misc_parameters_2.metadata_reg_c_0,
1446                          mlx5_eswitch_get_vport_metadata_mask());
1447         } else {
1448                 MLX5_SET(create_flow_group_in, flow_group_in,
1449                          match_criteria_enable,
1450                          MLX5_MATCH_MISC_PARAMETERS);
1451
1452                 MLX5_SET_TO_ONES(fte_match_param, match_criteria,
1453                                  misc_parameters.source_port);
1454         }
1455 }
1456
1457 #if IS_ENABLED(CONFIG_MLX5_CLS_ACT)
1458 static void esw_vport_tbl_put(struct mlx5_eswitch *esw)
1459 {
1460         struct mlx5_vport_tbl_attr attr;
1461         struct mlx5_vport *vport;
1462         unsigned long i;
1463
1464         attr.chain = 0;
1465         attr.prio = 1;
1466         mlx5_esw_for_each_vport(esw, i, vport) {
1467                 attr.vport = vport->vport;
1468                 attr.vport_ns = &mlx5_esw_vport_tbl_mirror_ns;
1469                 mlx5_esw_vporttbl_put(esw, &attr);
1470         }
1471 }
1472
1473 static int esw_vport_tbl_get(struct mlx5_eswitch *esw)
1474 {
1475         struct mlx5_vport_tbl_attr attr;
1476         struct mlx5_flow_table *fdb;
1477         struct mlx5_vport *vport;
1478         unsigned long i;
1479
1480         attr.chain = 0;
1481         attr.prio = 1;
1482         mlx5_esw_for_each_vport(esw, i, vport) {
1483                 attr.vport = vport->vport;
1484                 attr.vport_ns = &mlx5_esw_vport_tbl_mirror_ns;
1485                 fdb = mlx5_esw_vporttbl_get(esw, &attr);
1486                 if (IS_ERR(fdb))
1487                         goto out;
1488         }
1489         return 0;
1490
1491 out:
1492         esw_vport_tbl_put(esw);
1493         return PTR_ERR(fdb);
1494 }
1495
1496 #define fdb_modify_header_fwd_to_table_supported(esw) \
1497         (MLX5_CAP_ESW_FLOWTABLE((esw)->dev, fdb_modify_header_fwd_to_table))
1498 static void esw_init_chains_offload_flags(struct mlx5_eswitch *esw, u32 *flags)
1499 {
1500         struct mlx5_core_dev *dev = esw->dev;
1501
1502         if (MLX5_CAP_ESW_FLOWTABLE_FDB(dev, ignore_flow_level))
1503                 *flags |= MLX5_CHAINS_IGNORE_FLOW_LEVEL_SUPPORTED;
1504
1505         if (!MLX5_CAP_ESW_FLOWTABLE(dev, multi_fdb_encap) &&
1506             esw->offloads.encap != DEVLINK_ESWITCH_ENCAP_MODE_NONE) {
1507                 *flags &= ~MLX5_CHAINS_AND_PRIOS_SUPPORTED;
1508                 esw_warn(dev, "Tc chains and priorities offload aren't supported, update firmware if needed\n");
1509         } else if (!mlx5_eswitch_reg_c1_loopback_enabled(esw)) {
1510                 *flags &= ~MLX5_CHAINS_AND_PRIOS_SUPPORTED;
1511                 esw_warn(dev, "Tc chains and priorities offload aren't supported\n");
1512         } else if (!fdb_modify_header_fwd_to_table_supported(esw)) {
1513                 /* Disabled when ttl workaround is needed, e.g
1514                  * when ESWITCH_IPV4_TTL_MODIFY_ENABLE = true in mlxconfig
1515                  */
1516                 esw_warn(dev,
1517                          "Tc chains and priorities offload aren't supported, check firmware version, or mlxconfig settings\n");
1518                 *flags &= ~MLX5_CHAINS_AND_PRIOS_SUPPORTED;
1519         } else {
1520                 *flags |= MLX5_CHAINS_AND_PRIOS_SUPPORTED;
1521                 esw_info(dev, "Supported tc chains and prios offload\n");
1522         }
1523
1524         if (esw->offloads.encap != DEVLINK_ESWITCH_ENCAP_MODE_NONE)
1525                 *flags |= MLX5_CHAINS_FT_TUNNEL_SUPPORTED;
1526 }
1527
1528 static int
1529 esw_chains_create(struct mlx5_eswitch *esw, struct mlx5_flow_table *miss_fdb)
1530 {
1531         struct mlx5_core_dev *dev = esw->dev;
1532         struct mlx5_flow_table *nf_ft, *ft;
1533         struct mlx5_chains_attr attr = {};
1534         struct mlx5_fs_chains *chains;
1535         u32 fdb_max;
1536         int err;
1537
1538         fdb_max = 1 << MLX5_CAP_ESW_FLOWTABLE_FDB(dev, log_max_ft_size);
1539
1540         esw_init_chains_offload_flags(esw, &attr.flags);
1541         attr.ns = MLX5_FLOW_NAMESPACE_FDB;
1542         attr.max_ft_sz = fdb_max;
1543         attr.max_grp_num = esw->params.large_group_num;
1544         attr.default_ft = miss_fdb;
1545         attr.mapping = esw->offloads.reg_c0_obj_pool;
1546
1547         chains = mlx5_chains_create(dev, &attr);
1548         if (IS_ERR(chains)) {
1549                 err = PTR_ERR(chains);
1550                 esw_warn(dev, "Failed to create fdb chains err(%d)\n", err);
1551                 return err;
1552         }
1553
1554         esw->fdb_table.offloads.esw_chains_priv = chains;
1555
1556         /* Create tc_end_ft which is the always created ft chain */
1557         nf_ft = mlx5_chains_get_table(chains, mlx5_chains_get_nf_ft_chain(chains),
1558                                       1, 0);
1559         if (IS_ERR(nf_ft)) {
1560                 err = PTR_ERR(nf_ft);
1561                 goto nf_ft_err;
1562         }
1563
1564         /* Always open the root for fast path */
1565         ft = mlx5_chains_get_table(chains, 0, 1, 0);
1566         if (IS_ERR(ft)) {
1567                 err = PTR_ERR(ft);
1568                 goto level_0_err;
1569         }
1570
1571         /* Open level 1 for split fdb rules now if prios isn't supported  */
1572         if (!mlx5_chains_prios_supported(chains)) {
1573                 err = esw_vport_tbl_get(esw);
1574                 if (err)
1575                         goto level_1_err;
1576         }
1577
1578         mlx5_chains_set_end_ft(chains, nf_ft);
1579
1580         return 0;
1581
1582 level_1_err:
1583         mlx5_chains_put_table(chains, 0, 1, 0);
1584 level_0_err:
1585         mlx5_chains_put_table(chains, mlx5_chains_get_nf_ft_chain(chains), 1, 0);
1586 nf_ft_err:
1587         mlx5_chains_destroy(chains);
1588         esw->fdb_table.offloads.esw_chains_priv = NULL;
1589
1590         return err;
1591 }
1592
1593 static void
1594 esw_chains_destroy(struct mlx5_eswitch *esw, struct mlx5_fs_chains *chains)
1595 {
1596         if (!mlx5_chains_prios_supported(chains))
1597                 esw_vport_tbl_put(esw);
1598         mlx5_chains_put_table(chains, 0, 1, 0);
1599         mlx5_chains_put_table(chains, mlx5_chains_get_nf_ft_chain(chains), 1, 0);
1600         mlx5_chains_destroy(chains);
1601 }
1602
1603 #else /* CONFIG_MLX5_CLS_ACT */
1604
1605 static int
1606 esw_chains_create(struct mlx5_eswitch *esw, struct mlx5_flow_table *miss_fdb)
1607 { return 0; }
1608
1609 static void
1610 esw_chains_destroy(struct mlx5_eswitch *esw, struct mlx5_fs_chains *chains)
1611 {}
1612
1613 #endif
1614
1615 static int esw_create_offloads_fdb_tables(struct mlx5_eswitch *esw)
1616 {
1617         int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
1618         struct mlx5_flow_table_attr ft_attr = {};
1619         int num_vfs, table_size, ix, err = 0;
1620         struct mlx5_core_dev *dev = esw->dev;
1621         struct mlx5_flow_namespace *root_ns;
1622         struct mlx5_flow_table *fdb = NULL;
1623         u32 flags = 0, *flow_group_in;
1624         struct mlx5_flow_group *g;
1625         void *match_criteria;
1626         u8 *dmac;
1627
1628         esw_debug(esw->dev, "Create offloads FDB Tables\n");
1629
1630         flow_group_in = kvzalloc(inlen, GFP_KERNEL);
1631         if (!flow_group_in)
1632                 return -ENOMEM;
1633
1634         root_ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_FDB);
1635         if (!root_ns) {
1636                 esw_warn(dev, "Failed to get FDB flow namespace\n");
1637                 err = -EOPNOTSUPP;
1638                 goto ns_err;
1639         }
1640         esw->fdb_table.offloads.ns = root_ns;
1641         err = mlx5_flow_namespace_set_mode(root_ns,
1642                                            esw->dev->priv.steering->mode);
1643         if (err) {
1644                 esw_warn(dev, "Failed to set FDB namespace steering mode\n");
1645                 goto ns_err;
1646         }
1647
1648         /* To be strictly correct:
1649          *      MLX5_MAX_PORTS * (esw->total_vports * MAX_SQ_NVPORTS + MAX_PF_SQ)
1650          * should be:
1651          *      esw->total_vports * MAX_SQ_NVPORTS + MAX_PF_SQ +
1652          *      peer_esw->total_vports * MAX_SQ_NVPORTS + MAX_PF_SQ
1653          * but as the peer device might not be in switchdev mode it's not
1654          * possible. We use the fact that by default FW sets max vfs and max sfs
1655          * to the same value on both devices. If it needs to be changed in the future note
1656          * the peer miss group should also be created based on the number of
1657          * total vports of the peer (currently is also uses esw->total_vports).
1658          */
1659         table_size = MLX5_MAX_PORTS * (esw->total_vports * MAX_SQ_NVPORTS + MAX_PF_SQ) +
1660                 MLX5_ESW_MISS_FLOWS + esw->total_vports + esw->esw_funcs.num_vfs;
1661
1662         /* create the slow path fdb with encap set, so further table instances
1663          * can be created at run time while VFs are probed if the FW allows that.
1664          */
1665         if (esw->offloads.encap != DEVLINK_ESWITCH_ENCAP_MODE_NONE)
1666                 flags |= (MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT |
1667                           MLX5_FLOW_TABLE_TUNNEL_EN_DECAP);
1668
1669         ft_attr.flags = flags;
1670         ft_attr.max_fte = table_size;
1671         ft_attr.prio = FDB_SLOW_PATH;
1672
1673         fdb = mlx5_create_flow_table(root_ns, &ft_attr);
1674         if (IS_ERR(fdb)) {
1675                 err = PTR_ERR(fdb);
1676                 esw_warn(dev, "Failed to create slow path FDB Table err %d\n", err);
1677                 goto slow_fdb_err;
1678         }
1679         esw->fdb_table.offloads.slow_fdb = fdb;
1680
1681         /* Create empty TC-miss managed table. This allows plugging in following
1682          * priorities without directly exposing their level 0 table to
1683          * eswitch_offloads and passing it as miss_fdb to following call to
1684          * esw_chains_create().
1685          */
1686         memset(&ft_attr, 0, sizeof(ft_attr));
1687         ft_attr.prio = FDB_TC_MISS;
1688         esw->fdb_table.offloads.tc_miss_table = mlx5_create_flow_table(root_ns, &ft_attr);
1689         if (IS_ERR(esw->fdb_table.offloads.tc_miss_table)) {
1690                 err = PTR_ERR(esw->fdb_table.offloads.tc_miss_table);
1691                 esw_warn(dev, "Failed to create TC miss FDB Table err %d\n", err);
1692                 goto tc_miss_table_err;
1693         }
1694
1695         err = esw_chains_create(esw, esw->fdb_table.offloads.tc_miss_table);
1696         if (err) {
1697                 esw_warn(dev, "Failed to open fdb chains err(%d)\n", err);
1698                 goto fdb_chains_err;
1699         }
1700
1701         /* create send-to-vport group */
1702         MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
1703                  MLX5_MATCH_MISC_PARAMETERS);
1704
1705         match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in, match_criteria);
1706
1707         MLX5_SET_TO_ONES(fte_match_param, match_criteria, misc_parameters.source_sqn);
1708         MLX5_SET_TO_ONES(fte_match_param, match_criteria, misc_parameters.source_port);
1709         if (MLX5_CAP_ESW(esw->dev, merged_eswitch)) {
1710                 MLX5_SET_TO_ONES(fte_match_param, match_criteria,
1711                                  misc_parameters.source_eswitch_owner_vhca_id);
1712                 MLX5_SET(create_flow_group_in, flow_group_in,
1713                          source_eswitch_owner_vhca_id_valid, 1);
1714         }
1715
1716         /* See comment above table_size calculation */
1717         ix = MLX5_MAX_PORTS * (esw->total_vports * MAX_SQ_NVPORTS + MAX_PF_SQ);
1718         MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 0);
1719         MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, ix - 1);
1720
1721         g = mlx5_create_flow_group(fdb, flow_group_in);
1722         if (IS_ERR(g)) {
1723                 err = PTR_ERR(g);
1724                 esw_warn(dev, "Failed to create send-to-vport flow group err(%d)\n", err);
1725                 goto send_vport_err;
1726         }
1727         esw->fdb_table.offloads.send_to_vport_grp = g;
1728
1729         if (esw_src_port_rewrite_supported(esw)) {
1730                 /* meta send to vport */
1731                 memset(flow_group_in, 0, inlen);
1732                 MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
1733                          MLX5_MATCH_MISC_PARAMETERS_2);
1734
1735                 match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in, match_criteria);
1736
1737                 MLX5_SET(fte_match_param, match_criteria,
1738                          misc_parameters_2.metadata_reg_c_0,
1739                          mlx5_eswitch_get_vport_metadata_mask());
1740                 MLX5_SET(fte_match_param, match_criteria,
1741                          misc_parameters_2.metadata_reg_c_1, ESW_TUN_MASK);
1742
1743                 num_vfs = esw->esw_funcs.num_vfs;
1744                 if (num_vfs) {
1745                         MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, ix);
1746                         MLX5_SET(create_flow_group_in, flow_group_in,
1747                                  end_flow_index, ix + num_vfs - 1);
1748                         ix += num_vfs;
1749
1750                         g = mlx5_create_flow_group(fdb, flow_group_in);
1751                         if (IS_ERR(g)) {
1752                                 err = PTR_ERR(g);
1753                                 esw_warn(dev, "Failed to create send-to-vport meta flow group err(%d)\n",
1754                                          err);
1755                                 goto send_vport_meta_err;
1756                         }
1757                         esw->fdb_table.offloads.send_to_vport_meta_grp = g;
1758
1759                         err = mlx5_eswitch_add_send_to_vport_meta_rules(esw);
1760                         if (err)
1761                                 goto meta_rule_err;
1762                 }
1763         }
1764
1765         if (MLX5_CAP_ESW(esw->dev, merged_eswitch)) {
1766                 /* create peer esw miss group */
1767                 memset(flow_group_in, 0, inlen);
1768
1769                 esw_set_flow_group_source_port(esw, flow_group_in);
1770
1771                 if (!mlx5_eswitch_vport_match_metadata_enabled(esw)) {
1772                         match_criteria = MLX5_ADDR_OF(create_flow_group_in,
1773                                                       flow_group_in,
1774                                                       match_criteria);
1775
1776                         MLX5_SET_TO_ONES(fte_match_param, match_criteria,
1777                                          misc_parameters.source_eswitch_owner_vhca_id);
1778
1779                         MLX5_SET(create_flow_group_in, flow_group_in,
1780                                  source_eswitch_owner_vhca_id_valid, 1);
1781                 }
1782
1783                 MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, ix);
1784                 MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index,
1785                          ix + esw->total_vports - 1);
1786                 ix += esw->total_vports;
1787
1788                 g = mlx5_create_flow_group(fdb, flow_group_in);
1789                 if (IS_ERR(g)) {
1790                         err = PTR_ERR(g);
1791                         esw_warn(dev, "Failed to create peer miss flow group err(%d)\n", err);
1792                         goto peer_miss_err;
1793                 }
1794                 esw->fdb_table.offloads.peer_miss_grp = g;
1795         }
1796
1797         /* create miss group */
1798         memset(flow_group_in, 0, inlen);
1799         MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
1800                  MLX5_MATCH_OUTER_HEADERS);
1801         match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in,
1802                                       match_criteria);
1803         dmac = MLX5_ADDR_OF(fte_match_param, match_criteria,
1804                             outer_headers.dmac_47_16);
1805         dmac[0] = 0x01;
1806
1807         MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, ix);
1808         MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index,
1809                  ix + MLX5_ESW_MISS_FLOWS);
1810
1811         g = mlx5_create_flow_group(fdb, flow_group_in);
1812         if (IS_ERR(g)) {
1813                 err = PTR_ERR(g);
1814                 esw_warn(dev, "Failed to create miss flow group err(%d)\n", err);
1815                 goto miss_err;
1816         }
1817         esw->fdb_table.offloads.miss_grp = g;
1818
1819         err = esw_add_fdb_miss_rule(esw);
1820         if (err)
1821                 goto miss_rule_err;
1822
1823         kvfree(flow_group_in);
1824         return 0;
1825
1826 miss_rule_err:
1827         mlx5_destroy_flow_group(esw->fdb_table.offloads.miss_grp);
1828 miss_err:
1829         if (MLX5_CAP_ESW(esw->dev, merged_eswitch))
1830                 mlx5_destroy_flow_group(esw->fdb_table.offloads.peer_miss_grp);
1831 peer_miss_err:
1832         mlx5_eswitch_del_send_to_vport_meta_rules(esw);
1833 meta_rule_err:
1834         if (esw->fdb_table.offloads.send_to_vport_meta_grp)
1835                 mlx5_destroy_flow_group(esw->fdb_table.offloads.send_to_vport_meta_grp);
1836 send_vport_meta_err:
1837         mlx5_destroy_flow_group(esw->fdb_table.offloads.send_to_vport_grp);
1838 send_vport_err:
1839         esw_chains_destroy(esw, esw_chains(esw));
1840 fdb_chains_err:
1841         mlx5_destroy_flow_table(esw->fdb_table.offloads.tc_miss_table);
1842 tc_miss_table_err:
1843         mlx5_destroy_flow_table(esw->fdb_table.offloads.slow_fdb);
1844 slow_fdb_err:
1845         /* Holds true only as long as DMFS is the default */
1846         mlx5_flow_namespace_set_mode(root_ns, MLX5_FLOW_STEERING_MODE_DMFS);
1847 ns_err:
1848         kvfree(flow_group_in);
1849         return err;
1850 }
1851
1852 static void esw_destroy_offloads_fdb_tables(struct mlx5_eswitch *esw)
1853 {
1854         if (!esw->fdb_table.offloads.slow_fdb)
1855                 return;
1856
1857         esw_debug(esw->dev, "Destroy offloads FDB Tables\n");
1858         mlx5_del_flow_rules(esw->fdb_table.offloads.miss_rule_multi);
1859         mlx5_del_flow_rules(esw->fdb_table.offloads.miss_rule_uni);
1860         mlx5_eswitch_del_send_to_vport_meta_rules(esw);
1861         mlx5_destroy_flow_group(esw->fdb_table.offloads.send_to_vport_grp);
1862         if (esw->fdb_table.offloads.send_to_vport_meta_grp)
1863                 mlx5_destroy_flow_group(esw->fdb_table.offloads.send_to_vport_meta_grp);
1864         if (MLX5_CAP_ESW(esw->dev, merged_eswitch))
1865                 mlx5_destroy_flow_group(esw->fdb_table.offloads.peer_miss_grp);
1866         mlx5_destroy_flow_group(esw->fdb_table.offloads.miss_grp);
1867
1868         esw_chains_destroy(esw, esw_chains(esw));
1869
1870         mlx5_destroy_flow_table(esw->fdb_table.offloads.tc_miss_table);
1871         mlx5_destroy_flow_table(esw->fdb_table.offloads.slow_fdb);
1872         /* Holds true only as long as DMFS is the default */
1873         mlx5_flow_namespace_set_mode(esw->fdb_table.offloads.ns,
1874                                      MLX5_FLOW_STEERING_MODE_DMFS);
1875         atomic64_set(&esw->user_count, 0);
1876 }
1877
1878 static int esw_get_offloads_ft_size(struct mlx5_eswitch *esw)
1879 {
1880         int nvports;
1881
1882         nvports = esw->total_vports + MLX5_ESW_MISS_FLOWS;
1883         if (mlx5e_tc_int_port_supported(esw))
1884                 nvports += MLX5E_TC_MAX_INT_PORT_NUM;
1885
1886         return nvports;
1887 }
1888
1889 static int esw_create_offloads_table(struct mlx5_eswitch *esw)
1890 {
1891         struct mlx5_flow_table_attr ft_attr = {};
1892         struct mlx5_core_dev *dev = esw->dev;
1893         struct mlx5_flow_table *ft_offloads;
1894         struct mlx5_flow_namespace *ns;
1895         int err = 0;
1896
1897         ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_OFFLOADS);
1898         if (!ns) {
1899                 esw_warn(esw->dev, "Failed to get offloads flow namespace\n");
1900                 return -EOPNOTSUPP;
1901         }
1902
1903         ft_attr.max_fte = esw_get_offloads_ft_size(esw);
1904         ft_attr.prio = 1;
1905
1906         ft_offloads = mlx5_create_flow_table(ns, &ft_attr);
1907         if (IS_ERR(ft_offloads)) {
1908                 err = PTR_ERR(ft_offloads);
1909                 esw_warn(esw->dev, "Failed to create offloads table, err %d\n", err);
1910                 return err;
1911         }
1912
1913         esw->offloads.ft_offloads = ft_offloads;
1914         return 0;
1915 }
1916
1917 static void esw_destroy_offloads_table(struct mlx5_eswitch *esw)
1918 {
1919         struct mlx5_esw_offload *offloads = &esw->offloads;
1920
1921         mlx5_destroy_flow_table(offloads->ft_offloads);
1922 }
1923
1924 static int esw_create_vport_rx_group(struct mlx5_eswitch *esw)
1925 {
1926         int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
1927         struct mlx5_flow_group *g;
1928         u32 *flow_group_in;
1929         int nvports;
1930         int err = 0;
1931
1932         nvports = esw_get_offloads_ft_size(esw);
1933         flow_group_in = kvzalloc(inlen, GFP_KERNEL);
1934         if (!flow_group_in)
1935                 return -ENOMEM;
1936
1937         /* create vport rx group */
1938         esw_set_flow_group_source_port(esw, flow_group_in);
1939
1940         MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 0);
1941         MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, nvports - 1);
1942
1943         g = mlx5_create_flow_group(esw->offloads.ft_offloads, flow_group_in);
1944
1945         if (IS_ERR(g)) {
1946                 err = PTR_ERR(g);
1947                 mlx5_core_warn(esw->dev, "Failed to create vport rx group err %d\n", err);
1948                 goto out;
1949         }
1950
1951         esw->offloads.vport_rx_group = g;
1952 out:
1953         kvfree(flow_group_in);
1954         return err;
1955 }
1956
1957 static void esw_destroy_vport_rx_group(struct mlx5_eswitch *esw)
1958 {
1959         mlx5_destroy_flow_group(esw->offloads.vport_rx_group);
1960 }
1961
1962 struct mlx5_flow_handle *
1963 mlx5_eswitch_create_vport_rx_rule(struct mlx5_eswitch *esw, u16 vport,
1964                                   struct mlx5_flow_destination *dest)
1965 {
1966         struct mlx5_flow_act flow_act = {0};
1967         struct mlx5_flow_handle *flow_rule;
1968         struct mlx5_flow_spec *spec;
1969         void *misc;
1970
1971         spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
1972         if (!spec) {
1973                 flow_rule = ERR_PTR(-ENOMEM);
1974                 goto out;
1975         }
1976
1977         if (mlx5_eswitch_vport_match_metadata_enabled(esw)) {
1978                 misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters_2);
1979                 MLX5_SET(fte_match_set_misc2, misc, metadata_reg_c_0,
1980                          mlx5_eswitch_get_vport_metadata_for_match(esw, vport));
1981
1982                 misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters_2);
1983                 MLX5_SET(fte_match_set_misc2, misc, metadata_reg_c_0,
1984                          mlx5_eswitch_get_vport_metadata_mask());
1985
1986                 spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS_2;
1987         } else {
1988                 misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters);
1989                 MLX5_SET(fte_match_set_misc, misc, source_port, vport);
1990
1991                 misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters);
1992                 MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port);
1993
1994                 spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS;
1995         }
1996
1997         flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
1998         flow_rule = mlx5_add_flow_rules(esw->offloads.ft_offloads, spec,
1999                                         &flow_act, dest, 1);
2000         if (IS_ERR(flow_rule)) {
2001                 esw_warn(esw->dev, "fs offloads: Failed to add vport rx rule err %ld\n", PTR_ERR(flow_rule));
2002                 goto out;
2003         }
2004
2005 out:
2006         kvfree(spec);
2007         return flow_rule;
2008 }
2009
2010 static int mlx5_eswitch_inline_mode_get(struct mlx5_eswitch *esw, u8 *mode)
2011 {
2012         u8 prev_mlx5_mode, mlx5_mode = MLX5_INLINE_MODE_L2;
2013         struct mlx5_core_dev *dev = esw->dev;
2014         struct mlx5_vport *vport;
2015         unsigned long i;
2016
2017         if (!MLX5_CAP_GEN(dev, vport_group_manager))
2018                 return -EOPNOTSUPP;
2019
2020         if (esw->mode == MLX5_ESWITCH_NONE)
2021                 return -EOPNOTSUPP;
2022
2023         switch (MLX5_CAP_ETH(dev, wqe_inline_mode)) {
2024         case MLX5_CAP_INLINE_MODE_NOT_REQUIRED:
2025                 mlx5_mode = MLX5_INLINE_MODE_NONE;
2026                 goto out;
2027         case MLX5_CAP_INLINE_MODE_L2:
2028                 mlx5_mode = MLX5_INLINE_MODE_L2;
2029                 goto out;
2030         case MLX5_CAP_INLINE_MODE_VPORT_CONTEXT:
2031                 goto query_vports;
2032         }
2033
2034 query_vports:
2035         mlx5_query_nic_vport_min_inline(dev, esw->first_host_vport, &prev_mlx5_mode);
2036         mlx5_esw_for_each_host_func_vport(esw, i, vport, esw->esw_funcs.num_vfs) {
2037                 mlx5_query_nic_vport_min_inline(dev, vport->vport, &mlx5_mode);
2038                 if (prev_mlx5_mode != mlx5_mode)
2039                         return -EINVAL;
2040                 prev_mlx5_mode = mlx5_mode;
2041         }
2042
2043 out:
2044         *mode = mlx5_mode;
2045         return 0;
2046 }
2047
2048 static void esw_destroy_restore_table(struct mlx5_eswitch *esw)
2049 {
2050         struct mlx5_esw_offload *offloads = &esw->offloads;
2051
2052         if (!mlx5_eswitch_reg_c1_loopback_supported(esw))
2053                 return;
2054
2055         mlx5_modify_header_dealloc(esw->dev, offloads->restore_copy_hdr_id);
2056         mlx5_destroy_flow_group(offloads->restore_group);
2057         mlx5_destroy_flow_table(offloads->ft_offloads_restore);
2058 }
2059
2060 static int esw_create_restore_table(struct mlx5_eswitch *esw)
2061 {
2062         u8 modact[MLX5_UN_SZ_BYTES(set_add_copy_action_in_auto)] = {};
2063         int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
2064         struct mlx5_flow_table_attr ft_attr = {};
2065         struct mlx5_core_dev *dev = esw->dev;
2066         struct mlx5_flow_namespace *ns;
2067         struct mlx5_modify_hdr *mod_hdr;
2068         void *match_criteria, *misc;
2069         struct mlx5_flow_table *ft;
2070         struct mlx5_flow_group *g;
2071         u32 *flow_group_in;
2072         int err = 0;
2073
2074         if (!mlx5_eswitch_reg_c1_loopback_supported(esw))
2075                 return 0;
2076
2077         ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_OFFLOADS);
2078         if (!ns) {
2079                 esw_warn(esw->dev, "Failed to get offloads flow namespace\n");
2080                 return -EOPNOTSUPP;
2081         }
2082
2083         flow_group_in = kvzalloc(inlen, GFP_KERNEL);
2084         if (!flow_group_in) {
2085                 err = -ENOMEM;
2086                 goto out_free;
2087         }
2088
2089         ft_attr.max_fte = 1 << ESW_REG_C0_USER_DATA_METADATA_BITS;
2090         ft = mlx5_create_flow_table(ns, &ft_attr);
2091         if (IS_ERR(ft)) {
2092                 err = PTR_ERR(ft);
2093                 esw_warn(esw->dev, "Failed to create restore table, err %d\n",
2094                          err);
2095                 goto out_free;
2096         }
2097
2098         match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in,
2099                                       match_criteria);
2100         misc = MLX5_ADDR_OF(fte_match_param, match_criteria,
2101                             misc_parameters_2);
2102
2103         MLX5_SET(fte_match_set_misc2, misc, metadata_reg_c_0,
2104                  ESW_REG_C0_USER_DATA_METADATA_MASK);
2105         MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 0);
2106         MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index,
2107                  ft_attr.max_fte - 1);
2108         MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
2109                  MLX5_MATCH_MISC_PARAMETERS_2);
2110         g = mlx5_create_flow_group(ft, flow_group_in);
2111         if (IS_ERR(g)) {
2112                 err = PTR_ERR(g);
2113                 esw_warn(dev, "Failed to create restore flow group, err: %d\n",
2114                          err);
2115                 goto err_group;
2116         }
2117
2118         MLX5_SET(copy_action_in, modact, action_type, MLX5_ACTION_TYPE_COPY);
2119         MLX5_SET(copy_action_in, modact, src_field,
2120                  MLX5_ACTION_IN_FIELD_METADATA_REG_C_1);
2121         MLX5_SET(copy_action_in, modact, dst_field,
2122                  MLX5_ACTION_IN_FIELD_METADATA_REG_B);
2123         mod_hdr = mlx5_modify_header_alloc(esw->dev,
2124                                            MLX5_FLOW_NAMESPACE_KERNEL, 1,
2125                                            modact);
2126         if (IS_ERR(mod_hdr)) {
2127                 err = PTR_ERR(mod_hdr);
2128                 esw_warn(dev, "Failed to create restore mod header, err: %d\n",
2129                          err);
2130                 goto err_mod_hdr;
2131         }
2132
2133         esw->offloads.ft_offloads_restore = ft;
2134         esw->offloads.restore_group = g;
2135         esw->offloads.restore_copy_hdr_id = mod_hdr;
2136
2137         kvfree(flow_group_in);
2138
2139         return 0;
2140
2141 err_mod_hdr:
2142         mlx5_destroy_flow_group(g);
2143 err_group:
2144         mlx5_destroy_flow_table(ft);
2145 out_free:
2146         kvfree(flow_group_in);
2147
2148         return err;
2149 }
2150
2151 static int esw_offloads_start(struct mlx5_eswitch *esw,
2152                               struct netlink_ext_ack *extack)
2153 {
2154         int err, err1;
2155
2156         mlx5_eswitch_disable_locked(esw, false);
2157         err = mlx5_eswitch_enable_locked(esw, MLX5_ESWITCH_OFFLOADS,
2158                                          esw->dev->priv.sriov.num_vfs);
2159         if (err) {
2160                 NL_SET_ERR_MSG_MOD(extack,
2161                                    "Failed setting eswitch to offloads");
2162                 err1 = mlx5_eswitch_enable_locked(esw, MLX5_ESWITCH_LEGACY,
2163                                                   MLX5_ESWITCH_IGNORE_NUM_VFS);
2164                 if (err1) {
2165                         NL_SET_ERR_MSG_MOD(extack,
2166                                            "Failed setting eswitch back to legacy");
2167                 }
2168         }
2169         if (esw->offloads.inline_mode == MLX5_INLINE_MODE_NONE) {
2170                 if (mlx5_eswitch_inline_mode_get(esw,
2171                                                  &esw->offloads.inline_mode)) {
2172                         esw->offloads.inline_mode = MLX5_INLINE_MODE_L2;
2173                         NL_SET_ERR_MSG_MOD(extack,
2174                                            "Inline mode is different between vports");
2175                 }
2176         }
2177         return err;
2178 }
2179
2180 static void mlx5_esw_offloads_rep_mark_set(struct mlx5_eswitch *esw,
2181                                            struct mlx5_eswitch_rep *rep,
2182                                            xa_mark_t mark)
2183 {
2184         bool mark_set;
2185
2186         /* Copy the mark from vport to its rep */
2187         mark_set = xa_get_mark(&esw->vports, rep->vport, mark);
2188         if (mark_set)
2189                 xa_set_mark(&esw->offloads.vport_reps, rep->vport, mark);
2190 }
2191
2192 static int mlx5_esw_offloads_rep_init(struct mlx5_eswitch *esw, const struct mlx5_vport *vport)
2193 {
2194         struct mlx5_eswitch_rep *rep;
2195         int rep_type;
2196         int err;
2197
2198         rep = kzalloc(sizeof(*rep), GFP_KERNEL);
2199         if (!rep)
2200                 return -ENOMEM;
2201
2202         rep->vport = vport->vport;
2203         rep->vport_index = vport->index;
2204         for (rep_type = 0; rep_type < NUM_REP_TYPES; rep_type++)
2205                 atomic_set(&rep->rep_data[rep_type].state, REP_UNREGISTERED);
2206
2207         err = xa_insert(&esw->offloads.vport_reps, rep->vport, rep, GFP_KERNEL);
2208         if (err)
2209                 goto insert_err;
2210
2211         mlx5_esw_offloads_rep_mark_set(esw, rep, MLX5_ESW_VPT_HOST_FN);
2212         mlx5_esw_offloads_rep_mark_set(esw, rep, MLX5_ESW_VPT_VF);
2213         mlx5_esw_offloads_rep_mark_set(esw, rep, MLX5_ESW_VPT_SF);
2214         return 0;
2215
2216 insert_err:
2217         kfree(rep);
2218         return err;
2219 }
2220
2221 static void mlx5_esw_offloads_rep_cleanup(struct mlx5_eswitch *esw,
2222                                           struct mlx5_eswitch_rep *rep)
2223 {
2224         xa_erase(&esw->offloads.vport_reps, rep->vport);
2225         kfree(rep);
2226 }
2227
2228 void esw_offloads_cleanup_reps(struct mlx5_eswitch *esw)
2229 {
2230         struct mlx5_eswitch_rep *rep;
2231         unsigned long i;
2232
2233         mlx5_esw_for_each_rep(esw, i, rep)
2234                 mlx5_esw_offloads_rep_cleanup(esw, rep);
2235         xa_destroy(&esw->offloads.vport_reps);
2236 }
2237
2238 int esw_offloads_init_reps(struct mlx5_eswitch *esw)
2239 {
2240         struct mlx5_vport *vport;
2241         unsigned long i;
2242         int err;
2243
2244         xa_init(&esw->offloads.vport_reps);
2245
2246         mlx5_esw_for_each_vport(esw, i, vport) {
2247                 err = mlx5_esw_offloads_rep_init(esw, vport);
2248                 if (err)
2249                         goto err;
2250         }
2251         return 0;
2252
2253 err:
2254         esw_offloads_cleanup_reps(esw);
2255         return err;
2256 }
2257
2258 static void __esw_offloads_unload_rep(struct mlx5_eswitch *esw,
2259                                       struct mlx5_eswitch_rep *rep, u8 rep_type)
2260 {
2261         if (atomic_cmpxchg(&rep->rep_data[rep_type].state,
2262                            REP_LOADED, REP_REGISTERED) == REP_LOADED)
2263                 esw->offloads.rep_ops[rep_type]->unload(rep);
2264 }
2265
2266 static void __unload_reps_sf_vport(struct mlx5_eswitch *esw, u8 rep_type)
2267 {
2268         struct mlx5_eswitch_rep *rep;
2269         unsigned long i;
2270
2271         mlx5_esw_for_each_sf_rep(esw, i, rep)
2272                 __esw_offloads_unload_rep(esw, rep, rep_type);
2273 }
2274
2275 static void __unload_reps_all_vport(struct mlx5_eswitch *esw, u8 rep_type)
2276 {
2277         struct mlx5_eswitch_rep *rep;
2278         unsigned long i;
2279
2280         __unload_reps_sf_vport(esw, rep_type);
2281
2282         mlx5_esw_for_each_vf_rep(esw, i, rep)
2283                 __esw_offloads_unload_rep(esw, rep, rep_type);
2284
2285         if (mlx5_ecpf_vport_exists(esw->dev)) {
2286                 rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_ECPF);
2287                 __esw_offloads_unload_rep(esw, rep, rep_type);
2288         }
2289
2290         if (mlx5_core_is_ecpf_esw_manager(esw->dev)) {
2291                 rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_PF);
2292                 __esw_offloads_unload_rep(esw, rep, rep_type);
2293         }
2294
2295         rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_UPLINK);
2296         __esw_offloads_unload_rep(esw, rep, rep_type);
2297 }
2298
2299 int mlx5_esw_offloads_rep_load(struct mlx5_eswitch *esw, u16 vport_num)
2300 {
2301         struct mlx5_eswitch_rep *rep;
2302         int rep_type;
2303         int err;
2304
2305         rep = mlx5_eswitch_get_rep(esw, vport_num);
2306         for (rep_type = 0; rep_type < NUM_REP_TYPES; rep_type++)
2307                 if (atomic_cmpxchg(&rep->rep_data[rep_type].state,
2308                                    REP_REGISTERED, REP_LOADED) == REP_REGISTERED) {
2309                         err = esw->offloads.rep_ops[rep_type]->load(esw->dev, rep);
2310                         if (err)
2311                                 goto err_reps;
2312                 }
2313
2314         return 0;
2315
2316 err_reps:
2317         atomic_set(&rep->rep_data[rep_type].state, REP_REGISTERED);
2318         for (--rep_type; rep_type >= 0; rep_type--)
2319                 __esw_offloads_unload_rep(esw, rep, rep_type);
2320         return err;
2321 }
2322
2323 void mlx5_esw_offloads_rep_unload(struct mlx5_eswitch *esw, u16 vport_num)
2324 {
2325         struct mlx5_eswitch_rep *rep;
2326         int rep_type;
2327
2328         rep = mlx5_eswitch_get_rep(esw, vport_num);
2329         for (rep_type = NUM_REP_TYPES - 1; rep_type >= 0; rep_type--)
2330                 __esw_offloads_unload_rep(esw, rep, rep_type);
2331 }
2332
2333 int esw_offloads_load_rep(struct mlx5_eswitch *esw, u16 vport_num)
2334 {
2335         int err;
2336
2337         if (esw->mode != MLX5_ESWITCH_OFFLOADS)
2338                 return 0;
2339
2340         if (vport_num != MLX5_VPORT_UPLINK) {
2341                 err = mlx5_esw_offloads_devlink_port_register(esw, vport_num);
2342                 if (err)
2343                         return err;
2344         }
2345
2346         err = mlx5_esw_offloads_rep_load(esw, vport_num);
2347         if (err)
2348                 goto load_err;
2349         return err;
2350
2351 load_err:
2352         if (vport_num != MLX5_VPORT_UPLINK)
2353                 mlx5_esw_offloads_devlink_port_unregister(esw, vport_num);
2354         return err;
2355 }
2356
2357 void esw_offloads_unload_rep(struct mlx5_eswitch *esw, u16 vport_num)
2358 {
2359         if (esw->mode != MLX5_ESWITCH_OFFLOADS)
2360                 return;
2361
2362         mlx5_esw_offloads_rep_unload(esw, vport_num);
2363
2364         if (vport_num != MLX5_VPORT_UPLINK)
2365                 mlx5_esw_offloads_devlink_port_unregister(esw, vport_num);
2366 }
2367
2368 static int esw_set_uplink_slave_ingress_root(struct mlx5_core_dev *master,
2369                                              struct mlx5_core_dev *slave)
2370 {
2371         u32 in[MLX5_ST_SZ_DW(set_flow_table_root_in)]   = {};
2372         u32 out[MLX5_ST_SZ_DW(set_flow_table_root_out)] = {};
2373         struct mlx5_eswitch *esw;
2374         struct mlx5_flow_root_namespace *root;
2375         struct mlx5_flow_namespace *ns;
2376         struct mlx5_vport *vport;
2377         int err;
2378
2379         MLX5_SET(set_flow_table_root_in, in, opcode,
2380                  MLX5_CMD_OP_SET_FLOW_TABLE_ROOT);
2381         MLX5_SET(set_flow_table_root_in, in, table_type, FS_FT_ESW_INGRESS_ACL);
2382         MLX5_SET(set_flow_table_root_in, in, other_vport, 1);
2383         MLX5_SET(set_flow_table_root_in, in, vport_number, MLX5_VPORT_UPLINK);
2384
2385         if (master) {
2386                 esw = master->priv.eswitch;
2387                 vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_UPLINK);
2388                 MLX5_SET(set_flow_table_root_in, in, table_of_other_vport, 1);
2389                 MLX5_SET(set_flow_table_root_in, in, table_vport_number,
2390                          MLX5_VPORT_UPLINK);
2391
2392                 ns = mlx5_get_flow_vport_acl_namespace(master,
2393                                                        MLX5_FLOW_NAMESPACE_ESW_INGRESS,
2394                                                        vport->index);
2395                 root = find_root(&ns->node);
2396                 mutex_lock(&root->chain_lock);
2397
2398                 MLX5_SET(set_flow_table_root_in, in,
2399                          table_eswitch_owner_vhca_id_valid, 1);
2400                 MLX5_SET(set_flow_table_root_in, in,
2401                          table_eswitch_owner_vhca_id,
2402                          MLX5_CAP_GEN(master, vhca_id));
2403                 MLX5_SET(set_flow_table_root_in, in, table_id,
2404                          root->root_ft->id);
2405         } else {
2406                 esw = slave->priv.eswitch;
2407                 vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_UPLINK);
2408                 ns = mlx5_get_flow_vport_acl_namespace(slave,
2409                                                        MLX5_FLOW_NAMESPACE_ESW_INGRESS,
2410                                                        vport->index);
2411                 root = find_root(&ns->node);
2412                 mutex_lock(&root->chain_lock);
2413                 MLX5_SET(set_flow_table_root_in, in, table_id, root->root_ft->id);
2414         }
2415
2416         err = mlx5_cmd_exec(slave, in, sizeof(in), out, sizeof(out));
2417         mutex_unlock(&root->chain_lock);
2418
2419         return err;
2420 }
2421
2422 static int esw_set_slave_root_fdb(struct mlx5_core_dev *master,
2423                                   struct mlx5_core_dev *slave)
2424 {
2425         u32 in[MLX5_ST_SZ_DW(set_flow_table_root_in)]   = {};
2426         u32 out[MLX5_ST_SZ_DW(set_flow_table_root_out)] = {};
2427         struct mlx5_flow_root_namespace *root;
2428         struct mlx5_flow_namespace *ns;
2429         int err;
2430
2431         MLX5_SET(set_flow_table_root_in, in, opcode,
2432                  MLX5_CMD_OP_SET_FLOW_TABLE_ROOT);
2433         MLX5_SET(set_flow_table_root_in, in, table_type,
2434                  FS_FT_FDB);
2435
2436         if (master) {
2437                 ns = mlx5_get_flow_namespace(master,
2438                                              MLX5_FLOW_NAMESPACE_FDB);
2439                 root = find_root(&ns->node);
2440                 mutex_lock(&root->chain_lock);
2441                 MLX5_SET(set_flow_table_root_in, in,
2442                          table_eswitch_owner_vhca_id_valid, 1);
2443                 MLX5_SET(set_flow_table_root_in, in,
2444                          table_eswitch_owner_vhca_id,
2445                          MLX5_CAP_GEN(master, vhca_id));
2446                 MLX5_SET(set_flow_table_root_in, in, table_id,
2447                          root->root_ft->id);
2448         } else {
2449                 ns = mlx5_get_flow_namespace(slave,
2450                                              MLX5_FLOW_NAMESPACE_FDB);
2451                 root = find_root(&ns->node);
2452                 mutex_lock(&root->chain_lock);
2453                 MLX5_SET(set_flow_table_root_in, in, table_id,
2454                          root->root_ft->id);
2455         }
2456
2457         err = mlx5_cmd_exec(slave, in, sizeof(in), out, sizeof(out));
2458         mutex_unlock(&root->chain_lock);
2459
2460         return err;
2461 }
2462
2463 static int __esw_set_master_egress_rule(struct mlx5_core_dev *master,
2464                                         struct mlx5_core_dev *slave,
2465                                         struct mlx5_vport *vport,
2466                                         struct mlx5_flow_table *acl)
2467 {
2468         struct mlx5_flow_handle *flow_rule = NULL;
2469         struct mlx5_flow_destination dest = {};
2470         struct mlx5_flow_act flow_act = {};
2471         struct mlx5_flow_spec *spec;
2472         int err = 0;
2473         void *misc;
2474
2475         spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
2476         if (!spec)
2477                 return -ENOMEM;
2478
2479         spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS;
2480         misc = MLX5_ADDR_OF(fte_match_param, spec->match_value,
2481                             misc_parameters);
2482         MLX5_SET(fte_match_set_misc, misc, source_port, MLX5_VPORT_UPLINK);
2483         MLX5_SET(fte_match_set_misc, misc, source_eswitch_owner_vhca_id,
2484                  MLX5_CAP_GEN(slave, vhca_id));
2485
2486         misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters);
2487         MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port);
2488         MLX5_SET_TO_ONES(fte_match_set_misc, misc,
2489                          source_eswitch_owner_vhca_id);
2490
2491         flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
2492         dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
2493         dest.vport.num = slave->priv.eswitch->manager_vport;
2494         dest.vport.vhca_id = MLX5_CAP_GEN(slave, vhca_id);
2495         dest.vport.flags |= MLX5_FLOW_DEST_VPORT_VHCA_ID;
2496
2497         flow_rule = mlx5_add_flow_rules(acl, spec, &flow_act,
2498                                         &dest, 1);
2499         if (IS_ERR(flow_rule))
2500                 err = PTR_ERR(flow_rule);
2501         else
2502                 vport->egress.offloads.bounce_rule = flow_rule;
2503
2504         kvfree(spec);
2505         return err;
2506 }
2507
2508 static int esw_set_master_egress_rule(struct mlx5_core_dev *master,
2509                                       struct mlx5_core_dev *slave)
2510 {
2511         int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
2512         struct mlx5_eswitch *esw = master->priv.eswitch;
2513         struct mlx5_flow_table_attr ft_attr = {
2514                 .max_fte = 1, .prio = 0, .level = 0,
2515         };
2516         struct mlx5_flow_namespace *egress_ns;
2517         struct mlx5_flow_table *acl;
2518         struct mlx5_flow_group *g;
2519         struct mlx5_vport *vport;
2520         void *match_criteria;
2521         u32 *flow_group_in;
2522         int err;
2523
2524         vport = mlx5_eswitch_get_vport(esw, esw->manager_vport);
2525         if (IS_ERR(vport))
2526                 return PTR_ERR(vport);
2527
2528         egress_ns = mlx5_get_flow_vport_acl_namespace(master,
2529                                                       MLX5_FLOW_NAMESPACE_ESW_EGRESS,
2530                                                       vport->index);
2531         if (!egress_ns)
2532                 return -EINVAL;
2533
2534         if (vport->egress.acl)
2535                 return -EINVAL;
2536
2537         flow_group_in = kvzalloc(inlen, GFP_KERNEL);
2538         if (!flow_group_in)
2539                 return -ENOMEM;
2540
2541         acl = mlx5_create_vport_flow_table(egress_ns, &ft_attr, vport->vport);
2542         if (IS_ERR(acl)) {
2543                 err = PTR_ERR(acl);
2544                 goto out;
2545         }
2546
2547         match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in,
2548                                       match_criteria);
2549         MLX5_SET_TO_ONES(fte_match_param, match_criteria,
2550                          misc_parameters.source_port);
2551         MLX5_SET_TO_ONES(fte_match_param, match_criteria,
2552                          misc_parameters.source_eswitch_owner_vhca_id);
2553         MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
2554                  MLX5_MATCH_MISC_PARAMETERS);
2555
2556         MLX5_SET(create_flow_group_in, flow_group_in,
2557                  source_eswitch_owner_vhca_id_valid, 1);
2558         MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 0);
2559         MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 0);
2560
2561         g = mlx5_create_flow_group(acl, flow_group_in);
2562         if (IS_ERR(g)) {
2563                 err = PTR_ERR(g);
2564                 goto err_group;
2565         }
2566
2567         err = __esw_set_master_egress_rule(master, slave, vport, acl);
2568         if (err)
2569                 goto err_rule;
2570
2571         vport->egress.acl = acl;
2572         vport->egress.offloads.bounce_grp = g;
2573
2574         kvfree(flow_group_in);
2575
2576         return 0;
2577
2578 err_rule:
2579         mlx5_destroy_flow_group(g);
2580 err_group:
2581         mlx5_destroy_flow_table(acl);
2582 out:
2583         kvfree(flow_group_in);
2584         return err;
2585 }
2586
2587 static void esw_unset_master_egress_rule(struct mlx5_core_dev *dev)
2588 {
2589         struct mlx5_vport *vport;
2590
2591         vport = mlx5_eswitch_get_vport(dev->priv.eswitch,
2592                                        dev->priv.eswitch->manager_vport);
2593
2594         esw_acl_egress_ofld_cleanup(vport);
2595 }
2596
2597 int mlx5_eswitch_offloads_config_single_fdb(struct mlx5_eswitch *master_esw,
2598                                             struct mlx5_eswitch *slave_esw)
2599 {
2600         int err;
2601
2602         err = esw_set_uplink_slave_ingress_root(master_esw->dev,
2603                                                 slave_esw->dev);
2604         if (err)
2605                 return -EINVAL;
2606
2607         err = esw_set_slave_root_fdb(master_esw->dev,
2608                                      slave_esw->dev);
2609         if (err)
2610                 goto err_fdb;
2611
2612         err = esw_set_master_egress_rule(master_esw->dev,
2613                                          slave_esw->dev);
2614         if (err)
2615                 goto err_acl;
2616
2617         return err;
2618
2619 err_acl:
2620         esw_set_slave_root_fdb(NULL, slave_esw->dev);
2621
2622 err_fdb:
2623         esw_set_uplink_slave_ingress_root(NULL, slave_esw->dev);
2624
2625         return err;
2626 }
2627
2628 void mlx5_eswitch_offloads_destroy_single_fdb(struct mlx5_eswitch *master_esw,
2629                                               struct mlx5_eswitch *slave_esw)
2630 {
2631         esw_unset_master_egress_rule(master_esw->dev);
2632         esw_set_slave_root_fdb(NULL, slave_esw->dev);
2633         esw_set_uplink_slave_ingress_root(NULL, slave_esw->dev);
2634 }
2635
2636 #define ESW_OFFLOADS_DEVCOM_PAIR        (0)
2637 #define ESW_OFFLOADS_DEVCOM_UNPAIR      (1)
2638
2639 static void mlx5_esw_offloads_rep_event_unpair(struct mlx5_eswitch *esw)
2640 {
2641         const struct mlx5_eswitch_rep_ops *ops;
2642         struct mlx5_eswitch_rep *rep;
2643         unsigned long i;
2644         u8 rep_type;
2645
2646         mlx5_esw_for_each_rep(esw, i, rep) {
2647                 rep_type = NUM_REP_TYPES;
2648                 while (rep_type--) {
2649                         ops = esw->offloads.rep_ops[rep_type];
2650                         if (atomic_read(&rep->rep_data[rep_type].state) == REP_LOADED &&
2651                             ops->event)
2652                                 ops->event(esw, rep, MLX5_SWITCHDEV_EVENT_UNPAIR, NULL);
2653                 }
2654         }
2655 }
2656
2657 static void mlx5_esw_offloads_unpair(struct mlx5_eswitch *esw)
2658 {
2659 #if IS_ENABLED(CONFIG_MLX5_CLS_ACT)
2660         mlx5e_tc_clean_fdb_peer_flows(esw);
2661 #endif
2662         mlx5_esw_offloads_rep_event_unpair(esw);
2663         esw_del_fdb_peer_miss_rules(esw);
2664 }
2665
2666 static int mlx5_esw_offloads_pair(struct mlx5_eswitch *esw,
2667                                   struct mlx5_eswitch *peer_esw)
2668 {
2669         const struct mlx5_eswitch_rep_ops *ops;
2670         struct mlx5_eswitch_rep *rep;
2671         unsigned long i;
2672         u8 rep_type;
2673         int err;
2674
2675         err = esw_add_fdb_peer_miss_rules(esw, peer_esw->dev);
2676         if (err)
2677                 return err;
2678
2679         mlx5_esw_for_each_rep(esw, i, rep) {
2680                 for (rep_type = 0; rep_type < NUM_REP_TYPES; rep_type++) {
2681                         ops = esw->offloads.rep_ops[rep_type];
2682                         if (atomic_read(&rep->rep_data[rep_type].state) == REP_LOADED &&
2683                             ops->event) {
2684                                 err = ops->event(esw, rep, MLX5_SWITCHDEV_EVENT_PAIR, peer_esw);
2685                                 if (err)
2686                                         goto err_out;
2687                         }
2688                 }
2689         }
2690
2691         return 0;
2692
2693 err_out:
2694         mlx5_esw_offloads_unpair(esw);
2695         return err;
2696 }
2697
2698 static int mlx5_esw_offloads_set_ns_peer(struct mlx5_eswitch *esw,
2699                                          struct mlx5_eswitch *peer_esw,
2700                                          bool pair)
2701 {
2702         struct mlx5_flow_root_namespace *peer_ns;
2703         struct mlx5_flow_root_namespace *ns;
2704         int err;
2705
2706         peer_ns = peer_esw->dev->priv.steering->fdb_root_ns;
2707         ns = esw->dev->priv.steering->fdb_root_ns;
2708
2709         if (pair) {
2710                 err = mlx5_flow_namespace_set_peer(ns, peer_ns);
2711                 if (err)
2712                         return err;
2713
2714                 err = mlx5_flow_namespace_set_peer(peer_ns, ns);
2715                 if (err) {
2716                         mlx5_flow_namespace_set_peer(ns, NULL);
2717                         return err;
2718                 }
2719         } else {
2720                 mlx5_flow_namespace_set_peer(ns, NULL);
2721                 mlx5_flow_namespace_set_peer(peer_ns, NULL);
2722         }
2723
2724         return 0;
2725 }
2726
2727 static int mlx5_esw_offloads_devcom_event(int event,
2728                                           void *my_data,
2729                                           void *event_data)
2730 {
2731         struct mlx5_eswitch *esw = my_data;
2732         struct mlx5_devcom *devcom = esw->dev->priv.devcom;
2733         struct mlx5_eswitch *peer_esw = event_data;
2734         int err;
2735
2736         switch (event) {
2737         case ESW_OFFLOADS_DEVCOM_PAIR:
2738                 if (mlx5_get_next_phys_dev(esw->dev) != peer_esw->dev)
2739                         break;
2740
2741                 if (mlx5_eswitch_vport_match_metadata_enabled(esw) !=
2742                     mlx5_eswitch_vport_match_metadata_enabled(peer_esw))
2743                         break;
2744
2745                 err = mlx5_esw_offloads_set_ns_peer(esw, peer_esw, true);
2746                 if (err)
2747                         goto err_out;
2748                 err = mlx5_esw_offloads_pair(esw, peer_esw);
2749                 if (err)
2750                         goto err_peer;
2751
2752                 err = mlx5_esw_offloads_pair(peer_esw, esw);
2753                 if (err)
2754                         goto err_pair;
2755
2756                 mlx5_devcom_set_paired(devcom, MLX5_DEVCOM_ESW_OFFLOADS, true);
2757                 break;
2758
2759         case ESW_OFFLOADS_DEVCOM_UNPAIR:
2760                 if (!mlx5_devcom_is_paired(devcom, MLX5_DEVCOM_ESW_OFFLOADS))
2761                         break;
2762
2763                 mlx5_devcom_set_paired(devcom, MLX5_DEVCOM_ESW_OFFLOADS, false);
2764                 mlx5_esw_offloads_unpair(peer_esw);
2765                 mlx5_esw_offloads_unpair(esw);
2766                 mlx5_esw_offloads_set_ns_peer(esw, peer_esw, false);
2767                 break;
2768         }
2769
2770         return 0;
2771
2772 err_pair:
2773         mlx5_esw_offloads_unpair(esw);
2774 err_peer:
2775         mlx5_esw_offloads_set_ns_peer(esw, peer_esw, false);
2776 err_out:
2777         mlx5_core_err(esw->dev, "esw offloads devcom event failure, event %u err %d",
2778                       event, err);
2779         return err;
2780 }
2781
2782 static void esw_offloads_devcom_init(struct mlx5_eswitch *esw)
2783 {
2784         struct mlx5_devcom *devcom = esw->dev->priv.devcom;
2785
2786         INIT_LIST_HEAD(&esw->offloads.peer_flows);
2787         mutex_init(&esw->offloads.peer_mutex);
2788
2789         if (!MLX5_CAP_ESW(esw->dev, merged_eswitch))
2790                 return;
2791
2792         mlx5_devcom_register_component(devcom,
2793                                        MLX5_DEVCOM_ESW_OFFLOADS,
2794                                        mlx5_esw_offloads_devcom_event,
2795                                        esw);
2796
2797         mlx5_devcom_send_event(devcom,
2798                                MLX5_DEVCOM_ESW_OFFLOADS,
2799                                ESW_OFFLOADS_DEVCOM_PAIR, esw);
2800 }
2801
2802 static void esw_offloads_devcom_cleanup(struct mlx5_eswitch *esw)
2803 {
2804         struct mlx5_devcom *devcom = esw->dev->priv.devcom;
2805
2806         if (!MLX5_CAP_ESW(esw->dev, merged_eswitch))
2807                 return;
2808
2809         mlx5_devcom_send_event(devcom, MLX5_DEVCOM_ESW_OFFLOADS,
2810                                ESW_OFFLOADS_DEVCOM_UNPAIR, esw);
2811
2812         mlx5_devcom_unregister_component(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
2813 }
2814
2815 bool mlx5_esw_vport_match_metadata_supported(const struct mlx5_eswitch *esw)
2816 {
2817         if (!MLX5_CAP_ESW(esw->dev, esw_uplink_ingress_acl))
2818                 return false;
2819
2820         if (!(MLX5_CAP_ESW_FLOWTABLE(esw->dev, fdb_to_vport_reg_c_id) &
2821               MLX5_FDB_TO_VPORT_REG_C_0))
2822                 return false;
2823
2824         if (!MLX5_CAP_ESW_FLOWTABLE(esw->dev, flow_source))
2825                 return false;
2826
2827         if (mlx5_core_is_ecpf_esw_manager(esw->dev) ||
2828             mlx5_ecpf_vport_exists(esw->dev))
2829                 return false;
2830
2831         return true;
2832 }
2833
2834 u32 mlx5_esw_match_metadata_alloc(struct mlx5_eswitch *esw)
2835 {
2836         u32 vport_end_ida = (1 << ESW_VPORT_BITS) - 1;
2837         /* Reserve 0xf for internal port offload */
2838         u32 max_pf_num = (1 << ESW_PFNUM_BITS) - 2;
2839         u32 pf_num;
2840         int id;
2841
2842         /* Only 4 bits of pf_num */
2843         pf_num = mlx5_get_dev_index(esw->dev);
2844         if (pf_num > max_pf_num)
2845                 return 0;
2846
2847         /* Metadata is 4 bits of PFNUM and 12 bits of unique id */
2848         /* Use only non-zero vport_id (1-4095) for all PF's */
2849         id = ida_alloc_range(&esw->offloads.vport_metadata_ida, 1, vport_end_ida, GFP_KERNEL);
2850         if (id < 0)
2851                 return 0;
2852         id = (pf_num << ESW_VPORT_BITS) | id;
2853         return id;
2854 }
2855
2856 void mlx5_esw_match_metadata_free(struct mlx5_eswitch *esw, u32 metadata)
2857 {
2858         u32 vport_bit_mask = (1 << ESW_VPORT_BITS) - 1;
2859
2860         /* Metadata contains only 12 bits of actual ida id */
2861         ida_free(&esw->offloads.vport_metadata_ida, metadata & vport_bit_mask);
2862 }
2863
2864 static int esw_offloads_vport_metadata_setup(struct mlx5_eswitch *esw,
2865                                              struct mlx5_vport *vport)
2866 {
2867         vport->default_metadata = mlx5_esw_match_metadata_alloc(esw);
2868         vport->metadata = vport->default_metadata;
2869         return vport->metadata ? 0 : -ENOSPC;
2870 }
2871
2872 static void esw_offloads_vport_metadata_cleanup(struct mlx5_eswitch *esw,
2873                                                 struct mlx5_vport *vport)
2874 {
2875         if (!vport->default_metadata)
2876                 return;
2877
2878         WARN_ON(vport->metadata != vport->default_metadata);
2879         mlx5_esw_match_metadata_free(esw, vport->default_metadata);
2880 }
2881
2882 static void esw_offloads_metadata_uninit(struct mlx5_eswitch *esw)
2883 {
2884         struct mlx5_vport *vport;
2885         unsigned long i;
2886
2887         if (!mlx5_eswitch_vport_match_metadata_enabled(esw))
2888                 return;
2889
2890         mlx5_esw_for_each_vport(esw, i, vport)
2891                 esw_offloads_vport_metadata_cleanup(esw, vport);
2892 }
2893
2894 static int esw_offloads_metadata_init(struct mlx5_eswitch *esw)
2895 {
2896         struct mlx5_vport *vport;
2897         unsigned long i;
2898         int err;
2899
2900         if (!mlx5_eswitch_vport_match_metadata_enabled(esw))
2901                 return 0;
2902
2903         mlx5_esw_for_each_vport(esw, i, vport) {
2904                 err = esw_offloads_vport_metadata_setup(esw, vport);
2905                 if (err)
2906                         goto metadata_err;
2907         }
2908
2909         return 0;
2910
2911 metadata_err:
2912         esw_offloads_metadata_uninit(esw);
2913         return err;
2914 }
2915
2916 int mlx5_esw_offloads_vport_metadata_set(struct mlx5_eswitch *esw, bool enable)
2917 {
2918         int err = 0;
2919
2920         down_write(&esw->mode_lock);
2921         if (esw->mode != MLX5_ESWITCH_NONE) {
2922                 err = -EBUSY;
2923                 goto done;
2924         }
2925         if (!mlx5_esw_vport_match_metadata_supported(esw)) {
2926                 err = -EOPNOTSUPP;
2927                 goto done;
2928         }
2929         if (enable)
2930                 esw->flags |= MLX5_ESWITCH_VPORT_MATCH_METADATA;
2931         else
2932                 esw->flags &= ~MLX5_ESWITCH_VPORT_MATCH_METADATA;
2933 done:
2934         up_write(&esw->mode_lock);
2935         return err;
2936 }
2937
2938 int
2939 esw_vport_create_offloads_acl_tables(struct mlx5_eswitch *esw,
2940                                      struct mlx5_vport *vport)
2941 {
2942         int err;
2943
2944         err = esw_acl_ingress_ofld_setup(esw, vport);
2945         if (err)
2946                 return err;
2947
2948         err = esw_acl_egress_ofld_setup(esw, vport);
2949         if (err)
2950                 goto egress_err;
2951
2952         return 0;
2953
2954 egress_err:
2955         esw_acl_ingress_ofld_cleanup(esw, vport);
2956         return err;
2957 }
2958
2959 void
2960 esw_vport_destroy_offloads_acl_tables(struct mlx5_eswitch *esw,
2961                                       struct mlx5_vport *vport)
2962 {
2963         esw_acl_egress_ofld_cleanup(vport);
2964         esw_acl_ingress_ofld_cleanup(esw, vport);
2965 }
2966
2967 static int esw_create_uplink_offloads_acl_tables(struct mlx5_eswitch *esw)
2968 {
2969         struct mlx5_vport *vport;
2970
2971         vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_UPLINK);
2972         if (IS_ERR(vport))
2973                 return PTR_ERR(vport);
2974
2975         return esw_vport_create_offloads_acl_tables(esw, vport);
2976 }
2977
2978 static void esw_destroy_uplink_offloads_acl_tables(struct mlx5_eswitch *esw)
2979 {
2980         struct mlx5_vport *vport;
2981
2982         vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_UPLINK);
2983         if (IS_ERR(vport))
2984                 return;
2985
2986         esw_vport_destroy_offloads_acl_tables(esw, vport);
2987 }
2988
2989 int mlx5_eswitch_reload_reps(struct mlx5_eswitch *esw)
2990 {
2991         struct mlx5_eswitch_rep *rep;
2992         unsigned long i;
2993         int ret;
2994
2995         if (!esw || esw->mode != MLX5_ESWITCH_OFFLOADS)
2996                 return 0;
2997
2998         rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_UPLINK);
2999         if (atomic_read(&rep->rep_data[REP_ETH].state) != REP_LOADED)
3000                 return 0;
3001
3002         ret = mlx5_esw_offloads_rep_load(esw, MLX5_VPORT_UPLINK);
3003         if (ret)
3004                 return ret;
3005
3006         mlx5_esw_for_each_rep(esw, i, rep) {
3007                 if (atomic_read(&rep->rep_data[REP_ETH].state) == REP_LOADED)
3008                         mlx5_esw_offloads_rep_load(esw, rep->vport);
3009         }
3010
3011         return 0;
3012 }
3013
3014 static int esw_offloads_steering_init(struct mlx5_eswitch *esw)
3015 {
3016         struct mlx5_esw_indir_table *indir;
3017         int err;
3018
3019         memset(&esw->fdb_table.offloads, 0, sizeof(struct offloads_fdb));
3020         mutex_init(&esw->fdb_table.offloads.vports.lock);
3021         hash_init(esw->fdb_table.offloads.vports.table);
3022         atomic64_set(&esw->user_count, 0);
3023
3024         indir = mlx5_esw_indir_table_init();
3025         if (IS_ERR(indir)) {
3026                 err = PTR_ERR(indir);
3027                 goto create_indir_err;
3028         }
3029         esw->fdb_table.offloads.indir = indir;
3030
3031         err = esw_create_uplink_offloads_acl_tables(esw);
3032         if (err)
3033                 goto create_acl_err;
3034
3035         err = esw_create_offloads_table(esw);
3036         if (err)
3037                 goto create_offloads_err;
3038
3039         err = esw_create_restore_table(esw);
3040         if (err)
3041                 goto create_restore_err;
3042
3043         err = esw_create_offloads_fdb_tables(esw);
3044         if (err)
3045                 goto create_fdb_err;
3046
3047         err = esw_create_vport_rx_group(esw);
3048         if (err)
3049                 goto create_fg_err;
3050
3051         return 0;
3052
3053 create_fg_err:
3054         esw_destroy_offloads_fdb_tables(esw);
3055 create_fdb_err:
3056         esw_destroy_restore_table(esw);
3057 create_restore_err:
3058         esw_destroy_offloads_table(esw);
3059 create_offloads_err:
3060         esw_destroy_uplink_offloads_acl_tables(esw);
3061 create_acl_err:
3062         mlx5_esw_indir_table_destroy(esw->fdb_table.offloads.indir);
3063 create_indir_err:
3064         mutex_destroy(&esw->fdb_table.offloads.vports.lock);
3065         return err;
3066 }
3067
3068 static void esw_offloads_steering_cleanup(struct mlx5_eswitch *esw)
3069 {
3070         esw_destroy_vport_rx_group(esw);
3071         esw_destroy_offloads_fdb_tables(esw);
3072         esw_destroy_restore_table(esw);
3073         esw_destroy_offloads_table(esw);
3074         esw_destroy_uplink_offloads_acl_tables(esw);
3075         mlx5_esw_indir_table_destroy(esw->fdb_table.offloads.indir);
3076         mutex_destroy(&esw->fdb_table.offloads.vports.lock);
3077 }
3078
3079 static void
3080 esw_vfs_changed_event_handler(struct mlx5_eswitch *esw, const u32 *out)
3081 {
3082         bool host_pf_disabled;
3083         u16 new_num_vfs;
3084
3085         new_num_vfs = MLX5_GET(query_esw_functions_out, out,
3086                                host_params_context.host_num_of_vfs);
3087         host_pf_disabled = MLX5_GET(query_esw_functions_out, out,
3088                                     host_params_context.host_pf_disabled);
3089
3090         if (new_num_vfs == esw->esw_funcs.num_vfs || host_pf_disabled)
3091                 return;
3092
3093         /* Number of VFs can only change from "0 to x" or "x to 0". */
3094         if (esw->esw_funcs.num_vfs > 0) {
3095                 mlx5_eswitch_unload_vf_vports(esw, esw->esw_funcs.num_vfs);
3096         } else {
3097                 int err;
3098
3099                 err = mlx5_eswitch_load_vf_vports(esw, new_num_vfs,
3100                                                   MLX5_VPORT_UC_ADDR_CHANGE);
3101                 if (err)
3102                         return;
3103         }
3104         esw->esw_funcs.num_vfs = new_num_vfs;
3105 }
3106
3107 static void esw_functions_changed_event_handler(struct work_struct *work)
3108 {
3109         struct mlx5_host_work *host_work;
3110         struct mlx5_eswitch *esw;
3111         const u32 *out;
3112
3113         host_work = container_of(work, struct mlx5_host_work, work);
3114         esw = host_work->esw;
3115
3116         out = mlx5_esw_query_functions(esw->dev);
3117         if (IS_ERR(out))
3118                 goto out;
3119
3120         esw_vfs_changed_event_handler(esw, out);
3121         kvfree(out);
3122 out:
3123         kfree(host_work);
3124 }
3125
3126 int mlx5_esw_funcs_changed_handler(struct notifier_block *nb, unsigned long type, void *data)
3127 {
3128         struct mlx5_esw_functions *esw_funcs;
3129         struct mlx5_host_work *host_work;
3130         struct mlx5_eswitch *esw;
3131
3132         host_work = kzalloc(sizeof(*host_work), GFP_ATOMIC);
3133         if (!host_work)
3134                 return NOTIFY_DONE;
3135
3136         esw_funcs = mlx5_nb_cof(nb, struct mlx5_esw_functions, nb);
3137         esw = container_of(esw_funcs, struct mlx5_eswitch, esw_funcs);
3138
3139         host_work->esw = esw;
3140
3141         INIT_WORK(&host_work->work, esw_functions_changed_event_handler);
3142         queue_work(esw->work_queue, &host_work->work);
3143
3144         return NOTIFY_OK;
3145 }
3146
3147 static int mlx5_esw_host_number_init(struct mlx5_eswitch *esw)
3148 {
3149         const u32 *query_host_out;
3150
3151         if (!mlx5_core_is_ecpf_esw_manager(esw->dev))
3152                 return 0;
3153
3154         query_host_out = mlx5_esw_query_functions(esw->dev);
3155         if (IS_ERR(query_host_out))
3156                 return PTR_ERR(query_host_out);
3157
3158         /* Mark non local controller with non zero controller number. */
3159         esw->offloads.host_number = MLX5_GET(query_esw_functions_out, query_host_out,
3160                                              host_params_context.host_number);
3161         kvfree(query_host_out);
3162         return 0;
3163 }
3164
3165 bool mlx5_esw_offloads_controller_valid(const struct mlx5_eswitch *esw, u32 controller)
3166 {
3167         /* Local controller is always valid */
3168         if (controller == 0)
3169                 return true;
3170
3171         if (!mlx5_core_is_ecpf_esw_manager(esw->dev))
3172                 return false;
3173
3174         /* External host number starts with zero in device */
3175         return (controller == esw->offloads.host_number + 1);
3176 }
3177
3178 int esw_offloads_enable(struct mlx5_eswitch *esw)
3179 {
3180         struct mapping_ctx *reg_c0_obj_pool;
3181         struct mlx5_vport *vport;
3182         unsigned long i;
3183         u64 mapping_id;
3184         int err;
3185
3186         mutex_init(&esw->offloads.termtbl_mutex);
3187         mlx5_rdma_enable_roce(esw->dev);
3188
3189         err = mlx5_esw_host_number_init(esw);
3190         if (err)
3191                 goto err_metadata;
3192
3193         err = esw_offloads_metadata_init(esw);
3194         if (err)
3195                 goto err_metadata;
3196
3197         err = esw_set_passing_vport_metadata(esw, true);
3198         if (err)
3199                 goto err_vport_metadata;
3200
3201         mapping_id = mlx5_query_nic_system_image_guid(esw->dev);
3202
3203         reg_c0_obj_pool = mapping_create_for_id(mapping_id, MAPPING_TYPE_CHAIN,
3204                                                 sizeof(struct mlx5_mapped_obj),
3205                                                 ESW_REG_C0_USER_DATA_METADATA_MASK,
3206                                                 true);
3207
3208         if (IS_ERR(reg_c0_obj_pool)) {
3209                 err = PTR_ERR(reg_c0_obj_pool);
3210                 goto err_pool;
3211         }
3212         esw->offloads.reg_c0_obj_pool = reg_c0_obj_pool;
3213
3214         err = esw_offloads_steering_init(esw);
3215         if (err)
3216                 goto err_steering_init;
3217
3218         /* Representor will control the vport link state */
3219         mlx5_esw_for_each_vf_vport(esw, i, vport, esw->esw_funcs.num_vfs)
3220                 vport->info.link_state = MLX5_VPORT_ADMIN_STATE_DOWN;
3221
3222         /* Uplink vport rep must load first. */
3223         err = esw_offloads_load_rep(esw, MLX5_VPORT_UPLINK);
3224         if (err)
3225                 goto err_uplink;
3226
3227         err = mlx5_eswitch_enable_pf_vf_vports(esw, MLX5_VPORT_UC_ADDR_CHANGE);
3228         if (err)
3229                 goto err_vports;
3230
3231         esw_offloads_devcom_init(esw);
3232
3233         return 0;
3234
3235 err_vports:
3236         esw_offloads_unload_rep(esw, MLX5_VPORT_UPLINK);
3237 err_uplink:
3238         esw_offloads_steering_cleanup(esw);
3239 err_steering_init:
3240         mapping_destroy(reg_c0_obj_pool);
3241 err_pool:
3242         esw_set_passing_vport_metadata(esw, false);
3243 err_vport_metadata:
3244         esw_offloads_metadata_uninit(esw);
3245 err_metadata:
3246         mlx5_rdma_disable_roce(esw->dev);
3247         mutex_destroy(&esw->offloads.termtbl_mutex);
3248         return err;
3249 }
3250
3251 static int esw_offloads_stop(struct mlx5_eswitch *esw,
3252                              struct netlink_ext_ack *extack)
3253 {
3254         int err, err1;
3255
3256         mlx5_eswitch_disable_locked(esw, false);
3257         err = mlx5_eswitch_enable_locked(esw, MLX5_ESWITCH_LEGACY,
3258                                          MLX5_ESWITCH_IGNORE_NUM_VFS);
3259         if (err) {
3260                 NL_SET_ERR_MSG_MOD(extack, "Failed setting eswitch to legacy");
3261                 err1 = mlx5_eswitch_enable_locked(esw, MLX5_ESWITCH_OFFLOADS,
3262                                                   MLX5_ESWITCH_IGNORE_NUM_VFS);
3263                 if (err1) {
3264                         NL_SET_ERR_MSG_MOD(extack,
3265                                            "Failed setting eswitch back to offloads");
3266                 }
3267         }
3268
3269         return err;
3270 }
3271
3272 void esw_offloads_disable(struct mlx5_eswitch *esw)
3273 {
3274         esw_offloads_devcom_cleanup(esw);
3275         mlx5_eswitch_disable_pf_vf_vports(esw);
3276         esw_offloads_unload_rep(esw, MLX5_VPORT_UPLINK);
3277         esw_set_passing_vport_metadata(esw, false);
3278         esw_offloads_steering_cleanup(esw);
3279         mapping_destroy(esw->offloads.reg_c0_obj_pool);
3280         esw_offloads_metadata_uninit(esw);
3281         mlx5_rdma_disable_roce(esw->dev);
3282         mutex_destroy(&esw->offloads.termtbl_mutex);
3283 }
3284
3285 static int esw_mode_from_devlink(u16 mode, u16 *mlx5_mode)
3286 {
3287         switch (mode) {
3288         case DEVLINK_ESWITCH_MODE_LEGACY:
3289                 *mlx5_mode = MLX5_ESWITCH_LEGACY;
3290                 break;
3291         case DEVLINK_ESWITCH_MODE_SWITCHDEV:
3292                 *mlx5_mode = MLX5_ESWITCH_OFFLOADS;
3293                 break;
3294         default:
3295                 return -EINVAL;
3296         }
3297
3298         return 0;
3299 }
3300
3301 static int esw_mode_to_devlink(u16 mlx5_mode, u16 *mode)
3302 {
3303         switch (mlx5_mode) {
3304         case MLX5_ESWITCH_LEGACY:
3305                 *mode = DEVLINK_ESWITCH_MODE_LEGACY;
3306                 break;
3307         case MLX5_ESWITCH_OFFLOADS:
3308                 *mode = DEVLINK_ESWITCH_MODE_SWITCHDEV;
3309                 break;
3310         default:
3311                 return -EINVAL;
3312         }
3313
3314         return 0;
3315 }
3316
3317 static int esw_inline_mode_from_devlink(u8 mode, u8 *mlx5_mode)
3318 {
3319         switch (mode) {
3320         case DEVLINK_ESWITCH_INLINE_MODE_NONE:
3321                 *mlx5_mode = MLX5_INLINE_MODE_NONE;
3322                 break;
3323         case DEVLINK_ESWITCH_INLINE_MODE_LINK:
3324                 *mlx5_mode = MLX5_INLINE_MODE_L2;
3325                 break;
3326         case DEVLINK_ESWITCH_INLINE_MODE_NETWORK:
3327                 *mlx5_mode = MLX5_INLINE_MODE_IP;
3328                 break;
3329         case DEVLINK_ESWITCH_INLINE_MODE_TRANSPORT:
3330                 *mlx5_mode = MLX5_INLINE_MODE_TCP_UDP;
3331                 break;
3332         default:
3333                 return -EINVAL;
3334         }
3335
3336         return 0;
3337 }
3338
3339 static int esw_inline_mode_to_devlink(u8 mlx5_mode, u8 *mode)
3340 {
3341         switch (mlx5_mode) {
3342         case MLX5_INLINE_MODE_NONE:
3343                 *mode = DEVLINK_ESWITCH_INLINE_MODE_NONE;
3344                 break;
3345         case MLX5_INLINE_MODE_L2:
3346                 *mode = DEVLINK_ESWITCH_INLINE_MODE_LINK;
3347                 break;
3348         case MLX5_INLINE_MODE_IP:
3349                 *mode = DEVLINK_ESWITCH_INLINE_MODE_NETWORK;
3350                 break;
3351         case MLX5_INLINE_MODE_TCP_UDP:
3352                 *mode = DEVLINK_ESWITCH_INLINE_MODE_TRANSPORT;
3353                 break;
3354         default:
3355                 return -EINVAL;
3356         }
3357
3358         return 0;
3359 }
3360
3361 static int eswitch_devlink_esw_mode_check(const struct mlx5_eswitch *esw)
3362 {
3363         /* devlink commands in NONE eswitch mode are currently supported only
3364          * on ECPF.
3365          */
3366         return (esw->mode == MLX5_ESWITCH_NONE &&
3367                 !mlx5_core_is_ecpf_esw_manager(esw->dev)) ? -EOPNOTSUPP : 0;
3368 }
3369
3370 int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode,
3371                                   struct netlink_ext_ack *extack)
3372 {
3373         u16 cur_mlx5_mode, mlx5_mode = 0;
3374         struct mlx5_eswitch *esw;
3375         int err = 0;
3376
3377         esw = mlx5_devlink_eswitch_get(devlink);
3378         if (IS_ERR(esw))
3379                 return PTR_ERR(esw);
3380
3381         if (esw_mode_from_devlink(mode, &mlx5_mode))
3382                 return -EINVAL;
3383
3384         mlx5_lag_disable_change(esw->dev);
3385         err = mlx5_esw_try_lock(esw);
3386         if (err < 0) {
3387                 NL_SET_ERR_MSG_MOD(extack, "Can't change mode, E-Switch is busy");
3388                 goto enable_lag;
3389         }
3390         cur_mlx5_mode = err;
3391         err = 0;
3392
3393         if (cur_mlx5_mode == mlx5_mode)
3394                 goto unlock;
3395
3396         if (mode == DEVLINK_ESWITCH_MODE_SWITCHDEV) {
3397                 if (mlx5_devlink_trap_get_num_active(esw->dev)) {
3398                         NL_SET_ERR_MSG_MOD(extack,
3399                                            "Can't change mode while devlink traps are active");
3400                         err = -EOPNOTSUPP;
3401                         goto unlock;
3402                 }
3403                 err = esw_offloads_start(esw, extack);
3404         } else if (mode == DEVLINK_ESWITCH_MODE_LEGACY) {
3405                 err = esw_offloads_stop(esw, extack);
3406         } else {
3407                 err = -EINVAL;
3408         }
3409
3410 unlock:
3411         mlx5_esw_unlock(esw);
3412 enable_lag:
3413         mlx5_lag_enable_change(esw->dev);
3414         return err;
3415 }
3416
3417 int mlx5_devlink_eswitch_mode_get(struct devlink *devlink, u16 *mode)
3418 {
3419         struct mlx5_eswitch *esw;
3420         int err;
3421
3422         esw = mlx5_devlink_eswitch_get(devlink);
3423         if (IS_ERR(esw))
3424                 return PTR_ERR(esw);
3425
3426         down_write(&esw->mode_lock);
3427         err = eswitch_devlink_esw_mode_check(esw);
3428         if (err)
3429                 goto unlock;
3430
3431         err = esw_mode_to_devlink(esw->mode, mode);
3432 unlock:
3433         up_write(&esw->mode_lock);
3434         return err;
3435 }
3436
3437 static int mlx5_esw_vports_inline_set(struct mlx5_eswitch *esw, u8 mlx5_mode,
3438                                       struct netlink_ext_ack *extack)
3439 {
3440         struct mlx5_core_dev *dev = esw->dev;
3441         struct mlx5_vport *vport;
3442         u16 err_vport_num = 0;
3443         unsigned long i;
3444         int err = 0;
3445
3446         mlx5_esw_for_each_host_func_vport(esw, i, vport, esw->esw_funcs.num_vfs) {
3447                 err = mlx5_modify_nic_vport_min_inline(dev, vport->vport, mlx5_mode);
3448                 if (err) {
3449                         err_vport_num = vport->vport;
3450                         NL_SET_ERR_MSG_MOD(extack,
3451                                            "Failed to set min inline on vport");
3452                         goto revert_inline_mode;
3453                 }
3454         }
3455         return 0;
3456
3457 revert_inline_mode:
3458         mlx5_esw_for_each_host_func_vport(esw, i, vport, esw->esw_funcs.num_vfs) {
3459                 if (vport->vport == err_vport_num)
3460                         break;
3461                 mlx5_modify_nic_vport_min_inline(dev,
3462                                                  vport->vport,
3463                                                  esw->offloads.inline_mode);
3464         }
3465         return err;
3466 }
3467
3468 int mlx5_devlink_eswitch_inline_mode_set(struct devlink *devlink, u8 mode,
3469                                          struct netlink_ext_ack *extack)
3470 {
3471         struct mlx5_core_dev *dev = devlink_priv(devlink);
3472         struct mlx5_eswitch *esw;
3473         u8 mlx5_mode;
3474         int err;
3475
3476         esw = mlx5_devlink_eswitch_get(devlink);
3477         if (IS_ERR(esw))
3478                 return PTR_ERR(esw);
3479
3480         down_write(&esw->mode_lock);
3481         err = eswitch_devlink_esw_mode_check(esw);
3482         if (err)
3483                 goto out;
3484
3485         switch (MLX5_CAP_ETH(dev, wqe_inline_mode)) {
3486         case MLX5_CAP_INLINE_MODE_NOT_REQUIRED:
3487                 if (mode == DEVLINK_ESWITCH_INLINE_MODE_NONE) {
3488                         err = 0;
3489                         goto out;
3490                 }
3491
3492                 fallthrough;
3493         case MLX5_CAP_INLINE_MODE_L2:
3494                 NL_SET_ERR_MSG_MOD(extack, "Inline mode can't be set");
3495                 err = -EOPNOTSUPP;
3496                 goto out;
3497         case MLX5_CAP_INLINE_MODE_VPORT_CONTEXT:
3498                 break;
3499         }
3500
3501         if (atomic64_read(&esw->offloads.num_flows) > 0) {
3502                 NL_SET_ERR_MSG_MOD(extack,
3503                                    "Can't set inline mode when flows are configured");
3504                 err = -EOPNOTSUPP;
3505                 goto out;
3506         }
3507
3508         err = esw_inline_mode_from_devlink(mode, &mlx5_mode);
3509         if (err)
3510                 goto out;
3511
3512         err = mlx5_esw_vports_inline_set(esw, mlx5_mode, extack);
3513         if (err)
3514                 goto out;
3515
3516         esw->offloads.inline_mode = mlx5_mode;
3517         up_write(&esw->mode_lock);
3518         return 0;
3519
3520 out:
3521         up_write(&esw->mode_lock);
3522         return err;
3523 }
3524
3525 int mlx5_devlink_eswitch_inline_mode_get(struct devlink *devlink, u8 *mode)
3526 {
3527         struct mlx5_eswitch *esw;
3528         int err;
3529
3530         esw = mlx5_devlink_eswitch_get(devlink);
3531         if (IS_ERR(esw))
3532                 return PTR_ERR(esw);
3533
3534         down_write(&esw->mode_lock);
3535         err = eswitch_devlink_esw_mode_check(esw);
3536         if (err)
3537                 goto unlock;
3538
3539         err = esw_inline_mode_to_devlink(esw->offloads.inline_mode, mode);
3540 unlock:
3541         up_write(&esw->mode_lock);
3542         return err;
3543 }
3544
3545 int mlx5_devlink_eswitch_encap_mode_set(struct devlink *devlink,
3546                                         enum devlink_eswitch_encap_mode encap,
3547                                         struct netlink_ext_ack *extack)
3548 {
3549         struct mlx5_core_dev *dev = devlink_priv(devlink);
3550         struct mlx5_eswitch *esw;
3551         int err;
3552
3553         esw = mlx5_devlink_eswitch_get(devlink);
3554         if (IS_ERR(esw))
3555                 return PTR_ERR(esw);
3556
3557         down_write(&esw->mode_lock);
3558         err = eswitch_devlink_esw_mode_check(esw);
3559         if (err)
3560                 goto unlock;
3561
3562         if (encap != DEVLINK_ESWITCH_ENCAP_MODE_NONE &&
3563             (!MLX5_CAP_ESW_FLOWTABLE_FDB(dev, reformat) ||
3564              !MLX5_CAP_ESW_FLOWTABLE_FDB(dev, decap))) {
3565                 err = -EOPNOTSUPP;
3566                 goto unlock;
3567         }
3568
3569         if (encap && encap != DEVLINK_ESWITCH_ENCAP_MODE_BASIC) {
3570                 err = -EOPNOTSUPP;
3571                 goto unlock;
3572         }
3573
3574         if (esw->mode == MLX5_ESWITCH_LEGACY) {
3575                 esw->offloads.encap = encap;
3576                 goto unlock;
3577         }
3578
3579         if (esw->offloads.encap == encap)
3580                 goto unlock;
3581
3582         if (atomic64_read(&esw->offloads.num_flows) > 0) {
3583                 NL_SET_ERR_MSG_MOD(extack,
3584                                    "Can't set encapsulation when flows are configured");
3585                 err = -EOPNOTSUPP;
3586                 goto unlock;
3587         }
3588
3589         esw_destroy_offloads_fdb_tables(esw);
3590
3591         esw->offloads.encap = encap;
3592
3593         err = esw_create_offloads_fdb_tables(esw);
3594
3595         if (err) {
3596                 NL_SET_ERR_MSG_MOD(extack,
3597                                    "Failed re-creating fast FDB table");
3598                 esw->offloads.encap = !encap;
3599                 (void)esw_create_offloads_fdb_tables(esw);
3600         }
3601
3602 unlock:
3603         up_write(&esw->mode_lock);
3604         return err;
3605 }
3606
3607 int mlx5_devlink_eswitch_encap_mode_get(struct devlink *devlink,
3608                                         enum devlink_eswitch_encap_mode *encap)
3609 {
3610         struct mlx5_eswitch *esw;
3611         int err;
3612
3613         esw = mlx5_devlink_eswitch_get(devlink);
3614         if (IS_ERR(esw))
3615                 return PTR_ERR(esw);
3616
3617
3618         down_write(&esw->mode_lock);
3619         err = eswitch_devlink_esw_mode_check(esw);
3620         if (err)
3621                 goto unlock;
3622
3623         *encap = esw->offloads.encap;
3624 unlock:
3625         up_write(&esw->mode_lock);
3626         return err;
3627 }
3628
3629 static bool
3630 mlx5_eswitch_vport_has_rep(const struct mlx5_eswitch *esw, u16 vport_num)
3631 {
3632         /* Currently, only ECPF based device has representor for host PF. */
3633         if (vport_num == MLX5_VPORT_PF &&
3634             !mlx5_core_is_ecpf_esw_manager(esw->dev))
3635                 return false;
3636
3637         if (vport_num == MLX5_VPORT_ECPF &&
3638             !mlx5_ecpf_vport_exists(esw->dev))
3639                 return false;
3640
3641         return true;
3642 }
3643
3644 void mlx5_eswitch_register_vport_reps(struct mlx5_eswitch *esw,
3645                                       const struct mlx5_eswitch_rep_ops *ops,
3646                                       u8 rep_type)
3647 {
3648         struct mlx5_eswitch_rep_data *rep_data;
3649         struct mlx5_eswitch_rep *rep;
3650         unsigned long i;
3651
3652         esw->offloads.rep_ops[rep_type] = ops;
3653         mlx5_esw_for_each_rep(esw, i, rep) {
3654                 if (likely(mlx5_eswitch_vport_has_rep(esw, rep->vport))) {
3655                         rep->esw = esw;
3656                         rep_data = &rep->rep_data[rep_type];
3657                         atomic_set(&rep_data->state, REP_REGISTERED);
3658                 }
3659         }
3660 }
3661 EXPORT_SYMBOL(mlx5_eswitch_register_vport_reps);
3662
3663 void mlx5_eswitch_unregister_vport_reps(struct mlx5_eswitch *esw, u8 rep_type)
3664 {
3665         struct mlx5_eswitch_rep *rep;
3666         unsigned long i;
3667
3668         if (esw->mode == MLX5_ESWITCH_OFFLOADS)
3669                 __unload_reps_all_vport(esw, rep_type);
3670
3671         mlx5_esw_for_each_rep(esw, i, rep)
3672                 atomic_set(&rep->rep_data[rep_type].state, REP_UNREGISTERED);
3673 }
3674 EXPORT_SYMBOL(mlx5_eswitch_unregister_vport_reps);
3675
3676 void *mlx5_eswitch_get_uplink_priv(struct mlx5_eswitch *esw, u8 rep_type)
3677 {
3678         struct mlx5_eswitch_rep *rep;
3679
3680         rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_UPLINK);
3681         return rep->rep_data[rep_type].priv;
3682 }
3683
3684 void *mlx5_eswitch_get_proto_dev(struct mlx5_eswitch *esw,
3685                                  u16 vport,
3686                                  u8 rep_type)
3687 {
3688         struct mlx5_eswitch_rep *rep;
3689
3690         rep = mlx5_eswitch_get_rep(esw, vport);
3691
3692         if (atomic_read(&rep->rep_data[rep_type].state) == REP_LOADED &&
3693             esw->offloads.rep_ops[rep_type]->get_proto_dev)
3694                 return esw->offloads.rep_ops[rep_type]->get_proto_dev(rep);
3695         return NULL;
3696 }
3697 EXPORT_SYMBOL(mlx5_eswitch_get_proto_dev);
3698
3699 void *mlx5_eswitch_uplink_get_proto_dev(struct mlx5_eswitch *esw, u8 rep_type)
3700 {
3701         return mlx5_eswitch_get_proto_dev(esw, MLX5_VPORT_UPLINK, rep_type);
3702 }
3703 EXPORT_SYMBOL(mlx5_eswitch_uplink_get_proto_dev);
3704
3705 struct mlx5_eswitch_rep *mlx5_eswitch_vport_rep(struct mlx5_eswitch *esw,
3706                                                 u16 vport)
3707 {
3708         return mlx5_eswitch_get_rep(esw, vport);
3709 }
3710 EXPORT_SYMBOL(mlx5_eswitch_vport_rep);
3711
3712 bool mlx5_eswitch_reg_c1_loopback_enabled(const struct mlx5_eswitch *esw)
3713 {
3714         return !!(esw->flags & MLX5_ESWITCH_REG_C1_LOOPBACK_ENABLED);
3715 }
3716 EXPORT_SYMBOL(mlx5_eswitch_reg_c1_loopback_enabled);
3717
3718 bool mlx5_eswitch_vport_match_metadata_enabled(const struct mlx5_eswitch *esw)
3719 {
3720         return !!(esw->flags & MLX5_ESWITCH_VPORT_MATCH_METADATA);
3721 }
3722 EXPORT_SYMBOL(mlx5_eswitch_vport_match_metadata_enabled);
3723
3724 u32 mlx5_eswitch_get_vport_metadata_for_match(struct mlx5_eswitch *esw,
3725                                               u16 vport_num)
3726 {
3727         struct mlx5_vport *vport = mlx5_eswitch_get_vport(esw, vport_num);
3728
3729         if (WARN_ON_ONCE(IS_ERR(vport)))
3730                 return 0;
3731
3732         return vport->metadata << (32 - ESW_SOURCE_PORT_METADATA_BITS);
3733 }
3734 EXPORT_SYMBOL(mlx5_eswitch_get_vport_metadata_for_match);
3735
3736 int mlx5_esw_offloads_sf_vport_enable(struct mlx5_eswitch *esw, struct devlink_port *dl_port,
3737                                       u16 vport_num, u32 controller, u32 sfnum)
3738 {
3739         int err;
3740
3741         err = mlx5_esw_vport_enable(esw, vport_num, MLX5_VPORT_UC_ADDR_CHANGE);
3742         if (err)
3743                 return err;
3744
3745         err = mlx5_esw_devlink_sf_port_register(esw, dl_port, vport_num, controller, sfnum);
3746         if (err)
3747                 goto devlink_err;
3748
3749         err = mlx5_esw_offloads_rep_load(esw, vport_num);
3750         if (err)
3751                 goto rep_err;
3752         return 0;
3753
3754 rep_err:
3755         mlx5_esw_devlink_sf_port_unregister(esw, vport_num);
3756 devlink_err:
3757         mlx5_esw_vport_disable(esw, vport_num);
3758         return err;
3759 }
3760
3761 void mlx5_esw_offloads_sf_vport_disable(struct mlx5_eswitch *esw, u16 vport_num)
3762 {
3763         mlx5_esw_offloads_rep_unload(esw, vport_num);
3764         mlx5_esw_devlink_sf_port_unregister(esw, vport_num);
3765         mlx5_esw_vport_disable(esw, vport_num);
3766 }
3767
3768 static int mlx5_esw_query_vport_vhca_id(struct mlx5_eswitch *esw, u16 vport_num, u16 *vhca_id)
3769 {
3770         int query_out_sz = MLX5_ST_SZ_BYTES(query_hca_cap_out);
3771         void *query_ctx;
3772         void *hca_caps;
3773         int err;
3774
3775         *vhca_id = 0;
3776         if (mlx5_esw_is_manager_vport(esw, vport_num) ||
3777             !MLX5_CAP_GEN(esw->dev, vhca_resource_manager))
3778                 return -EPERM;
3779
3780         query_ctx = kzalloc(query_out_sz, GFP_KERNEL);
3781         if (!query_ctx)
3782                 return -ENOMEM;
3783
3784         err = mlx5_vport_get_other_func_cap(esw->dev, vport_num, query_ctx);
3785         if (err)
3786                 goto out_free;
3787
3788         hca_caps = MLX5_ADDR_OF(query_hca_cap_out, query_ctx, capability);
3789         *vhca_id = MLX5_GET(cmd_hca_cap, hca_caps, vhca_id);
3790
3791 out_free:
3792         kfree(query_ctx);
3793         return err;
3794 }
3795
3796 int mlx5_esw_vport_vhca_id_set(struct mlx5_eswitch *esw, u16 vport_num)
3797 {
3798         u16 *old_entry, *vhca_map_entry, vhca_id;
3799         int err;
3800
3801         err = mlx5_esw_query_vport_vhca_id(esw, vport_num, &vhca_id);
3802         if (err) {
3803                 esw_warn(esw->dev, "Getting vhca_id for vport failed (vport=%u,err=%d)\n",
3804                          vport_num, err);
3805                 return err;
3806         }
3807
3808         vhca_map_entry = kmalloc(sizeof(*vhca_map_entry), GFP_KERNEL);
3809         if (!vhca_map_entry)
3810                 return -ENOMEM;
3811
3812         *vhca_map_entry = vport_num;
3813         old_entry = xa_store(&esw->offloads.vhca_map, vhca_id, vhca_map_entry, GFP_KERNEL);
3814         if (xa_is_err(old_entry)) {
3815                 kfree(vhca_map_entry);
3816                 return xa_err(old_entry);
3817         }
3818         kfree(old_entry);
3819         return 0;
3820 }
3821
3822 void mlx5_esw_vport_vhca_id_clear(struct mlx5_eswitch *esw, u16 vport_num)
3823 {
3824         u16 *vhca_map_entry, vhca_id;
3825         int err;
3826
3827         err = mlx5_esw_query_vport_vhca_id(esw, vport_num, &vhca_id);
3828         if (err)
3829                 esw_warn(esw->dev, "Getting vhca_id for vport failed (vport=%hu,err=%d)\n",
3830                          vport_num, err);
3831
3832         vhca_map_entry = xa_erase(&esw->offloads.vhca_map, vhca_id);
3833         kfree(vhca_map_entry);
3834 }
3835
3836 int mlx5_eswitch_vhca_id_to_vport(struct mlx5_eswitch *esw, u16 vhca_id, u16 *vport_num)
3837 {
3838         u16 *res = xa_load(&esw->offloads.vhca_map, vhca_id);
3839
3840         if (!res)
3841                 return -ENOENT;
3842
3843         *vport_num = *res;
3844         return 0;
3845 }
3846
3847 u32 mlx5_eswitch_get_vport_metadata_for_set(struct mlx5_eswitch *esw,
3848                                             u16 vport_num)
3849 {
3850         struct mlx5_vport *vport = mlx5_eswitch_get_vport(esw, vport_num);
3851
3852         if (WARN_ON_ONCE(IS_ERR(vport)))
3853                 return 0;
3854
3855         return vport->metadata;
3856 }
3857 EXPORT_SYMBOL(mlx5_eswitch_get_vport_metadata_for_set);