Merge tag 'for-linus-20160527' of git://git.infradead.org/linux-mtd
[cascardo/linux.git] / drivers / net / ethernet / mellanox / mlx5 / core / en_fs.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/list.h>
34 #include <linux/ip.h>
35 #include <linux/ipv6.h>
36 #include <linux/tcp.h>
37 #include <linux/mlx5/fs.h>
38 #include "en.h"
39
40 static int mlx5e_add_l2_flow_rule(struct mlx5e_priv *priv,
41                                   struct mlx5e_l2_rule *ai, int type);
42 static void mlx5e_del_l2_flow_rule(struct mlx5e_priv *priv,
43                                    struct mlx5e_l2_rule *ai);
44
45 enum {
46         MLX5E_FULLMATCH = 0,
47         MLX5E_ALLMULTI  = 1,
48         MLX5E_PROMISC   = 2,
49 };
50
51 enum {
52         MLX5E_UC        = 0,
53         MLX5E_MC_IPV4   = 1,
54         MLX5E_MC_IPV6   = 2,
55         MLX5E_MC_OTHER  = 3,
56 };
57
58 enum {
59         MLX5E_ACTION_NONE = 0,
60         MLX5E_ACTION_ADD  = 1,
61         MLX5E_ACTION_DEL  = 2,
62 };
63
64 struct mlx5e_l2_hash_node {
65         struct hlist_node          hlist;
66         u8                         action;
67         struct mlx5e_l2_rule ai;
68 };
69
70 static inline int mlx5e_hash_l2(u8 *addr)
71 {
72         return addr[5];
73 }
74
75 static void mlx5e_add_l2_to_hash(struct hlist_head *hash, u8 *addr)
76 {
77         struct mlx5e_l2_hash_node *hn;
78         int ix = mlx5e_hash_l2(addr);
79         int found = 0;
80
81         hlist_for_each_entry(hn, &hash[ix], hlist)
82                 if (ether_addr_equal_64bits(hn->ai.addr, addr)) {
83                         found = 1;
84                         break;
85                 }
86
87         if (found) {
88                 hn->action = MLX5E_ACTION_NONE;
89                 return;
90         }
91
92         hn = kzalloc(sizeof(*hn), GFP_ATOMIC);
93         if (!hn)
94                 return;
95
96         ether_addr_copy(hn->ai.addr, addr);
97         hn->action = MLX5E_ACTION_ADD;
98
99         hlist_add_head(&hn->hlist, &hash[ix]);
100 }
101
102 static void mlx5e_del_l2_from_hash(struct mlx5e_l2_hash_node *hn)
103 {
104         hlist_del(&hn->hlist);
105         kfree(hn);
106 }
107
108 static int mlx5e_vport_context_update_vlans(struct mlx5e_priv *priv)
109 {
110         struct net_device *ndev = priv->netdev;
111         int max_list_size;
112         int list_size;
113         u16 *vlans;
114         int vlan;
115         int err;
116         int i;
117
118         list_size = 0;
119         for_each_set_bit(vlan, priv->fs.vlan.active_vlans, VLAN_N_VID)
120                 list_size++;
121
122         max_list_size = 1 << MLX5_CAP_GEN(priv->mdev, log_max_vlan_list);
123
124         if (list_size > max_list_size) {
125                 netdev_warn(ndev,
126                             "netdev vlans list size (%d) > (%d) max vport list size, some vlans will be dropped\n",
127                             list_size, max_list_size);
128                 list_size = max_list_size;
129         }
130
131         vlans = kcalloc(list_size, sizeof(*vlans), GFP_KERNEL);
132         if (!vlans)
133                 return -ENOMEM;
134
135         i = 0;
136         for_each_set_bit(vlan, priv->fs.vlan.active_vlans, VLAN_N_VID) {
137                 if (i >= list_size)
138                         break;
139                 vlans[i++] = vlan;
140         }
141
142         err = mlx5_modify_nic_vport_vlans(priv->mdev, vlans, list_size);
143         if (err)
144                 netdev_err(ndev, "Failed to modify vport vlans list err(%d)\n",
145                            err);
146
147         kfree(vlans);
148         return err;
149 }
150
151 enum mlx5e_vlan_rule_type {
152         MLX5E_VLAN_RULE_TYPE_UNTAGGED,
153         MLX5E_VLAN_RULE_TYPE_ANY_VID,
154         MLX5E_VLAN_RULE_TYPE_MATCH_VID,
155 };
156
157 static int __mlx5e_add_vlan_rule(struct mlx5e_priv *priv,
158                                  enum mlx5e_vlan_rule_type rule_type,
159                                  u16 vid, u32 *mc, u32 *mv)
160 {
161         struct mlx5_flow_table *ft = priv->fs.vlan.ft.t;
162         struct mlx5_flow_destination dest;
163         u8 match_criteria_enable = 0;
164         struct mlx5_flow_rule **rule_p;
165         int err = 0;
166
167         dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
168         dest.ft = priv->fs.l2.ft.t;
169
170         match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
171         MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.vlan_tag);
172
173         switch (rule_type) {
174         case MLX5E_VLAN_RULE_TYPE_UNTAGGED:
175                 rule_p = &priv->fs.vlan.untagged_rule;
176                 break;
177         case MLX5E_VLAN_RULE_TYPE_ANY_VID:
178                 rule_p = &priv->fs.vlan.any_vlan_rule;
179                 MLX5_SET(fte_match_param, mv, outer_headers.vlan_tag, 1);
180                 break;
181         default: /* MLX5E_VLAN_RULE_TYPE_MATCH_VID */
182                 rule_p = &priv->fs.vlan.active_vlans_rule[vid];
183                 MLX5_SET(fte_match_param, mv, outer_headers.vlan_tag, 1);
184                 MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.first_vid);
185                 MLX5_SET(fte_match_param, mv, outer_headers.first_vid, vid);
186                 break;
187         }
188
189         *rule_p = mlx5_add_flow_rule(ft, match_criteria_enable, mc, mv,
190                                      MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
191                                      MLX5_FS_DEFAULT_FLOW_TAG,
192                                      &dest);
193
194         if (IS_ERR(*rule_p)) {
195                 err = PTR_ERR(*rule_p);
196                 *rule_p = NULL;
197                 netdev_err(priv->netdev, "%s: add rule failed\n", __func__);
198         }
199
200         return err;
201 }
202
203 static int mlx5e_add_vlan_rule(struct mlx5e_priv *priv,
204                                enum mlx5e_vlan_rule_type rule_type, u16 vid)
205 {
206         u32 *match_criteria;
207         u32 *match_value;
208         int err = 0;
209
210         match_value     = mlx5_vzalloc(MLX5_ST_SZ_BYTES(fte_match_param));
211         match_criteria  = mlx5_vzalloc(MLX5_ST_SZ_BYTES(fte_match_param));
212         if (!match_value || !match_criteria) {
213                 netdev_err(priv->netdev, "%s: alloc failed\n", __func__);
214                 err = -ENOMEM;
215                 goto add_vlan_rule_out;
216         }
217
218         if (rule_type == MLX5E_VLAN_RULE_TYPE_MATCH_VID)
219                 mlx5e_vport_context_update_vlans(priv);
220
221         err = __mlx5e_add_vlan_rule(priv, rule_type, vid, match_criteria,
222                                     match_value);
223
224 add_vlan_rule_out:
225         kvfree(match_criteria);
226         kvfree(match_value);
227
228         return err;
229 }
230
231 static void mlx5e_del_vlan_rule(struct mlx5e_priv *priv,
232                                 enum mlx5e_vlan_rule_type rule_type, u16 vid)
233 {
234         switch (rule_type) {
235         case MLX5E_VLAN_RULE_TYPE_UNTAGGED:
236                 if (priv->fs.vlan.untagged_rule) {
237                         mlx5_del_flow_rule(priv->fs.vlan.untagged_rule);
238                         priv->fs.vlan.untagged_rule = NULL;
239                 }
240                 break;
241         case MLX5E_VLAN_RULE_TYPE_ANY_VID:
242                 if (priv->fs.vlan.any_vlan_rule) {
243                         mlx5_del_flow_rule(priv->fs.vlan.any_vlan_rule);
244                         priv->fs.vlan.any_vlan_rule = NULL;
245                 }
246                 break;
247         case MLX5E_VLAN_RULE_TYPE_MATCH_VID:
248                 mlx5e_vport_context_update_vlans(priv);
249                 if (priv->fs.vlan.active_vlans_rule[vid]) {
250                         mlx5_del_flow_rule(priv->fs.vlan.active_vlans_rule[vid]);
251                         priv->fs.vlan.active_vlans_rule[vid] = NULL;
252                 }
253                 mlx5e_vport_context_update_vlans(priv);
254                 break;
255         }
256 }
257
258 void mlx5e_enable_vlan_filter(struct mlx5e_priv *priv)
259 {
260         if (!priv->fs.vlan.filter_disabled)
261                 return;
262
263         priv->fs.vlan.filter_disabled = false;
264         if (priv->netdev->flags & IFF_PROMISC)
265                 return;
266         mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_VID, 0);
267 }
268
269 void mlx5e_disable_vlan_filter(struct mlx5e_priv *priv)
270 {
271         if (priv->fs.vlan.filter_disabled)
272                 return;
273
274         priv->fs.vlan.filter_disabled = true;
275         if (priv->netdev->flags & IFF_PROMISC)
276                 return;
277         mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_VID, 0);
278 }
279
280 int mlx5e_vlan_rx_add_vid(struct net_device *dev, __always_unused __be16 proto,
281                           u16 vid)
282 {
283         struct mlx5e_priv *priv = netdev_priv(dev);
284
285         set_bit(vid, priv->fs.vlan.active_vlans);
286
287         return mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_MATCH_VID, vid);
288 }
289
290 int mlx5e_vlan_rx_kill_vid(struct net_device *dev, __always_unused __be16 proto,
291                            u16 vid)
292 {
293         struct mlx5e_priv *priv = netdev_priv(dev);
294
295         clear_bit(vid, priv->fs.vlan.active_vlans);
296
297         mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_MATCH_VID, vid);
298
299         return 0;
300 }
301
302 #define mlx5e_for_each_hash_node(hn, tmp, hash, i) \
303         for (i = 0; i < MLX5E_L2_ADDR_HASH_SIZE; i++) \
304                 hlist_for_each_entry_safe(hn, tmp, &hash[i], hlist)
305
306 static void mlx5e_execute_l2_action(struct mlx5e_priv *priv,
307                                     struct mlx5e_l2_hash_node *hn)
308 {
309         switch (hn->action) {
310         case MLX5E_ACTION_ADD:
311                 mlx5e_add_l2_flow_rule(priv, &hn->ai, MLX5E_FULLMATCH);
312                 hn->action = MLX5E_ACTION_NONE;
313                 break;
314
315         case MLX5E_ACTION_DEL:
316                 mlx5e_del_l2_flow_rule(priv, &hn->ai);
317                 mlx5e_del_l2_from_hash(hn);
318                 break;
319         }
320 }
321
322 static void mlx5e_sync_netdev_addr(struct mlx5e_priv *priv)
323 {
324         struct net_device *netdev = priv->netdev;
325         struct netdev_hw_addr *ha;
326
327         netif_addr_lock_bh(netdev);
328
329         mlx5e_add_l2_to_hash(priv->fs.l2.netdev_uc,
330                              priv->netdev->dev_addr);
331
332         netdev_for_each_uc_addr(ha, netdev)
333                 mlx5e_add_l2_to_hash(priv->fs.l2.netdev_uc, ha->addr);
334
335         netdev_for_each_mc_addr(ha, netdev)
336                 mlx5e_add_l2_to_hash(priv->fs.l2.netdev_mc, ha->addr);
337
338         netif_addr_unlock_bh(netdev);
339 }
340
341 static void mlx5e_fill_addr_array(struct mlx5e_priv *priv, int list_type,
342                                   u8 addr_array[][ETH_ALEN], int size)
343 {
344         bool is_uc = (list_type == MLX5_NVPRT_LIST_TYPE_UC);
345         struct net_device *ndev = priv->netdev;
346         struct mlx5e_l2_hash_node *hn;
347         struct hlist_head *addr_list;
348         struct hlist_node *tmp;
349         int i = 0;
350         int hi;
351
352         addr_list = is_uc ? priv->fs.l2.netdev_uc : priv->fs.l2.netdev_mc;
353
354         if (is_uc) /* Make sure our own address is pushed first */
355                 ether_addr_copy(addr_array[i++], ndev->dev_addr);
356         else if (priv->fs.l2.broadcast_enabled)
357                 ether_addr_copy(addr_array[i++], ndev->broadcast);
358
359         mlx5e_for_each_hash_node(hn, tmp, addr_list, hi) {
360                 if (ether_addr_equal(ndev->dev_addr, hn->ai.addr))
361                         continue;
362                 if (i >= size)
363                         break;
364                 ether_addr_copy(addr_array[i++], hn->ai.addr);
365         }
366 }
367
368 static void mlx5e_vport_context_update_addr_list(struct mlx5e_priv *priv,
369                                                  int list_type)
370 {
371         bool is_uc = (list_type == MLX5_NVPRT_LIST_TYPE_UC);
372         struct mlx5e_l2_hash_node *hn;
373         u8 (*addr_array)[ETH_ALEN] = NULL;
374         struct hlist_head *addr_list;
375         struct hlist_node *tmp;
376         int max_size;
377         int size;
378         int err;
379         int hi;
380
381         size = is_uc ? 0 : (priv->fs.l2.broadcast_enabled ? 1 : 0);
382         max_size = is_uc ?
383                 1 << MLX5_CAP_GEN(priv->mdev, log_max_current_uc_list) :
384                 1 << MLX5_CAP_GEN(priv->mdev, log_max_current_mc_list);
385
386         addr_list = is_uc ? priv->fs.l2.netdev_uc : priv->fs.l2.netdev_mc;
387         mlx5e_for_each_hash_node(hn, tmp, addr_list, hi)
388                 size++;
389
390         if (size > max_size) {
391                 netdev_warn(priv->netdev,
392                             "netdev %s list size (%d) > (%d) max vport list size, some addresses will be dropped\n",
393                             is_uc ? "UC" : "MC", size, max_size);
394                 size = max_size;
395         }
396
397         if (size) {
398                 addr_array = kcalloc(size, ETH_ALEN, GFP_KERNEL);
399                 if (!addr_array) {
400                         err = -ENOMEM;
401                         goto out;
402                 }
403                 mlx5e_fill_addr_array(priv, list_type, addr_array, size);
404         }
405
406         err = mlx5_modify_nic_vport_mac_list(priv->mdev, list_type, addr_array, size);
407 out:
408         if (err)
409                 netdev_err(priv->netdev,
410                            "Failed to modify vport %s list err(%d)\n",
411                            is_uc ? "UC" : "MC", err);
412         kfree(addr_array);
413 }
414
415 static void mlx5e_vport_context_update(struct mlx5e_priv *priv)
416 {
417         struct mlx5e_l2_table *ea = &priv->fs.l2;
418
419         mlx5e_vport_context_update_addr_list(priv, MLX5_NVPRT_LIST_TYPE_UC);
420         mlx5e_vport_context_update_addr_list(priv, MLX5_NVPRT_LIST_TYPE_MC);
421         mlx5_modify_nic_vport_promisc(priv->mdev, 0,
422                                       ea->allmulti_enabled,
423                                       ea->promisc_enabled);
424 }
425
426 static void mlx5e_apply_netdev_addr(struct mlx5e_priv *priv)
427 {
428         struct mlx5e_l2_hash_node *hn;
429         struct hlist_node *tmp;
430         int i;
431
432         mlx5e_for_each_hash_node(hn, tmp, priv->fs.l2.netdev_uc, i)
433                 mlx5e_execute_l2_action(priv, hn);
434
435         mlx5e_for_each_hash_node(hn, tmp, priv->fs.l2.netdev_mc, i)
436                 mlx5e_execute_l2_action(priv, hn);
437 }
438
439 static void mlx5e_handle_netdev_addr(struct mlx5e_priv *priv)
440 {
441         struct mlx5e_l2_hash_node *hn;
442         struct hlist_node *tmp;
443         int i;
444
445         mlx5e_for_each_hash_node(hn, tmp, priv->fs.l2.netdev_uc, i)
446                 hn->action = MLX5E_ACTION_DEL;
447         mlx5e_for_each_hash_node(hn, tmp, priv->fs.l2.netdev_mc, i)
448                 hn->action = MLX5E_ACTION_DEL;
449
450         if (!test_bit(MLX5E_STATE_DESTROYING, &priv->state))
451                 mlx5e_sync_netdev_addr(priv);
452
453         mlx5e_apply_netdev_addr(priv);
454 }
455
456 void mlx5e_set_rx_mode_work(struct work_struct *work)
457 {
458         struct mlx5e_priv *priv = container_of(work, struct mlx5e_priv,
459                                                set_rx_mode_work);
460
461         struct mlx5e_l2_table *ea = &priv->fs.l2;
462         struct net_device *ndev = priv->netdev;
463
464         bool rx_mode_enable   = !test_bit(MLX5E_STATE_DESTROYING, &priv->state);
465         bool promisc_enabled   = rx_mode_enable && (ndev->flags & IFF_PROMISC);
466         bool allmulti_enabled  = rx_mode_enable && (ndev->flags & IFF_ALLMULTI);
467         bool broadcast_enabled = rx_mode_enable;
468
469         bool enable_promisc    = !ea->promisc_enabled   &&  promisc_enabled;
470         bool disable_promisc   =  ea->promisc_enabled   && !promisc_enabled;
471         bool enable_allmulti   = !ea->allmulti_enabled  &&  allmulti_enabled;
472         bool disable_allmulti  =  ea->allmulti_enabled  && !allmulti_enabled;
473         bool enable_broadcast  = !ea->broadcast_enabled &&  broadcast_enabled;
474         bool disable_broadcast =  ea->broadcast_enabled && !broadcast_enabled;
475
476         if (enable_promisc) {
477                 mlx5e_add_l2_flow_rule(priv, &ea->promisc, MLX5E_PROMISC);
478                 if (!priv->fs.vlan.filter_disabled)
479                         mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_VID,
480                                             0);
481         }
482         if (enable_allmulti)
483                 mlx5e_add_l2_flow_rule(priv, &ea->allmulti, MLX5E_ALLMULTI);
484         if (enable_broadcast)
485                 mlx5e_add_l2_flow_rule(priv, &ea->broadcast, MLX5E_FULLMATCH);
486
487         mlx5e_handle_netdev_addr(priv);
488
489         if (disable_broadcast)
490                 mlx5e_del_l2_flow_rule(priv, &ea->broadcast);
491         if (disable_allmulti)
492                 mlx5e_del_l2_flow_rule(priv, &ea->allmulti);
493         if (disable_promisc) {
494                 if (!priv->fs.vlan.filter_disabled)
495                         mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_VID,
496                                             0);
497                 mlx5e_del_l2_flow_rule(priv, &ea->promisc);
498         }
499
500         ea->promisc_enabled   = promisc_enabled;
501         ea->allmulti_enabled  = allmulti_enabled;
502         ea->broadcast_enabled = broadcast_enabled;
503
504         mlx5e_vport_context_update(priv);
505 }
506
507 static void mlx5e_destroy_groups(struct mlx5e_flow_table *ft)
508 {
509         int i;
510
511         for (i = ft->num_groups - 1; i >= 0; i--) {
512                 if (!IS_ERR_OR_NULL(ft->g[i]))
513                         mlx5_destroy_flow_group(ft->g[i]);
514                 ft->g[i] = NULL;
515         }
516         ft->num_groups = 0;
517 }
518
519 void mlx5e_init_l2_addr(struct mlx5e_priv *priv)
520 {
521         ether_addr_copy(priv->fs.l2.broadcast.addr, priv->netdev->broadcast);
522 }
523
524 void mlx5e_destroy_flow_table(struct mlx5e_flow_table *ft)
525 {
526         mlx5e_destroy_groups(ft);
527         kfree(ft->g);
528         mlx5_destroy_flow_table(ft->t);
529         ft->t = NULL;
530 }
531
532 static void mlx5e_cleanup_ttc_rules(struct mlx5e_ttc_table *ttc)
533 {
534         int i;
535
536         for (i = 0; i < MLX5E_NUM_TT; i++) {
537                 if (!IS_ERR_OR_NULL(ttc->rules[i])) {
538                         mlx5_del_flow_rule(ttc->rules[i]);
539                         ttc->rules[i] = NULL;
540                 }
541         }
542 }
543
544 static struct {
545         u16 etype;
546         u8 proto;
547 } ttc_rules[] = {
548         [MLX5E_TT_IPV4_TCP] = {
549                 .etype = ETH_P_IP,
550                 .proto = IPPROTO_TCP,
551         },
552         [MLX5E_TT_IPV6_TCP] = {
553                 .etype = ETH_P_IPV6,
554                 .proto = IPPROTO_TCP,
555         },
556         [MLX5E_TT_IPV4_UDP] = {
557                 .etype = ETH_P_IP,
558                 .proto = IPPROTO_UDP,
559         },
560         [MLX5E_TT_IPV6_UDP] = {
561                 .etype = ETH_P_IPV6,
562                 .proto = IPPROTO_UDP,
563         },
564         [MLX5E_TT_IPV4_IPSEC_AH] = {
565                 .etype = ETH_P_IP,
566                 .proto = IPPROTO_AH,
567         },
568         [MLX5E_TT_IPV6_IPSEC_AH] = {
569                 .etype = ETH_P_IPV6,
570                 .proto = IPPROTO_AH,
571         },
572         [MLX5E_TT_IPV4_IPSEC_ESP] = {
573                 .etype = ETH_P_IP,
574                 .proto = IPPROTO_ESP,
575         },
576         [MLX5E_TT_IPV6_IPSEC_ESP] = {
577                 .etype = ETH_P_IPV6,
578                 .proto = IPPROTO_ESP,
579         },
580         [MLX5E_TT_IPV4] = {
581                 .etype = ETH_P_IP,
582                 .proto = 0,
583         },
584         [MLX5E_TT_IPV6] = {
585                 .etype = ETH_P_IPV6,
586                 .proto = 0,
587         },
588         [MLX5E_TT_ANY] = {
589                 .etype = 0,
590                 .proto = 0,
591         },
592 };
593
594 static struct mlx5_flow_rule *mlx5e_generate_ttc_rule(struct mlx5e_priv *priv,
595                                                       struct mlx5_flow_table *ft,
596                                                       struct mlx5_flow_destination *dest,
597                                                       u16 etype,
598                                                       u8 proto)
599 {
600         struct mlx5_flow_rule *rule;
601         u8 match_criteria_enable = 0;
602         u32 *match_criteria;
603         u32 *match_value;
604         int err = 0;
605
606         match_value     = mlx5_vzalloc(MLX5_ST_SZ_BYTES(fte_match_param));
607         match_criteria  = mlx5_vzalloc(MLX5_ST_SZ_BYTES(fte_match_param));
608         if (!match_value || !match_criteria) {
609                 netdev_err(priv->netdev, "%s: alloc failed\n", __func__);
610                 err = -ENOMEM;
611                 goto out;
612         }
613
614         if (proto) {
615                 match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
616                 MLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.ip_protocol);
617                 MLX5_SET(fte_match_param, match_value, outer_headers.ip_protocol, proto);
618         }
619         if (etype) {
620                 match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
621                 MLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.ethertype);
622                 MLX5_SET(fte_match_param, match_value, outer_headers.ethertype, etype);
623         }
624
625         rule = mlx5_add_flow_rule(ft, match_criteria_enable,
626                                   match_criteria, match_value,
627                                   MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
628                                   MLX5_FS_DEFAULT_FLOW_TAG,
629                                   dest);
630         if (IS_ERR(rule)) {
631                 err = PTR_ERR(rule);
632                 netdev_err(priv->netdev, "%s: add rule failed\n", __func__);
633         }
634 out:
635         kvfree(match_criteria);
636         kvfree(match_value);
637         return err ? ERR_PTR(err) : rule;
638 }
639
640 static int mlx5e_generate_ttc_table_rules(struct mlx5e_priv *priv)
641 {
642         struct mlx5_flow_destination dest;
643         struct mlx5e_ttc_table *ttc;
644         struct mlx5_flow_rule **rules;
645         struct mlx5_flow_table *ft;
646         int tt;
647         int err;
648
649         ttc = &priv->fs.ttc;
650         ft = ttc->ft.t;
651         rules = ttc->rules;
652
653         dest.type = MLX5_FLOW_DESTINATION_TYPE_TIR;
654         for (tt = 0; tt < MLX5E_NUM_TT; tt++) {
655                 if (tt == MLX5E_TT_ANY)
656                         dest.tir_num = priv->direct_tir[0].tirn;
657                 else
658                         dest.tir_num = priv->indir_tirn[tt];
659                 rules[tt] = mlx5e_generate_ttc_rule(priv, ft, &dest,
660                                                     ttc_rules[tt].etype,
661                                                     ttc_rules[tt].proto);
662                 if (IS_ERR(rules[tt]))
663                         goto del_rules;
664         }
665
666         return 0;
667
668 del_rules:
669         err = PTR_ERR(rules[tt]);
670         rules[tt] = NULL;
671         mlx5e_cleanup_ttc_rules(ttc);
672         return err;
673 }
674
675 #define MLX5E_TTC_NUM_GROUPS    3
676 #define MLX5E_TTC_GROUP1_SIZE   BIT(3)
677 #define MLX5E_TTC_GROUP2_SIZE   BIT(1)
678 #define MLX5E_TTC_GROUP3_SIZE   BIT(0)
679 #define MLX5E_TTC_TABLE_SIZE    (MLX5E_TTC_GROUP1_SIZE +\
680                                  MLX5E_TTC_GROUP2_SIZE +\
681                                  MLX5E_TTC_GROUP3_SIZE)
682 static int mlx5e_create_ttc_table_groups(struct mlx5e_ttc_table *ttc)
683 {
684         int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
685         struct mlx5e_flow_table *ft = &ttc->ft;
686         int ix = 0;
687         u32 *in;
688         int err;
689         u8 *mc;
690
691         ft->g = kcalloc(MLX5E_TTC_NUM_GROUPS,
692                         sizeof(*ft->g), GFP_KERNEL);
693         if (!ft->g)
694                 return -ENOMEM;
695         in = mlx5_vzalloc(inlen);
696         if (!in) {
697                 kfree(ft->g);
698                 return -ENOMEM;
699         }
700
701         /* L4 Group */
702         mc = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria);
703         MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.ip_protocol);
704         MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.ethertype);
705         MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
706         MLX5_SET_CFG(in, start_flow_index, ix);
707         ix += MLX5E_TTC_GROUP1_SIZE;
708         MLX5_SET_CFG(in, end_flow_index, ix - 1);
709         ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
710         if (IS_ERR(ft->g[ft->num_groups]))
711                 goto err;
712         ft->num_groups++;
713
714         /* L3 Group */
715         MLX5_SET(fte_match_param, mc, outer_headers.ip_protocol, 0);
716         MLX5_SET_CFG(in, start_flow_index, ix);
717         ix += MLX5E_TTC_GROUP2_SIZE;
718         MLX5_SET_CFG(in, end_flow_index, ix - 1);
719         ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
720         if (IS_ERR(ft->g[ft->num_groups]))
721                 goto err;
722         ft->num_groups++;
723
724         /* Any Group */
725         memset(in, 0, inlen);
726         MLX5_SET_CFG(in, start_flow_index, ix);
727         ix += MLX5E_TTC_GROUP3_SIZE;
728         MLX5_SET_CFG(in, end_flow_index, ix - 1);
729         ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
730         if (IS_ERR(ft->g[ft->num_groups]))
731                 goto err;
732         ft->num_groups++;
733
734         kvfree(in);
735         return 0;
736
737 err:
738         err = PTR_ERR(ft->g[ft->num_groups]);
739         ft->g[ft->num_groups] = NULL;
740         kvfree(in);
741
742         return err;
743 }
744
745 static void mlx5e_destroy_ttc_table(struct mlx5e_priv *priv)
746 {
747         struct mlx5e_ttc_table *ttc = &priv->fs.ttc;
748
749         mlx5e_cleanup_ttc_rules(ttc);
750         mlx5e_destroy_flow_table(&ttc->ft);
751 }
752
753 static int mlx5e_create_ttc_table(struct mlx5e_priv *priv)
754 {
755         struct mlx5e_ttc_table *ttc = &priv->fs.ttc;
756         struct mlx5e_flow_table *ft = &ttc->ft;
757         int err;
758
759         ft->t = mlx5_create_flow_table(priv->fs.ns, MLX5E_NIC_PRIO,
760                                        MLX5E_TTC_TABLE_SIZE, MLX5E_TTC_FT_LEVEL);
761         if (IS_ERR(ft->t)) {
762                 err = PTR_ERR(ft->t);
763                 ft->t = NULL;
764                 return err;
765         }
766
767         err = mlx5e_create_ttc_table_groups(ttc);
768         if (err)
769                 goto err;
770
771         err = mlx5e_generate_ttc_table_rules(priv);
772         if (err)
773                 goto err;
774
775         return 0;
776 err:
777         mlx5e_destroy_flow_table(ft);
778         return err;
779 }
780
781 static void mlx5e_del_l2_flow_rule(struct mlx5e_priv *priv,
782                                    struct mlx5e_l2_rule *ai)
783 {
784         if (!IS_ERR_OR_NULL(ai->rule)) {
785                 mlx5_del_flow_rule(ai->rule);
786                 ai->rule = NULL;
787         }
788 }
789
790 static int mlx5e_add_l2_flow_rule(struct mlx5e_priv *priv,
791                                   struct mlx5e_l2_rule *ai, int type)
792 {
793         struct mlx5_flow_table *ft = priv->fs.l2.ft.t;
794         struct mlx5_flow_destination dest;
795         u8 match_criteria_enable = 0;
796         u32 *match_criteria;
797         u32 *match_value;
798         int err = 0;
799         u8 *mc_dmac;
800         u8 *mv_dmac;
801
802         match_value    = mlx5_vzalloc(MLX5_ST_SZ_BYTES(fte_match_param));
803         match_criteria = mlx5_vzalloc(MLX5_ST_SZ_BYTES(fte_match_param));
804         if (!match_value || !match_criteria) {
805                 netdev_err(priv->netdev, "%s: alloc failed\n", __func__);
806                 err = -ENOMEM;
807                 goto add_l2_rule_out;
808         }
809
810         mc_dmac = MLX5_ADDR_OF(fte_match_param, match_criteria,
811                                outer_headers.dmac_47_16);
812         mv_dmac = MLX5_ADDR_OF(fte_match_param, match_value,
813                                outer_headers.dmac_47_16);
814
815         dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
816         dest.ft = priv->fs.ttc.ft.t;
817
818         switch (type) {
819         case MLX5E_FULLMATCH:
820                 match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
821                 eth_broadcast_addr(mc_dmac);
822                 ether_addr_copy(mv_dmac, ai->addr);
823                 break;
824
825         case MLX5E_ALLMULTI:
826                 match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
827                 mc_dmac[0] = 0x01;
828                 mv_dmac[0] = 0x01;
829                 break;
830
831         case MLX5E_PROMISC:
832                 break;
833         }
834
835         ai->rule = mlx5_add_flow_rule(ft, match_criteria_enable, match_criteria,
836                                       match_value,
837                                       MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
838                                       MLX5_FS_DEFAULT_FLOW_TAG, &dest);
839         if (IS_ERR(ai->rule)) {
840                 netdev_err(priv->netdev, "%s: add l2 rule(mac:%pM) failed\n",
841                            __func__, mv_dmac);
842                 err = PTR_ERR(ai->rule);
843                 ai->rule = NULL;
844         }
845
846 add_l2_rule_out:
847         kvfree(match_criteria);
848         kvfree(match_value);
849
850         return err;
851 }
852
853 #define MLX5E_NUM_L2_GROUPS        3
854 #define MLX5E_L2_GROUP1_SIZE       BIT(0)
855 #define MLX5E_L2_GROUP2_SIZE       BIT(15)
856 #define MLX5E_L2_GROUP3_SIZE       BIT(0)
857 #define MLX5E_L2_TABLE_SIZE        (MLX5E_L2_GROUP1_SIZE +\
858                                     MLX5E_L2_GROUP2_SIZE +\
859                                     MLX5E_L2_GROUP3_SIZE)
860 static int mlx5e_create_l2_table_groups(struct mlx5e_l2_table *l2_table)
861 {
862         int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
863         struct mlx5e_flow_table *ft = &l2_table->ft;
864         int ix = 0;
865         u8 *mc_dmac;
866         u32 *in;
867         int err;
868         u8 *mc;
869
870         ft->g = kcalloc(MLX5E_NUM_L2_GROUPS, sizeof(*ft->g), GFP_KERNEL);
871         if (!ft->g)
872                 return -ENOMEM;
873         in = mlx5_vzalloc(inlen);
874         if (!in) {
875                 kfree(ft->g);
876                 return -ENOMEM;
877         }
878
879         mc = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria);
880         mc_dmac = MLX5_ADDR_OF(fte_match_param, mc,
881                                outer_headers.dmac_47_16);
882         /* Flow Group for promiscuous */
883         MLX5_SET_CFG(in, start_flow_index, ix);
884         ix += MLX5E_L2_GROUP1_SIZE;
885         MLX5_SET_CFG(in, end_flow_index, ix - 1);
886         ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
887         if (IS_ERR(ft->g[ft->num_groups]))
888                 goto err_destroy_groups;
889         ft->num_groups++;
890
891         /* Flow Group for full match */
892         eth_broadcast_addr(mc_dmac);
893         MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
894         MLX5_SET_CFG(in, start_flow_index, ix);
895         ix += MLX5E_L2_GROUP2_SIZE;
896         MLX5_SET_CFG(in, end_flow_index, ix - 1);
897         ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
898         if (IS_ERR(ft->g[ft->num_groups]))
899                 goto err_destroy_groups;
900         ft->num_groups++;
901
902         /* Flow Group for allmulti */
903         eth_zero_addr(mc_dmac);
904         mc_dmac[0] = 0x01;
905         MLX5_SET_CFG(in, start_flow_index, ix);
906         ix += MLX5E_L2_GROUP3_SIZE;
907         MLX5_SET_CFG(in, end_flow_index, ix - 1);
908         ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
909         if (IS_ERR(ft->g[ft->num_groups]))
910                 goto err_destroy_groups;
911         ft->num_groups++;
912
913         kvfree(in);
914         return 0;
915
916 err_destroy_groups:
917         err = PTR_ERR(ft->g[ft->num_groups]);
918         ft->g[ft->num_groups] = NULL;
919         mlx5e_destroy_groups(ft);
920         kvfree(in);
921
922         return err;
923 }
924
925 static void mlx5e_destroy_l2_table(struct mlx5e_priv *priv)
926 {
927         mlx5e_destroy_flow_table(&priv->fs.l2.ft);
928 }
929
930 static int mlx5e_create_l2_table(struct mlx5e_priv *priv)
931 {
932         struct mlx5e_l2_table *l2_table = &priv->fs.l2;
933         struct mlx5e_flow_table *ft = &l2_table->ft;
934         int err;
935
936         ft->num_groups = 0;
937         ft->t = mlx5_create_flow_table(priv->fs.ns, MLX5E_NIC_PRIO,
938                                        MLX5E_L2_TABLE_SIZE, MLX5E_L2_FT_LEVEL);
939
940         if (IS_ERR(ft->t)) {
941                 err = PTR_ERR(ft->t);
942                 ft->t = NULL;
943                 return err;
944         }
945
946         err = mlx5e_create_l2_table_groups(l2_table);
947         if (err)
948                 goto err_destroy_flow_table;
949
950         return 0;
951
952 err_destroy_flow_table:
953         mlx5_destroy_flow_table(ft->t);
954         ft->t = NULL;
955
956         return err;
957 }
958
959 #define MLX5E_NUM_VLAN_GROUPS   2
960 #define MLX5E_VLAN_GROUP0_SIZE  BIT(12)
961 #define MLX5E_VLAN_GROUP1_SIZE  BIT(1)
962 #define MLX5E_VLAN_TABLE_SIZE   (MLX5E_VLAN_GROUP0_SIZE +\
963                                  MLX5E_VLAN_GROUP1_SIZE)
964
965 static int __mlx5e_create_vlan_table_groups(struct mlx5e_flow_table *ft, u32 *in,
966                                             int inlen)
967 {
968         int err;
969         int ix = 0;
970         u8 *mc = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria);
971
972         memset(in, 0, inlen);
973         MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
974         MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.vlan_tag);
975         MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.first_vid);
976         MLX5_SET_CFG(in, start_flow_index, ix);
977         ix += MLX5E_VLAN_GROUP0_SIZE;
978         MLX5_SET_CFG(in, end_flow_index, ix - 1);
979         ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
980         if (IS_ERR(ft->g[ft->num_groups]))
981                 goto err_destroy_groups;
982         ft->num_groups++;
983
984         memset(in, 0, inlen);
985         MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
986         MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.vlan_tag);
987         MLX5_SET_CFG(in, start_flow_index, ix);
988         ix += MLX5E_VLAN_GROUP1_SIZE;
989         MLX5_SET_CFG(in, end_flow_index, ix - 1);
990         ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
991         if (IS_ERR(ft->g[ft->num_groups]))
992                 goto err_destroy_groups;
993         ft->num_groups++;
994
995         return 0;
996
997 err_destroy_groups:
998         err = PTR_ERR(ft->g[ft->num_groups]);
999         ft->g[ft->num_groups] = NULL;
1000         mlx5e_destroy_groups(ft);
1001
1002         return err;
1003 }
1004
1005 static int mlx5e_create_vlan_table_groups(struct mlx5e_flow_table *ft)
1006 {
1007         u32 *in;
1008         int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
1009         int err;
1010
1011         in = mlx5_vzalloc(inlen);
1012         if (!in)
1013                 return -ENOMEM;
1014
1015         err = __mlx5e_create_vlan_table_groups(ft, in, inlen);
1016
1017         kvfree(in);
1018         return err;
1019 }
1020
1021 static int mlx5e_create_vlan_table(struct mlx5e_priv *priv)
1022 {
1023         struct mlx5e_flow_table *ft = &priv->fs.vlan.ft;
1024         int err;
1025
1026         ft->num_groups = 0;
1027         ft->t = mlx5_create_flow_table(priv->fs.ns, MLX5E_NIC_PRIO,
1028                                        MLX5E_VLAN_TABLE_SIZE, MLX5E_VLAN_FT_LEVEL);
1029
1030         if (IS_ERR(ft->t)) {
1031                 err = PTR_ERR(ft->t);
1032                 ft->t = NULL;
1033                 return err;
1034         }
1035         ft->g = kcalloc(MLX5E_NUM_VLAN_GROUPS, sizeof(*ft->g), GFP_KERNEL);
1036         if (!ft->g) {
1037                 err = -ENOMEM;
1038                 goto err_destroy_vlan_table;
1039         }
1040
1041         err = mlx5e_create_vlan_table_groups(ft);
1042         if (err)
1043                 goto err_free_g;
1044
1045         err = mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_UNTAGGED, 0);
1046         if (err)
1047                 goto err_destroy_vlan_flow_groups;
1048
1049         return 0;
1050
1051 err_destroy_vlan_flow_groups:
1052         mlx5e_destroy_groups(ft);
1053 err_free_g:
1054         kfree(ft->g);
1055 err_destroy_vlan_table:
1056         mlx5_destroy_flow_table(ft->t);
1057         ft->t = NULL;
1058
1059         return err;
1060 }
1061
1062 static void mlx5e_destroy_vlan_table(struct mlx5e_priv *priv)
1063 {
1064         mlx5e_destroy_flow_table(&priv->fs.vlan.ft);
1065 }
1066
1067 int mlx5e_create_flow_steering(struct mlx5e_priv *priv)
1068 {
1069         int err;
1070
1071         priv->fs.ns = mlx5_get_flow_namespace(priv->mdev,
1072                                                MLX5_FLOW_NAMESPACE_KERNEL);
1073
1074         if (!priv->fs.ns)
1075                 return -EINVAL;
1076
1077         err = mlx5e_arfs_create_tables(priv);
1078         if (err) {
1079                 netdev_err(priv->netdev, "Failed to create arfs tables, err=%d\n",
1080                            err);
1081                 priv->netdev->hw_features &= ~NETIF_F_NTUPLE;
1082         }
1083
1084         err = mlx5e_create_ttc_table(priv);
1085         if (err) {
1086                 netdev_err(priv->netdev, "Failed to create ttc table, err=%d\n",
1087                            err);
1088                 goto err_destroy_arfs_tables;
1089         }
1090
1091         err = mlx5e_create_l2_table(priv);
1092         if (err) {
1093                 netdev_err(priv->netdev, "Failed to create l2 table, err=%d\n",
1094                            err);
1095                 goto err_destroy_ttc_table;
1096         }
1097
1098         err = mlx5e_create_vlan_table(priv);
1099         if (err) {
1100                 netdev_err(priv->netdev, "Failed to create vlan table, err=%d\n",
1101                            err);
1102                 goto err_destroy_l2_table;
1103         }
1104
1105         return 0;
1106
1107 err_destroy_l2_table:
1108         mlx5e_destroy_l2_table(priv);
1109 err_destroy_ttc_table:
1110         mlx5e_destroy_ttc_table(priv);
1111 err_destroy_arfs_tables:
1112         mlx5e_arfs_destroy_tables(priv);
1113
1114         return err;
1115 }
1116
1117 void mlx5e_destroy_flow_steering(struct mlx5e_priv *priv)
1118 {
1119         mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_UNTAGGED, 0);
1120         mlx5e_destroy_vlan_table(priv);
1121         mlx5e_destroy_l2_table(priv);
1122         mlx5e_destroy_ttc_table(priv);
1123         mlx5e_arfs_destroy_tables(priv);
1124 }