Merge branch 'core-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6-microblaze.git] / drivers / net / ethernet / mellanox / mlx5 / core / eswitch.c
1 /*
2  * Copyright (c) 2015, Mellanox Technologies. All rights reserved.
3  *
4  * This software is available to you under a choice of one of two
5  * licenses.  You may choose to be licensed under the terms of the GNU
6  * General Public License (GPL) Version 2, available from the file
7  * COPYING in the main directory of this source tree, or the
8  * OpenIB.org BSD license below:
9  *
10  *     Redistribution and use in source and binary forms, with or
11  *     without modification, are permitted provided that the following
12  *     conditions are met:
13  *
14  *      - Redistributions of source code must retain the above
15  *        copyright notice, this list of conditions and the following
16  *        disclaimer.
17  *
18  *      - Redistributions in binary form must reproduce the above
19  *        copyright notice, this list of conditions and the following
20  *        disclaimer in the documentation and/or other materials
21  *        provided with the distribution.
22  *
23  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30  * SOFTWARE.
31  */
32
33 #include <linux/etherdevice.h>
34 #include <linux/mlx5/driver.h>
35 #include <linux/mlx5/mlx5_ifc.h>
36 #include <linux/mlx5/vport.h>
37 #include <linux/mlx5/fs.h>
38 #include "mlx5_core.h"
39 #include "lib/eq.h"
40 #include "eswitch.h"
41 #include "fs_core.h"
42 #include "ecpf.h"
43
44 enum {
45         MLX5_ACTION_NONE = 0,
46         MLX5_ACTION_ADD  = 1,
47         MLX5_ACTION_DEL  = 2,
48 };
49
50 /* Vport UC/MC hash node */
51 struct vport_addr {
52         struct l2addr_node     node;
53         u8                     action;
54         u16                    vport;
55         struct mlx5_flow_handle *flow_rule;
56         bool mpfs; /* UC MAC was added to MPFs */
57         /* A flag indicating that mac was added due to mc promiscuous vport */
58         bool mc_promisc;
59 };
60
61 enum {
62         UC_ADDR_CHANGE = BIT(0),
63         MC_ADDR_CHANGE = BIT(1),
64         PROMISC_CHANGE = BIT(3),
65 };
66
67 static void esw_destroy_legacy_fdb_table(struct mlx5_eswitch *esw);
68 static void esw_cleanup_vepa_rules(struct mlx5_eswitch *esw);
69
70 /* Vport context events */
71 #define SRIOV_VPORT_EVENTS (UC_ADDR_CHANGE | \
72                             MC_ADDR_CHANGE | \
73                             PROMISC_CHANGE)
74
75 struct mlx5_vport *__must_check
76 mlx5_eswitch_get_vport(struct mlx5_eswitch *esw, u16 vport_num)
77 {
78         u16 idx;
79
80         if (!esw || !MLX5_CAP_GEN(esw->dev, vport_group_manager))
81                 return ERR_PTR(-EPERM);
82
83         idx = mlx5_eswitch_vport_num_to_index(esw, vport_num);
84
85         if (idx > esw->total_vports - 1) {
86                 esw_debug(esw->dev, "vport out of range: num(0x%x), idx(0x%x)\n",
87                           vport_num, idx);
88                 return ERR_PTR(-EINVAL);
89         }
90
91         return &esw->vports[idx];
92 }
93
94 static int arm_vport_context_events_cmd(struct mlx5_core_dev *dev, u16 vport,
95                                         u32 events_mask)
96 {
97         int in[MLX5_ST_SZ_DW(modify_nic_vport_context_in)]   = {0};
98         int out[MLX5_ST_SZ_DW(modify_nic_vport_context_out)] = {0};
99         void *nic_vport_ctx;
100
101         MLX5_SET(modify_nic_vport_context_in, in,
102                  opcode, MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT);
103         MLX5_SET(modify_nic_vport_context_in, in, field_select.change_event, 1);
104         MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport);
105         MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1);
106         nic_vport_ctx = MLX5_ADDR_OF(modify_nic_vport_context_in,
107                                      in, nic_vport_context);
108
109         MLX5_SET(nic_vport_context, nic_vport_ctx, arm_change_event, 1);
110
111         if (events_mask & UC_ADDR_CHANGE)
112                 MLX5_SET(nic_vport_context, nic_vport_ctx,
113                          event_on_uc_address_change, 1);
114         if (events_mask & MC_ADDR_CHANGE)
115                 MLX5_SET(nic_vport_context, nic_vport_ctx,
116                          event_on_mc_address_change, 1);
117         if (events_mask & PROMISC_CHANGE)
118                 MLX5_SET(nic_vport_context, nic_vport_ctx,
119                          event_on_promisc_change, 1);
120
121         return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
122 }
123
124 /* E-Switch vport context HW commands */
125 static int modify_esw_vport_context_cmd(struct mlx5_core_dev *dev, u16 vport,
126                                         void *in, int inlen)
127 {
128         u32 out[MLX5_ST_SZ_DW(modify_esw_vport_context_out)] = {0};
129
130         MLX5_SET(modify_esw_vport_context_in, in, opcode,
131                  MLX5_CMD_OP_MODIFY_ESW_VPORT_CONTEXT);
132         MLX5_SET(modify_esw_vport_context_in, in, vport_number, vport);
133         MLX5_SET(modify_esw_vport_context_in, in, other_vport, 1);
134         return mlx5_cmd_exec(dev, in, inlen, out, sizeof(out));
135 }
136
137 static int modify_esw_vport_cvlan(struct mlx5_core_dev *dev, u16 vport,
138                                   u16 vlan, u8 qos, u8 set_flags)
139 {
140         u32 in[MLX5_ST_SZ_DW(modify_esw_vport_context_in)] = {0};
141
142         if (!MLX5_CAP_ESW(dev, vport_cvlan_strip) ||
143             !MLX5_CAP_ESW(dev, vport_cvlan_insert_if_not_exist))
144                 return -EOPNOTSUPP;
145
146         esw_debug(dev, "Set Vport[%d] VLAN %d qos %d set=%x\n",
147                   vport, vlan, qos, set_flags);
148
149         if (set_flags & SET_VLAN_STRIP)
150                 MLX5_SET(modify_esw_vport_context_in, in,
151                          esw_vport_context.vport_cvlan_strip, 1);
152
153         if (set_flags & SET_VLAN_INSERT) {
154                 /* insert only if no vlan in packet */
155                 MLX5_SET(modify_esw_vport_context_in, in,
156                          esw_vport_context.vport_cvlan_insert, 1);
157
158                 MLX5_SET(modify_esw_vport_context_in, in,
159                          esw_vport_context.cvlan_pcp, qos);
160                 MLX5_SET(modify_esw_vport_context_in, in,
161                          esw_vport_context.cvlan_id, vlan);
162         }
163
164         MLX5_SET(modify_esw_vport_context_in, in,
165                  field_select.vport_cvlan_strip, 1);
166         MLX5_SET(modify_esw_vport_context_in, in,
167                  field_select.vport_cvlan_insert, 1);
168
169         return modify_esw_vport_context_cmd(dev, vport, in, sizeof(in));
170 }
171
172 /* E-Switch FDB */
173 static struct mlx5_flow_handle *
174 __esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u16 vport, bool rx_rule,
175                          u8 mac_c[ETH_ALEN], u8 mac_v[ETH_ALEN])
176 {
177         int match_header = (is_zero_ether_addr(mac_c) ? 0 :
178                             MLX5_MATCH_OUTER_HEADERS);
179         struct mlx5_flow_handle *flow_rule = NULL;
180         struct mlx5_flow_act flow_act = {0};
181         struct mlx5_flow_destination dest = {};
182         struct mlx5_flow_spec *spec;
183         void *mv_misc = NULL;
184         void *mc_misc = NULL;
185         u8 *dmac_v = NULL;
186         u8 *dmac_c = NULL;
187
188         if (rx_rule)
189                 match_header |= MLX5_MATCH_MISC_PARAMETERS;
190
191         spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
192         if (!spec)
193                 return NULL;
194
195         dmac_v = MLX5_ADDR_OF(fte_match_param, spec->match_value,
196                               outer_headers.dmac_47_16);
197         dmac_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
198                               outer_headers.dmac_47_16);
199
200         if (match_header & MLX5_MATCH_OUTER_HEADERS) {
201                 ether_addr_copy(dmac_v, mac_v);
202                 ether_addr_copy(dmac_c, mac_c);
203         }
204
205         if (match_header & MLX5_MATCH_MISC_PARAMETERS) {
206                 mv_misc  = MLX5_ADDR_OF(fte_match_param, spec->match_value,
207                                         misc_parameters);
208                 mc_misc  = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
209                                         misc_parameters);
210                 MLX5_SET(fte_match_set_misc, mv_misc, source_port, MLX5_VPORT_UPLINK);
211                 MLX5_SET_TO_ONES(fte_match_set_misc, mc_misc, source_port);
212         }
213
214         dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
215         dest.vport.num = vport;
216
217         esw_debug(esw->dev,
218                   "\tFDB add rule dmac_v(%pM) dmac_c(%pM) -> vport(%d)\n",
219                   dmac_v, dmac_c, vport);
220         spec->match_criteria_enable = match_header;
221         flow_act.action =  MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
222         flow_rule =
223                 mlx5_add_flow_rules(esw->fdb_table.legacy.fdb, spec,
224                                     &flow_act, &dest, 1);
225         if (IS_ERR(flow_rule)) {
226                 esw_warn(esw->dev,
227                          "FDB: Failed to add flow rule: dmac_v(%pM) dmac_c(%pM) -> vport(%d), err(%ld)\n",
228                          dmac_v, dmac_c, vport, PTR_ERR(flow_rule));
229                 flow_rule = NULL;
230         }
231
232         kvfree(spec);
233         return flow_rule;
234 }
235
236 static struct mlx5_flow_handle *
237 esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u8 mac[ETH_ALEN], u16 vport)
238 {
239         u8 mac_c[ETH_ALEN];
240
241         eth_broadcast_addr(mac_c);
242         return __esw_fdb_set_vport_rule(esw, vport, false, mac_c, mac);
243 }
244
245 static struct mlx5_flow_handle *
246 esw_fdb_set_vport_allmulti_rule(struct mlx5_eswitch *esw, u16 vport)
247 {
248         u8 mac_c[ETH_ALEN];
249         u8 mac_v[ETH_ALEN];
250
251         eth_zero_addr(mac_c);
252         eth_zero_addr(mac_v);
253         mac_c[0] = 0x01;
254         mac_v[0] = 0x01;
255         return __esw_fdb_set_vport_rule(esw, vport, false, mac_c, mac_v);
256 }
257
258 static struct mlx5_flow_handle *
259 esw_fdb_set_vport_promisc_rule(struct mlx5_eswitch *esw, u16 vport)
260 {
261         u8 mac_c[ETH_ALEN];
262         u8 mac_v[ETH_ALEN];
263
264         eth_zero_addr(mac_c);
265         eth_zero_addr(mac_v);
266         return __esw_fdb_set_vport_rule(esw, vport, true, mac_c, mac_v);
267 }
268
269 enum {
270         LEGACY_VEPA_PRIO = 0,
271         LEGACY_FDB_PRIO,
272 };
273
274 static int esw_create_legacy_vepa_table(struct mlx5_eswitch *esw)
275 {
276         struct mlx5_core_dev *dev = esw->dev;
277         struct mlx5_flow_namespace *root_ns;
278         struct mlx5_flow_table *fdb;
279         int err;
280
281         root_ns = mlx5_get_fdb_sub_ns(dev, 0);
282         if (!root_ns) {
283                 esw_warn(dev, "Failed to get FDB flow namespace\n");
284                 return -EOPNOTSUPP;
285         }
286
287         /* num FTE 2, num FG 2 */
288         fdb = mlx5_create_auto_grouped_flow_table(root_ns, LEGACY_VEPA_PRIO,
289                                                   2, 2, 0, 0);
290         if (IS_ERR(fdb)) {
291                 err = PTR_ERR(fdb);
292                 esw_warn(dev, "Failed to create VEPA FDB err %d\n", err);
293                 return err;
294         }
295         esw->fdb_table.legacy.vepa_fdb = fdb;
296
297         return 0;
298 }
299
300 static int esw_create_legacy_fdb_table(struct mlx5_eswitch *esw)
301 {
302         int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
303         struct mlx5_flow_table_attr ft_attr = {};
304         struct mlx5_core_dev *dev = esw->dev;
305         struct mlx5_flow_namespace *root_ns;
306         struct mlx5_flow_table *fdb;
307         struct mlx5_flow_group *g;
308         void *match_criteria;
309         int table_size;
310         u32 *flow_group_in;
311         u8 *dmac;
312         int err = 0;
313
314         esw_debug(dev, "Create FDB log_max_size(%d)\n",
315                   MLX5_CAP_ESW_FLOWTABLE_FDB(dev, log_max_ft_size));
316
317         root_ns = mlx5_get_fdb_sub_ns(dev, 0);
318         if (!root_ns) {
319                 esw_warn(dev, "Failed to get FDB flow namespace\n");
320                 return -EOPNOTSUPP;
321         }
322
323         flow_group_in = kvzalloc(inlen, GFP_KERNEL);
324         if (!flow_group_in)
325                 return -ENOMEM;
326
327         table_size = BIT(MLX5_CAP_ESW_FLOWTABLE_FDB(dev, log_max_ft_size));
328         ft_attr.max_fte = table_size;
329         ft_attr.prio = LEGACY_FDB_PRIO;
330         fdb = mlx5_create_flow_table(root_ns, &ft_attr);
331         if (IS_ERR(fdb)) {
332                 err = PTR_ERR(fdb);
333                 esw_warn(dev, "Failed to create FDB Table err %d\n", err);
334                 goto out;
335         }
336         esw->fdb_table.legacy.fdb = fdb;
337
338         /* Addresses group : Full match unicast/multicast addresses */
339         MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
340                  MLX5_MATCH_OUTER_HEADERS);
341         match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in, match_criteria);
342         dmac = MLX5_ADDR_OF(fte_match_param, match_criteria, outer_headers.dmac_47_16);
343         MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 0);
344         /* Preserve 2 entries for allmulti and promisc rules*/
345         MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, table_size - 3);
346         eth_broadcast_addr(dmac);
347         g = mlx5_create_flow_group(fdb, flow_group_in);
348         if (IS_ERR(g)) {
349                 err = PTR_ERR(g);
350                 esw_warn(dev, "Failed to create flow group err(%d)\n", err);
351                 goto out;
352         }
353         esw->fdb_table.legacy.addr_grp = g;
354
355         /* Allmulti group : One rule that forwards any mcast traffic */
356         MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
357                  MLX5_MATCH_OUTER_HEADERS);
358         MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, table_size - 2);
359         MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, table_size - 2);
360         eth_zero_addr(dmac);
361         dmac[0] = 0x01;
362         g = mlx5_create_flow_group(fdb, flow_group_in);
363         if (IS_ERR(g)) {
364                 err = PTR_ERR(g);
365                 esw_warn(dev, "Failed to create allmulti flow group err(%d)\n", err);
366                 goto out;
367         }
368         esw->fdb_table.legacy.allmulti_grp = g;
369
370         /* Promiscuous group :
371          * One rule that forward all unmatched traffic from previous groups
372          */
373         eth_zero_addr(dmac);
374         MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
375                  MLX5_MATCH_MISC_PARAMETERS);
376         MLX5_SET_TO_ONES(fte_match_param, match_criteria, misc_parameters.source_port);
377         MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, table_size - 1);
378         MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, table_size - 1);
379         g = mlx5_create_flow_group(fdb, flow_group_in);
380         if (IS_ERR(g)) {
381                 err = PTR_ERR(g);
382                 esw_warn(dev, "Failed to create promisc flow group err(%d)\n", err);
383                 goto out;
384         }
385         esw->fdb_table.legacy.promisc_grp = g;
386
387 out:
388         if (err)
389                 esw_destroy_legacy_fdb_table(esw);
390
391         kvfree(flow_group_in);
392         return err;
393 }
394
395 static void esw_destroy_legacy_vepa_table(struct mlx5_eswitch *esw)
396 {
397         esw_debug(esw->dev, "Destroy VEPA Table\n");
398         if (!esw->fdb_table.legacy.vepa_fdb)
399                 return;
400
401         mlx5_destroy_flow_table(esw->fdb_table.legacy.vepa_fdb);
402         esw->fdb_table.legacy.vepa_fdb = NULL;
403 }
404
405 static void esw_destroy_legacy_fdb_table(struct mlx5_eswitch *esw)
406 {
407         esw_debug(esw->dev, "Destroy FDB Table\n");
408         if (!esw->fdb_table.legacy.fdb)
409                 return;
410
411         if (esw->fdb_table.legacy.promisc_grp)
412                 mlx5_destroy_flow_group(esw->fdb_table.legacy.promisc_grp);
413         if (esw->fdb_table.legacy.allmulti_grp)
414                 mlx5_destroy_flow_group(esw->fdb_table.legacy.allmulti_grp);
415         if (esw->fdb_table.legacy.addr_grp)
416                 mlx5_destroy_flow_group(esw->fdb_table.legacy.addr_grp);
417         mlx5_destroy_flow_table(esw->fdb_table.legacy.fdb);
418
419         esw->fdb_table.legacy.fdb = NULL;
420         esw->fdb_table.legacy.addr_grp = NULL;
421         esw->fdb_table.legacy.allmulti_grp = NULL;
422         esw->fdb_table.legacy.promisc_grp = NULL;
423 }
424
425 static int esw_create_legacy_table(struct mlx5_eswitch *esw)
426 {
427         int err;
428
429         memset(&esw->fdb_table.legacy, 0, sizeof(struct legacy_fdb));
430
431         err = esw_create_legacy_vepa_table(esw);
432         if (err)
433                 return err;
434
435         err = esw_create_legacy_fdb_table(esw);
436         if (err)
437                 esw_destroy_legacy_vepa_table(esw);
438
439         return err;
440 }
441
442 static void esw_destroy_legacy_table(struct mlx5_eswitch *esw)
443 {
444         esw_cleanup_vepa_rules(esw);
445         esw_destroy_legacy_fdb_table(esw);
446         esw_destroy_legacy_vepa_table(esw);
447 }
448
449 /* E-Switch vport UC/MC lists management */
450 typedef int (*vport_addr_action)(struct mlx5_eswitch *esw,
451                                  struct vport_addr *vaddr);
452
453 static int esw_add_uc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr)
454 {
455         u8 *mac = vaddr->node.addr;
456         u16 vport = vaddr->vport;
457         int err;
458
459         /* Skip mlx5_mpfs_add_mac for eswitch_managers,
460          * it is already done by its netdev in mlx5e_execute_l2_action
461          */
462         if (esw->manager_vport == vport)
463                 goto fdb_add;
464
465         err = mlx5_mpfs_add_mac(esw->dev, mac);
466         if (err) {
467                 esw_warn(esw->dev,
468                          "Failed to add L2 table mac(%pM) for vport(0x%x), err(%d)\n",
469                          mac, vport, err);
470                 return err;
471         }
472         vaddr->mpfs = true;
473
474 fdb_add:
475         /* SRIOV is enabled: Forward UC MAC to vport */
476         if (esw->fdb_table.legacy.fdb && esw->mode == SRIOV_LEGACY)
477                 vaddr->flow_rule = esw_fdb_set_vport_rule(esw, mac, vport);
478
479         esw_debug(esw->dev, "\tADDED UC MAC: vport[%d] %pM fr(%p)\n",
480                   vport, mac, vaddr->flow_rule);
481
482         return 0;
483 }
484
485 static int esw_del_uc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr)
486 {
487         u8 *mac = vaddr->node.addr;
488         u16 vport = vaddr->vport;
489         int err = 0;
490
491         /* Skip mlx5_mpfs_del_mac for eswitch managerss,
492          * it is already done by its netdev in mlx5e_execute_l2_action
493          */
494         if (!vaddr->mpfs || esw->manager_vport == vport)
495                 goto fdb_del;
496
497         err = mlx5_mpfs_del_mac(esw->dev, mac);
498         if (err)
499                 esw_warn(esw->dev,
500                          "Failed to del L2 table mac(%pM) for vport(%d), err(%d)\n",
501                          mac, vport, err);
502         vaddr->mpfs = false;
503
504 fdb_del:
505         if (vaddr->flow_rule)
506                 mlx5_del_flow_rules(vaddr->flow_rule);
507         vaddr->flow_rule = NULL;
508
509         return 0;
510 }
511
512 static void update_allmulti_vports(struct mlx5_eswitch *esw,
513                                    struct vport_addr *vaddr,
514                                    struct esw_mc_addr *esw_mc)
515 {
516         u8 *mac = vaddr->node.addr;
517         struct mlx5_vport *vport;
518         u16 i, vport_num;
519
520         mlx5_esw_for_all_vports(esw, i, vport) {
521                 struct hlist_head *vport_hash = vport->mc_list;
522                 struct vport_addr *iter_vaddr =
523                                         l2addr_hash_find(vport_hash,
524                                                          mac,
525                                                          struct vport_addr);
526                 vport_num = vport->vport;
527                 if (IS_ERR_OR_NULL(vport->allmulti_rule) ||
528                     vaddr->vport == vport_num)
529                         continue;
530                 switch (vaddr->action) {
531                 case MLX5_ACTION_ADD:
532                         if (iter_vaddr)
533                                 continue;
534                         iter_vaddr = l2addr_hash_add(vport_hash, mac,
535                                                      struct vport_addr,
536                                                      GFP_KERNEL);
537                         if (!iter_vaddr) {
538                                 esw_warn(esw->dev,
539                                          "ALL-MULTI: Failed to add MAC(%pM) to vport[%d] DB\n",
540                                          mac, vport_num);
541                                 continue;
542                         }
543                         iter_vaddr->vport = vport_num;
544                         iter_vaddr->flow_rule =
545                                         esw_fdb_set_vport_rule(esw,
546                                                                mac,
547                                                                vport_num);
548                         iter_vaddr->mc_promisc = true;
549                         break;
550                 case MLX5_ACTION_DEL:
551                         if (!iter_vaddr)
552                                 continue;
553                         mlx5_del_flow_rules(iter_vaddr->flow_rule);
554                         l2addr_hash_del(iter_vaddr);
555                         break;
556                 }
557         }
558 }
559
560 static int esw_add_mc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr)
561 {
562         struct hlist_head *hash = esw->mc_table;
563         struct esw_mc_addr *esw_mc;
564         u8 *mac = vaddr->node.addr;
565         u16 vport = vaddr->vport;
566
567         if (!esw->fdb_table.legacy.fdb)
568                 return 0;
569
570         esw_mc = l2addr_hash_find(hash, mac, struct esw_mc_addr);
571         if (esw_mc)
572                 goto add;
573
574         esw_mc = l2addr_hash_add(hash, mac, struct esw_mc_addr, GFP_KERNEL);
575         if (!esw_mc)
576                 return -ENOMEM;
577
578         esw_mc->uplink_rule = /* Forward MC MAC to Uplink */
579                 esw_fdb_set_vport_rule(esw, mac, MLX5_VPORT_UPLINK);
580
581         /* Add this multicast mac to all the mc promiscuous vports */
582         update_allmulti_vports(esw, vaddr, esw_mc);
583
584 add:
585         /* If the multicast mac is added as a result of mc promiscuous vport,
586          * don't increment the multicast ref count
587          */
588         if (!vaddr->mc_promisc)
589                 esw_mc->refcnt++;
590
591         /* Forward MC MAC to vport */
592         vaddr->flow_rule = esw_fdb_set_vport_rule(esw, mac, vport);
593         esw_debug(esw->dev,
594                   "\tADDED MC MAC: vport[%d] %pM fr(%p) refcnt(%d) uplinkfr(%p)\n",
595                   vport, mac, vaddr->flow_rule,
596                   esw_mc->refcnt, esw_mc->uplink_rule);
597         return 0;
598 }
599
600 static int esw_del_mc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr)
601 {
602         struct hlist_head *hash = esw->mc_table;
603         struct esw_mc_addr *esw_mc;
604         u8 *mac = vaddr->node.addr;
605         u16 vport = vaddr->vport;
606
607         if (!esw->fdb_table.legacy.fdb)
608                 return 0;
609
610         esw_mc = l2addr_hash_find(hash, mac, struct esw_mc_addr);
611         if (!esw_mc) {
612                 esw_warn(esw->dev,
613                          "Failed to find eswitch MC addr for MAC(%pM) vport(%d)",
614                          mac, vport);
615                 return -EINVAL;
616         }
617         esw_debug(esw->dev,
618                   "\tDELETE MC MAC: vport[%d] %pM fr(%p) refcnt(%d) uplinkfr(%p)\n",
619                   vport, mac, vaddr->flow_rule, esw_mc->refcnt,
620                   esw_mc->uplink_rule);
621
622         if (vaddr->flow_rule)
623                 mlx5_del_flow_rules(vaddr->flow_rule);
624         vaddr->flow_rule = NULL;
625
626         /* If the multicast mac is added as a result of mc promiscuous vport,
627          * don't decrement the multicast ref count.
628          */
629         if (vaddr->mc_promisc || (--esw_mc->refcnt > 0))
630                 return 0;
631
632         /* Remove this multicast mac from all the mc promiscuous vports */
633         update_allmulti_vports(esw, vaddr, esw_mc);
634
635         if (esw_mc->uplink_rule)
636                 mlx5_del_flow_rules(esw_mc->uplink_rule);
637
638         l2addr_hash_del(esw_mc);
639         return 0;
640 }
641
642 /* Apply vport UC/MC list to HW l2 table and FDB table */
643 static void esw_apply_vport_addr_list(struct mlx5_eswitch *esw,
644                                       struct mlx5_vport *vport, int list_type)
645 {
646         bool is_uc = list_type == MLX5_NVPRT_LIST_TYPE_UC;
647         vport_addr_action vport_addr_add;
648         vport_addr_action vport_addr_del;
649         struct vport_addr *addr;
650         struct l2addr_node *node;
651         struct hlist_head *hash;
652         struct hlist_node *tmp;
653         int hi;
654
655         vport_addr_add = is_uc ? esw_add_uc_addr :
656                                  esw_add_mc_addr;
657         vport_addr_del = is_uc ? esw_del_uc_addr :
658                                  esw_del_mc_addr;
659
660         hash = is_uc ? vport->uc_list : vport->mc_list;
661         for_each_l2hash_node(node, tmp, hash, hi) {
662                 addr = container_of(node, struct vport_addr, node);
663                 switch (addr->action) {
664                 case MLX5_ACTION_ADD:
665                         vport_addr_add(esw, addr);
666                         addr->action = MLX5_ACTION_NONE;
667                         break;
668                 case MLX5_ACTION_DEL:
669                         vport_addr_del(esw, addr);
670                         l2addr_hash_del(addr);
671                         break;
672                 }
673         }
674 }
675
676 /* Sync vport UC/MC list from vport context */
677 static void esw_update_vport_addr_list(struct mlx5_eswitch *esw,
678                                        struct mlx5_vport *vport, int list_type)
679 {
680         bool is_uc = list_type == MLX5_NVPRT_LIST_TYPE_UC;
681         u8 (*mac_list)[ETH_ALEN];
682         struct l2addr_node *node;
683         struct vport_addr *addr;
684         struct hlist_head *hash;
685         struct hlist_node *tmp;
686         int size;
687         int err;
688         int hi;
689         int i;
690
691         size = is_uc ? MLX5_MAX_UC_PER_VPORT(esw->dev) :
692                        MLX5_MAX_MC_PER_VPORT(esw->dev);
693
694         mac_list = kcalloc(size, ETH_ALEN, GFP_KERNEL);
695         if (!mac_list)
696                 return;
697
698         hash = is_uc ? vport->uc_list : vport->mc_list;
699
700         for_each_l2hash_node(node, tmp, hash, hi) {
701                 addr = container_of(node, struct vport_addr, node);
702                 addr->action = MLX5_ACTION_DEL;
703         }
704
705         if (!vport->enabled)
706                 goto out;
707
708         err = mlx5_query_nic_vport_mac_list(esw->dev, vport->vport, list_type,
709                                             mac_list, &size);
710         if (err)
711                 goto out;
712         esw_debug(esw->dev, "vport[%d] context update %s list size (%d)\n",
713                   vport->vport, is_uc ? "UC" : "MC", size);
714
715         for (i = 0; i < size; i++) {
716                 if (is_uc && !is_valid_ether_addr(mac_list[i]))
717                         continue;
718
719                 if (!is_uc && !is_multicast_ether_addr(mac_list[i]))
720                         continue;
721
722                 addr = l2addr_hash_find(hash, mac_list[i], struct vport_addr);
723                 if (addr) {
724                         addr->action = MLX5_ACTION_NONE;
725                         /* If this mac was previously added because of allmulti
726                          * promiscuous rx mode, its now converted to be original
727                          * vport mac.
728                          */
729                         if (addr->mc_promisc) {
730                                 struct esw_mc_addr *esw_mc =
731                                         l2addr_hash_find(esw->mc_table,
732                                                          mac_list[i],
733                                                          struct esw_mc_addr);
734                                 if (!esw_mc) {
735                                         esw_warn(esw->dev,
736                                                  "Failed to MAC(%pM) in mcast DB\n",
737                                                  mac_list[i]);
738                                         continue;
739                                 }
740                                 esw_mc->refcnt++;
741                                 addr->mc_promisc = false;
742                         }
743                         continue;
744                 }
745
746                 addr = l2addr_hash_add(hash, mac_list[i], struct vport_addr,
747                                        GFP_KERNEL);
748                 if (!addr) {
749                         esw_warn(esw->dev,
750                                  "Failed to add MAC(%pM) to vport[%d] DB\n",
751                                  mac_list[i], vport->vport);
752                         continue;
753                 }
754                 addr->vport = vport->vport;
755                 addr->action = MLX5_ACTION_ADD;
756         }
757 out:
758         kfree(mac_list);
759 }
760
761 /* Sync vport UC/MC list from vport context
762  * Must be called after esw_update_vport_addr_list
763  */
764 static void esw_update_vport_mc_promisc(struct mlx5_eswitch *esw,
765                                         struct mlx5_vport *vport)
766 {
767         struct l2addr_node *node;
768         struct vport_addr *addr;
769         struct hlist_head *hash;
770         struct hlist_node *tmp;
771         int hi;
772
773         hash = vport->mc_list;
774
775         for_each_l2hash_node(node, tmp, esw->mc_table, hi) {
776                 u8 *mac = node->addr;
777
778                 addr = l2addr_hash_find(hash, mac, struct vport_addr);
779                 if (addr) {
780                         if (addr->action == MLX5_ACTION_DEL)
781                                 addr->action = MLX5_ACTION_NONE;
782                         continue;
783                 }
784                 addr = l2addr_hash_add(hash, mac, struct vport_addr,
785                                        GFP_KERNEL);
786                 if (!addr) {
787                         esw_warn(esw->dev,
788                                  "Failed to add allmulti MAC(%pM) to vport[%d] DB\n",
789                                  mac, vport->vport);
790                         continue;
791                 }
792                 addr->vport = vport->vport;
793                 addr->action = MLX5_ACTION_ADD;
794                 addr->mc_promisc = true;
795         }
796 }
797
798 /* Apply vport rx mode to HW FDB table */
799 static void esw_apply_vport_rx_mode(struct mlx5_eswitch *esw,
800                                     struct mlx5_vport *vport,
801                                     bool promisc, bool mc_promisc)
802 {
803         struct esw_mc_addr *allmulti_addr = &esw->mc_promisc;
804
805         if (IS_ERR_OR_NULL(vport->allmulti_rule) != mc_promisc)
806                 goto promisc;
807
808         if (mc_promisc) {
809                 vport->allmulti_rule =
810                         esw_fdb_set_vport_allmulti_rule(esw, vport->vport);
811                 if (!allmulti_addr->uplink_rule)
812                         allmulti_addr->uplink_rule =
813                                 esw_fdb_set_vport_allmulti_rule(esw,
814                                                                 MLX5_VPORT_UPLINK);
815                 allmulti_addr->refcnt++;
816         } else if (vport->allmulti_rule) {
817                 mlx5_del_flow_rules(vport->allmulti_rule);
818                 vport->allmulti_rule = NULL;
819
820                 if (--allmulti_addr->refcnt > 0)
821                         goto promisc;
822
823                 if (allmulti_addr->uplink_rule)
824                         mlx5_del_flow_rules(allmulti_addr->uplink_rule);
825                 allmulti_addr->uplink_rule = NULL;
826         }
827
828 promisc:
829         if (IS_ERR_OR_NULL(vport->promisc_rule) != promisc)
830                 return;
831
832         if (promisc) {
833                 vport->promisc_rule =
834                         esw_fdb_set_vport_promisc_rule(esw, vport->vport);
835         } else if (vport->promisc_rule) {
836                 mlx5_del_flow_rules(vport->promisc_rule);
837                 vport->promisc_rule = NULL;
838         }
839 }
840
841 /* Sync vport rx mode from vport context */
842 static void esw_update_vport_rx_mode(struct mlx5_eswitch *esw,
843                                      struct mlx5_vport *vport)
844 {
845         int promisc_all = 0;
846         int promisc_uc = 0;
847         int promisc_mc = 0;
848         int err;
849
850         err = mlx5_query_nic_vport_promisc(esw->dev,
851                                            vport->vport,
852                                            &promisc_uc,
853                                            &promisc_mc,
854                                            &promisc_all);
855         if (err)
856                 return;
857         esw_debug(esw->dev, "vport[%d] context update rx mode promisc_all=%d, all_multi=%d\n",
858                   vport->vport, promisc_all, promisc_mc);
859
860         if (!vport->info.trusted || !vport->enabled) {
861                 promisc_uc = 0;
862                 promisc_mc = 0;
863                 promisc_all = 0;
864         }
865
866         esw_apply_vport_rx_mode(esw, vport, promisc_all,
867                                 (promisc_all || promisc_mc));
868 }
869
870 static void esw_vport_change_handle_locked(struct mlx5_vport *vport)
871 {
872         struct mlx5_core_dev *dev = vport->dev;
873         struct mlx5_eswitch *esw = dev->priv.eswitch;
874         u8 mac[ETH_ALEN];
875
876         mlx5_query_nic_vport_mac_address(dev, vport->vport, mac);
877         esw_debug(dev, "vport[%d] Context Changed: perm mac: %pM\n",
878                   vport->vport, mac);
879
880         if (vport->enabled_events & UC_ADDR_CHANGE) {
881                 esw_update_vport_addr_list(esw, vport, MLX5_NVPRT_LIST_TYPE_UC);
882                 esw_apply_vport_addr_list(esw, vport, MLX5_NVPRT_LIST_TYPE_UC);
883         }
884
885         if (vport->enabled_events & MC_ADDR_CHANGE)
886                 esw_update_vport_addr_list(esw, vport, MLX5_NVPRT_LIST_TYPE_MC);
887
888         if (vport->enabled_events & PROMISC_CHANGE) {
889                 esw_update_vport_rx_mode(esw, vport);
890                 if (!IS_ERR_OR_NULL(vport->allmulti_rule))
891                         esw_update_vport_mc_promisc(esw, vport);
892         }
893
894         if (vport->enabled_events & (PROMISC_CHANGE | MC_ADDR_CHANGE))
895                 esw_apply_vport_addr_list(esw, vport, MLX5_NVPRT_LIST_TYPE_MC);
896
897         esw_debug(esw->dev, "vport[%d] Context Changed: Done\n", vport->vport);
898         if (vport->enabled)
899                 arm_vport_context_events_cmd(dev, vport->vport,
900                                              vport->enabled_events);
901 }
902
903 static void esw_vport_change_handler(struct work_struct *work)
904 {
905         struct mlx5_vport *vport =
906                 container_of(work, struct mlx5_vport, vport_change_handler);
907         struct mlx5_eswitch *esw = vport->dev->priv.eswitch;
908
909         mutex_lock(&esw->state_lock);
910         esw_vport_change_handle_locked(vport);
911         mutex_unlock(&esw->state_lock);
912 }
913
914 int esw_vport_enable_egress_acl(struct mlx5_eswitch *esw,
915                                 struct mlx5_vport *vport)
916 {
917         int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
918         struct mlx5_flow_group *vlan_grp = NULL;
919         struct mlx5_flow_group *drop_grp = NULL;
920         struct mlx5_core_dev *dev = esw->dev;
921         struct mlx5_flow_namespace *root_ns;
922         struct mlx5_flow_table *acl;
923         void *match_criteria;
924         u32 *flow_group_in;
925         /* The egress acl table contains 2 rules:
926          * 1)Allow traffic with vlan_tag=vst_vlan_id
927          * 2)Drop all other traffic.
928          */
929         int table_size = 2;
930         int err = 0;
931
932         if (!MLX5_CAP_ESW_EGRESS_ACL(dev, ft_support))
933                 return -EOPNOTSUPP;
934
935         if (!IS_ERR_OR_NULL(vport->egress.acl))
936                 return 0;
937
938         esw_debug(dev, "Create vport[%d] egress ACL log_max_size(%d)\n",
939                   vport->vport, MLX5_CAP_ESW_EGRESS_ACL(dev, log_max_ft_size));
940
941         root_ns = mlx5_get_flow_vport_acl_namespace(dev, MLX5_FLOW_NAMESPACE_ESW_EGRESS,
942                                                     vport->vport);
943         if (!root_ns) {
944                 esw_warn(dev, "Failed to get E-Switch egress flow namespace for vport (%d)\n", vport->vport);
945                 return -EOPNOTSUPP;
946         }
947
948         flow_group_in = kvzalloc(inlen, GFP_KERNEL);
949         if (!flow_group_in)
950                 return -ENOMEM;
951
952         acl = mlx5_create_vport_flow_table(root_ns, 0, table_size, 0, vport->vport);
953         if (IS_ERR(acl)) {
954                 err = PTR_ERR(acl);
955                 esw_warn(dev, "Failed to create E-Switch vport[%d] egress flow Table, err(%d)\n",
956                          vport->vport, err);
957                 goto out;
958         }
959
960         MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
961         match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in, match_criteria);
962         MLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.cvlan_tag);
963         MLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.first_vid);
964         MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 0);
965         MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 0);
966
967         vlan_grp = mlx5_create_flow_group(acl, flow_group_in);
968         if (IS_ERR(vlan_grp)) {
969                 err = PTR_ERR(vlan_grp);
970                 esw_warn(dev, "Failed to create E-Switch vport[%d] egress allowed vlans flow group, err(%d)\n",
971                          vport->vport, err);
972                 goto out;
973         }
974
975         memset(flow_group_in, 0, inlen);
976         MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 1);
977         MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 1);
978         drop_grp = mlx5_create_flow_group(acl, flow_group_in);
979         if (IS_ERR(drop_grp)) {
980                 err = PTR_ERR(drop_grp);
981                 esw_warn(dev, "Failed to create E-Switch vport[%d] egress drop flow group, err(%d)\n",
982                          vport->vport, err);
983                 goto out;
984         }
985
986         vport->egress.acl = acl;
987         vport->egress.drop_grp = drop_grp;
988         vport->egress.allowed_vlans_grp = vlan_grp;
989 out:
990         kvfree(flow_group_in);
991         if (err && !IS_ERR_OR_NULL(vlan_grp))
992                 mlx5_destroy_flow_group(vlan_grp);
993         if (err && !IS_ERR_OR_NULL(acl))
994                 mlx5_destroy_flow_table(acl);
995         return err;
996 }
997
998 void esw_vport_cleanup_egress_rules(struct mlx5_eswitch *esw,
999                                     struct mlx5_vport *vport)
1000 {
1001         if (!IS_ERR_OR_NULL(vport->egress.allowed_vlan))
1002                 mlx5_del_flow_rules(vport->egress.allowed_vlan);
1003
1004         if (!IS_ERR_OR_NULL(vport->egress.drop_rule))
1005                 mlx5_del_flow_rules(vport->egress.drop_rule);
1006
1007         vport->egress.allowed_vlan = NULL;
1008         vport->egress.drop_rule = NULL;
1009 }
1010
1011 void esw_vport_disable_egress_acl(struct mlx5_eswitch *esw,
1012                                   struct mlx5_vport *vport)
1013 {
1014         if (IS_ERR_OR_NULL(vport->egress.acl))
1015                 return;
1016
1017         esw_debug(esw->dev, "Destroy vport[%d] E-Switch egress ACL\n", vport->vport);
1018
1019         esw_vport_cleanup_egress_rules(esw, vport);
1020         mlx5_destroy_flow_group(vport->egress.allowed_vlans_grp);
1021         mlx5_destroy_flow_group(vport->egress.drop_grp);
1022         mlx5_destroy_flow_table(vport->egress.acl);
1023         vport->egress.allowed_vlans_grp = NULL;
1024         vport->egress.drop_grp = NULL;
1025         vport->egress.acl = NULL;
1026 }
1027
1028 int esw_vport_enable_ingress_acl(struct mlx5_eswitch *esw,
1029                                  struct mlx5_vport *vport)
1030 {
1031         int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
1032         struct mlx5_core_dev *dev = esw->dev;
1033         struct mlx5_flow_namespace *root_ns;
1034         struct mlx5_flow_table *acl;
1035         struct mlx5_flow_group *g;
1036         void *match_criteria;
1037         u32 *flow_group_in;
1038         /* The ingress acl table contains 4 groups
1039          * (2 active rules at the same time -
1040          *      1 allow rule from one of the first 3 groups.
1041          *      1 drop rule from the last group):
1042          * 1)Allow untagged traffic with smac=original mac.
1043          * 2)Allow untagged traffic.
1044          * 3)Allow traffic with smac=original mac.
1045          * 4)Drop all other traffic.
1046          */
1047         int table_size = 4;
1048         int err = 0;
1049
1050         if (!MLX5_CAP_ESW_INGRESS_ACL(dev, ft_support))
1051                 return -EOPNOTSUPP;
1052
1053         if (!IS_ERR_OR_NULL(vport->ingress.acl))
1054                 return 0;
1055
1056         esw_debug(dev, "Create vport[%d] ingress ACL log_max_size(%d)\n",
1057                   vport->vport, MLX5_CAP_ESW_INGRESS_ACL(dev, log_max_ft_size));
1058
1059         root_ns = mlx5_get_flow_vport_acl_namespace(dev, MLX5_FLOW_NAMESPACE_ESW_INGRESS,
1060                                                     vport->vport);
1061         if (!root_ns) {
1062                 esw_warn(dev, "Failed to get E-Switch ingress flow namespace for vport (%d)\n", vport->vport);
1063                 return -EOPNOTSUPP;
1064         }
1065
1066         flow_group_in = kvzalloc(inlen, GFP_KERNEL);
1067         if (!flow_group_in)
1068                 return -ENOMEM;
1069
1070         acl = mlx5_create_vport_flow_table(root_ns, 0, table_size, 0, vport->vport);
1071         if (IS_ERR(acl)) {
1072                 err = PTR_ERR(acl);
1073                 esw_warn(dev, "Failed to create E-Switch vport[%d] ingress flow Table, err(%d)\n",
1074                          vport->vport, err);
1075                 goto out;
1076         }
1077         vport->ingress.acl = acl;
1078
1079         match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in, match_criteria);
1080
1081         MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
1082         MLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.cvlan_tag);
1083         MLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.smac_47_16);
1084         MLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.smac_15_0);
1085         MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 0);
1086         MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 0);
1087
1088         g = mlx5_create_flow_group(acl, flow_group_in);
1089         if (IS_ERR(g)) {
1090                 err = PTR_ERR(g);
1091                 esw_warn(dev, "Failed to create E-Switch vport[%d] ingress untagged spoofchk flow group, err(%d)\n",
1092                          vport->vport, err);
1093                 goto out;
1094         }
1095         vport->ingress.allow_untagged_spoofchk_grp = g;
1096
1097         memset(flow_group_in, 0, inlen);
1098         MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
1099         MLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.cvlan_tag);
1100         MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 1);
1101         MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 1);
1102
1103         g = mlx5_create_flow_group(acl, flow_group_in);
1104         if (IS_ERR(g)) {
1105                 err = PTR_ERR(g);
1106                 esw_warn(dev, "Failed to create E-Switch vport[%d] ingress untagged flow group, err(%d)\n",
1107                          vport->vport, err);
1108                 goto out;
1109         }
1110         vport->ingress.allow_untagged_only_grp = g;
1111
1112         memset(flow_group_in, 0, inlen);
1113         MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
1114         MLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.smac_47_16);
1115         MLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.smac_15_0);
1116         MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 2);
1117         MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 2);
1118
1119         g = mlx5_create_flow_group(acl, flow_group_in);
1120         if (IS_ERR(g)) {
1121                 err = PTR_ERR(g);
1122                 esw_warn(dev, "Failed to create E-Switch vport[%d] ingress spoofchk flow group, err(%d)\n",
1123                          vport->vport, err);
1124                 goto out;
1125         }
1126         vport->ingress.allow_spoofchk_only_grp = g;
1127
1128         memset(flow_group_in, 0, inlen);
1129         MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 3);
1130         MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 3);
1131
1132         g = mlx5_create_flow_group(acl, flow_group_in);
1133         if (IS_ERR(g)) {
1134                 err = PTR_ERR(g);
1135                 esw_warn(dev, "Failed to create E-Switch vport[%d] ingress drop flow group, err(%d)\n",
1136                          vport->vport, err);
1137                 goto out;
1138         }
1139         vport->ingress.drop_grp = g;
1140
1141 out:
1142         if (err) {
1143                 if (!IS_ERR_OR_NULL(vport->ingress.allow_spoofchk_only_grp))
1144                         mlx5_destroy_flow_group(
1145                                         vport->ingress.allow_spoofchk_only_grp);
1146                 if (!IS_ERR_OR_NULL(vport->ingress.allow_untagged_only_grp))
1147                         mlx5_destroy_flow_group(
1148                                         vport->ingress.allow_untagged_only_grp);
1149                 if (!IS_ERR_OR_NULL(vport->ingress.allow_untagged_spoofchk_grp))
1150                         mlx5_destroy_flow_group(
1151                                 vport->ingress.allow_untagged_spoofchk_grp);
1152                 if (!IS_ERR_OR_NULL(vport->ingress.acl))
1153                         mlx5_destroy_flow_table(vport->ingress.acl);
1154         }
1155
1156         kvfree(flow_group_in);
1157         return err;
1158 }
1159
1160 void esw_vport_cleanup_ingress_rules(struct mlx5_eswitch *esw,
1161                                      struct mlx5_vport *vport)
1162 {
1163         if (!IS_ERR_OR_NULL(vport->ingress.drop_rule))
1164                 mlx5_del_flow_rules(vport->ingress.drop_rule);
1165
1166         if (!IS_ERR_OR_NULL(vport->ingress.allow_rule))
1167                 mlx5_del_flow_rules(vport->ingress.allow_rule);
1168
1169         vport->ingress.drop_rule = NULL;
1170         vport->ingress.allow_rule = NULL;
1171 }
1172
1173 void esw_vport_disable_ingress_acl(struct mlx5_eswitch *esw,
1174                                    struct mlx5_vport *vport)
1175 {
1176         if (IS_ERR_OR_NULL(vport->ingress.acl))
1177                 return;
1178
1179         esw_debug(esw->dev, "Destroy vport[%d] E-Switch ingress ACL\n", vport->vport);
1180
1181         esw_vport_cleanup_ingress_rules(esw, vport);
1182         mlx5_destroy_flow_group(vport->ingress.allow_spoofchk_only_grp);
1183         mlx5_destroy_flow_group(vport->ingress.allow_untagged_only_grp);
1184         mlx5_destroy_flow_group(vport->ingress.allow_untagged_spoofchk_grp);
1185         mlx5_destroy_flow_group(vport->ingress.drop_grp);
1186         mlx5_destroy_flow_table(vport->ingress.acl);
1187         vport->ingress.acl = NULL;
1188         vport->ingress.drop_grp = NULL;
1189         vport->ingress.allow_spoofchk_only_grp = NULL;
1190         vport->ingress.allow_untagged_only_grp = NULL;
1191         vport->ingress.allow_untagged_spoofchk_grp = NULL;
1192 }
1193
1194 static int esw_vport_ingress_config(struct mlx5_eswitch *esw,
1195                                     struct mlx5_vport *vport)
1196 {
1197         struct mlx5_fc *counter = vport->ingress.drop_counter;
1198         struct mlx5_flow_destination drop_ctr_dst = {0};
1199         struct mlx5_flow_destination *dst = NULL;
1200         struct mlx5_flow_act flow_act = {0};
1201         struct mlx5_flow_spec *spec;
1202         int dest_num = 0;
1203         int err = 0;
1204         u8 *smac_v;
1205
1206         esw_vport_cleanup_ingress_rules(esw, vport);
1207
1208         if (!vport->info.vlan && !vport->info.qos && !vport->info.spoofchk) {
1209                 esw_vport_disable_ingress_acl(esw, vport);
1210                 return 0;
1211         }
1212
1213         err = esw_vport_enable_ingress_acl(esw, vport);
1214         if (err) {
1215                 mlx5_core_warn(esw->dev,
1216                                "failed to enable ingress acl (%d) on vport[%d]\n",
1217                                err, vport->vport);
1218                 return err;
1219         }
1220
1221         esw_debug(esw->dev,
1222                   "vport[%d] configure ingress rules, vlan(%d) qos(%d)\n",
1223                   vport->vport, vport->info.vlan, vport->info.qos);
1224
1225         spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
1226         if (!spec) {
1227                 err = -ENOMEM;
1228                 goto out;
1229         }
1230
1231         if (vport->info.vlan || vport->info.qos)
1232                 MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.cvlan_tag);
1233
1234         if (vport->info.spoofchk) {
1235                 MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.smac_47_16);
1236                 MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.smac_15_0);
1237                 smac_v = MLX5_ADDR_OF(fte_match_param,
1238                                       spec->match_value,
1239                                       outer_headers.smac_47_16);
1240                 ether_addr_copy(smac_v, vport->info.mac);
1241         }
1242
1243         spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
1244         flow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW;
1245         vport->ingress.allow_rule =
1246                 mlx5_add_flow_rules(vport->ingress.acl, spec,
1247                                     &flow_act, NULL, 0);
1248         if (IS_ERR(vport->ingress.allow_rule)) {
1249                 err = PTR_ERR(vport->ingress.allow_rule);
1250                 esw_warn(esw->dev,
1251                          "vport[%d] configure ingress allow rule, err(%d)\n",
1252                          vport->vport, err);
1253                 vport->ingress.allow_rule = NULL;
1254                 goto out;
1255         }
1256
1257         memset(spec, 0, sizeof(*spec));
1258         flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP;
1259
1260         /* Attach drop flow counter */
1261         if (counter) {
1262                 flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_COUNT;
1263                 drop_ctr_dst.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
1264                 drop_ctr_dst.counter_id = mlx5_fc_id(counter);
1265                 dst = &drop_ctr_dst;
1266                 dest_num++;
1267         }
1268         vport->ingress.drop_rule =
1269                 mlx5_add_flow_rules(vport->ingress.acl, spec,
1270                                     &flow_act, dst, dest_num);
1271         if (IS_ERR(vport->ingress.drop_rule)) {
1272                 err = PTR_ERR(vport->ingress.drop_rule);
1273                 esw_warn(esw->dev,
1274                          "vport[%d] configure ingress drop rule, err(%d)\n",
1275                          vport->vport, err);
1276                 vport->ingress.drop_rule = NULL;
1277                 goto out;
1278         }
1279
1280 out:
1281         if (err)
1282                 esw_vport_cleanup_ingress_rules(esw, vport);
1283         kvfree(spec);
1284         return err;
1285 }
1286
1287 static int esw_vport_egress_config(struct mlx5_eswitch *esw,
1288                                    struct mlx5_vport *vport)
1289 {
1290         struct mlx5_fc *counter = vport->egress.drop_counter;
1291         struct mlx5_flow_destination drop_ctr_dst = {0};
1292         struct mlx5_flow_destination *dst = NULL;
1293         struct mlx5_flow_act flow_act = {0};
1294         struct mlx5_flow_spec *spec;
1295         int dest_num = 0;
1296         int err = 0;
1297
1298         esw_vport_cleanup_egress_rules(esw, vport);
1299
1300         if (!vport->info.vlan && !vport->info.qos) {
1301                 esw_vport_disable_egress_acl(esw, vport);
1302                 return 0;
1303         }
1304
1305         err = esw_vport_enable_egress_acl(esw, vport);
1306         if (err) {
1307                 mlx5_core_warn(esw->dev,
1308                                "failed to enable egress acl (%d) on vport[%d]\n",
1309                                err, vport->vport);
1310                 return err;
1311         }
1312
1313         esw_debug(esw->dev,
1314                   "vport[%d] configure egress rules, vlan(%d) qos(%d)\n",
1315                   vport->vport, vport->info.vlan, vport->info.qos);
1316
1317         spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
1318         if (!spec) {
1319                 err = -ENOMEM;
1320                 goto out;
1321         }
1322
1323         /* Allowed vlan rule */
1324         MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.cvlan_tag);
1325         MLX5_SET_TO_ONES(fte_match_param, spec->match_value, outer_headers.cvlan_tag);
1326         MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.first_vid);
1327         MLX5_SET(fte_match_param, spec->match_value, outer_headers.first_vid, vport->info.vlan);
1328
1329         spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
1330         flow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW;
1331         vport->egress.allowed_vlan =
1332                 mlx5_add_flow_rules(vport->egress.acl, spec,
1333                                     &flow_act, NULL, 0);
1334         if (IS_ERR(vport->egress.allowed_vlan)) {
1335                 err = PTR_ERR(vport->egress.allowed_vlan);
1336                 esw_warn(esw->dev,
1337                          "vport[%d] configure egress allowed vlan rule failed, err(%d)\n",
1338                          vport->vport, err);
1339                 vport->egress.allowed_vlan = NULL;
1340                 goto out;
1341         }
1342
1343         /* Drop others rule (star rule) */
1344         memset(spec, 0, sizeof(*spec));
1345         flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP;
1346
1347         /* Attach egress drop flow counter */
1348         if (counter) {
1349                 flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_COUNT;
1350                 drop_ctr_dst.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
1351                 drop_ctr_dst.counter_id = mlx5_fc_id(counter);
1352                 dst = &drop_ctr_dst;
1353                 dest_num++;
1354         }
1355         vport->egress.drop_rule =
1356                 mlx5_add_flow_rules(vport->egress.acl, spec,
1357                                     &flow_act, dst, dest_num);
1358         if (IS_ERR(vport->egress.drop_rule)) {
1359                 err = PTR_ERR(vport->egress.drop_rule);
1360                 esw_warn(esw->dev,
1361                          "vport[%d] configure egress drop rule failed, err(%d)\n",
1362                          vport->vport, err);
1363                 vport->egress.drop_rule = NULL;
1364         }
1365 out:
1366         kvfree(spec);
1367         return err;
1368 }
1369
1370 /* Vport QoS management */
1371 static int esw_create_tsar(struct mlx5_eswitch *esw)
1372 {
1373         u32 tsar_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {0};
1374         struct mlx5_core_dev *dev = esw->dev;
1375         int err;
1376
1377         if (!MLX5_CAP_GEN(dev, qos) || !MLX5_CAP_QOS(dev, esw_scheduling))
1378                 return 0;
1379
1380         if (esw->qos.enabled)
1381                 return -EEXIST;
1382
1383         err = mlx5_create_scheduling_element_cmd(dev,
1384                                                  SCHEDULING_HIERARCHY_E_SWITCH,
1385                                                  tsar_ctx,
1386                                                  &esw->qos.root_tsar_id);
1387         if (err) {
1388                 esw_warn(esw->dev, "E-Switch create TSAR failed (%d)\n", err);
1389                 return err;
1390         }
1391
1392         esw->qos.enabled = true;
1393         return 0;
1394 }
1395
1396 static void esw_destroy_tsar(struct mlx5_eswitch *esw)
1397 {
1398         int err;
1399
1400         if (!esw->qos.enabled)
1401                 return;
1402
1403         err = mlx5_destroy_scheduling_element_cmd(esw->dev,
1404                                                   SCHEDULING_HIERARCHY_E_SWITCH,
1405                                                   esw->qos.root_tsar_id);
1406         if (err)
1407                 esw_warn(esw->dev, "E-Switch destroy TSAR failed (%d)\n", err);
1408
1409         esw->qos.enabled = false;
1410 }
1411
1412 static int esw_vport_enable_qos(struct mlx5_eswitch *esw,
1413                                 struct mlx5_vport *vport,
1414                                 u32 initial_max_rate, u32 initial_bw_share)
1415 {
1416         u32 sched_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {0};
1417         struct mlx5_core_dev *dev = esw->dev;
1418         void *vport_elem;
1419         int err = 0;
1420
1421         if (!esw->qos.enabled || !MLX5_CAP_GEN(dev, qos) ||
1422             !MLX5_CAP_QOS(dev, esw_scheduling))
1423                 return 0;
1424
1425         if (vport->qos.enabled)
1426                 return -EEXIST;
1427
1428         MLX5_SET(scheduling_context, sched_ctx, element_type,
1429                  SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT);
1430         vport_elem = MLX5_ADDR_OF(scheduling_context, sched_ctx,
1431                                   element_attributes);
1432         MLX5_SET(vport_element, vport_elem, vport_number, vport->vport);
1433         MLX5_SET(scheduling_context, sched_ctx, parent_element_id,
1434                  esw->qos.root_tsar_id);
1435         MLX5_SET(scheduling_context, sched_ctx, max_average_bw,
1436                  initial_max_rate);
1437         MLX5_SET(scheduling_context, sched_ctx, bw_share, initial_bw_share);
1438
1439         err = mlx5_create_scheduling_element_cmd(dev,
1440                                                  SCHEDULING_HIERARCHY_E_SWITCH,
1441                                                  sched_ctx,
1442                                                  &vport->qos.esw_tsar_ix);
1443         if (err) {
1444                 esw_warn(esw->dev, "E-Switch create TSAR vport element failed (vport=%d,err=%d)\n",
1445                          vport->vport, err);
1446                 return err;
1447         }
1448
1449         vport->qos.enabled = true;
1450         return 0;
1451 }
1452
1453 static void esw_vport_disable_qos(struct mlx5_eswitch *esw,
1454                                   struct mlx5_vport *vport)
1455 {
1456         int err;
1457
1458         if (!vport->qos.enabled)
1459                 return;
1460
1461         err = mlx5_destroy_scheduling_element_cmd(esw->dev,
1462                                                   SCHEDULING_HIERARCHY_E_SWITCH,
1463                                                   vport->qos.esw_tsar_ix);
1464         if (err)
1465                 esw_warn(esw->dev, "E-Switch destroy TSAR vport element failed (vport=%d,err=%d)\n",
1466                          vport->vport, err);
1467
1468         vport->qos.enabled = false;
1469 }
1470
1471 static int esw_vport_qos_config(struct mlx5_eswitch *esw,
1472                                 struct mlx5_vport *vport,
1473                                 u32 max_rate, u32 bw_share)
1474 {
1475         u32 sched_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {0};
1476         struct mlx5_core_dev *dev = esw->dev;
1477         void *vport_elem;
1478         u32 bitmask = 0;
1479         int err = 0;
1480
1481         if (!MLX5_CAP_GEN(dev, qos) || !MLX5_CAP_QOS(dev, esw_scheduling))
1482                 return -EOPNOTSUPP;
1483
1484         if (!vport->qos.enabled)
1485                 return -EIO;
1486
1487         MLX5_SET(scheduling_context, sched_ctx, element_type,
1488                  SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT);
1489         vport_elem = MLX5_ADDR_OF(scheduling_context, sched_ctx,
1490                                   element_attributes);
1491         MLX5_SET(vport_element, vport_elem, vport_number, vport->vport);
1492         MLX5_SET(scheduling_context, sched_ctx, parent_element_id,
1493                  esw->qos.root_tsar_id);
1494         MLX5_SET(scheduling_context, sched_ctx, max_average_bw,
1495                  max_rate);
1496         MLX5_SET(scheduling_context, sched_ctx, bw_share, bw_share);
1497         bitmask |= MODIFY_SCHEDULING_ELEMENT_IN_MODIFY_BITMASK_MAX_AVERAGE_BW;
1498         bitmask |= MODIFY_SCHEDULING_ELEMENT_IN_MODIFY_BITMASK_BW_SHARE;
1499
1500         err = mlx5_modify_scheduling_element_cmd(dev,
1501                                                  SCHEDULING_HIERARCHY_E_SWITCH,
1502                                                  sched_ctx,
1503                                                  vport->qos.esw_tsar_ix,
1504                                                  bitmask);
1505         if (err) {
1506                 esw_warn(esw->dev, "E-Switch modify TSAR vport element failed (vport=%d,err=%d)\n",
1507                          vport->vport, err);
1508                 return err;
1509         }
1510
1511         return 0;
1512 }
1513
1514 static void node_guid_gen_from_mac(u64 *node_guid, u8 mac[ETH_ALEN])
1515 {
1516         ((u8 *)node_guid)[7] = mac[0];
1517         ((u8 *)node_guid)[6] = mac[1];
1518         ((u8 *)node_guid)[5] = mac[2];
1519         ((u8 *)node_guid)[4] = 0xff;
1520         ((u8 *)node_guid)[3] = 0xfe;
1521         ((u8 *)node_guid)[2] = mac[3];
1522         ((u8 *)node_guid)[1] = mac[4];
1523         ((u8 *)node_guid)[0] = mac[5];
1524 }
1525
1526 static void esw_apply_vport_conf(struct mlx5_eswitch *esw,
1527                                  struct mlx5_vport *vport)
1528 {
1529         int vport_num = vport->vport;
1530
1531         if (esw->manager_vport == vport_num)
1532                 return;
1533
1534         mlx5_modify_vport_admin_state(esw->dev,
1535                                       MLX5_VPORT_STATE_OP_MOD_ESW_VPORT,
1536                                       vport_num, 1,
1537                                       vport->info.link_state);
1538
1539         /* Host PF has its own mac/guid. */
1540         if (vport_num) {
1541                 mlx5_modify_nic_vport_mac_address(esw->dev, vport_num,
1542                                                   vport->info.mac);
1543                 mlx5_modify_nic_vport_node_guid(esw->dev, vport_num,
1544                                                 vport->info.node_guid);
1545         }
1546
1547         modify_esw_vport_cvlan(esw->dev, vport_num, vport->info.vlan, vport->info.qos,
1548                                (vport->info.vlan || vport->info.qos));
1549
1550         /* Only legacy mode needs ACLs */
1551         if (esw->mode == SRIOV_LEGACY) {
1552                 esw_vport_ingress_config(esw, vport);
1553                 esw_vport_egress_config(esw, vport);
1554         }
1555 }
1556
1557 static void esw_vport_create_drop_counters(struct mlx5_vport *vport)
1558 {
1559         struct mlx5_core_dev *dev = vport->dev;
1560
1561         if (MLX5_CAP_ESW_INGRESS_ACL(dev, flow_counter)) {
1562                 vport->ingress.drop_counter = mlx5_fc_create(dev, false);
1563                 if (IS_ERR(vport->ingress.drop_counter)) {
1564                         esw_warn(dev,
1565                                  "vport[%d] configure ingress drop rule counter failed\n",
1566                                  vport->vport);
1567                         vport->ingress.drop_counter = NULL;
1568                 }
1569         }
1570
1571         if (MLX5_CAP_ESW_EGRESS_ACL(dev, flow_counter)) {
1572                 vport->egress.drop_counter = mlx5_fc_create(dev, false);
1573                 if (IS_ERR(vport->egress.drop_counter)) {
1574                         esw_warn(dev,
1575                                  "vport[%d] configure egress drop rule counter failed\n",
1576                                  vport->vport);
1577                         vport->egress.drop_counter = NULL;
1578                 }
1579         }
1580 }
1581
1582 static void esw_vport_destroy_drop_counters(struct mlx5_vport *vport)
1583 {
1584         struct mlx5_core_dev *dev = vport->dev;
1585
1586         if (vport->ingress.drop_counter)
1587                 mlx5_fc_destroy(dev, vport->ingress.drop_counter);
1588         if (vport->egress.drop_counter)
1589                 mlx5_fc_destroy(dev, vport->egress.drop_counter);
1590 }
1591
1592 static void esw_enable_vport(struct mlx5_eswitch *esw, struct mlx5_vport *vport,
1593                              int enable_events)
1594 {
1595         u16 vport_num = vport->vport;
1596
1597         mutex_lock(&esw->state_lock);
1598         WARN_ON(vport->enabled);
1599
1600         esw_debug(esw->dev, "Enabling VPORT(%d)\n", vport_num);
1601
1602         /* Create steering drop counters for ingress and egress ACLs */
1603         if (vport_num && esw->mode == SRIOV_LEGACY)
1604                 esw_vport_create_drop_counters(vport);
1605
1606         /* Restore old vport configuration */
1607         esw_apply_vport_conf(esw, vport);
1608
1609         /* Attach vport to the eswitch rate limiter */
1610         if (esw_vport_enable_qos(esw, vport, vport->info.max_rate,
1611                                  vport->qos.bw_share))
1612                 esw_warn(esw->dev, "Failed to attach vport %d to eswitch rate limiter", vport_num);
1613
1614         /* Sync with current vport context */
1615         vport->enabled_events = enable_events;
1616         vport->enabled = true;
1617
1618         /* Esw manager is trusted by default. Host PF (vport 0) is trusted as well
1619          * in smartNIC as it's a vport group manager.
1620          */
1621         if (esw->manager_vport == vport_num ||
1622             (!vport_num && mlx5_core_is_ecpf(esw->dev)))
1623                 vport->info.trusted = true;
1624
1625         esw_vport_change_handle_locked(vport);
1626
1627         esw->enabled_vports++;
1628         esw_debug(esw->dev, "Enabled VPORT(%d)\n", vport_num);
1629         mutex_unlock(&esw->state_lock);
1630 }
1631
1632 static void esw_disable_vport(struct mlx5_eswitch *esw,
1633                               struct mlx5_vport *vport)
1634 {
1635         u16 vport_num = vport->vport;
1636
1637         if (!vport->enabled)
1638                 return;
1639
1640         esw_debug(esw->dev, "Disabling vport(%d)\n", vport_num);
1641         /* Mark this vport as disabled to discard new events */
1642         vport->enabled = false;
1643
1644         /* Wait for current already scheduled events to complete */
1645         flush_workqueue(esw->work_queue);
1646         /* Disable events from this vport */
1647         arm_vport_context_events_cmd(esw->dev, vport->vport, 0);
1648         mutex_lock(&esw->state_lock);
1649         /* We don't assume VFs will cleanup after themselves.
1650          * Calling vport change handler while vport is disabled will cleanup
1651          * the vport resources.
1652          */
1653         esw_vport_change_handle_locked(vport);
1654         vport->enabled_events = 0;
1655         esw_vport_disable_qos(esw, vport);
1656         if (esw->manager_vport != vport_num &&
1657             esw->mode == SRIOV_LEGACY) {
1658                 mlx5_modify_vport_admin_state(esw->dev,
1659                                               MLX5_VPORT_STATE_OP_MOD_ESW_VPORT,
1660                                               vport_num, 1,
1661                                               MLX5_VPORT_ADMIN_STATE_DOWN);
1662                 esw_vport_disable_egress_acl(esw, vport);
1663                 esw_vport_disable_ingress_acl(esw, vport);
1664                 esw_vport_destroy_drop_counters(vport);
1665         }
1666         esw->enabled_vports--;
1667         mutex_unlock(&esw->state_lock);
1668 }
1669
1670 static int eswitch_vport_event(struct notifier_block *nb,
1671                                unsigned long type, void *data)
1672 {
1673         struct mlx5_eswitch *esw = mlx5_nb_cof(nb, struct mlx5_eswitch, nb);
1674         struct mlx5_eqe *eqe = data;
1675         struct mlx5_vport *vport;
1676         u16 vport_num;
1677
1678         vport_num = be16_to_cpu(eqe->data.vport_change.vport_num);
1679         vport = mlx5_eswitch_get_vport(esw, vport_num);
1680         if (IS_ERR(vport))
1681                 return NOTIFY_OK;
1682
1683         if (vport->enabled)
1684                 queue_work(esw->work_queue, &vport->vport_change_handler);
1685
1686         return NOTIFY_OK;
1687 }
1688
1689 /* Public E-Switch API */
1690 #define ESW_ALLOWED(esw) ((esw) && MLX5_ESWITCH_MANAGER((esw)->dev))
1691
1692 int mlx5_eswitch_enable_sriov(struct mlx5_eswitch *esw, int nvfs, int mode)
1693 {
1694         int vf_nvports = 0, total_nvports = 0;
1695         struct mlx5_vport *vport;
1696         int err;
1697         int i, enabled_events;
1698
1699         if (!ESW_ALLOWED(esw) ||
1700             !MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, ft_support)) {
1701                 esw_warn(esw->dev, "E-Switch FDB is not supported, aborting ...\n");
1702                 return -EOPNOTSUPP;
1703         }
1704
1705         if (!MLX5_CAP_ESW_INGRESS_ACL(esw->dev, ft_support))
1706                 esw_warn(esw->dev, "E-Switch ingress ACL is not supported by FW\n");
1707
1708         if (!MLX5_CAP_ESW_EGRESS_ACL(esw->dev, ft_support))
1709                 esw_warn(esw->dev, "E-Switch engress ACL is not supported by FW\n");
1710
1711         esw_info(esw->dev, "E-Switch enable SRIOV: nvfs(%d) mode (%d)\n", nvfs, mode);
1712
1713         if (mode == SRIOV_OFFLOADS) {
1714                 if (mlx5_core_is_ecpf_esw_manager(esw->dev)) {
1715                         err = mlx5_query_host_params_num_vfs(esw->dev, &vf_nvports);
1716                         if (err)
1717                                 return err;
1718                         total_nvports = esw->total_vports;
1719                 } else {
1720                         vf_nvports = nvfs;
1721                         total_nvports = nvfs + MLX5_SPECIAL_VPORTS(esw->dev);
1722                 }
1723         }
1724
1725         esw->mode = mode;
1726
1727         mlx5_lag_update(esw->dev);
1728
1729         if (mode == SRIOV_LEGACY) {
1730                 err = esw_create_legacy_table(esw);
1731                 if (err)
1732                         goto abort;
1733         } else {
1734                 mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_ETH);
1735                 mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_IB);
1736                 err = esw_offloads_init(esw, vf_nvports, total_nvports);
1737         }
1738
1739         if (err)
1740                 goto abort;
1741
1742         err = esw_create_tsar(esw);
1743         if (err)
1744                 esw_warn(esw->dev, "Failed to create eswitch TSAR");
1745
1746         /* Don't enable vport events when in SRIOV_OFFLOADS mode, since:
1747          * 1. L2 table (MPFS) is programmed by PF/VF representors netdevs set_rx_mode
1748          * 2. FDB/Eswitch is programmed by user space tools
1749          */
1750         enabled_events = (mode == SRIOV_LEGACY) ? SRIOV_VPORT_EVENTS : 0;
1751
1752         /* Enable PF vport */
1753         vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_PF);
1754         esw_enable_vport(esw, vport, enabled_events);
1755
1756         /* Enable ECPF vports */
1757         if (mlx5_ecpf_vport_exists(esw->dev)) {
1758                 vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_ECPF);
1759                 esw_enable_vport(esw, vport, enabled_events);
1760         }
1761
1762         /* Enable VF vports */
1763         mlx5_esw_for_each_vf_vport(esw, i, vport, nvfs)
1764                 esw_enable_vport(esw, vport, enabled_events);
1765
1766         if (mode == SRIOV_LEGACY) {
1767                 MLX5_NB_INIT(&esw->nb, eswitch_vport_event, NIC_VPORT_CHANGE);
1768                 mlx5_eq_notifier_register(esw->dev, &esw->nb);
1769         }
1770
1771         esw_info(esw->dev, "SRIOV enabled: active vports(%d)\n",
1772                  esw->enabled_vports);
1773         return 0;
1774
1775 abort:
1776         esw->mode = SRIOV_NONE;
1777
1778         if (mode == SRIOV_OFFLOADS) {
1779                 mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_IB);
1780                 mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_ETH);
1781         }
1782
1783         return err;
1784 }
1785
1786 void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw)
1787 {
1788         struct esw_mc_addr *mc_promisc;
1789         struct mlx5_vport *vport;
1790         int old_mode;
1791         int i;
1792
1793         if (!ESW_ALLOWED(esw) || esw->mode == SRIOV_NONE)
1794                 return;
1795
1796         esw_info(esw->dev, "disable SRIOV: active vports(%d) mode(%d)\n",
1797                  esw->enabled_vports, esw->mode);
1798
1799         mc_promisc = &esw->mc_promisc;
1800
1801         if (esw->mode == SRIOV_LEGACY)
1802                 mlx5_eq_notifier_unregister(esw->dev, &esw->nb);
1803
1804         mlx5_esw_for_all_vports(esw, i, vport)
1805                 esw_disable_vport(esw, vport);
1806
1807         if (mc_promisc && mc_promisc->uplink_rule)
1808                 mlx5_del_flow_rules(mc_promisc->uplink_rule);
1809
1810         esw_destroy_tsar(esw);
1811
1812         if (esw->mode == SRIOV_LEGACY)
1813                 esw_destroy_legacy_table(esw);
1814         else if (esw->mode == SRIOV_OFFLOADS)
1815                 esw_offloads_cleanup(esw);
1816
1817         old_mode = esw->mode;
1818         esw->mode = SRIOV_NONE;
1819
1820         mlx5_lag_update(esw->dev);
1821
1822         if (old_mode == SRIOV_OFFLOADS) {
1823                 mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_IB);
1824                 mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_ETH);
1825         }
1826 }
1827
1828 int mlx5_eswitch_init(struct mlx5_core_dev *dev)
1829 {
1830         int total_vports = MLX5_TOTAL_VPORTS(dev);
1831         struct mlx5_eswitch *esw;
1832         struct mlx5_vport *vport;
1833         int err, i;
1834
1835         if (!MLX5_VPORT_MANAGER(dev))
1836                 return 0;
1837
1838         esw_info(dev,
1839                  "Total vports %d, per vport: max uc(%d) max mc(%d)\n",
1840                  total_vports,
1841                  MLX5_MAX_UC_PER_VPORT(dev),
1842                  MLX5_MAX_MC_PER_VPORT(dev));
1843
1844         esw = kzalloc(sizeof(*esw), GFP_KERNEL);
1845         if (!esw)
1846                 return -ENOMEM;
1847
1848         esw->dev = dev;
1849         esw->manager_vport = mlx5_eswitch_manager_vport(dev);
1850
1851         esw->work_queue = create_singlethread_workqueue("mlx5_esw_wq");
1852         if (!esw->work_queue) {
1853                 err = -ENOMEM;
1854                 goto abort;
1855         }
1856
1857         esw->vports = kcalloc(total_vports, sizeof(struct mlx5_vport),
1858                               GFP_KERNEL);
1859         if (!esw->vports) {
1860                 err = -ENOMEM;
1861                 goto abort;
1862         }
1863
1864         esw->total_vports = total_vports;
1865
1866         err = esw_offloads_init_reps(esw);
1867         if (err)
1868                 goto abort;
1869
1870         hash_init(esw->offloads.encap_tbl);
1871         hash_init(esw->offloads.mod_hdr_tbl);
1872         mutex_init(&esw->state_lock);
1873
1874         mlx5_esw_for_all_vports(esw, i, vport) {
1875                 vport->vport = mlx5_eswitch_index_to_vport_num(esw, i);
1876                 vport->info.link_state = MLX5_VPORT_ADMIN_STATE_AUTO;
1877                 vport->dev = dev;
1878                 INIT_WORK(&vport->vport_change_handler,
1879                           esw_vport_change_handler);
1880         }
1881
1882         esw->enabled_vports = 0;
1883         esw->mode = SRIOV_NONE;
1884         esw->offloads.inline_mode = MLX5_INLINE_MODE_NONE;
1885         if (MLX5_CAP_ESW_FLOWTABLE_FDB(dev, reformat) &&
1886             MLX5_CAP_ESW_FLOWTABLE_FDB(dev, decap))
1887                 esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_BASIC;
1888         else
1889                 esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_NONE;
1890
1891         dev->priv.eswitch = esw;
1892         return 0;
1893 abort:
1894         if (esw->work_queue)
1895                 destroy_workqueue(esw->work_queue);
1896         esw_offloads_cleanup_reps(esw);
1897         kfree(esw->vports);
1898         kfree(esw);
1899         return err;
1900 }
1901
1902 void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw)
1903 {
1904         if (!esw || !MLX5_VPORT_MANAGER(esw->dev))
1905                 return;
1906
1907         esw_info(esw->dev, "cleanup\n");
1908
1909         esw->dev->priv.eswitch = NULL;
1910         destroy_workqueue(esw->work_queue);
1911         esw_offloads_cleanup_reps(esw);
1912         kfree(esw->vports);
1913         kfree(esw);
1914 }
1915
1916 /* Vport Administration */
1917 int mlx5_eswitch_set_vport_mac(struct mlx5_eswitch *esw,
1918                                int vport, u8 mac[ETH_ALEN])
1919 {
1920         struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
1921         u64 node_guid;
1922         int err = 0;
1923
1924         if (IS_ERR(evport))
1925                 return PTR_ERR(evport);
1926         if (is_multicast_ether_addr(mac))
1927                 return -EINVAL;
1928
1929         mutex_lock(&esw->state_lock);
1930
1931         if (evport->info.spoofchk && !is_valid_ether_addr(mac))
1932                 mlx5_core_warn(esw->dev,
1933                                "Set invalid MAC while spoofchk is on, vport(%d)\n",
1934                                vport);
1935
1936         err = mlx5_modify_nic_vport_mac_address(esw->dev, vport, mac);
1937         if (err) {
1938                 mlx5_core_warn(esw->dev,
1939                                "Failed to mlx5_modify_nic_vport_mac vport(%d) err=(%d)\n",
1940                                vport, err);
1941                 goto unlock;
1942         }
1943
1944         node_guid_gen_from_mac(&node_guid, mac);
1945         err = mlx5_modify_nic_vport_node_guid(esw->dev, vport, node_guid);
1946         if (err)
1947                 mlx5_core_warn(esw->dev,
1948                                "Failed to set vport %d node guid, err = %d. RDMA_CM will not function properly for this VF.\n",
1949                                vport, err);
1950
1951         ether_addr_copy(evport->info.mac, mac);
1952         evport->info.node_guid = node_guid;
1953         if (evport->enabled && esw->mode == SRIOV_LEGACY)
1954                 err = esw_vport_ingress_config(esw, evport);
1955
1956 unlock:
1957         mutex_unlock(&esw->state_lock);
1958         return err;
1959 }
1960
1961 int mlx5_eswitch_set_vport_state(struct mlx5_eswitch *esw,
1962                                  int vport, int link_state)
1963 {
1964         struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
1965         int err = 0;
1966
1967         if (!ESW_ALLOWED(esw))
1968                 return -EPERM;
1969         if (IS_ERR(evport))
1970                 return PTR_ERR(evport);
1971
1972         mutex_lock(&esw->state_lock);
1973
1974         err = mlx5_modify_vport_admin_state(esw->dev,
1975                                             MLX5_VPORT_STATE_OP_MOD_ESW_VPORT,
1976                                             vport, 1, link_state);
1977         if (err) {
1978                 mlx5_core_warn(esw->dev,
1979                                "Failed to set vport %d link state, err = %d",
1980                                vport, err);
1981                 goto unlock;
1982         }
1983
1984         evport->info.link_state = link_state;
1985
1986 unlock:
1987         mutex_unlock(&esw->state_lock);
1988         return 0;
1989 }
1990
1991 int mlx5_eswitch_get_vport_config(struct mlx5_eswitch *esw,
1992                                   int vport, struct ifla_vf_info *ivi)
1993 {
1994         struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
1995
1996         if (IS_ERR(evport))
1997                 return PTR_ERR(evport);
1998
1999         memset(ivi, 0, sizeof(*ivi));
2000         ivi->vf = vport - 1;
2001
2002         mutex_lock(&esw->state_lock);
2003         ether_addr_copy(ivi->mac, evport->info.mac);
2004         ivi->linkstate = evport->info.link_state;
2005         ivi->vlan = evport->info.vlan;
2006         ivi->qos = evport->info.qos;
2007         ivi->spoofchk = evport->info.spoofchk;
2008         ivi->trusted = evport->info.trusted;
2009         ivi->min_tx_rate = evport->info.min_rate;
2010         ivi->max_tx_rate = evport->info.max_rate;
2011         mutex_unlock(&esw->state_lock);
2012
2013         return 0;
2014 }
2015
2016 int __mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw,
2017                                   int vport, u16 vlan, u8 qos, u8 set_flags)
2018 {
2019         struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
2020         int err = 0;
2021
2022         if (!ESW_ALLOWED(esw))
2023                 return -EPERM;
2024         if (IS_ERR(evport))
2025                 return PTR_ERR(evport);
2026         if (vlan > 4095 || qos > 7)
2027                 return -EINVAL;
2028
2029         mutex_lock(&esw->state_lock);
2030
2031         err = modify_esw_vport_cvlan(esw->dev, vport, vlan, qos, set_flags);
2032         if (err)
2033                 goto unlock;
2034
2035         evport->info.vlan = vlan;
2036         evport->info.qos = qos;
2037         if (evport->enabled && esw->mode == SRIOV_LEGACY) {
2038                 err = esw_vport_ingress_config(esw, evport);
2039                 if (err)
2040                         goto unlock;
2041                 err = esw_vport_egress_config(esw, evport);
2042         }
2043
2044 unlock:
2045         mutex_unlock(&esw->state_lock);
2046         return err;
2047 }
2048
2049 int mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw,
2050                                 int vport, u16 vlan, u8 qos)
2051 {
2052         u8 set_flags = 0;
2053
2054         if (vlan || qos)
2055                 set_flags = SET_VLAN_STRIP | SET_VLAN_INSERT;
2056
2057         return __mlx5_eswitch_set_vport_vlan(esw, vport, vlan, qos, set_flags);
2058 }
2059
2060 int mlx5_eswitch_set_vport_spoofchk(struct mlx5_eswitch *esw,
2061                                     int vport, bool spoofchk)
2062 {
2063         struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
2064         bool pschk;
2065         int err = 0;
2066
2067         if (!ESW_ALLOWED(esw))
2068                 return -EPERM;
2069         if (IS_ERR(evport))
2070                 return PTR_ERR(evport);
2071
2072         mutex_lock(&esw->state_lock);
2073         pschk = evport->info.spoofchk;
2074         evport->info.spoofchk = spoofchk;
2075         if (pschk && !is_valid_ether_addr(evport->info.mac))
2076                 mlx5_core_warn(esw->dev,
2077                                "Spoofchk in set while MAC is invalid, vport(%d)\n",
2078                                evport->vport);
2079         if (evport->enabled && esw->mode == SRIOV_LEGACY)
2080                 err = esw_vport_ingress_config(esw, evport);
2081         if (err)
2082                 evport->info.spoofchk = pschk;
2083         mutex_unlock(&esw->state_lock);
2084
2085         return err;
2086 }
2087
2088 static void esw_cleanup_vepa_rules(struct mlx5_eswitch *esw)
2089 {
2090         if (esw->fdb_table.legacy.vepa_uplink_rule)
2091                 mlx5_del_flow_rules(esw->fdb_table.legacy.vepa_uplink_rule);
2092
2093         if (esw->fdb_table.legacy.vepa_star_rule)
2094                 mlx5_del_flow_rules(esw->fdb_table.legacy.vepa_star_rule);
2095
2096         esw->fdb_table.legacy.vepa_uplink_rule = NULL;
2097         esw->fdb_table.legacy.vepa_star_rule = NULL;
2098 }
2099
2100 static int _mlx5_eswitch_set_vepa_locked(struct mlx5_eswitch *esw,
2101                                          u8 setting)
2102 {
2103         struct mlx5_flow_destination dest = {};
2104         struct mlx5_flow_act flow_act = {};
2105         struct mlx5_flow_handle *flow_rule;
2106         struct mlx5_flow_spec *spec;
2107         int err = 0;
2108         void *misc;
2109
2110         if (!setting) {
2111                 esw_cleanup_vepa_rules(esw);
2112                 return 0;
2113         }
2114
2115         if (esw->fdb_table.legacy.vepa_uplink_rule)
2116                 return 0;
2117
2118         spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
2119         if (!spec)
2120                 return -ENOMEM;
2121
2122         /* Uplink rule forward uplink traffic to FDB */
2123         misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters);
2124         MLX5_SET(fte_match_set_misc, misc, source_port, MLX5_VPORT_UPLINK);
2125
2126         misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters);
2127         MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port);
2128
2129         spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS;
2130         dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
2131         dest.ft = esw->fdb_table.legacy.fdb;
2132         flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
2133         flow_rule = mlx5_add_flow_rules(esw->fdb_table.legacy.vepa_fdb, spec,
2134                                         &flow_act, &dest, 1);
2135         if (IS_ERR(flow_rule)) {
2136                 err = PTR_ERR(flow_rule);
2137                 goto out;
2138         } else {
2139                 esw->fdb_table.legacy.vepa_uplink_rule = flow_rule;
2140         }
2141
2142         /* Star rule to forward all traffic to uplink vport */
2143         memset(spec, 0, sizeof(*spec));
2144         memset(&dest, 0, sizeof(dest));
2145         dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
2146         dest.vport.num = MLX5_VPORT_UPLINK;
2147         flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
2148         flow_rule = mlx5_add_flow_rules(esw->fdb_table.legacy.vepa_fdb, spec,
2149                                         &flow_act, &dest, 1);
2150         if (IS_ERR(flow_rule)) {
2151                 err = PTR_ERR(flow_rule);
2152                 goto out;
2153         } else {
2154                 esw->fdb_table.legacy.vepa_star_rule = flow_rule;
2155         }
2156
2157 out:
2158         kvfree(spec);
2159         if (err)
2160                 esw_cleanup_vepa_rules(esw);
2161         return err;
2162 }
2163
2164 int mlx5_eswitch_set_vepa(struct mlx5_eswitch *esw, u8 setting)
2165 {
2166         int err = 0;
2167
2168         if (!esw)
2169                 return -EOPNOTSUPP;
2170
2171         if (!ESW_ALLOWED(esw))
2172                 return -EPERM;
2173
2174         mutex_lock(&esw->state_lock);
2175         if (esw->mode != SRIOV_LEGACY) {
2176                 err = -EOPNOTSUPP;
2177                 goto out;
2178         }
2179
2180         err = _mlx5_eswitch_set_vepa_locked(esw, setting);
2181
2182 out:
2183         mutex_unlock(&esw->state_lock);
2184         return err;
2185 }
2186
2187 int mlx5_eswitch_get_vepa(struct mlx5_eswitch *esw, u8 *setting)
2188 {
2189         int err = 0;
2190
2191         if (!esw)
2192                 return -EOPNOTSUPP;
2193
2194         if (!ESW_ALLOWED(esw))
2195                 return -EPERM;
2196
2197         mutex_lock(&esw->state_lock);
2198         if (esw->mode != SRIOV_LEGACY) {
2199                 err = -EOPNOTSUPP;
2200                 goto out;
2201         }
2202
2203         *setting = esw->fdb_table.legacy.vepa_uplink_rule ? 1 : 0;
2204
2205 out:
2206         mutex_unlock(&esw->state_lock);
2207         return err;
2208 }
2209
2210 int mlx5_eswitch_set_vport_trust(struct mlx5_eswitch *esw,
2211                                  int vport, bool setting)
2212 {
2213         struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
2214
2215         if (!ESW_ALLOWED(esw))
2216                 return -EPERM;
2217         if (IS_ERR(evport))
2218                 return PTR_ERR(evport);
2219
2220         mutex_lock(&esw->state_lock);
2221         evport->info.trusted = setting;
2222         if (evport->enabled)
2223                 esw_vport_change_handle_locked(evport);
2224         mutex_unlock(&esw->state_lock);
2225
2226         return 0;
2227 }
2228
2229 static u32 calculate_vports_min_rate_divider(struct mlx5_eswitch *esw)
2230 {
2231         u32 fw_max_bw_share = MLX5_CAP_QOS(esw->dev, max_tsar_bw_share);
2232         struct mlx5_vport *evport;
2233         u32 max_guarantee = 0;
2234         int i;
2235
2236         mlx5_esw_for_all_vports(esw, i, evport) {
2237                 if (!evport->enabled || evport->info.min_rate < max_guarantee)
2238                         continue;
2239                 max_guarantee = evport->info.min_rate;
2240         }
2241
2242         return max_t(u32, max_guarantee / fw_max_bw_share, 1);
2243 }
2244
2245 static int normalize_vports_min_rate(struct mlx5_eswitch *esw, u32 divider)
2246 {
2247         u32 fw_max_bw_share = MLX5_CAP_QOS(esw->dev, max_tsar_bw_share);
2248         struct mlx5_vport *evport;
2249         u32 vport_max_rate;
2250         u32 vport_min_rate;
2251         u32 bw_share;
2252         int err;
2253         int i;
2254
2255         mlx5_esw_for_all_vports(esw, i, evport) {
2256                 if (!evport->enabled)
2257                         continue;
2258                 vport_min_rate = evport->info.min_rate;
2259                 vport_max_rate = evport->info.max_rate;
2260                 bw_share = MLX5_MIN_BW_SHARE;
2261
2262                 if (vport_min_rate)
2263                         bw_share = MLX5_RATE_TO_BW_SHARE(vport_min_rate,
2264                                                          divider,
2265                                                          fw_max_bw_share);
2266
2267                 if (bw_share == evport->qos.bw_share)
2268                         continue;
2269
2270                 err = esw_vport_qos_config(esw, evport, vport_max_rate,
2271                                            bw_share);
2272                 if (!err)
2273                         evport->qos.bw_share = bw_share;
2274                 else
2275                         return err;
2276         }
2277
2278         return 0;
2279 }
2280
2281 int mlx5_eswitch_set_vport_rate(struct mlx5_eswitch *esw, int vport,
2282                                 u32 max_rate, u32 min_rate)
2283 {
2284         struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
2285         u32 fw_max_bw_share;
2286         u32 previous_min_rate;
2287         u32 divider;
2288         bool min_rate_supported;
2289         bool max_rate_supported;
2290         int err = 0;
2291
2292         if (!ESW_ALLOWED(esw))
2293                 return -EPERM;
2294         if (IS_ERR(evport))
2295                 return PTR_ERR(evport);
2296
2297         fw_max_bw_share = MLX5_CAP_QOS(esw->dev, max_tsar_bw_share);
2298         min_rate_supported = MLX5_CAP_QOS(esw->dev, esw_bw_share) &&
2299                                 fw_max_bw_share >= MLX5_MIN_BW_SHARE;
2300         max_rate_supported = MLX5_CAP_QOS(esw->dev, esw_rate_limit);
2301
2302         if ((min_rate && !min_rate_supported) || (max_rate && !max_rate_supported))
2303                 return -EOPNOTSUPP;
2304
2305         mutex_lock(&esw->state_lock);
2306
2307         if (min_rate == evport->info.min_rate)
2308                 goto set_max_rate;
2309
2310         previous_min_rate = evport->info.min_rate;
2311         evport->info.min_rate = min_rate;
2312         divider = calculate_vports_min_rate_divider(esw);
2313         err = normalize_vports_min_rate(esw, divider);
2314         if (err) {
2315                 evport->info.min_rate = previous_min_rate;
2316                 goto unlock;
2317         }
2318
2319 set_max_rate:
2320         if (max_rate == evport->info.max_rate)
2321                 goto unlock;
2322
2323         err = esw_vport_qos_config(esw, evport, max_rate, evport->qos.bw_share);
2324         if (!err)
2325                 evport->info.max_rate = max_rate;
2326
2327 unlock:
2328         mutex_unlock(&esw->state_lock);
2329         return err;
2330 }
2331
2332 static int mlx5_eswitch_query_vport_drop_stats(struct mlx5_core_dev *dev,
2333                                                struct mlx5_vport *vport,
2334                                                struct mlx5_vport_drop_stats *stats)
2335 {
2336         struct mlx5_eswitch *esw = dev->priv.eswitch;
2337         u64 rx_discard_vport_down, tx_discard_vport_down;
2338         u64 bytes = 0;
2339         int err = 0;
2340
2341         if (!vport->enabled || esw->mode != SRIOV_LEGACY)
2342                 return 0;
2343
2344         if (vport->egress.drop_counter)
2345                 mlx5_fc_query(dev, vport->egress.drop_counter,
2346                               &stats->rx_dropped, &bytes);
2347
2348         if (vport->ingress.drop_counter)
2349                 mlx5_fc_query(dev, vport->ingress.drop_counter,
2350                               &stats->tx_dropped, &bytes);
2351
2352         if (!MLX5_CAP_GEN(dev, receive_discard_vport_down) &&
2353             !MLX5_CAP_GEN(dev, transmit_discard_vport_down))
2354                 return 0;
2355
2356         err = mlx5_query_vport_down_stats(dev, vport->vport, 1,
2357                                           &rx_discard_vport_down,
2358                                           &tx_discard_vport_down);
2359         if (err)
2360                 return err;
2361
2362         if (MLX5_CAP_GEN(dev, receive_discard_vport_down))
2363                 stats->rx_dropped += rx_discard_vport_down;
2364         if (MLX5_CAP_GEN(dev, transmit_discard_vport_down))
2365                 stats->tx_dropped += tx_discard_vport_down;
2366
2367         return 0;
2368 }
2369
2370 int mlx5_eswitch_get_vport_stats(struct mlx5_eswitch *esw,
2371                                  int vport_num,
2372                                  struct ifla_vf_stats *vf_stats)
2373 {
2374         struct mlx5_vport *vport = mlx5_eswitch_get_vport(esw, vport_num);
2375         int outlen = MLX5_ST_SZ_BYTES(query_vport_counter_out);
2376         u32 in[MLX5_ST_SZ_DW(query_vport_counter_in)] = {0};
2377         struct mlx5_vport_drop_stats stats = {0};
2378         int err = 0;
2379         u32 *out;
2380
2381         if (IS_ERR(vport))
2382                 return PTR_ERR(vport);
2383
2384         out = kvzalloc(outlen, GFP_KERNEL);
2385         if (!out)
2386                 return -ENOMEM;
2387
2388         MLX5_SET(query_vport_counter_in, in, opcode,
2389                  MLX5_CMD_OP_QUERY_VPORT_COUNTER);
2390         MLX5_SET(query_vport_counter_in, in, op_mod, 0);
2391         MLX5_SET(query_vport_counter_in, in, vport_number, vport->vport);
2392         MLX5_SET(query_vport_counter_in, in, other_vport, 1);
2393
2394         memset(out, 0, outlen);
2395         err = mlx5_cmd_exec(esw->dev, in, sizeof(in), out, outlen);
2396         if (err)
2397                 goto free_out;
2398
2399         #define MLX5_GET_CTR(p, x) \
2400                 MLX5_GET64(query_vport_counter_out, p, x)
2401
2402         memset(vf_stats, 0, sizeof(*vf_stats));
2403         vf_stats->rx_packets =
2404                 MLX5_GET_CTR(out, received_eth_unicast.packets) +
2405                 MLX5_GET_CTR(out, received_ib_unicast.packets) +
2406                 MLX5_GET_CTR(out, received_eth_multicast.packets) +
2407                 MLX5_GET_CTR(out, received_ib_multicast.packets) +
2408                 MLX5_GET_CTR(out, received_eth_broadcast.packets);
2409
2410         vf_stats->rx_bytes =
2411                 MLX5_GET_CTR(out, received_eth_unicast.octets) +
2412                 MLX5_GET_CTR(out, received_ib_unicast.octets) +
2413                 MLX5_GET_CTR(out, received_eth_multicast.octets) +
2414                 MLX5_GET_CTR(out, received_ib_multicast.octets) +
2415                 MLX5_GET_CTR(out, received_eth_broadcast.octets);
2416
2417         vf_stats->tx_packets =
2418                 MLX5_GET_CTR(out, transmitted_eth_unicast.packets) +
2419                 MLX5_GET_CTR(out, transmitted_ib_unicast.packets) +
2420                 MLX5_GET_CTR(out, transmitted_eth_multicast.packets) +
2421                 MLX5_GET_CTR(out, transmitted_ib_multicast.packets) +
2422                 MLX5_GET_CTR(out, transmitted_eth_broadcast.packets);
2423
2424         vf_stats->tx_bytes =
2425                 MLX5_GET_CTR(out, transmitted_eth_unicast.octets) +
2426                 MLX5_GET_CTR(out, transmitted_ib_unicast.octets) +
2427                 MLX5_GET_CTR(out, transmitted_eth_multicast.octets) +
2428                 MLX5_GET_CTR(out, transmitted_ib_multicast.octets) +
2429                 MLX5_GET_CTR(out, transmitted_eth_broadcast.octets);
2430
2431         vf_stats->multicast =
2432                 MLX5_GET_CTR(out, received_eth_multicast.packets) +
2433                 MLX5_GET_CTR(out, received_ib_multicast.packets);
2434
2435         vf_stats->broadcast =
2436                 MLX5_GET_CTR(out, received_eth_broadcast.packets);
2437
2438         err = mlx5_eswitch_query_vport_drop_stats(esw->dev, vport, &stats);
2439         if (err)
2440                 goto free_out;
2441         vf_stats->rx_dropped = stats.rx_dropped;
2442         vf_stats->tx_dropped = stats.tx_dropped;
2443
2444 free_out:
2445         kvfree(out);
2446         return err;
2447 }
2448
2449 u8 mlx5_eswitch_mode(struct mlx5_eswitch *esw)
2450 {
2451         return ESW_ALLOWED(esw) ? esw->mode : SRIOV_NONE;
2452 }
2453 EXPORT_SYMBOL_GPL(mlx5_eswitch_mode);
2454
2455 bool mlx5_esw_lag_prereq(struct mlx5_core_dev *dev0, struct mlx5_core_dev *dev1)
2456 {
2457         if ((dev0->priv.eswitch->mode == SRIOV_NONE &&
2458              dev1->priv.eswitch->mode == SRIOV_NONE) ||
2459             (dev0->priv.eswitch->mode == SRIOV_OFFLOADS &&
2460              dev1->priv.eswitch->mode == SRIOV_OFFLOADS))
2461                 return true;
2462
2463         return false;
2464 }
2465
2466 bool mlx5_esw_multipath_prereq(struct mlx5_core_dev *dev0,
2467                                struct mlx5_core_dev *dev1)
2468 {
2469         return (dev0->priv.eswitch->mode == SRIOV_OFFLOADS &&
2470                 dev1->priv.eswitch->mode == SRIOV_OFFLOADS);
2471 }