GNU Linux-libre 4.14.290-gnu1
[releases.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 "eswitch.h"
40
41 #define UPLINK_VPORT 0xFFFF
42
43 enum {
44         MLX5_ACTION_NONE = 0,
45         MLX5_ACTION_ADD  = 1,
46         MLX5_ACTION_DEL  = 2,
47 };
48
49 /* Vport UC/MC hash node */
50 struct vport_addr {
51         struct l2addr_node     node;
52         u8                     action;
53         u32                    vport;
54         struct mlx5_flow_handle *flow_rule;
55         bool mpfs; /* UC MAC was added to MPFs */
56         /* A flag indicating that mac was added due to mc promiscuous vport */
57         bool mc_promisc;
58 };
59
60 enum {
61         UC_ADDR_CHANGE = BIT(0),
62         MC_ADDR_CHANGE = BIT(1),
63         PROMISC_CHANGE = BIT(3),
64 };
65
66 /* Vport context events */
67 #define SRIOV_VPORT_EVENTS (UC_ADDR_CHANGE | \
68                             MC_ADDR_CHANGE | \
69                             PROMISC_CHANGE)
70
71 static int arm_vport_context_events_cmd(struct mlx5_core_dev *dev, u16 vport,
72                                         u32 events_mask)
73 {
74         int in[MLX5_ST_SZ_DW(modify_nic_vport_context_in)]   = {0};
75         int out[MLX5_ST_SZ_DW(modify_nic_vport_context_out)] = {0};
76         void *nic_vport_ctx;
77
78         MLX5_SET(modify_nic_vport_context_in, in,
79                  opcode, MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT);
80         MLX5_SET(modify_nic_vport_context_in, in, field_select.change_event, 1);
81         MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport);
82         MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1);
83         nic_vport_ctx = MLX5_ADDR_OF(modify_nic_vport_context_in,
84                                      in, nic_vport_context);
85
86         MLX5_SET(nic_vport_context, nic_vport_ctx, arm_change_event, 1);
87
88         if (events_mask & UC_ADDR_CHANGE)
89                 MLX5_SET(nic_vport_context, nic_vport_ctx,
90                          event_on_uc_address_change, 1);
91         if (events_mask & MC_ADDR_CHANGE)
92                 MLX5_SET(nic_vport_context, nic_vport_ctx,
93                          event_on_mc_address_change, 1);
94         if (events_mask & PROMISC_CHANGE)
95                 MLX5_SET(nic_vport_context, nic_vport_ctx,
96                          event_on_promisc_change, 1);
97
98         return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
99 }
100
101 /* E-Switch vport context HW commands */
102 static int modify_esw_vport_context_cmd(struct mlx5_core_dev *dev, u16 vport,
103                                         void *in, int inlen)
104 {
105         u32 out[MLX5_ST_SZ_DW(modify_esw_vport_context_out)] = {0};
106
107         MLX5_SET(modify_esw_vport_context_in, in, opcode,
108                  MLX5_CMD_OP_MODIFY_ESW_VPORT_CONTEXT);
109         MLX5_SET(modify_esw_vport_context_in, in, vport_number, vport);
110         MLX5_SET(modify_esw_vport_context_in, in, other_vport, 1);
111         return mlx5_cmd_exec(dev, in, inlen, out, sizeof(out));
112 }
113
114 static int modify_esw_vport_cvlan(struct mlx5_core_dev *dev, u32 vport,
115                                   u16 vlan, u8 qos, u8 set_flags)
116 {
117         u32 in[MLX5_ST_SZ_DW(modify_esw_vport_context_in)] = {0};
118
119         if (!MLX5_CAP_ESW(dev, vport_cvlan_strip) ||
120             !MLX5_CAP_ESW(dev, vport_cvlan_insert_if_not_exist))
121                 return -EOPNOTSUPP;
122
123         esw_debug(dev, "Set Vport[%d] VLAN %d qos %d set=%x\n",
124                   vport, vlan, qos, set_flags);
125
126         if (set_flags & SET_VLAN_STRIP)
127                 MLX5_SET(modify_esw_vport_context_in, in,
128                          esw_vport_context.vport_cvlan_strip, 1);
129
130         if (set_flags & SET_VLAN_INSERT) {
131                 /* insert only if no vlan in packet */
132                 MLX5_SET(modify_esw_vport_context_in, in,
133                          esw_vport_context.vport_cvlan_insert, 1);
134
135                 MLX5_SET(modify_esw_vport_context_in, in,
136                          esw_vport_context.cvlan_pcp, qos);
137                 MLX5_SET(modify_esw_vport_context_in, in,
138                          esw_vport_context.cvlan_id, vlan);
139         }
140
141         MLX5_SET(modify_esw_vport_context_in, in,
142                  field_select.vport_cvlan_strip, 1);
143         MLX5_SET(modify_esw_vport_context_in, in,
144                  field_select.vport_cvlan_insert, 1);
145
146         return modify_esw_vport_context_cmd(dev, vport, in, sizeof(in));
147 }
148
149 /* E-Switch FDB */
150 static struct mlx5_flow_handle *
151 __esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u32 vport, bool rx_rule,
152                          u8 mac_c[ETH_ALEN], u8 mac_v[ETH_ALEN])
153 {
154         int match_header = (is_zero_ether_addr(mac_c) ? 0 :
155                             MLX5_MATCH_OUTER_HEADERS);
156         struct mlx5_flow_handle *flow_rule = NULL;
157         struct mlx5_flow_act flow_act = {0};
158         struct mlx5_flow_destination dest;
159         struct mlx5_flow_spec *spec;
160         void *mv_misc = NULL;
161         void *mc_misc = NULL;
162         u8 *dmac_v = NULL;
163         u8 *dmac_c = NULL;
164
165         if (rx_rule)
166                 match_header |= MLX5_MATCH_MISC_PARAMETERS;
167
168         spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
169         if (!spec)
170                 return NULL;
171
172         dmac_v = MLX5_ADDR_OF(fte_match_param, spec->match_value,
173                               outer_headers.dmac_47_16);
174         dmac_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
175                               outer_headers.dmac_47_16);
176
177         if (match_header & MLX5_MATCH_OUTER_HEADERS) {
178                 ether_addr_copy(dmac_v, mac_v);
179                 ether_addr_copy(dmac_c, mac_c);
180         }
181
182         if (match_header & MLX5_MATCH_MISC_PARAMETERS) {
183                 mv_misc  = MLX5_ADDR_OF(fte_match_param, spec->match_value,
184                                         misc_parameters);
185                 mc_misc  = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
186                                         misc_parameters);
187                 MLX5_SET(fte_match_set_misc, mv_misc, source_port, UPLINK_VPORT);
188                 MLX5_SET_TO_ONES(fte_match_set_misc, mc_misc, source_port);
189         }
190
191         dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
192         dest.vport_num = vport;
193
194         esw_debug(esw->dev,
195                   "\tFDB add rule dmac_v(%pM) dmac_c(%pM) -> vport(%d)\n",
196                   dmac_v, dmac_c, vport);
197         spec->match_criteria_enable = match_header;
198         flow_act.action =  MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
199         flow_rule =
200                 mlx5_add_flow_rules(esw->fdb_table.fdb, spec,
201                                     &flow_act, &dest, 1);
202         if (IS_ERR(flow_rule)) {
203                 esw_warn(esw->dev,
204                          "FDB: Failed to add flow rule: dmac_v(%pM) dmac_c(%pM) -> vport(%d), err(%ld)\n",
205                          dmac_v, dmac_c, vport, PTR_ERR(flow_rule));
206                 flow_rule = NULL;
207         }
208
209         kvfree(spec);
210         return flow_rule;
211 }
212
213 static struct mlx5_flow_handle *
214 esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u8 mac[ETH_ALEN], u32 vport)
215 {
216         u8 mac_c[ETH_ALEN];
217
218         eth_broadcast_addr(mac_c);
219         return __esw_fdb_set_vport_rule(esw, vport, false, mac_c, mac);
220 }
221
222 static struct mlx5_flow_handle *
223 esw_fdb_set_vport_allmulti_rule(struct mlx5_eswitch *esw, u32 vport)
224 {
225         u8 mac_c[ETH_ALEN];
226         u8 mac_v[ETH_ALEN];
227
228         eth_zero_addr(mac_c);
229         eth_zero_addr(mac_v);
230         mac_c[0] = 0x01;
231         mac_v[0] = 0x01;
232         return __esw_fdb_set_vport_rule(esw, vport, false, mac_c, mac_v);
233 }
234
235 static struct mlx5_flow_handle *
236 esw_fdb_set_vport_promisc_rule(struct mlx5_eswitch *esw, u32 vport)
237 {
238         u8 mac_c[ETH_ALEN];
239         u8 mac_v[ETH_ALEN];
240
241         eth_zero_addr(mac_c);
242         eth_zero_addr(mac_v);
243         return __esw_fdb_set_vport_rule(esw, vport, true, mac_c, mac_v);
244 }
245
246 static int esw_create_legacy_fdb_table(struct mlx5_eswitch *esw, int nvports)
247 {
248         int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
249         struct mlx5_flow_table_attr ft_attr = {};
250         struct mlx5_core_dev *dev = esw->dev;
251         struct mlx5_flow_namespace *root_ns;
252         struct mlx5_flow_table *fdb;
253         struct mlx5_flow_group *g;
254         void *match_criteria;
255         int table_size;
256         u32 *flow_group_in;
257         u8 *dmac;
258         int err = 0;
259
260         esw_debug(dev, "Create FDB log_max_size(%d)\n",
261                   MLX5_CAP_ESW_FLOWTABLE_FDB(dev, log_max_ft_size));
262
263         root_ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_FDB);
264         if (!root_ns) {
265                 esw_warn(dev, "Failed to get FDB flow namespace\n");
266                 return -EOPNOTSUPP;
267         }
268
269         flow_group_in = kvzalloc(inlen, GFP_KERNEL);
270         if (!flow_group_in)
271                 return -ENOMEM;
272
273         table_size = BIT(MLX5_CAP_ESW_FLOWTABLE_FDB(dev, log_max_ft_size));
274
275         ft_attr.max_fte = table_size;
276         fdb = mlx5_create_flow_table(root_ns, &ft_attr);
277         if (IS_ERR(fdb)) {
278                 err = PTR_ERR(fdb);
279                 esw_warn(dev, "Failed to create FDB Table err %d\n", err);
280                 goto out;
281         }
282         esw->fdb_table.fdb = fdb;
283
284         /* Addresses group : Full match unicast/multicast addresses */
285         MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
286                  MLX5_MATCH_OUTER_HEADERS);
287         match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in, match_criteria);
288         dmac = MLX5_ADDR_OF(fte_match_param, match_criteria, outer_headers.dmac_47_16);
289         MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 0);
290         /* Preserve 2 entries for allmulti and promisc rules*/
291         MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, table_size - 3);
292         eth_broadcast_addr(dmac);
293         g = mlx5_create_flow_group(fdb, flow_group_in);
294         if (IS_ERR(g)) {
295                 err = PTR_ERR(g);
296                 esw_warn(dev, "Failed to create flow group err(%d)\n", err);
297                 goto out;
298         }
299         esw->fdb_table.legacy.addr_grp = g;
300
301         /* Allmulti group : One rule that forwards any mcast traffic */
302         MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
303                  MLX5_MATCH_OUTER_HEADERS);
304         MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, table_size - 2);
305         MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, table_size - 2);
306         eth_zero_addr(dmac);
307         dmac[0] = 0x01;
308         g = mlx5_create_flow_group(fdb, flow_group_in);
309         if (IS_ERR(g)) {
310                 err = PTR_ERR(g);
311                 esw_warn(dev, "Failed to create allmulti flow group err(%d)\n", err);
312                 goto out;
313         }
314         esw->fdb_table.legacy.allmulti_grp = g;
315
316         /* Promiscuous group :
317          * One rule that forward all unmatched traffic from previous groups
318          */
319         eth_zero_addr(dmac);
320         MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
321                  MLX5_MATCH_MISC_PARAMETERS);
322         MLX5_SET_TO_ONES(fte_match_param, match_criteria, misc_parameters.source_port);
323         MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, table_size - 1);
324         MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, table_size - 1);
325         g = mlx5_create_flow_group(fdb, flow_group_in);
326         if (IS_ERR(g)) {
327                 err = PTR_ERR(g);
328                 esw_warn(dev, "Failed to create promisc flow group err(%d)\n", err);
329                 goto out;
330         }
331         esw->fdb_table.legacy.promisc_grp = g;
332
333 out:
334         if (err) {
335                 if (!IS_ERR_OR_NULL(esw->fdb_table.legacy.allmulti_grp)) {
336                         mlx5_destroy_flow_group(esw->fdb_table.legacy.allmulti_grp);
337                         esw->fdb_table.legacy.allmulti_grp = NULL;
338                 }
339                 if (!IS_ERR_OR_NULL(esw->fdb_table.legacy.addr_grp)) {
340                         mlx5_destroy_flow_group(esw->fdb_table.legacy.addr_grp);
341                         esw->fdb_table.legacy.addr_grp = NULL;
342                 }
343                 if (!IS_ERR_OR_NULL(esw->fdb_table.fdb)) {
344                         mlx5_destroy_flow_table(esw->fdb_table.fdb);
345                         esw->fdb_table.fdb = NULL;
346                 }
347         }
348
349         kvfree(flow_group_in);
350         return err;
351 }
352
353 static void esw_destroy_legacy_fdb_table(struct mlx5_eswitch *esw)
354 {
355         if (!esw->fdb_table.fdb)
356                 return;
357
358         esw_debug(esw->dev, "Destroy FDB Table\n");
359         mlx5_destroy_flow_group(esw->fdb_table.legacy.promisc_grp);
360         mlx5_destroy_flow_group(esw->fdb_table.legacy.allmulti_grp);
361         mlx5_destroy_flow_group(esw->fdb_table.legacy.addr_grp);
362         mlx5_destroy_flow_table(esw->fdb_table.fdb);
363         esw->fdb_table.fdb = NULL;
364         esw->fdb_table.legacy.addr_grp = NULL;
365         esw->fdb_table.legacy.allmulti_grp = NULL;
366         esw->fdb_table.legacy.promisc_grp = NULL;
367 }
368
369 /* E-Switch vport UC/MC lists management */
370 typedef int (*vport_addr_action)(struct mlx5_eswitch *esw,
371                                  struct vport_addr *vaddr);
372
373 static int esw_add_uc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr)
374 {
375         u8 *mac = vaddr->node.addr;
376         u32 vport = vaddr->vport;
377         int err;
378
379         /* Skip mlx5_mpfs_add_mac for PFs,
380          * it is already done by the PF netdev in mlx5e_execute_l2_action
381          */
382         if (!vport)
383                 goto fdb_add;
384
385         err = mlx5_mpfs_add_mac(esw->dev, mac);
386         if (err) {
387                 esw_warn(esw->dev,
388                          "Failed to add L2 table mac(%pM) for vport(%d), err(%d)\n",
389                          mac, vport, err);
390                 return err;
391         }
392         vaddr->mpfs = true;
393
394 fdb_add:
395         /* SRIOV is enabled: Forward UC MAC to vport */
396         if (esw->fdb_table.fdb && esw->mode == SRIOV_LEGACY)
397                 vaddr->flow_rule = esw_fdb_set_vport_rule(esw, mac, vport);
398
399         esw_debug(esw->dev, "\tADDED UC MAC: vport[%d] %pM fr(%p)\n",
400                   vport, mac, vaddr->flow_rule);
401
402         return 0;
403 }
404
405 static int esw_del_uc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr)
406 {
407         u8 *mac = vaddr->node.addr;
408         u32 vport = vaddr->vport;
409         int err = 0;
410
411         /* Skip mlx5_mpfs_del_mac for PFs,
412          * it is already done by the PF netdev in mlx5e_execute_l2_action
413          */
414         if (!vport || !vaddr->mpfs)
415                 goto fdb_del;
416
417         err = mlx5_mpfs_del_mac(esw->dev, mac);
418         if (err)
419                 esw_warn(esw->dev,
420                          "Failed to del L2 table mac(%pM) for vport(%d), err(%d)\n",
421                          mac, vport, err);
422         vaddr->mpfs = false;
423
424 fdb_del:
425         if (vaddr->flow_rule)
426                 mlx5_del_flow_rules(vaddr->flow_rule);
427         vaddr->flow_rule = NULL;
428
429         return 0;
430 }
431
432 static void update_allmulti_vports(struct mlx5_eswitch *esw,
433                                    struct vport_addr *vaddr,
434                                    struct esw_mc_addr *esw_mc)
435 {
436         u8 *mac = vaddr->node.addr;
437         u32 vport_idx = 0;
438
439         for (vport_idx = 0; vport_idx < esw->total_vports; vport_idx++) {
440                 struct mlx5_vport *vport = &esw->vports[vport_idx];
441                 struct hlist_head *vport_hash = vport->mc_list;
442                 struct vport_addr *iter_vaddr =
443                                         l2addr_hash_find(vport_hash,
444                                                          mac,
445                                                          struct vport_addr);
446                 if (IS_ERR_OR_NULL(vport->allmulti_rule) ||
447                     vaddr->vport == vport_idx)
448                         continue;
449                 switch (vaddr->action) {
450                 case MLX5_ACTION_ADD:
451                         if (iter_vaddr)
452                                 continue;
453                         iter_vaddr = l2addr_hash_add(vport_hash, mac,
454                                                      struct vport_addr,
455                                                      GFP_KERNEL);
456                         if (!iter_vaddr) {
457                                 esw_warn(esw->dev,
458                                          "ALL-MULTI: Failed to add MAC(%pM) to vport[%d] DB\n",
459                                          mac, vport_idx);
460                                 continue;
461                         }
462                         iter_vaddr->vport = vport_idx;
463                         iter_vaddr->flow_rule =
464                                         esw_fdb_set_vport_rule(esw,
465                                                                mac,
466                                                                vport_idx);
467                         iter_vaddr->mc_promisc = true;
468                         break;
469                 case MLX5_ACTION_DEL:
470                         if (!iter_vaddr)
471                                 continue;
472                         mlx5_del_flow_rules(iter_vaddr->flow_rule);
473                         l2addr_hash_del(iter_vaddr);
474                         break;
475                 }
476         }
477 }
478
479 static int esw_add_mc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr)
480 {
481         struct hlist_head *hash = esw->mc_table;
482         struct esw_mc_addr *esw_mc;
483         u8 *mac = vaddr->node.addr;
484         u32 vport = vaddr->vport;
485
486         if (!esw->fdb_table.fdb)
487                 return 0;
488
489         esw_mc = l2addr_hash_find(hash, mac, struct esw_mc_addr);
490         if (esw_mc)
491                 goto add;
492
493         esw_mc = l2addr_hash_add(hash, mac, struct esw_mc_addr, GFP_KERNEL);
494         if (!esw_mc)
495                 return -ENOMEM;
496
497         esw_mc->uplink_rule = /* Forward MC MAC to Uplink */
498                 esw_fdb_set_vport_rule(esw, mac, UPLINK_VPORT);
499
500         /* Add this multicast mac to all the mc promiscuous vports */
501         update_allmulti_vports(esw, vaddr, esw_mc);
502
503 add:
504         /* If the multicast mac is added as a result of mc promiscuous vport,
505          * don't increment the multicast ref count
506          */
507         if (!vaddr->mc_promisc)
508                 esw_mc->refcnt++;
509
510         /* Forward MC MAC to vport */
511         vaddr->flow_rule = esw_fdb_set_vport_rule(esw, mac, vport);
512         esw_debug(esw->dev,
513                   "\tADDED MC MAC: vport[%d] %pM fr(%p) refcnt(%d) uplinkfr(%p)\n",
514                   vport, mac, vaddr->flow_rule,
515                   esw_mc->refcnt, esw_mc->uplink_rule);
516         return 0;
517 }
518
519 static int esw_del_mc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr)
520 {
521         struct hlist_head *hash = esw->mc_table;
522         struct esw_mc_addr *esw_mc;
523         u8 *mac = vaddr->node.addr;
524         u32 vport = vaddr->vport;
525
526         if (!esw->fdb_table.fdb)
527                 return 0;
528
529         esw_mc = l2addr_hash_find(hash, mac, struct esw_mc_addr);
530         if (!esw_mc) {
531                 esw_warn(esw->dev,
532                          "Failed to find eswitch MC addr for MAC(%pM) vport(%d)",
533                          mac, vport);
534                 return -EINVAL;
535         }
536         esw_debug(esw->dev,
537                   "\tDELETE MC MAC: vport[%d] %pM fr(%p) refcnt(%d) uplinkfr(%p)\n",
538                   vport, mac, vaddr->flow_rule, esw_mc->refcnt,
539                   esw_mc->uplink_rule);
540
541         if (vaddr->flow_rule)
542                 mlx5_del_flow_rules(vaddr->flow_rule);
543         vaddr->flow_rule = NULL;
544
545         /* If the multicast mac is added as a result of mc promiscuous vport,
546          * don't decrement the multicast ref count.
547          */
548         if (vaddr->mc_promisc || (--esw_mc->refcnt > 0))
549                 return 0;
550
551         /* Remove this multicast mac from all the mc promiscuous vports */
552         update_allmulti_vports(esw, vaddr, esw_mc);
553
554         if (esw_mc->uplink_rule)
555                 mlx5_del_flow_rules(esw_mc->uplink_rule);
556
557         l2addr_hash_del(esw_mc);
558         return 0;
559 }
560
561 /* Apply vport UC/MC list to HW l2 table and FDB table */
562 static void esw_apply_vport_addr_list(struct mlx5_eswitch *esw,
563                                       u32 vport_num, int list_type)
564 {
565         struct mlx5_vport *vport = &esw->vports[vport_num];
566         bool is_uc = list_type == MLX5_NVPRT_LIST_TYPE_UC;
567         vport_addr_action vport_addr_add;
568         vport_addr_action vport_addr_del;
569         struct vport_addr *addr;
570         struct l2addr_node *node;
571         struct hlist_head *hash;
572         struct hlist_node *tmp;
573         int hi;
574
575         vport_addr_add = is_uc ? esw_add_uc_addr :
576                                  esw_add_mc_addr;
577         vport_addr_del = is_uc ? esw_del_uc_addr :
578                                  esw_del_mc_addr;
579
580         hash = is_uc ? vport->uc_list : vport->mc_list;
581         for_each_l2hash_node(node, tmp, hash, hi) {
582                 addr = container_of(node, struct vport_addr, node);
583                 switch (addr->action) {
584                 case MLX5_ACTION_ADD:
585                         vport_addr_add(esw, addr);
586                         addr->action = MLX5_ACTION_NONE;
587                         break;
588                 case MLX5_ACTION_DEL:
589                         vport_addr_del(esw, addr);
590                         l2addr_hash_del(addr);
591                         break;
592                 }
593         }
594 }
595
596 /* Sync vport UC/MC list from vport context */
597 static void esw_update_vport_addr_list(struct mlx5_eswitch *esw,
598                                        u32 vport_num, int list_type)
599 {
600         struct mlx5_vport *vport = &esw->vports[vport_num];
601         bool is_uc = list_type == MLX5_NVPRT_LIST_TYPE_UC;
602         u8 (*mac_list)[ETH_ALEN];
603         struct l2addr_node *node;
604         struct vport_addr *addr;
605         struct hlist_head *hash;
606         struct hlist_node *tmp;
607         int size;
608         int err;
609         int hi;
610         int i;
611
612         size = is_uc ? MLX5_MAX_UC_PER_VPORT(esw->dev) :
613                        MLX5_MAX_MC_PER_VPORT(esw->dev);
614
615         mac_list = kcalloc(size, ETH_ALEN, GFP_KERNEL);
616         if (!mac_list)
617                 return;
618
619         hash = is_uc ? vport->uc_list : vport->mc_list;
620
621         for_each_l2hash_node(node, tmp, hash, hi) {
622                 addr = container_of(node, struct vport_addr, node);
623                 addr->action = MLX5_ACTION_DEL;
624         }
625
626         if (!vport->enabled)
627                 goto out;
628
629         err = mlx5_query_nic_vport_mac_list(esw->dev, vport_num, list_type,
630                                             mac_list, &size);
631         if (err)
632                 goto out;
633         esw_debug(esw->dev, "vport[%d] context update %s list size (%d)\n",
634                   vport_num, is_uc ? "UC" : "MC", size);
635
636         for (i = 0; i < size; i++) {
637                 if (is_uc && !is_valid_ether_addr(mac_list[i]))
638                         continue;
639
640                 if (!is_uc && !is_multicast_ether_addr(mac_list[i]))
641                         continue;
642
643                 addr = l2addr_hash_find(hash, mac_list[i], struct vport_addr);
644                 if (addr) {
645                         addr->action = MLX5_ACTION_NONE;
646                         /* If this mac was previously added because of allmulti
647                          * promiscuous rx mode, its now converted to be original
648                          * vport mac.
649                          */
650                         if (addr->mc_promisc) {
651                                 struct esw_mc_addr *esw_mc =
652                                         l2addr_hash_find(esw->mc_table,
653                                                          mac_list[i],
654                                                          struct esw_mc_addr);
655                                 if (!esw_mc) {
656                                         esw_warn(esw->dev,
657                                                  "Failed to MAC(%pM) in mcast DB\n",
658                                                  mac_list[i]);
659                                         continue;
660                                 }
661                                 esw_mc->refcnt++;
662                                 addr->mc_promisc = false;
663                         }
664                         continue;
665                 }
666
667                 addr = l2addr_hash_add(hash, mac_list[i], struct vport_addr,
668                                        GFP_KERNEL);
669                 if (!addr) {
670                         esw_warn(esw->dev,
671                                  "Failed to add MAC(%pM) to vport[%d] DB\n",
672                                  mac_list[i], vport_num);
673                         continue;
674                 }
675                 addr->vport = vport_num;
676                 addr->action = MLX5_ACTION_ADD;
677         }
678 out:
679         kfree(mac_list);
680 }
681
682 /* Sync vport UC/MC list from vport context
683  * Must be called after esw_update_vport_addr_list
684  */
685 static void esw_update_vport_mc_promisc(struct mlx5_eswitch *esw, u32 vport_num)
686 {
687         struct mlx5_vport *vport = &esw->vports[vport_num];
688         struct l2addr_node *node;
689         struct vport_addr *addr;
690         struct hlist_head *hash;
691         struct hlist_node *tmp;
692         int hi;
693
694         hash = vport->mc_list;
695
696         for_each_l2hash_node(node, tmp, esw->mc_table, hi) {
697                 u8 *mac = node->addr;
698
699                 addr = l2addr_hash_find(hash, mac, struct vport_addr);
700                 if (addr) {
701                         if (addr->action == MLX5_ACTION_DEL)
702                                 addr->action = MLX5_ACTION_NONE;
703                         continue;
704                 }
705                 addr = l2addr_hash_add(hash, mac, struct vport_addr,
706                                        GFP_KERNEL);
707                 if (!addr) {
708                         esw_warn(esw->dev,
709                                  "Failed to add allmulti MAC(%pM) to vport[%d] DB\n",
710                                  mac, vport_num);
711                         continue;
712                 }
713                 addr->vport = vport_num;
714                 addr->action = MLX5_ACTION_ADD;
715                 addr->mc_promisc = true;
716         }
717 }
718
719 /* Apply vport rx mode to HW FDB table */
720 static void esw_apply_vport_rx_mode(struct mlx5_eswitch *esw, u32 vport_num,
721                                     bool promisc, bool mc_promisc)
722 {
723         struct esw_mc_addr *allmulti_addr = &esw->mc_promisc;
724         struct mlx5_vport *vport = &esw->vports[vport_num];
725
726         if (IS_ERR_OR_NULL(vport->allmulti_rule) != mc_promisc)
727                 goto promisc;
728
729         if (mc_promisc) {
730                 vport->allmulti_rule =
731                                 esw_fdb_set_vport_allmulti_rule(esw, vport_num);
732                 if (!allmulti_addr->uplink_rule)
733                         allmulti_addr->uplink_rule =
734                                 esw_fdb_set_vport_allmulti_rule(esw,
735                                                                 UPLINK_VPORT);
736                 allmulti_addr->refcnt++;
737         } else if (vport->allmulti_rule) {
738                 mlx5_del_flow_rules(vport->allmulti_rule);
739                 vport->allmulti_rule = NULL;
740
741                 if (--allmulti_addr->refcnt > 0)
742                         goto promisc;
743
744                 if (allmulti_addr->uplink_rule)
745                         mlx5_del_flow_rules(allmulti_addr->uplink_rule);
746                 allmulti_addr->uplink_rule = NULL;
747         }
748
749 promisc:
750         if (IS_ERR_OR_NULL(vport->promisc_rule) != promisc)
751                 return;
752
753         if (promisc) {
754                 vport->promisc_rule = esw_fdb_set_vport_promisc_rule(esw,
755                                                                      vport_num);
756         } else if (vport->promisc_rule) {
757                 mlx5_del_flow_rules(vport->promisc_rule);
758                 vport->promisc_rule = NULL;
759         }
760 }
761
762 /* Sync vport rx mode from vport context */
763 static void esw_update_vport_rx_mode(struct mlx5_eswitch *esw, u32 vport_num)
764 {
765         struct mlx5_vport *vport = &esw->vports[vport_num];
766         int promisc_all = 0;
767         int promisc_uc = 0;
768         int promisc_mc = 0;
769         int err;
770
771         err = mlx5_query_nic_vport_promisc(esw->dev,
772                                            vport_num,
773                                            &promisc_uc,
774                                            &promisc_mc,
775                                            &promisc_all);
776         if (err)
777                 return;
778         esw_debug(esw->dev, "vport[%d] context update rx mode promisc_all=%d, all_multi=%d\n",
779                   vport_num, promisc_all, promisc_mc);
780
781         if (!vport->info.trusted || !vport->enabled) {
782                 promisc_uc = 0;
783                 promisc_mc = 0;
784                 promisc_all = 0;
785         }
786
787         esw_apply_vport_rx_mode(esw, vport_num, promisc_all,
788                                 (promisc_all || promisc_mc));
789 }
790
791 static void esw_vport_change_handle_locked(struct mlx5_vport *vport)
792 {
793         struct mlx5_core_dev *dev = vport->dev;
794         struct mlx5_eswitch *esw = dev->priv.eswitch;
795         u8 mac[ETH_ALEN];
796
797         mlx5_query_nic_vport_mac_address(dev, vport->vport, mac);
798         esw_debug(dev, "vport[%d] Context Changed: perm mac: %pM\n",
799                   vport->vport, mac);
800
801         if (vport->enabled_events & UC_ADDR_CHANGE) {
802                 esw_update_vport_addr_list(esw, vport->vport,
803                                            MLX5_NVPRT_LIST_TYPE_UC);
804                 esw_apply_vport_addr_list(esw, vport->vport,
805                                           MLX5_NVPRT_LIST_TYPE_UC);
806         }
807
808         if (vport->enabled_events & MC_ADDR_CHANGE) {
809                 esw_update_vport_addr_list(esw, vport->vport,
810                                            MLX5_NVPRT_LIST_TYPE_MC);
811         }
812
813         if (vport->enabled_events & PROMISC_CHANGE) {
814                 esw_update_vport_rx_mode(esw, vport->vport);
815                 if (!IS_ERR_OR_NULL(vport->allmulti_rule))
816                         esw_update_vport_mc_promisc(esw, vport->vport);
817         }
818
819         if (vport->enabled_events & (PROMISC_CHANGE | MC_ADDR_CHANGE)) {
820                 esw_apply_vport_addr_list(esw, vport->vport,
821                                           MLX5_NVPRT_LIST_TYPE_MC);
822         }
823
824         esw_debug(esw->dev, "vport[%d] Context Changed: Done\n", vport->vport);
825         if (vport->enabled)
826                 arm_vport_context_events_cmd(dev, vport->vport,
827                                              vport->enabled_events);
828 }
829
830 static void esw_vport_change_handler(struct work_struct *work)
831 {
832         struct mlx5_vport *vport =
833                 container_of(work, struct mlx5_vport, vport_change_handler);
834         struct mlx5_eswitch *esw = vport->dev->priv.eswitch;
835
836         mutex_lock(&esw->state_lock);
837         esw_vport_change_handle_locked(vport);
838         mutex_unlock(&esw->state_lock);
839 }
840
841 static int esw_vport_enable_egress_acl(struct mlx5_eswitch *esw,
842                                        struct mlx5_vport *vport)
843 {
844         int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
845         struct mlx5_flow_group *vlan_grp = NULL;
846         struct mlx5_flow_group *drop_grp = NULL;
847         struct mlx5_core_dev *dev = esw->dev;
848         struct mlx5_flow_namespace *root_ns;
849         struct mlx5_flow_table *acl;
850         void *match_criteria;
851         u32 *flow_group_in;
852         /* The egress acl table contains 2 rules:
853          * 1)Allow traffic with vlan_tag=vst_vlan_id
854          * 2)Drop all other traffic.
855          */
856         int table_size = 2;
857         int err = 0;
858
859         if (!MLX5_CAP_ESW_EGRESS_ACL(dev, ft_support))
860                 return -EOPNOTSUPP;
861
862         if (!IS_ERR_OR_NULL(vport->egress.acl))
863                 return 0;
864
865         esw_debug(dev, "Create vport[%d] egress ACL log_max_size(%d)\n",
866                   vport->vport, MLX5_CAP_ESW_EGRESS_ACL(dev, log_max_ft_size));
867
868         root_ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_ESW_EGRESS);
869         if (!root_ns) {
870                 esw_warn(dev, "Failed to get E-Switch egress flow namespace\n");
871                 return -EOPNOTSUPP;
872         }
873
874         flow_group_in = kvzalloc(inlen, GFP_KERNEL);
875         if (!flow_group_in)
876                 return -ENOMEM;
877
878         acl = mlx5_create_vport_flow_table(root_ns, 0, table_size, 0, vport->vport);
879         if (IS_ERR(acl)) {
880                 err = PTR_ERR(acl);
881                 esw_warn(dev, "Failed to create E-Switch vport[%d] egress flow Table, err(%d)\n",
882                          vport->vport, err);
883                 goto out;
884         }
885
886         MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
887         match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in, match_criteria);
888         MLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.cvlan_tag);
889         MLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.first_vid);
890         MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 0);
891         MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 0);
892
893         vlan_grp = mlx5_create_flow_group(acl, flow_group_in);
894         if (IS_ERR(vlan_grp)) {
895                 err = PTR_ERR(vlan_grp);
896                 esw_warn(dev, "Failed to create E-Switch vport[%d] egress allowed vlans flow group, err(%d)\n",
897                          vport->vport, err);
898                 goto out;
899         }
900
901         memset(flow_group_in, 0, inlen);
902         MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 1);
903         MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 1);
904         drop_grp = mlx5_create_flow_group(acl, flow_group_in);
905         if (IS_ERR(drop_grp)) {
906                 err = PTR_ERR(drop_grp);
907                 esw_warn(dev, "Failed to create E-Switch vport[%d] egress drop flow group, err(%d)\n",
908                          vport->vport, err);
909                 goto out;
910         }
911
912         vport->egress.acl = acl;
913         vport->egress.drop_grp = drop_grp;
914         vport->egress.allowed_vlans_grp = vlan_grp;
915 out:
916         kvfree(flow_group_in);
917         if (err && !IS_ERR_OR_NULL(vlan_grp))
918                 mlx5_destroy_flow_group(vlan_grp);
919         if (err && !IS_ERR_OR_NULL(acl))
920                 mlx5_destroy_flow_table(acl);
921         return err;
922 }
923
924 static void esw_vport_cleanup_egress_rules(struct mlx5_eswitch *esw,
925                                            struct mlx5_vport *vport)
926 {
927         if (!IS_ERR_OR_NULL(vport->egress.allowed_vlan))
928                 mlx5_del_flow_rules(vport->egress.allowed_vlan);
929
930         if (!IS_ERR_OR_NULL(vport->egress.drop_rule))
931                 mlx5_del_flow_rules(vport->egress.drop_rule);
932
933         vport->egress.allowed_vlan = NULL;
934         vport->egress.drop_rule = NULL;
935 }
936
937 static void esw_vport_disable_egress_acl(struct mlx5_eswitch *esw,
938                                          struct mlx5_vport *vport)
939 {
940         if (IS_ERR_OR_NULL(vport->egress.acl))
941                 return;
942
943         esw_debug(esw->dev, "Destroy vport[%d] E-Switch egress ACL\n", vport->vport);
944
945         esw_vport_cleanup_egress_rules(esw, vport);
946         mlx5_destroy_flow_group(vport->egress.allowed_vlans_grp);
947         mlx5_destroy_flow_group(vport->egress.drop_grp);
948         mlx5_destroy_flow_table(vport->egress.acl);
949         vport->egress.allowed_vlans_grp = NULL;
950         vport->egress.drop_grp = NULL;
951         vport->egress.acl = NULL;
952 }
953
954 static int esw_vport_enable_ingress_acl(struct mlx5_eswitch *esw,
955                                         struct mlx5_vport *vport)
956 {
957         int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
958         struct mlx5_core_dev *dev = esw->dev;
959         struct mlx5_flow_namespace *root_ns;
960         struct mlx5_flow_table *acl;
961         struct mlx5_flow_group *g;
962         void *match_criteria;
963         u32 *flow_group_in;
964         /* The ingress acl table contains 4 groups
965          * (2 active rules at the same time -
966          *      1 allow rule from one of the first 3 groups.
967          *      1 drop rule from the last group):
968          * 1)Allow untagged traffic with smac=original mac.
969          * 2)Allow untagged traffic.
970          * 3)Allow traffic with smac=original mac.
971          * 4)Drop all other traffic.
972          */
973         int table_size = 4;
974         int err = 0;
975
976         if (!MLX5_CAP_ESW_INGRESS_ACL(dev, ft_support))
977                 return -EOPNOTSUPP;
978
979         if (!IS_ERR_OR_NULL(vport->ingress.acl))
980                 return 0;
981
982         esw_debug(dev, "Create vport[%d] ingress ACL log_max_size(%d)\n",
983                   vport->vport, MLX5_CAP_ESW_INGRESS_ACL(dev, log_max_ft_size));
984
985         root_ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_ESW_INGRESS);
986         if (!root_ns) {
987                 esw_warn(dev, "Failed to get E-Switch ingress flow namespace\n");
988                 return -EOPNOTSUPP;
989         }
990
991         flow_group_in = kvzalloc(inlen, GFP_KERNEL);
992         if (!flow_group_in)
993                 return -ENOMEM;
994
995         acl = mlx5_create_vport_flow_table(root_ns, 0, table_size, 0, vport->vport);
996         if (IS_ERR(acl)) {
997                 err = PTR_ERR(acl);
998                 esw_warn(dev, "Failed to create E-Switch vport[%d] ingress flow Table, err(%d)\n",
999                          vport->vport, err);
1000                 goto out;
1001         }
1002         vport->ingress.acl = acl;
1003
1004         match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in, match_criteria);
1005
1006         MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
1007         MLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.cvlan_tag);
1008         MLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.smac_47_16);
1009         MLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.smac_15_0);
1010         MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 0);
1011         MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 0);
1012
1013         g = mlx5_create_flow_group(acl, flow_group_in);
1014         if (IS_ERR(g)) {
1015                 err = PTR_ERR(g);
1016                 esw_warn(dev, "Failed to create E-Switch vport[%d] ingress untagged spoofchk flow group, err(%d)\n",
1017                          vport->vport, err);
1018                 goto out;
1019         }
1020         vport->ingress.allow_untagged_spoofchk_grp = g;
1021
1022         memset(flow_group_in, 0, inlen);
1023         MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
1024         MLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.cvlan_tag);
1025         MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 1);
1026         MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 1);
1027
1028         g = mlx5_create_flow_group(acl, flow_group_in);
1029         if (IS_ERR(g)) {
1030                 err = PTR_ERR(g);
1031                 esw_warn(dev, "Failed to create E-Switch vport[%d] ingress untagged flow group, err(%d)\n",
1032                          vport->vport, err);
1033                 goto out;
1034         }
1035         vport->ingress.allow_untagged_only_grp = g;
1036
1037         memset(flow_group_in, 0, inlen);
1038         MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
1039         MLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.smac_47_16);
1040         MLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.smac_15_0);
1041         MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 2);
1042         MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 2);
1043
1044         g = mlx5_create_flow_group(acl, flow_group_in);
1045         if (IS_ERR(g)) {
1046                 err = PTR_ERR(g);
1047                 esw_warn(dev, "Failed to create E-Switch vport[%d] ingress spoofchk flow group, err(%d)\n",
1048                          vport->vport, err);
1049                 goto out;
1050         }
1051         vport->ingress.allow_spoofchk_only_grp = g;
1052
1053         memset(flow_group_in, 0, inlen);
1054         MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 3);
1055         MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 3);
1056
1057         g = mlx5_create_flow_group(acl, flow_group_in);
1058         if (IS_ERR(g)) {
1059                 err = PTR_ERR(g);
1060                 esw_warn(dev, "Failed to create E-Switch vport[%d] ingress drop flow group, err(%d)\n",
1061                          vport->vport, err);
1062                 goto out;
1063         }
1064         vport->ingress.drop_grp = g;
1065
1066 out:
1067         if (err) {
1068                 if (!IS_ERR_OR_NULL(vport->ingress.allow_spoofchk_only_grp))
1069                         mlx5_destroy_flow_group(
1070                                         vport->ingress.allow_spoofchk_only_grp);
1071                 if (!IS_ERR_OR_NULL(vport->ingress.allow_untagged_only_grp))
1072                         mlx5_destroy_flow_group(
1073                                         vport->ingress.allow_untagged_only_grp);
1074                 if (!IS_ERR_OR_NULL(vport->ingress.allow_untagged_spoofchk_grp))
1075                         mlx5_destroy_flow_group(
1076                                 vport->ingress.allow_untagged_spoofchk_grp);
1077                 if (!IS_ERR_OR_NULL(vport->ingress.acl))
1078                         mlx5_destroy_flow_table(vport->ingress.acl);
1079         }
1080
1081         kvfree(flow_group_in);
1082         return err;
1083 }
1084
1085 static void esw_vport_cleanup_ingress_rules(struct mlx5_eswitch *esw,
1086                                             struct mlx5_vport *vport)
1087 {
1088         if (!IS_ERR_OR_NULL(vport->ingress.drop_rule))
1089                 mlx5_del_flow_rules(vport->ingress.drop_rule);
1090
1091         if (!IS_ERR_OR_NULL(vport->ingress.allow_rule))
1092                 mlx5_del_flow_rules(vport->ingress.allow_rule);
1093
1094         vport->ingress.drop_rule = NULL;
1095         vport->ingress.allow_rule = NULL;
1096 }
1097
1098 static void esw_vport_disable_ingress_acl(struct mlx5_eswitch *esw,
1099                                           struct mlx5_vport *vport)
1100 {
1101         if (IS_ERR_OR_NULL(vport->ingress.acl))
1102                 return;
1103
1104         esw_debug(esw->dev, "Destroy vport[%d] E-Switch ingress ACL\n", vport->vport);
1105
1106         esw_vport_cleanup_ingress_rules(esw, vport);
1107         mlx5_destroy_flow_group(vport->ingress.allow_spoofchk_only_grp);
1108         mlx5_destroy_flow_group(vport->ingress.allow_untagged_only_grp);
1109         mlx5_destroy_flow_group(vport->ingress.allow_untagged_spoofchk_grp);
1110         mlx5_destroy_flow_group(vport->ingress.drop_grp);
1111         mlx5_destroy_flow_table(vport->ingress.acl);
1112         vport->ingress.acl = NULL;
1113         vport->ingress.drop_grp = NULL;
1114         vport->ingress.allow_spoofchk_only_grp = NULL;
1115         vport->ingress.allow_untagged_only_grp = NULL;
1116         vport->ingress.allow_untagged_spoofchk_grp = NULL;
1117 }
1118
1119 static int esw_vport_ingress_config(struct mlx5_eswitch *esw,
1120                                     struct mlx5_vport *vport)
1121 {
1122         struct mlx5_flow_act flow_act = {0};
1123         struct mlx5_flow_spec *spec;
1124         int err = 0;
1125         u8 *smac_v;
1126
1127         esw_vport_cleanup_ingress_rules(esw, vport);
1128
1129         if (!vport->info.vlan && !vport->info.qos && !vport->info.spoofchk) {
1130                 esw_vport_disable_ingress_acl(esw, vport);
1131                 return 0;
1132         }
1133
1134         err = esw_vport_enable_ingress_acl(esw, vport);
1135         if (err) {
1136                 mlx5_core_warn(esw->dev,
1137                                "failed to enable ingress acl (%d) on vport[%d]\n",
1138                                err, vport->vport);
1139                 return err;
1140         }
1141
1142         esw_debug(esw->dev,
1143                   "vport[%d] configure ingress rules, vlan(%d) qos(%d)\n",
1144                   vport->vport, vport->info.vlan, vport->info.qos);
1145
1146         spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
1147         if (!spec) {
1148                 err = -ENOMEM;
1149                 goto out;
1150         }
1151
1152         if (vport->info.vlan || vport->info.qos)
1153                 MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.cvlan_tag);
1154
1155         if (vport->info.spoofchk) {
1156                 MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.smac_47_16);
1157                 MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.smac_15_0);
1158                 smac_v = MLX5_ADDR_OF(fte_match_param,
1159                                       spec->match_value,
1160                                       outer_headers.smac_47_16);
1161                 ether_addr_copy(smac_v, vport->info.mac);
1162         }
1163
1164         spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
1165         flow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW;
1166         vport->ingress.allow_rule =
1167                 mlx5_add_flow_rules(vport->ingress.acl, spec,
1168                                     &flow_act, NULL, 0);
1169         if (IS_ERR(vport->ingress.allow_rule)) {
1170                 err = PTR_ERR(vport->ingress.allow_rule);
1171                 esw_warn(esw->dev,
1172                          "vport[%d] configure ingress allow rule, err(%d)\n",
1173                          vport->vport, err);
1174                 vport->ingress.allow_rule = NULL;
1175                 goto out;
1176         }
1177
1178         memset(spec, 0, sizeof(*spec));
1179         flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP;
1180         vport->ingress.drop_rule =
1181                 mlx5_add_flow_rules(vport->ingress.acl, spec,
1182                                     &flow_act, NULL, 0);
1183         if (IS_ERR(vport->ingress.drop_rule)) {
1184                 err = PTR_ERR(vport->ingress.drop_rule);
1185                 esw_warn(esw->dev,
1186                          "vport[%d] configure ingress drop rule, err(%d)\n",
1187                          vport->vport, err);
1188                 vport->ingress.drop_rule = NULL;
1189                 goto out;
1190         }
1191
1192 out:
1193         if (err)
1194                 esw_vport_cleanup_ingress_rules(esw, vport);
1195         kvfree(spec);
1196         return err;
1197 }
1198
1199 static int esw_vport_egress_config(struct mlx5_eswitch *esw,
1200                                    struct mlx5_vport *vport)
1201 {
1202         struct mlx5_flow_act flow_act = {0};
1203         struct mlx5_flow_spec *spec;
1204         int err = 0;
1205
1206         esw_vport_cleanup_egress_rules(esw, vport);
1207
1208         if (!vport->info.vlan && !vport->info.qos) {
1209                 esw_vport_disable_egress_acl(esw, vport);
1210                 return 0;
1211         }
1212
1213         err = esw_vport_enable_egress_acl(esw, vport);
1214         if (err) {
1215                 mlx5_core_warn(esw->dev,
1216                                "failed to enable egress acl (%d) on vport[%d]\n",
1217                                err, vport->vport);
1218                 return err;
1219         }
1220
1221         esw_debug(esw->dev,
1222                   "vport[%d] configure egress 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         /* Allowed vlan rule */
1232         MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.cvlan_tag);
1233         MLX5_SET_TO_ONES(fte_match_param, spec->match_value, outer_headers.cvlan_tag);
1234         MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.first_vid);
1235         MLX5_SET(fte_match_param, spec->match_value, outer_headers.first_vid, vport->info.vlan);
1236
1237         spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
1238         flow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW;
1239         vport->egress.allowed_vlan =
1240                 mlx5_add_flow_rules(vport->egress.acl, spec,
1241                                     &flow_act, NULL, 0);
1242         if (IS_ERR(vport->egress.allowed_vlan)) {
1243                 err = PTR_ERR(vport->egress.allowed_vlan);
1244                 esw_warn(esw->dev,
1245                          "vport[%d] configure egress allowed vlan rule failed, err(%d)\n",
1246                          vport->vport, err);
1247                 vport->egress.allowed_vlan = NULL;
1248                 goto out;
1249         }
1250
1251         /* Drop others rule (star rule) */
1252         memset(spec, 0, sizeof(*spec));
1253         flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP;
1254         vport->egress.drop_rule =
1255                 mlx5_add_flow_rules(vport->egress.acl, spec,
1256                                     &flow_act, NULL, 0);
1257         if (IS_ERR(vport->egress.drop_rule)) {
1258                 err = PTR_ERR(vport->egress.drop_rule);
1259                 esw_warn(esw->dev,
1260                          "vport[%d] configure egress drop rule failed, err(%d)\n",
1261                          vport->vport, err);
1262                 vport->egress.drop_rule = NULL;
1263         }
1264 out:
1265         kvfree(spec);
1266         return err;
1267 }
1268
1269 /* Vport QoS management */
1270 static int esw_create_tsar(struct mlx5_eswitch *esw)
1271 {
1272         u32 tsar_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {0};
1273         struct mlx5_core_dev *dev = esw->dev;
1274         int err;
1275
1276         if (!MLX5_CAP_GEN(dev, qos) || !MLX5_CAP_QOS(dev, esw_scheduling))
1277                 return 0;
1278
1279         if (esw->qos.enabled)
1280                 return -EEXIST;
1281
1282         err = mlx5_create_scheduling_element_cmd(dev,
1283                                                  SCHEDULING_HIERARCHY_E_SWITCH,
1284                                                  &tsar_ctx,
1285                                                  &esw->qos.root_tsar_id);
1286         if (err) {
1287                 esw_warn(esw->dev, "E-Switch create TSAR failed (%d)\n", err);
1288                 return err;
1289         }
1290
1291         esw->qos.enabled = true;
1292         return 0;
1293 }
1294
1295 static void esw_destroy_tsar(struct mlx5_eswitch *esw)
1296 {
1297         int err;
1298
1299         if (!esw->qos.enabled)
1300                 return;
1301
1302         err = mlx5_destroy_scheduling_element_cmd(esw->dev,
1303                                                   SCHEDULING_HIERARCHY_E_SWITCH,
1304                                                   esw->qos.root_tsar_id);
1305         if (err)
1306                 esw_warn(esw->dev, "E-Switch destroy TSAR failed (%d)\n", err);
1307
1308         esw->qos.enabled = false;
1309 }
1310
1311 static int esw_vport_enable_qos(struct mlx5_eswitch *esw, int vport_num,
1312                                 u32 initial_max_rate, u32 initial_bw_share)
1313 {
1314         u32 sched_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {0};
1315         struct mlx5_vport *vport = &esw->vports[vport_num];
1316         struct mlx5_core_dev *dev = esw->dev;
1317         void *vport_elem;
1318         int err = 0;
1319
1320         if (!esw->qos.enabled || !MLX5_CAP_GEN(dev, qos) ||
1321             !MLX5_CAP_QOS(dev, esw_scheduling))
1322                 return 0;
1323
1324         if (vport->qos.enabled)
1325                 return -EEXIST;
1326
1327         MLX5_SET(scheduling_context, &sched_ctx, element_type,
1328                  SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT);
1329         vport_elem = MLX5_ADDR_OF(scheduling_context, &sched_ctx,
1330                                   element_attributes);
1331         MLX5_SET(vport_element, vport_elem, vport_number, vport_num);
1332         MLX5_SET(scheduling_context, &sched_ctx, parent_element_id,
1333                  esw->qos.root_tsar_id);
1334         MLX5_SET(scheduling_context, &sched_ctx, max_average_bw,
1335                  initial_max_rate);
1336         MLX5_SET(scheduling_context, &sched_ctx, bw_share, initial_bw_share);
1337
1338         err = mlx5_create_scheduling_element_cmd(dev,
1339                                                  SCHEDULING_HIERARCHY_E_SWITCH,
1340                                                  &sched_ctx,
1341                                                  &vport->qos.esw_tsar_ix);
1342         if (err) {
1343                 esw_warn(esw->dev, "E-Switch create TSAR vport element failed (vport=%d,err=%d)\n",
1344                          vport_num, err);
1345                 return err;
1346         }
1347
1348         vport->qos.enabled = true;
1349         return 0;
1350 }
1351
1352 static void esw_vport_disable_qos(struct mlx5_eswitch *esw, int vport_num)
1353 {
1354         struct mlx5_vport *vport = &esw->vports[vport_num];
1355         int err = 0;
1356
1357         if (!vport->qos.enabled)
1358                 return;
1359
1360         err = mlx5_destroy_scheduling_element_cmd(esw->dev,
1361                                                   SCHEDULING_HIERARCHY_E_SWITCH,
1362                                                   vport->qos.esw_tsar_ix);
1363         if (err)
1364                 esw_warn(esw->dev, "E-Switch destroy TSAR vport element failed (vport=%d,err=%d)\n",
1365                          vport_num, err);
1366
1367         vport->qos.enabled = false;
1368 }
1369
1370 static int esw_vport_qos_config(struct mlx5_eswitch *esw, int vport_num,
1371                                 u32 max_rate, u32 bw_share)
1372 {
1373         u32 sched_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {0};
1374         struct mlx5_vport *vport = &esw->vports[vport_num];
1375         struct mlx5_core_dev *dev = esw->dev;
1376         void *vport_elem;
1377         u32 bitmask = 0;
1378         int err = 0;
1379
1380         if (!MLX5_CAP_GEN(dev, qos) || !MLX5_CAP_QOS(dev, esw_scheduling))
1381                 return -EOPNOTSUPP;
1382
1383         if (!vport->qos.enabled)
1384                 return -EIO;
1385
1386         MLX5_SET(scheduling_context, &sched_ctx, element_type,
1387                  SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT);
1388         vport_elem = MLX5_ADDR_OF(scheduling_context, &sched_ctx,
1389                                   element_attributes);
1390         MLX5_SET(vport_element, vport_elem, vport_number, vport_num);
1391         MLX5_SET(scheduling_context, &sched_ctx, parent_element_id,
1392                  esw->qos.root_tsar_id);
1393         MLX5_SET(scheduling_context, &sched_ctx, max_average_bw,
1394                  max_rate);
1395         MLX5_SET(scheduling_context, &sched_ctx, bw_share, bw_share);
1396         bitmask |= MODIFY_SCHEDULING_ELEMENT_IN_MODIFY_BITMASK_MAX_AVERAGE_BW;
1397         bitmask |= MODIFY_SCHEDULING_ELEMENT_IN_MODIFY_BITMASK_BW_SHARE;
1398
1399         err = mlx5_modify_scheduling_element_cmd(dev,
1400                                                  SCHEDULING_HIERARCHY_E_SWITCH,
1401                                                  &sched_ctx,
1402                                                  vport->qos.esw_tsar_ix,
1403                                                  bitmask);
1404         if (err) {
1405                 esw_warn(esw->dev, "E-Switch modify TSAR vport element failed (vport=%d,err=%d)\n",
1406                          vport_num, err);
1407                 return err;
1408         }
1409
1410         return 0;
1411 }
1412
1413 static void node_guid_gen_from_mac(u64 *node_guid, u8 mac[ETH_ALEN])
1414 {
1415         ((u8 *)node_guid)[7] = mac[0];
1416         ((u8 *)node_guid)[6] = mac[1];
1417         ((u8 *)node_guid)[5] = mac[2];
1418         ((u8 *)node_guid)[4] = 0xff;
1419         ((u8 *)node_guid)[3] = 0xfe;
1420         ((u8 *)node_guid)[2] = mac[3];
1421         ((u8 *)node_guid)[1] = mac[4];
1422         ((u8 *)node_guid)[0] = mac[5];
1423 }
1424
1425 static void esw_apply_vport_conf(struct mlx5_eswitch *esw,
1426                                  struct mlx5_vport *vport)
1427 {
1428         int vport_num = vport->vport;
1429
1430         if (!vport_num)
1431                 return;
1432
1433         mlx5_modify_vport_admin_state(esw->dev,
1434                                       MLX5_QUERY_VPORT_STATE_IN_OP_MOD_ESW_VPORT,
1435                                       vport_num,
1436                                       vport->info.link_state);
1437         mlx5_modify_nic_vport_mac_address(esw->dev, vport_num, vport->info.mac);
1438         mlx5_modify_nic_vport_node_guid(esw->dev, vport_num, vport->info.node_guid);
1439         modify_esw_vport_cvlan(esw->dev, vport_num, vport->info.vlan, vport->info.qos,
1440                                (vport->info.vlan || vport->info.qos));
1441
1442         /* Only legacy mode needs ACLs */
1443         if (esw->mode == SRIOV_LEGACY) {
1444                 esw_vport_ingress_config(esw, vport);
1445                 esw_vport_egress_config(esw, vport);
1446         }
1447 }
1448
1449 static void esw_enable_vport(struct mlx5_eswitch *esw, int vport_num,
1450                              int enable_events)
1451 {
1452         struct mlx5_vport *vport = &esw->vports[vport_num];
1453
1454         mutex_lock(&esw->state_lock);
1455         WARN_ON(vport->enabled);
1456
1457         esw_debug(esw->dev, "Enabling VPORT(%d)\n", vport_num);
1458
1459         /* Restore old vport configuration */
1460         esw_apply_vport_conf(esw, vport);
1461
1462         /* Attach vport to the eswitch rate limiter */
1463         if (esw_vport_enable_qos(esw, vport_num, vport->info.max_rate,
1464                                  vport->qos.bw_share))
1465                 esw_warn(esw->dev, "Failed to attach vport %d to eswitch rate limiter", vport_num);
1466
1467         /* Sync with current vport context */
1468         vport->enabled_events = enable_events;
1469         vport->enabled = true;
1470
1471         /* only PF is trusted by default */
1472         if (!vport_num)
1473                 vport->info.trusted = true;
1474
1475         esw_vport_change_handle_locked(vport);
1476
1477         esw->enabled_vports++;
1478         esw_debug(esw->dev, "Enabled VPORT(%d)\n", vport_num);
1479         mutex_unlock(&esw->state_lock);
1480 }
1481
1482 static void esw_disable_vport(struct mlx5_eswitch *esw, int vport_num)
1483 {
1484         struct mlx5_vport *vport = &esw->vports[vport_num];
1485
1486         if (!vport->enabled)
1487                 return;
1488
1489         esw_debug(esw->dev, "Disabling vport(%d)\n", vport_num);
1490         /* Mark this vport as disabled to discard new events */
1491         vport->enabled = false;
1492
1493         synchronize_irq(pci_irq_vector(esw->dev->pdev, MLX5_EQ_VEC_ASYNC));
1494         /* Wait for current already scheduled events to complete */
1495         flush_workqueue(esw->work_queue);
1496         /* Disable events from this vport */
1497         arm_vport_context_events_cmd(esw->dev, vport->vport, 0);
1498         mutex_lock(&esw->state_lock);
1499         /* We don't assume VFs will cleanup after themselves.
1500          * Calling vport change handler while vport is disabled will cleanup
1501          * the vport resources.
1502          */
1503         esw_vport_change_handle_locked(vport);
1504         vport->enabled_events = 0;
1505         esw_vport_disable_qos(esw, vport_num);
1506         if (vport_num && esw->mode == SRIOV_LEGACY) {
1507                 mlx5_modify_vport_admin_state(esw->dev,
1508                                               MLX5_QUERY_VPORT_STATE_IN_OP_MOD_ESW_VPORT,
1509                                               vport_num,
1510                                               MLX5_ESW_VPORT_ADMIN_STATE_DOWN);
1511                 esw_vport_disable_egress_acl(esw, vport);
1512                 esw_vport_disable_ingress_acl(esw, vport);
1513         }
1514         esw->enabled_vports--;
1515         mutex_unlock(&esw->state_lock);
1516 }
1517
1518 /* Public E-Switch API */
1519 #define ESW_ALLOWED(esw) ((esw) && MLX5_ESWITCH_MANAGER((esw)->dev))
1520
1521
1522 int mlx5_eswitch_enable_sriov(struct mlx5_eswitch *esw, int nvfs, int mode)
1523 {
1524         int err;
1525         int i, enabled_events;
1526
1527         if (!ESW_ALLOWED(esw) ||
1528             !MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, ft_support)) {
1529                 esw_warn(esw->dev, "E-Switch FDB is not supported, aborting ...\n");
1530                 return -EOPNOTSUPP;
1531         }
1532
1533         if (!MLX5_CAP_ESW_INGRESS_ACL(esw->dev, ft_support))
1534                 esw_warn(esw->dev, "E-Switch ingress ACL is not supported by FW\n");
1535
1536         if (!MLX5_CAP_ESW_EGRESS_ACL(esw->dev, ft_support))
1537                 esw_warn(esw->dev, "E-Switch engress ACL is not supported by FW\n");
1538
1539         esw_info(esw->dev, "E-Switch enable SRIOV: nvfs(%d) mode (%d)\n", nvfs, mode);
1540         esw->mode = mode;
1541
1542         if (mode == SRIOV_LEGACY)
1543                 err = esw_create_legacy_fdb_table(esw, nvfs + 1);
1544         else
1545                 err = esw_offloads_init(esw, nvfs + 1);
1546         if (err)
1547                 goto abort;
1548
1549         err = esw_create_tsar(esw);
1550         if (err)
1551                 esw_warn(esw->dev, "Failed to create eswitch TSAR");
1552
1553         /* Don't enable vport events when in SRIOV_OFFLOADS mode, since:
1554          * 1. L2 table (MPFS) is programmed by PF/VF representors netdevs set_rx_mode
1555          * 2. FDB/Eswitch is programmed by user space tools
1556          */
1557         enabled_events = (mode == SRIOV_LEGACY) ? SRIOV_VPORT_EVENTS : 0;
1558         for (i = 0; i <= nvfs; i++)
1559                 esw_enable_vport(esw, i, enabled_events);
1560
1561         esw_info(esw->dev, "SRIOV enabled: active vports(%d)\n",
1562                  esw->enabled_vports);
1563         return 0;
1564
1565 abort:
1566         esw->mode = SRIOV_NONE;
1567         return err;
1568 }
1569
1570 void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw)
1571 {
1572         struct esw_mc_addr *mc_promisc;
1573         int nvports;
1574         int i;
1575
1576         if (!ESW_ALLOWED(esw) || esw->mode == SRIOV_NONE)
1577                 return;
1578
1579         esw_info(esw->dev, "disable SRIOV: active vports(%d) mode(%d)\n",
1580                  esw->enabled_vports, esw->mode);
1581
1582         mc_promisc = &esw->mc_promisc;
1583         nvports = esw->enabled_vports;
1584
1585         for (i = 0; i < esw->total_vports; i++)
1586                 esw_disable_vport(esw, i);
1587
1588         if (mc_promisc && mc_promisc->uplink_rule)
1589                 mlx5_del_flow_rules(mc_promisc->uplink_rule);
1590
1591         esw_destroy_tsar(esw);
1592
1593         if (esw->mode == SRIOV_LEGACY)
1594                 esw_destroy_legacy_fdb_table(esw);
1595         else if (esw->mode == SRIOV_OFFLOADS)
1596                 esw_offloads_cleanup(esw, nvports);
1597
1598         esw->mode = SRIOV_NONE;
1599 }
1600
1601 int mlx5_eswitch_init(struct mlx5_core_dev *dev)
1602 {
1603         int total_vports = MLX5_TOTAL_VPORTS(dev);
1604         struct mlx5_eswitch *esw;
1605         int vport_num;
1606         int err;
1607
1608         if (!MLX5_VPORT_MANAGER(dev))
1609                 return 0;
1610
1611         esw_info(dev,
1612                  "Total vports %d, per vport: max uc(%d) max mc(%d)\n",
1613                  total_vports,
1614                  MLX5_MAX_UC_PER_VPORT(dev),
1615                  MLX5_MAX_MC_PER_VPORT(dev));
1616
1617         esw = kzalloc(sizeof(*esw), GFP_KERNEL);
1618         if (!esw)
1619                 return -ENOMEM;
1620
1621         esw->dev = dev;
1622
1623         esw->work_queue = create_singlethread_workqueue("mlx5_esw_wq");
1624         if (!esw->work_queue) {
1625                 err = -ENOMEM;
1626                 goto abort;
1627         }
1628
1629         esw->vports = kcalloc(total_vports, sizeof(struct mlx5_vport),
1630                               GFP_KERNEL);
1631         if (!esw->vports) {
1632                 err = -ENOMEM;
1633                 goto abort;
1634         }
1635
1636         esw->offloads.vport_reps =
1637                 kzalloc(total_vports * sizeof(struct mlx5_eswitch_rep),
1638                         GFP_KERNEL);
1639         if (!esw->offloads.vport_reps) {
1640                 err = -ENOMEM;
1641                 goto abort;
1642         }
1643
1644         hash_init(esw->offloads.encap_tbl);
1645         hash_init(esw->offloads.mod_hdr_tbl);
1646         mutex_init(&esw->state_lock);
1647
1648         for (vport_num = 0; vport_num < total_vports; vport_num++) {
1649                 struct mlx5_vport *vport = &esw->vports[vport_num];
1650
1651                 vport->vport = vport_num;
1652                 vport->info.link_state = MLX5_ESW_VPORT_ADMIN_STATE_AUTO;
1653                 vport->dev = dev;
1654                 INIT_WORK(&vport->vport_change_handler,
1655                           esw_vport_change_handler);
1656         }
1657
1658         esw->total_vports = total_vports;
1659         esw->enabled_vports = 0;
1660         esw->mode = SRIOV_NONE;
1661         esw->offloads.inline_mode = MLX5_INLINE_MODE_NONE;
1662         if (MLX5_CAP_ESW_FLOWTABLE_FDB(dev, encap) &&
1663             MLX5_CAP_ESW_FLOWTABLE_FDB(dev, decap))
1664                 esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_BASIC;
1665         else
1666                 esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_NONE;
1667
1668         dev->priv.eswitch = esw;
1669         return 0;
1670 abort:
1671         if (esw->work_queue)
1672                 destroy_workqueue(esw->work_queue);
1673         kfree(esw->vports);
1674         kfree(esw->offloads.vport_reps);
1675         kfree(esw);
1676         return err;
1677 }
1678
1679 void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw)
1680 {
1681         if (!esw || !MLX5_VPORT_MANAGER(esw->dev))
1682                 return;
1683
1684         esw_info(esw->dev, "cleanup\n");
1685
1686         esw->dev->priv.eswitch = NULL;
1687         destroy_workqueue(esw->work_queue);
1688         kfree(esw->offloads.vport_reps);
1689         kfree(esw->vports);
1690         kfree(esw);
1691 }
1692
1693 void mlx5_eswitch_vport_event(struct mlx5_eswitch *esw, struct mlx5_eqe *eqe)
1694 {
1695         struct mlx5_eqe_vport_change *vc_eqe = &eqe->data.vport_change;
1696         u16 vport_num = be16_to_cpu(vc_eqe->vport_num);
1697         struct mlx5_vport *vport;
1698
1699         if (!esw) {
1700                 pr_warn("MLX5 E-Switch: vport %d got an event while eswitch is not initialized\n",
1701                         vport_num);
1702                 return;
1703         }
1704
1705         vport = &esw->vports[vport_num];
1706         if (vport->enabled)
1707                 queue_work(esw->work_queue, &vport->vport_change_handler);
1708 }
1709
1710 /* Vport Administration */
1711 #define LEGAL_VPORT(esw, vport) (vport >= 0 && vport < esw->total_vports)
1712
1713 int mlx5_eswitch_set_vport_mac(struct mlx5_eswitch *esw,
1714                                int vport, u8 mac[ETH_ALEN])
1715 {
1716         struct mlx5_vport *evport;
1717         u64 node_guid;
1718         int err = 0;
1719
1720         if (!esw || !MLX5_CAP_GEN(esw->dev, vport_group_manager))
1721                 return -EPERM;
1722         if (!LEGAL_VPORT(esw, vport) || is_multicast_ether_addr(mac))
1723                 return -EINVAL;
1724
1725         mutex_lock(&esw->state_lock);
1726         evport = &esw->vports[vport];
1727
1728         if (evport->info.spoofchk && !is_valid_ether_addr(mac))
1729                 mlx5_core_warn(esw->dev,
1730                                "Set invalid MAC while spoofchk is on, vport(%d)\n",
1731                                vport);
1732
1733         err = mlx5_modify_nic_vport_mac_address(esw->dev, vport, mac);
1734         if (err) {
1735                 mlx5_core_warn(esw->dev,
1736                                "Failed to mlx5_modify_nic_vport_mac vport(%d) err=(%d)\n",
1737                                vport, err);
1738                 goto unlock;
1739         }
1740
1741         node_guid_gen_from_mac(&node_guid, mac);
1742         err = mlx5_modify_nic_vport_node_guid(esw->dev, vport, node_guid);
1743         if (err)
1744                 mlx5_core_warn(esw->dev,
1745                                "Failed to set vport %d node guid, err = %d. RDMA_CM will not function properly for this VF.\n",
1746                                vport, err);
1747
1748         ether_addr_copy(evport->info.mac, mac);
1749         evport->info.node_guid = node_guid;
1750         if (evport->enabled && esw->mode == SRIOV_LEGACY)
1751                 err = esw_vport_ingress_config(esw, evport);
1752
1753 unlock:
1754         mutex_unlock(&esw->state_lock);
1755         return err;
1756 }
1757
1758 int mlx5_eswitch_set_vport_state(struct mlx5_eswitch *esw,
1759                                  int vport, int link_state)
1760 {
1761         struct mlx5_vport *evport;
1762         int err = 0;
1763
1764         if (!ESW_ALLOWED(esw))
1765                 return -EPERM;
1766         if (!LEGAL_VPORT(esw, vport))
1767                 return -EINVAL;
1768
1769         mutex_lock(&esw->state_lock);
1770         evport = &esw->vports[vport];
1771
1772         err = mlx5_modify_vport_admin_state(esw->dev,
1773                                             MLX5_QUERY_VPORT_STATE_IN_OP_MOD_ESW_VPORT,
1774                                             vport, link_state);
1775         if (err) {
1776                 mlx5_core_warn(esw->dev,
1777                                "Failed to set vport %d link state, err = %d",
1778                                vport, err);
1779                 goto unlock;
1780         }
1781
1782         evport->info.link_state = link_state;
1783
1784 unlock:
1785         mutex_unlock(&esw->state_lock);
1786         return err;
1787 }
1788
1789 int mlx5_eswitch_get_vport_config(struct mlx5_eswitch *esw,
1790                                   int vport, struct ifla_vf_info *ivi)
1791 {
1792         struct mlx5_vport *evport;
1793
1794         if (!esw || !MLX5_CAP_GEN(esw->dev, vport_group_manager))
1795                 return -EPERM;
1796         if (!LEGAL_VPORT(esw, vport))
1797                 return -EINVAL;
1798
1799         evport = &esw->vports[vport];
1800
1801         memset(ivi, 0, sizeof(*ivi));
1802         ivi->vf = vport - 1;
1803
1804         mutex_lock(&esw->state_lock);
1805         ether_addr_copy(ivi->mac, evport->info.mac);
1806         ivi->linkstate = evport->info.link_state;
1807         ivi->vlan = evport->info.vlan;
1808         ivi->qos = evport->info.qos;
1809         ivi->spoofchk = evport->info.spoofchk;
1810         ivi->trusted = evport->info.trusted;
1811         ivi->min_tx_rate = evport->info.min_rate;
1812         ivi->max_tx_rate = evport->info.max_rate;
1813         mutex_unlock(&esw->state_lock);
1814
1815         return 0;
1816 }
1817
1818 int __mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw,
1819                                   int vport, u16 vlan, u8 qos, u8 set_flags)
1820 {
1821         struct mlx5_vport *evport;
1822         int err = 0;
1823
1824         if (!ESW_ALLOWED(esw))
1825                 return -EPERM;
1826         if (!LEGAL_VPORT(esw, vport) || (vlan > 4095) || (qos > 7))
1827                 return -EINVAL;
1828
1829         mutex_lock(&esw->state_lock);
1830         evport = &esw->vports[vport];
1831
1832         err = modify_esw_vport_cvlan(esw->dev, vport, vlan, qos, set_flags);
1833         if (err)
1834                 goto unlock;
1835
1836         evport->info.vlan = vlan;
1837         evport->info.qos = qos;
1838         if (evport->enabled && esw->mode == SRIOV_LEGACY) {
1839                 err = esw_vport_ingress_config(esw, evport);
1840                 if (err)
1841                         goto unlock;
1842                 err = esw_vport_egress_config(esw, evport);
1843         }
1844
1845 unlock:
1846         mutex_unlock(&esw->state_lock);
1847         return err;
1848 }
1849
1850 int mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw,
1851                                 int vport, u16 vlan, u8 qos)
1852 {
1853         u8 set_flags = 0;
1854
1855         if (vlan || qos)
1856                 set_flags = SET_VLAN_STRIP | SET_VLAN_INSERT;
1857
1858         return __mlx5_eswitch_set_vport_vlan(esw, vport, vlan, qos, set_flags);
1859 }
1860
1861 int mlx5_eswitch_set_vport_spoofchk(struct mlx5_eswitch *esw,
1862                                     int vport, bool spoofchk)
1863 {
1864         struct mlx5_vport *evport;
1865         bool pschk;
1866         int err = 0;
1867
1868         if (!ESW_ALLOWED(esw))
1869                 return -EPERM;
1870         if (!LEGAL_VPORT(esw, vport))
1871                 return -EINVAL;
1872
1873         mutex_lock(&esw->state_lock);
1874         evport = &esw->vports[vport];
1875         pschk = evport->info.spoofchk;
1876         evport->info.spoofchk = spoofchk;
1877         if (pschk && !is_valid_ether_addr(evport->info.mac))
1878                 mlx5_core_warn(esw->dev,
1879                                "Spoofchk in set while MAC is invalid, vport(%d)\n",
1880                                evport->vport);
1881         if (evport->enabled && esw->mode == SRIOV_LEGACY)
1882                 err = esw_vport_ingress_config(esw, evport);
1883         if (err)
1884                 evport->info.spoofchk = pschk;
1885         mutex_unlock(&esw->state_lock);
1886
1887         return err;
1888 }
1889
1890 int mlx5_eswitch_set_vport_trust(struct mlx5_eswitch *esw,
1891                                  int vport, bool setting)
1892 {
1893         struct mlx5_vport *evport;
1894
1895         if (!ESW_ALLOWED(esw))
1896                 return -EPERM;
1897         if (!LEGAL_VPORT(esw, vport))
1898                 return -EINVAL;
1899
1900         mutex_lock(&esw->state_lock);
1901         evport = &esw->vports[vport];
1902         evport->info.trusted = setting;
1903         if (evport->enabled)
1904                 esw_vport_change_handle_locked(evport);
1905         mutex_unlock(&esw->state_lock);
1906
1907         return 0;
1908 }
1909
1910 static u32 calculate_vports_min_rate_divider(struct mlx5_eswitch *esw)
1911 {
1912         u32 fw_max_bw_share = MLX5_CAP_QOS(esw->dev, max_tsar_bw_share);
1913         struct mlx5_vport *evport;
1914         u32 max_guarantee = 0;
1915         int i;
1916
1917         for (i = 0; i < esw->total_vports; i++) {
1918                 evport = &esw->vports[i];
1919                 if (!evport->enabled || evport->info.min_rate < max_guarantee)
1920                         continue;
1921                 max_guarantee = evport->info.min_rate;
1922         }
1923
1924         if (max_guarantee)
1925                 return max_t(u32, max_guarantee / fw_max_bw_share, 1);
1926         return 0;
1927 }
1928
1929 static int normalize_vports_min_rate(struct mlx5_eswitch *esw)
1930 {
1931         u32 fw_max_bw_share = MLX5_CAP_QOS(esw->dev, max_tsar_bw_share);
1932         u32 divider = calculate_vports_min_rate_divider(esw);
1933         struct mlx5_vport *evport;
1934         u32 vport_max_rate;
1935         u32 vport_min_rate;
1936         u32 bw_share;
1937         int err;
1938         int i;
1939
1940         for (i = 0; i < esw->total_vports; i++) {
1941                 evport = &esw->vports[i];
1942                 if (!evport->enabled)
1943                         continue;
1944                 vport_min_rate = evport->info.min_rate;
1945                 vport_max_rate = evport->info.max_rate;
1946                 bw_share = 0;
1947
1948                 if (divider)
1949                         bw_share = MLX5_RATE_TO_BW_SHARE(vport_min_rate,
1950                                                          divider,
1951                                                          fw_max_bw_share);
1952
1953                 if (bw_share == evport->qos.bw_share)
1954                         continue;
1955
1956                 err = esw_vport_qos_config(esw, i, vport_max_rate,
1957                                            bw_share);
1958                 if (!err)
1959                         evport->qos.bw_share = bw_share;
1960                 else
1961                         return err;
1962         }
1963
1964         return 0;
1965 }
1966
1967 int mlx5_eswitch_set_vport_rate(struct mlx5_eswitch *esw, int vport,
1968                                 u32 max_rate, u32 min_rate)
1969 {
1970         struct mlx5_vport *evport;
1971         u32 fw_max_bw_share;
1972         u32 previous_min_rate;
1973         bool min_rate_supported;
1974         bool max_rate_supported;
1975         int err = 0;
1976
1977         if (!ESW_ALLOWED(esw))
1978                 return -EPERM;
1979         if (!LEGAL_VPORT(esw, vport))
1980                 return -EINVAL;
1981
1982         fw_max_bw_share = MLX5_CAP_QOS(esw->dev, max_tsar_bw_share);
1983         min_rate_supported = MLX5_CAP_QOS(esw->dev, esw_bw_share) &&
1984                                 fw_max_bw_share >= MLX5_MIN_BW_SHARE;
1985         max_rate_supported = MLX5_CAP_QOS(esw->dev, esw_rate_limit);
1986
1987         if ((min_rate && !min_rate_supported) || (max_rate && !max_rate_supported))
1988                 return -EOPNOTSUPP;
1989
1990         mutex_lock(&esw->state_lock);
1991         evport = &esw->vports[vport];
1992
1993         if (min_rate == evport->info.min_rate)
1994                 goto set_max_rate;
1995
1996         previous_min_rate = evport->info.min_rate;
1997         evport->info.min_rate = min_rate;
1998         err = normalize_vports_min_rate(esw);
1999         if (err) {
2000                 evport->info.min_rate = previous_min_rate;
2001                 goto unlock;
2002         }
2003
2004 set_max_rate:
2005         if (max_rate == evport->info.max_rate)
2006                 goto unlock;
2007
2008         err = esw_vport_qos_config(esw, vport, max_rate, evport->qos.bw_share);
2009         if (!err)
2010                 evport->info.max_rate = max_rate;
2011
2012 unlock:
2013         mutex_unlock(&esw->state_lock);
2014         return err;
2015 }
2016
2017 int mlx5_eswitch_get_vport_stats(struct mlx5_eswitch *esw,
2018                                  int vport,
2019                                  struct ifla_vf_stats *vf_stats)
2020 {
2021         int outlen = MLX5_ST_SZ_BYTES(query_vport_counter_out);
2022         u32 in[MLX5_ST_SZ_DW(query_vport_counter_in)] = {0};
2023         int err = 0;
2024         u32 *out;
2025
2026         if (!ESW_ALLOWED(esw))
2027                 return -EPERM;
2028         if (!LEGAL_VPORT(esw, vport))
2029                 return -EINVAL;
2030
2031         out = kvzalloc(outlen, GFP_KERNEL);
2032         if (!out)
2033                 return -ENOMEM;
2034
2035         MLX5_SET(query_vport_counter_in, in, opcode,
2036                  MLX5_CMD_OP_QUERY_VPORT_COUNTER);
2037         MLX5_SET(query_vport_counter_in, in, op_mod, 0);
2038         MLX5_SET(query_vport_counter_in, in, vport_number, vport);
2039         if (vport)
2040                 MLX5_SET(query_vport_counter_in, in, other_vport, 1);
2041
2042         memset(out, 0, outlen);
2043         err = mlx5_cmd_exec(esw->dev, in, sizeof(in), out, outlen);
2044         if (err)
2045                 goto free_out;
2046
2047         #define MLX5_GET_CTR(p, x) \
2048                 MLX5_GET64(query_vport_counter_out, p, x)
2049
2050         memset(vf_stats, 0, sizeof(*vf_stats));
2051         vf_stats->rx_packets =
2052                 MLX5_GET_CTR(out, received_eth_unicast.packets) +
2053                 MLX5_GET_CTR(out, received_ib_unicast.packets) +
2054                 MLX5_GET_CTR(out, received_eth_multicast.packets) +
2055                 MLX5_GET_CTR(out, received_ib_multicast.packets) +
2056                 MLX5_GET_CTR(out, received_eth_broadcast.packets);
2057
2058         vf_stats->rx_bytes =
2059                 MLX5_GET_CTR(out, received_eth_unicast.octets) +
2060                 MLX5_GET_CTR(out, received_ib_unicast.octets) +
2061                 MLX5_GET_CTR(out, received_eth_multicast.octets) +
2062                 MLX5_GET_CTR(out, received_ib_multicast.octets) +
2063                 MLX5_GET_CTR(out, received_eth_broadcast.octets);
2064
2065         vf_stats->tx_packets =
2066                 MLX5_GET_CTR(out, transmitted_eth_unicast.packets) +
2067                 MLX5_GET_CTR(out, transmitted_ib_unicast.packets) +
2068                 MLX5_GET_CTR(out, transmitted_eth_multicast.packets) +
2069                 MLX5_GET_CTR(out, transmitted_ib_multicast.packets) +
2070                 MLX5_GET_CTR(out, transmitted_eth_broadcast.packets);
2071
2072         vf_stats->tx_bytes =
2073                 MLX5_GET_CTR(out, transmitted_eth_unicast.octets) +
2074                 MLX5_GET_CTR(out, transmitted_ib_unicast.octets) +
2075                 MLX5_GET_CTR(out, transmitted_eth_multicast.octets) +
2076                 MLX5_GET_CTR(out, transmitted_ib_multicast.octets) +
2077                 MLX5_GET_CTR(out, transmitted_eth_broadcast.octets);
2078
2079         vf_stats->multicast =
2080                 MLX5_GET_CTR(out, received_eth_multicast.packets) +
2081                 MLX5_GET_CTR(out, received_ib_multicast.packets);
2082
2083         vf_stats->broadcast =
2084                 MLX5_GET_CTR(out, received_eth_broadcast.packets);
2085
2086 free_out:
2087         kvfree(out);
2088         return err;
2089 }