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