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