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