Merge branch 'mlx5-next' of git://git.kernel.org/pub/scm/linux/kernel/git/mellanox...
[sfrench/cifs-2.6.git] / drivers / net / ethernet / mellanox / mlx5 / core / fs_core.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/mutex.h>
34 #include <linux/mlx5/driver.h>
35 #include <linux/mlx5/eswitch.h>
36
37 #include "mlx5_core.h"
38 #include "fs_core.h"
39 #include "fs_cmd.h"
40 #include "diag/fs_tracepoint.h"
41 #include "accel/ipsec.h"
42 #include "fpga/ipsec.h"
43
44 #define INIT_TREE_NODE_ARRAY_SIZE(...)  (sizeof((struct init_tree_node[]){__VA_ARGS__}) /\
45                                          sizeof(struct init_tree_node))
46
47 #define ADD_PRIO(num_prios_val, min_level_val, num_levels_val, caps_val,\
48                  ...) {.type = FS_TYPE_PRIO,\
49         .min_ft_level = min_level_val,\
50         .num_levels = num_levels_val,\
51         .num_leaf_prios = num_prios_val,\
52         .caps = caps_val,\
53         .children = (struct init_tree_node[]) {__VA_ARGS__},\
54         .ar_size = INIT_TREE_NODE_ARRAY_SIZE(__VA_ARGS__) \
55 }
56
57 #define ADD_MULTIPLE_PRIO(num_prios_val, num_levels_val, ...)\
58         ADD_PRIO(num_prios_val, 0, num_levels_val, {},\
59                  __VA_ARGS__)\
60
61 #define ADD_NS(...) {.type = FS_TYPE_NAMESPACE,\
62         .children = (struct init_tree_node[]) {__VA_ARGS__},\
63         .ar_size = INIT_TREE_NODE_ARRAY_SIZE(__VA_ARGS__) \
64 }
65
66 #define INIT_CAPS_ARRAY_SIZE(...) (sizeof((long[]){__VA_ARGS__}) /\
67                                    sizeof(long))
68
69 #define FS_CAP(cap) (__mlx5_bit_off(flow_table_nic_cap, cap))
70
71 #define FS_REQUIRED_CAPS(...) {.arr_sz = INIT_CAPS_ARRAY_SIZE(__VA_ARGS__), \
72                                .caps = (long[]) {__VA_ARGS__} }
73
74 #define FS_CHAINING_CAPS  FS_REQUIRED_CAPS(FS_CAP(flow_table_properties_nic_receive.flow_modify_en), \
75                                            FS_CAP(flow_table_properties_nic_receive.modify_root), \
76                                            FS_CAP(flow_table_properties_nic_receive.identified_miss_table_mode), \
77                                            FS_CAP(flow_table_properties_nic_receive.flow_table_modify))
78
79 #define LEFTOVERS_NUM_LEVELS 1
80 #define LEFTOVERS_NUM_PRIOS 1
81
82 #define BY_PASS_PRIO_NUM_LEVELS 1
83 #define BY_PASS_MIN_LEVEL (ETHTOOL_MIN_LEVEL + MLX5_BY_PASS_NUM_PRIOS +\
84                            LEFTOVERS_NUM_PRIOS)
85
86 #define ETHTOOL_PRIO_NUM_LEVELS 1
87 #define ETHTOOL_NUM_PRIOS 11
88 #define ETHTOOL_MIN_LEVEL (KERNEL_MIN_LEVEL + ETHTOOL_NUM_PRIOS)
89 /* Vlan, mac, ttc, inner ttc, aRFS */
90 #define KERNEL_NIC_PRIO_NUM_LEVELS 5
91 #define KERNEL_NIC_NUM_PRIOS 1
92 /* One more level for tc */
93 #define KERNEL_MIN_LEVEL (KERNEL_NIC_PRIO_NUM_LEVELS + 1)
94
95 #define KERNEL_NIC_TC_NUM_PRIOS  1
96 #define KERNEL_NIC_TC_NUM_LEVELS 2
97
98 #define ANCHOR_NUM_LEVELS 1
99 #define ANCHOR_NUM_PRIOS 1
100 #define ANCHOR_MIN_LEVEL (BY_PASS_MIN_LEVEL + 1)
101
102 #define OFFLOADS_MAX_FT 1
103 #define OFFLOADS_NUM_PRIOS 1
104 #define OFFLOADS_MIN_LEVEL (ANCHOR_MIN_LEVEL + 1)
105
106 #define LAG_PRIO_NUM_LEVELS 1
107 #define LAG_NUM_PRIOS 1
108 #define LAG_MIN_LEVEL (OFFLOADS_MIN_LEVEL + 1)
109
110 struct node_caps {
111         size_t  arr_sz;
112         long    *caps;
113 };
114
115 static struct init_tree_node {
116         enum fs_node_type       type;
117         struct init_tree_node *children;
118         int ar_size;
119         struct node_caps caps;
120         int min_ft_level;
121         int num_leaf_prios;
122         int prio;
123         int num_levels;
124 } root_fs = {
125         .type = FS_TYPE_NAMESPACE,
126         .ar_size = 7,
127         .children = (struct init_tree_node[]) {
128                 ADD_PRIO(0, BY_PASS_MIN_LEVEL, 0,
129                          FS_CHAINING_CAPS,
130                          ADD_NS(ADD_MULTIPLE_PRIO(MLX5_BY_PASS_NUM_PRIOS,
131                                                   BY_PASS_PRIO_NUM_LEVELS))),
132                 ADD_PRIO(0, LAG_MIN_LEVEL, 0,
133                          FS_CHAINING_CAPS,
134                          ADD_NS(ADD_MULTIPLE_PRIO(LAG_NUM_PRIOS,
135                                                   LAG_PRIO_NUM_LEVELS))),
136                 ADD_PRIO(0, OFFLOADS_MIN_LEVEL, 0, {},
137                          ADD_NS(ADD_MULTIPLE_PRIO(OFFLOADS_NUM_PRIOS, OFFLOADS_MAX_FT))),
138                 ADD_PRIO(0, ETHTOOL_MIN_LEVEL, 0,
139                          FS_CHAINING_CAPS,
140                          ADD_NS(ADD_MULTIPLE_PRIO(ETHTOOL_NUM_PRIOS,
141                                                   ETHTOOL_PRIO_NUM_LEVELS))),
142                 ADD_PRIO(0, KERNEL_MIN_LEVEL, 0, {},
143                          ADD_NS(ADD_MULTIPLE_PRIO(KERNEL_NIC_TC_NUM_PRIOS, KERNEL_NIC_TC_NUM_LEVELS),
144                                 ADD_MULTIPLE_PRIO(KERNEL_NIC_NUM_PRIOS,
145                                                   KERNEL_NIC_PRIO_NUM_LEVELS))),
146                 ADD_PRIO(0, BY_PASS_MIN_LEVEL, 0,
147                          FS_CHAINING_CAPS,
148                          ADD_NS(ADD_MULTIPLE_PRIO(LEFTOVERS_NUM_PRIOS, LEFTOVERS_NUM_LEVELS))),
149                 ADD_PRIO(0, ANCHOR_MIN_LEVEL, 0, {},
150                          ADD_NS(ADD_MULTIPLE_PRIO(ANCHOR_NUM_PRIOS, ANCHOR_NUM_LEVELS))),
151         }
152 };
153
154 enum fs_i_lock_class {
155         FS_LOCK_GRANDPARENT,
156         FS_LOCK_PARENT,
157         FS_LOCK_CHILD
158 };
159
160 static const struct rhashtable_params rhash_fte = {
161         .key_len = FIELD_SIZEOF(struct fs_fte, val),
162         .key_offset = offsetof(struct fs_fte, val),
163         .head_offset = offsetof(struct fs_fte, hash),
164         .automatic_shrinking = true,
165         .min_size = 1,
166 };
167
168 static const struct rhashtable_params rhash_fg = {
169         .key_len = FIELD_SIZEOF(struct mlx5_flow_group, mask),
170         .key_offset = offsetof(struct mlx5_flow_group, mask),
171         .head_offset = offsetof(struct mlx5_flow_group, hash),
172         .automatic_shrinking = true,
173         .min_size = 1,
174
175 };
176
177 static void del_hw_flow_table(struct fs_node *node);
178 static void del_hw_flow_group(struct fs_node *node);
179 static void del_hw_fte(struct fs_node *node);
180 static void del_sw_flow_table(struct fs_node *node);
181 static void del_sw_flow_group(struct fs_node *node);
182 static void del_sw_fte(struct fs_node *node);
183 static void del_sw_prio(struct fs_node *node);
184 static void del_sw_ns(struct fs_node *node);
185 /* Delete rule (destination) is special case that 
186  * requires to lock the FTE for all the deletion process.
187  */
188 static void del_sw_hw_rule(struct fs_node *node);
189 static bool mlx5_flow_dests_cmp(struct mlx5_flow_destination *d1,
190                                 struct mlx5_flow_destination *d2);
191 static void cleanup_root_ns(struct mlx5_flow_root_namespace *root_ns);
192 static struct mlx5_flow_rule *
193 find_flow_rule(struct fs_fte *fte,
194                struct mlx5_flow_destination *dest);
195
196 static void tree_init_node(struct fs_node *node,
197                            void (*del_hw_func)(struct fs_node *),
198                            void (*del_sw_func)(struct fs_node *))
199 {
200         refcount_set(&node->refcount, 1);
201         INIT_LIST_HEAD(&node->list);
202         INIT_LIST_HEAD(&node->children);
203         init_rwsem(&node->lock);
204         node->del_hw_func = del_hw_func;
205         node->del_sw_func = del_sw_func;
206         node->active = false;
207 }
208
209 static void tree_add_node(struct fs_node *node, struct fs_node *parent)
210 {
211         if (parent)
212                 refcount_inc(&parent->refcount);
213         node->parent = parent;
214
215         /* Parent is the root */
216         if (!parent)
217                 node->root = node;
218         else
219                 node->root = parent->root;
220 }
221
222 static int tree_get_node(struct fs_node *node)
223 {
224         return refcount_inc_not_zero(&node->refcount);
225 }
226
227 static void nested_down_read_ref_node(struct fs_node *node,
228                                       enum fs_i_lock_class class)
229 {
230         if (node) {
231                 down_read_nested(&node->lock, class);
232                 refcount_inc(&node->refcount);
233         }
234 }
235
236 static void nested_down_write_ref_node(struct fs_node *node,
237                                        enum fs_i_lock_class class)
238 {
239         if (node) {
240                 down_write_nested(&node->lock, class);
241                 refcount_inc(&node->refcount);
242         }
243 }
244
245 static void down_write_ref_node(struct fs_node *node)
246 {
247         if (node) {
248                 down_write(&node->lock);
249                 refcount_inc(&node->refcount);
250         }
251 }
252
253 static void up_read_ref_node(struct fs_node *node)
254 {
255         refcount_dec(&node->refcount);
256         up_read(&node->lock);
257 }
258
259 static void up_write_ref_node(struct fs_node *node)
260 {
261         refcount_dec(&node->refcount);
262         up_write(&node->lock);
263 }
264
265 static void tree_put_node(struct fs_node *node)
266 {
267         struct fs_node *parent_node = node->parent;
268
269         if (refcount_dec_and_test(&node->refcount)) {
270                 if (node->del_hw_func)
271                         node->del_hw_func(node);
272                 if (parent_node) {
273                         /* Only root namespace doesn't have parent and we just
274                          * need to free its node.
275                          */
276                         down_write_ref_node(parent_node);
277                         list_del_init(&node->list);
278                         if (node->del_sw_func)
279                                 node->del_sw_func(node);
280                         up_write_ref_node(parent_node);
281                 } else {
282                         kfree(node);
283                 }
284                 node = NULL;
285         }
286         if (!node && parent_node)
287                 tree_put_node(parent_node);
288 }
289
290 static int tree_remove_node(struct fs_node *node)
291 {
292         if (refcount_read(&node->refcount) > 1) {
293                 refcount_dec(&node->refcount);
294                 return -EEXIST;
295         }
296         tree_put_node(node);
297         return 0;
298 }
299
300 static struct fs_prio *find_prio(struct mlx5_flow_namespace *ns,
301                                  unsigned int prio)
302 {
303         struct fs_prio *iter_prio;
304
305         fs_for_each_prio(iter_prio, ns) {
306                 if (iter_prio->prio == prio)
307                         return iter_prio;
308         }
309
310         return NULL;
311 }
312
313 static bool check_last_reserved(const u32 *match_criteria)
314 {
315         char *match_criteria_reserved =
316                 MLX5_ADDR_OF(fte_match_param, match_criteria, MLX5_FTE_MATCH_PARAM_RESERVED);
317
318         return  !match_criteria_reserved[0] &&
319                 !memcmp(match_criteria_reserved, match_criteria_reserved + 1,
320                         MLX5_FLD_SZ_BYTES(fte_match_param,
321                                           MLX5_FTE_MATCH_PARAM_RESERVED) - 1);
322 }
323
324 static bool check_valid_mask(u8 match_criteria_enable, const u32 *match_criteria)
325 {
326         if (match_criteria_enable & ~(
327                 (1 << MLX5_CREATE_FLOW_GROUP_IN_MATCH_CRITERIA_ENABLE_OUTER_HEADERS)   |
328                 (1 << MLX5_CREATE_FLOW_GROUP_IN_MATCH_CRITERIA_ENABLE_MISC_PARAMETERS) |
329                 (1 << MLX5_CREATE_FLOW_GROUP_IN_MATCH_CRITERIA_ENABLE_INNER_HEADERS) |
330                 (1 << MLX5_CREATE_FLOW_GROUP_IN_MATCH_CRITERIA_ENABLE_MISC_PARAMETERS_2)))
331                 return false;
332
333         if (!(match_criteria_enable &
334               1 << MLX5_CREATE_FLOW_GROUP_IN_MATCH_CRITERIA_ENABLE_OUTER_HEADERS)) {
335                 char *fg_type_mask = MLX5_ADDR_OF(fte_match_param,
336                                                   match_criteria, outer_headers);
337
338                 if (fg_type_mask[0] ||
339                     memcmp(fg_type_mask, fg_type_mask + 1,
340                            MLX5_ST_SZ_BYTES(fte_match_set_lyr_2_4) - 1))
341                         return false;
342         }
343
344         if (!(match_criteria_enable &
345               1 << MLX5_CREATE_FLOW_GROUP_IN_MATCH_CRITERIA_ENABLE_MISC_PARAMETERS)) {
346                 char *fg_type_mask = MLX5_ADDR_OF(fte_match_param,
347                                                   match_criteria, misc_parameters);
348
349                 if (fg_type_mask[0] ||
350                     memcmp(fg_type_mask, fg_type_mask + 1,
351                            MLX5_ST_SZ_BYTES(fte_match_set_misc) - 1))
352                         return false;
353         }
354
355         if (!(match_criteria_enable &
356               1 << MLX5_CREATE_FLOW_GROUP_IN_MATCH_CRITERIA_ENABLE_INNER_HEADERS)) {
357                 char *fg_type_mask = MLX5_ADDR_OF(fte_match_param,
358                                                   match_criteria, inner_headers);
359
360                 if (fg_type_mask[0] ||
361                     memcmp(fg_type_mask, fg_type_mask + 1,
362                            MLX5_ST_SZ_BYTES(fte_match_set_lyr_2_4) - 1))
363                         return false;
364         }
365
366         if (!(match_criteria_enable &
367               1 << MLX5_CREATE_FLOW_GROUP_IN_MATCH_CRITERIA_ENABLE_MISC_PARAMETERS_2)) {
368                 char *fg_type_mask = MLX5_ADDR_OF(fte_match_param,
369                                                   match_criteria, misc_parameters_2);
370
371                 if (fg_type_mask[0] ||
372                     memcmp(fg_type_mask, fg_type_mask + 1,
373                            MLX5_ST_SZ_BYTES(fte_match_set_misc2) - 1))
374                         return false;
375         }
376
377         return check_last_reserved(match_criteria);
378 }
379
380 static bool check_valid_spec(const struct mlx5_flow_spec *spec)
381 {
382         int i;
383
384         if (!check_valid_mask(spec->match_criteria_enable, spec->match_criteria)) {
385                 pr_warn("mlx5_core: Match criteria given mismatches match_criteria_enable\n");
386                 return false;
387         }
388
389         for (i = 0; i < MLX5_ST_SZ_DW_MATCH_PARAM; i++)
390                 if (spec->match_value[i] & ~spec->match_criteria[i]) {
391                         pr_warn("mlx5_core: match_value differs from match_criteria\n");
392                         return false;
393                 }
394
395         return check_last_reserved(spec->match_value);
396 }
397
398 static struct mlx5_flow_root_namespace *find_root(struct fs_node *node)
399 {
400         struct fs_node *root;
401         struct mlx5_flow_namespace *ns;
402
403         root = node->root;
404
405         if (WARN_ON(root->type != FS_TYPE_NAMESPACE)) {
406                 pr_warn("mlx5: flow steering node is not in tree or garbaged\n");
407                 return NULL;
408         }
409
410         ns = container_of(root, struct mlx5_flow_namespace, node);
411         return container_of(ns, struct mlx5_flow_root_namespace, ns);
412 }
413
414 static inline struct mlx5_flow_steering *get_steering(struct fs_node *node)
415 {
416         struct mlx5_flow_root_namespace *root = find_root(node);
417
418         if (root)
419                 return root->dev->priv.steering;
420         return NULL;
421 }
422
423 static inline struct mlx5_core_dev *get_dev(struct fs_node *node)
424 {
425         struct mlx5_flow_root_namespace *root = find_root(node);
426
427         if (root)
428                 return root->dev;
429         return NULL;
430 }
431
432 static void del_sw_ns(struct fs_node *node)
433 {
434         kfree(node);
435 }
436
437 static void del_sw_prio(struct fs_node *node)
438 {
439         kfree(node);
440 }
441
442 static void del_hw_flow_table(struct fs_node *node)
443 {
444         struct mlx5_flow_root_namespace *root;
445         struct mlx5_flow_table *ft;
446         struct mlx5_core_dev *dev;
447         int err;
448
449         fs_get_obj(ft, node);
450         dev = get_dev(&ft->node);
451         root = find_root(&ft->node);
452
453         if (node->active) {
454                 err = root->cmds->destroy_flow_table(dev, ft);
455                 if (err)
456                         mlx5_core_warn(dev, "flow steering can't destroy ft\n");
457         }
458 }
459
460 static void del_sw_flow_table(struct fs_node *node)
461 {
462         struct mlx5_flow_table *ft;
463         struct fs_prio *prio;
464
465         fs_get_obj(ft, node);
466
467         rhltable_destroy(&ft->fgs_hash);
468         fs_get_obj(prio, ft->node.parent);
469         prio->num_ft--;
470         kfree(ft);
471 }
472
473 static void del_sw_hw_rule(struct fs_node *node)
474 {
475         struct mlx5_flow_root_namespace *root;
476         struct mlx5_flow_rule *rule;
477         struct mlx5_flow_table *ft;
478         struct mlx5_flow_group *fg;
479         struct fs_fte *fte;
480         int modify_mask;
481         struct mlx5_core_dev *dev = get_dev(node);
482         int err;
483         bool update_fte = false;
484
485         fs_get_obj(rule, node);
486         fs_get_obj(fte, rule->node.parent);
487         fs_get_obj(fg, fte->node.parent);
488         fs_get_obj(ft, fg->node.parent);
489         trace_mlx5_fs_del_rule(rule);
490         if (rule->sw_action == MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO) {
491                 mutex_lock(&rule->dest_attr.ft->lock);
492                 list_del(&rule->next_ft);
493                 mutex_unlock(&rule->dest_attr.ft->lock);
494         }
495
496         if (rule->dest_attr.type == MLX5_FLOW_DESTINATION_TYPE_COUNTER  &&
497             --fte->dests_size) {
498                 modify_mask = BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_ACTION) |
499                               BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_FLOW_COUNTERS);
500                 fte->action.action &= ~MLX5_FLOW_CONTEXT_ACTION_COUNT;
501                 update_fte = true;
502                 goto out;
503         }
504
505         if ((fte->action.action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) &&
506             --fte->dests_size) {
507                 modify_mask = BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_DESTINATION_LIST),
508                 update_fte = true;
509         }
510 out:
511         root = find_root(&ft->node);
512         if (update_fte && fte->dests_size) {
513                 err = root->cmds->update_fte(dev, ft, fg->id, modify_mask, fte);
514                 if (err)
515                         mlx5_core_warn(dev,
516                                        "%s can't del rule fg id=%d fte_index=%d\n",
517                                        __func__, fg->id, fte->index);
518         }
519         kfree(rule);
520 }
521
522 static void del_hw_fte(struct fs_node *node)
523 {
524         struct mlx5_flow_root_namespace *root;
525         struct mlx5_flow_table *ft;
526         struct mlx5_flow_group *fg;
527         struct mlx5_core_dev *dev;
528         struct fs_fte *fte;
529         int err;
530
531         fs_get_obj(fte, node);
532         fs_get_obj(fg, fte->node.parent);
533         fs_get_obj(ft, fg->node.parent);
534
535         trace_mlx5_fs_del_fte(fte);
536         dev = get_dev(&ft->node);
537         root = find_root(&ft->node);
538         if (node->active) {
539                 err = root->cmds->delete_fte(dev, ft, fte);
540                 if (err)
541                         mlx5_core_warn(dev,
542                                        "flow steering can't delete fte in index %d of flow group id %d\n",
543                                        fte->index, fg->id);
544         }
545 }
546
547 static void del_sw_fte(struct fs_node *node)
548 {
549         struct mlx5_flow_steering *steering = get_steering(node);
550         struct mlx5_flow_group *fg;
551         struct fs_fte *fte;
552         int err;
553
554         fs_get_obj(fte, node);
555         fs_get_obj(fg, fte->node.parent);
556
557         err = rhashtable_remove_fast(&fg->ftes_hash,
558                                      &fte->hash,
559                                      rhash_fte);
560         WARN_ON(err);
561         ida_simple_remove(&fg->fte_allocator, fte->index - fg->start_index);
562         kmem_cache_free(steering->ftes_cache, fte);
563 }
564
565 static void del_hw_flow_group(struct fs_node *node)
566 {
567         struct mlx5_flow_root_namespace *root;
568         struct mlx5_flow_group *fg;
569         struct mlx5_flow_table *ft;
570         struct mlx5_core_dev *dev;
571
572         fs_get_obj(fg, node);
573         fs_get_obj(ft, fg->node.parent);
574         dev = get_dev(&ft->node);
575         trace_mlx5_fs_del_fg(fg);
576
577         root = find_root(&ft->node);
578         if (fg->node.active && root->cmds->destroy_flow_group(dev, ft, fg->id))
579                 mlx5_core_warn(dev, "flow steering can't destroy fg %d of ft %d\n",
580                                fg->id, ft->id);
581 }
582
583 static void del_sw_flow_group(struct fs_node *node)
584 {
585         struct mlx5_flow_steering *steering = get_steering(node);
586         struct mlx5_flow_group *fg;
587         struct mlx5_flow_table *ft;
588         int err;
589
590         fs_get_obj(fg, node);
591         fs_get_obj(ft, fg->node.parent);
592
593         rhashtable_destroy(&fg->ftes_hash);
594         ida_destroy(&fg->fte_allocator);
595         if (ft->autogroup.active)
596                 ft->autogroup.num_groups--;
597         err = rhltable_remove(&ft->fgs_hash,
598                               &fg->hash,
599                               rhash_fg);
600         WARN_ON(err);
601         kmem_cache_free(steering->fgs_cache, fg);
602 }
603
604 static int insert_fte(struct mlx5_flow_group *fg, struct fs_fte *fte)
605 {
606         int index;
607         int ret;
608
609         index = ida_simple_get(&fg->fte_allocator, 0, fg->max_ftes, GFP_KERNEL);
610         if (index < 0)
611                 return index;
612
613         fte->index = index + fg->start_index;
614         ret = rhashtable_insert_fast(&fg->ftes_hash,
615                                      &fte->hash,
616                                      rhash_fte);
617         if (ret)
618                 goto err_ida_remove;
619
620         tree_add_node(&fte->node, &fg->node);
621         list_add_tail(&fte->node.list, &fg->node.children);
622         return 0;
623
624 err_ida_remove:
625         ida_simple_remove(&fg->fte_allocator, index);
626         return ret;
627 }
628
629 static struct fs_fte *alloc_fte(struct mlx5_flow_table *ft,
630                                 u32 *match_value,
631                                 struct mlx5_flow_act *flow_act)
632 {
633         struct mlx5_flow_steering *steering = get_steering(&ft->node);
634         struct fs_fte *fte;
635
636         fte = kmem_cache_zalloc(steering->ftes_cache, GFP_KERNEL);
637         if (!fte)
638                 return ERR_PTR(-ENOMEM);
639
640         memcpy(fte->val, match_value, sizeof(fte->val));
641         fte->node.type =  FS_TYPE_FLOW_ENTRY;
642         fte->action = *flow_act;
643
644         tree_init_node(&fte->node, del_hw_fte, del_sw_fte);
645
646         return fte;
647 }
648
649 static void dealloc_flow_group(struct mlx5_flow_steering *steering,
650                                struct mlx5_flow_group *fg)
651 {
652         rhashtable_destroy(&fg->ftes_hash);
653         kmem_cache_free(steering->fgs_cache, fg);
654 }
655
656 static struct mlx5_flow_group *alloc_flow_group(struct mlx5_flow_steering *steering,
657                                                 u8 match_criteria_enable,
658                                                 void *match_criteria,
659                                                 int start_index,
660                                                 int end_index)
661 {
662         struct mlx5_flow_group *fg;
663         int ret;
664
665         fg = kmem_cache_zalloc(steering->fgs_cache, GFP_KERNEL);
666         if (!fg)
667                 return ERR_PTR(-ENOMEM);
668
669         ret = rhashtable_init(&fg->ftes_hash, &rhash_fte);
670         if (ret) {
671                 kmem_cache_free(steering->fgs_cache, fg);
672                 return ERR_PTR(ret);
673 }
674         ida_init(&fg->fte_allocator);
675         fg->mask.match_criteria_enable = match_criteria_enable;
676         memcpy(&fg->mask.match_criteria, match_criteria,
677                sizeof(fg->mask.match_criteria));
678         fg->node.type =  FS_TYPE_FLOW_GROUP;
679         fg->start_index = start_index;
680         fg->max_ftes = end_index - start_index + 1;
681
682         return fg;
683 }
684
685 static struct mlx5_flow_group *alloc_insert_flow_group(struct mlx5_flow_table *ft,
686                                                        u8 match_criteria_enable,
687                                                        void *match_criteria,
688                                                        int start_index,
689                                                        int end_index,
690                                                        struct list_head *prev)
691 {
692         struct mlx5_flow_steering *steering = get_steering(&ft->node);
693         struct mlx5_flow_group *fg;
694         int ret;
695
696         fg = alloc_flow_group(steering, match_criteria_enable, match_criteria,
697                               start_index, end_index);
698         if (IS_ERR(fg))
699                 return fg;
700
701         /* initialize refcnt, add to parent list */
702         ret = rhltable_insert(&ft->fgs_hash,
703                               &fg->hash,
704                               rhash_fg);
705         if (ret) {
706                 dealloc_flow_group(steering, fg);
707                 return ERR_PTR(ret);
708         }
709
710         tree_init_node(&fg->node, del_hw_flow_group, del_sw_flow_group);
711         tree_add_node(&fg->node, &ft->node);
712         /* Add node to group list */
713         list_add(&fg->node.list, prev);
714         atomic_inc(&ft->node.version);
715
716         return fg;
717 }
718
719 static struct mlx5_flow_table *alloc_flow_table(int level, u16 vport, int max_fte,
720                                                 enum fs_flow_table_type table_type,
721                                                 enum fs_flow_table_op_mod op_mod,
722                                                 u32 flags)
723 {
724         struct mlx5_flow_table *ft;
725         int ret;
726
727         ft  = kzalloc(sizeof(*ft), GFP_KERNEL);
728         if (!ft)
729                 return ERR_PTR(-ENOMEM);
730
731         ret = rhltable_init(&ft->fgs_hash, &rhash_fg);
732         if (ret) {
733                 kfree(ft);
734                 return ERR_PTR(ret);
735         }
736
737         ft->level = level;
738         ft->node.type = FS_TYPE_FLOW_TABLE;
739         ft->op_mod = op_mod;
740         ft->type = table_type;
741         ft->vport = vport;
742         ft->max_fte = max_fte;
743         ft->flags = flags;
744         INIT_LIST_HEAD(&ft->fwd_rules);
745         mutex_init(&ft->lock);
746
747         return ft;
748 }
749
750 /* If reverse is false, then we search for the first flow table in the
751  * root sub-tree from start(closest from right), else we search for the
752  * last flow table in the root sub-tree till start(closest from left).
753  */
754 static struct mlx5_flow_table *find_closest_ft_recursive(struct fs_node  *root,
755                                                          struct list_head *start,
756                                                          bool reverse)
757 {
758 #define list_advance_entry(pos, reverse)                \
759         ((reverse) ? list_prev_entry(pos, list) : list_next_entry(pos, list))
760
761 #define list_for_each_advance_continue(pos, head, reverse)      \
762         for (pos = list_advance_entry(pos, reverse);            \
763              &pos->list != (head);                              \
764              pos = list_advance_entry(pos, reverse))
765
766         struct fs_node *iter = list_entry(start, struct fs_node, list);
767         struct mlx5_flow_table *ft = NULL;
768
769         if (!root)
770                 return NULL;
771
772         list_for_each_advance_continue(iter, &root->children, reverse) {
773                 if (iter->type == FS_TYPE_FLOW_TABLE) {
774                         fs_get_obj(ft, iter);
775                         return ft;
776                 }
777                 ft = find_closest_ft_recursive(iter, &iter->children, reverse);
778                 if (ft)
779                         return ft;
780         }
781
782         return ft;
783 }
784
785 /* If reverse if false then return the first flow table in next priority of
786  * prio in the tree, else return the last flow table in the previous priority
787  * of prio in the tree.
788  */
789 static struct mlx5_flow_table *find_closest_ft(struct fs_prio *prio, bool reverse)
790 {
791         struct mlx5_flow_table *ft = NULL;
792         struct fs_node *curr_node;
793         struct fs_node *parent;
794
795         parent = prio->node.parent;
796         curr_node = &prio->node;
797         while (!ft && parent) {
798                 ft = find_closest_ft_recursive(parent, &curr_node->list, reverse);
799                 curr_node = parent;
800                 parent = curr_node->parent;
801         }
802         return ft;
803 }
804
805 /* Assuming all the tree is locked by mutex chain lock */
806 static struct mlx5_flow_table *find_next_chained_ft(struct fs_prio *prio)
807 {
808         return find_closest_ft(prio, false);
809 }
810
811 /* Assuming all the tree is locked by mutex chain lock */
812 static struct mlx5_flow_table *find_prev_chained_ft(struct fs_prio *prio)
813 {
814         return find_closest_ft(prio, true);
815 }
816
817 static int connect_fts_in_prio(struct mlx5_core_dev *dev,
818                                struct fs_prio *prio,
819                                struct mlx5_flow_table *ft)
820 {
821         struct mlx5_flow_root_namespace *root = find_root(&prio->node);
822         struct mlx5_flow_table *iter;
823         int i = 0;
824         int err;
825
826         fs_for_each_ft(iter, prio) {
827                 i++;
828                 err = root->cmds->modify_flow_table(dev, iter, ft);
829                 if (err) {
830                         mlx5_core_warn(dev, "Failed to modify flow table %d\n",
831                                        iter->id);
832                         /* The driver is out of sync with the FW */
833                         if (i > 1)
834                                 WARN_ON(true);
835                         return err;
836                 }
837         }
838         return 0;
839 }
840
841 /* Connect flow tables from previous priority of prio to ft */
842 static int connect_prev_fts(struct mlx5_core_dev *dev,
843                             struct mlx5_flow_table *ft,
844                             struct fs_prio *prio)
845 {
846         struct mlx5_flow_table *prev_ft;
847
848         prev_ft = find_prev_chained_ft(prio);
849         if (prev_ft) {
850                 struct fs_prio *prev_prio;
851
852                 fs_get_obj(prev_prio, prev_ft->node.parent);
853                 return connect_fts_in_prio(dev, prev_prio, ft);
854         }
855         return 0;
856 }
857
858 static int update_root_ft_create(struct mlx5_flow_table *ft, struct fs_prio
859                                  *prio)
860 {
861         struct mlx5_flow_root_namespace *root = find_root(&prio->node);
862         struct mlx5_ft_underlay_qp *uqp;
863         int min_level = INT_MAX;
864         int err;
865         u32 qpn;
866
867         if (root->root_ft)
868                 min_level = root->root_ft->level;
869
870         if (ft->level >= min_level)
871                 return 0;
872
873         if (list_empty(&root->underlay_qpns)) {
874                 /* Don't set any QPN (zero) in case QPN list is empty */
875                 qpn = 0;
876                 err = root->cmds->update_root_ft(root->dev, ft, qpn, false);
877         } else {
878                 list_for_each_entry(uqp, &root->underlay_qpns, list) {
879                         qpn = uqp->qpn;
880                         err = root->cmds->update_root_ft(root->dev, ft,
881                                                          qpn, false);
882                         if (err)
883                                 break;
884                 }
885         }
886
887         if (err)
888                 mlx5_core_warn(root->dev,
889                                "Update root flow table of id(%u) qpn(%d) failed\n",
890                                ft->id, qpn);
891         else
892                 root->root_ft = ft;
893
894         return err;
895 }
896
897 static int _mlx5_modify_rule_destination(struct mlx5_flow_rule *rule,
898                                          struct mlx5_flow_destination *dest)
899 {
900         struct mlx5_flow_root_namespace *root;
901         struct mlx5_flow_table *ft;
902         struct mlx5_flow_group *fg;
903         struct fs_fte *fte;
904         int modify_mask = BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_DESTINATION_LIST);
905         int err = 0;
906
907         fs_get_obj(fte, rule->node.parent);
908         if (!(fte->action.action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST))
909                 return -EINVAL;
910         down_write_ref_node(&fte->node);
911         fs_get_obj(fg, fte->node.parent);
912         fs_get_obj(ft, fg->node.parent);
913
914         memcpy(&rule->dest_attr, dest, sizeof(*dest));
915         root = find_root(&ft->node);
916         err = root->cmds->update_fte(get_dev(&ft->node), ft, fg->id,
917                                      modify_mask, fte);
918         up_write_ref_node(&fte->node);
919
920         return err;
921 }
922
923 int mlx5_modify_rule_destination(struct mlx5_flow_handle *handle,
924                                  struct mlx5_flow_destination *new_dest,
925                                  struct mlx5_flow_destination *old_dest)
926 {
927         int i;
928
929         if (!old_dest) {
930                 if (handle->num_rules != 1)
931                         return -EINVAL;
932                 return _mlx5_modify_rule_destination(handle->rule[0],
933                                                      new_dest);
934         }
935
936         for (i = 0; i < handle->num_rules; i++) {
937                 if (mlx5_flow_dests_cmp(new_dest, &handle->rule[i]->dest_attr))
938                         return _mlx5_modify_rule_destination(handle->rule[i],
939                                                              new_dest);
940         }
941
942         return -EINVAL;
943 }
944
945 /* Modify/set FWD rules that point on old_next_ft to point on new_next_ft  */
946 static int connect_fwd_rules(struct mlx5_core_dev *dev,
947                              struct mlx5_flow_table *new_next_ft,
948                              struct mlx5_flow_table *old_next_ft)
949 {
950         struct mlx5_flow_destination dest = {};
951         struct mlx5_flow_rule *iter;
952         int err = 0;
953
954         /* new_next_ft and old_next_ft could be NULL only
955          * when we create/destroy the anchor flow table.
956          */
957         if (!new_next_ft || !old_next_ft)
958                 return 0;
959
960         dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
961         dest.ft = new_next_ft;
962
963         mutex_lock(&old_next_ft->lock);
964         list_splice_init(&old_next_ft->fwd_rules, &new_next_ft->fwd_rules);
965         mutex_unlock(&old_next_ft->lock);
966         list_for_each_entry(iter, &new_next_ft->fwd_rules, next_ft) {
967                 err = _mlx5_modify_rule_destination(iter, &dest);
968                 if (err)
969                         pr_err("mlx5_core: failed to modify rule to point on flow table %d\n",
970                                new_next_ft->id);
971         }
972         return 0;
973 }
974
975 static int connect_flow_table(struct mlx5_core_dev *dev, struct mlx5_flow_table *ft,
976                               struct fs_prio *prio)
977 {
978         struct mlx5_flow_table *next_ft;
979         int err = 0;
980
981         /* Connect_prev_fts and update_root_ft_create are mutually exclusive */
982
983         if (list_empty(&prio->node.children)) {
984                 err = connect_prev_fts(dev, ft, prio);
985                 if (err)
986                         return err;
987
988                 next_ft = find_next_chained_ft(prio);
989                 err = connect_fwd_rules(dev, ft, next_ft);
990                 if (err)
991                         return err;
992         }
993
994         if (MLX5_CAP_FLOWTABLE(dev,
995                                flow_table_properties_nic_receive.modify_root))
996                 err = update_root_ft_create(ft, prio);
997         return err;
998 }
999
1000 static void list_add_flow_table(struct mlx5_flow_table *ft,
1001                                 struct fs_prio *prio)
1002 {
1003         struct list_head *prev = &prio->node.children;
1004         struct mlx5_flow_table *iter;
1005
1006         fs_for_each_ft(iter, prio) {
1007                 if (iter->level > ft->level)
1008                         break;
1009                 prev = &iter->node.list;
1010         }
1011         list_add(&ft->node.list, prev);
1012 }
1013
1014 static struct mlx5_flow_table *__mlx5_create_flow_table(struct mlx5_flow_namespace *ns,
1015                                                         struct mlx5_flow_table_attr *ft_attr,
1016                                                         enum fs_flow_table_op_mod op_mod,
1017                                                         u16 vport)
1018 {
1019         struct mlx5_flow_root_namespace *root = find_root(&ns->node);
1020         struct mlx5_flow_table *next_ft = NULL;
1021         struct fs_prio *fs_prio = NULL;
1022         struct mlx5_flow_table *ft;
1023         int log_table_sz;
1024         int err;
1025
1026         if (!root) {
1027                 pr_err("mlx5: flow steering failed to find root of namespace\n");
1028                 return ERR_PTR(-ENODEV);
1029         }
1030
1031         mutex_lock(&root->chain_lock);
1032         fs_prio = find_prio(ns, ft_attr->prio);
1033         if (!fs_prio) {
1034                 err = -EINVAL;
1035                 goto unlock_root;
1036         }
1037         if (ft_attr->level >= fs_prio->num_levels) {
1038                 err = -ENOSPC;
1039                 goto unlock_root;
1040         }
1041         /* The level is related to the
1042          * priority level range.
1043          */
1044         ft_attr->level += fs_prio->start_level;
1045         ft = alloc_flow_table(ft_attr->level,
1046                               vport,
1047                               ft_attr->max_fte ? roundup_pow_of_two(ft_attr->max_fte) : 0,
1048                               root->table_type,
1049                               op_mod, ft_attr->flags);
1050         if (IS_ERR(ft)) {
1051                 err = PTR_ERR(ft);
1052                 goto unlock_root;
1053         }
1054
1055         tree_init_node(&ft->node, del_hw_flow_table, del_sw_flow_table);
1056         log_table_sz = ft->max_fte ? ilog2(ft->max_fte) : 0;
1057         next_ft = find_next_chained_ft(fs_prio);
1058         err = root->cmds->create_flow_table(root->dev, ft->vport, ft->op_mod,
1059                                             ft->type, ft->level, log_table_sz,
1060                                             next_ft, &ft->id, ft->flags);
1061         if (err)
1062                 goto free_ft;
1063
1064         err = connect_flow_table(root->dev, ft, fs_prio);
1065         if (err)
1066                 goto destroy_ft;
1067         ft->node.active = true;
1068         down_write_ref_node(&fs_prio->node);
1069         tree_add_node(&ft->node, &fs_prio->node);
1070         list_add_flow_table(ft, fs_prio);
1071         fs_prio->num_ft++;
1072         up_write_ref_node(&fs_prio->node);
1073         mutex_unlock(&root->chain_lock);
1074         return ft;
1075 destroy_ft:
1076         root->cmds->destroy_flow_table(root->dev, ft);
1077 free_ft:
1078         kfree(ft);
1079 unlock_root:
1080         mutex_unlock(&root->chain_lock);
1081         return ERR_PTR(err);
1082 }
1083
1084 struct mlx5_flow_table *mlx5_create_flow_table(struct mlx5_flow_namespace *ns,
1085                                                struct mlx5_flow_table_attr *ft_attr)
1086 {
1087         return __mlx5_create_flow_table(ns, ft_attr, FS_FT_OP_MOD_NORMAL, 0);
1088 }
1089
1090 struct mlx5_flow_table *mlx5_create_vport_flow_table(struct mlx5_flow_namespace *ns,
1091                                                      int prio, int max_fte,
1092                                                      u32 level, u16 vport)
1093 {
1094         struct mlx5_flow_table_attr ft_attr = {};
1095
1096         ft_attr.max_fte = max_fte;
1097         ft_attr.level   = level;
1098         ft_attr.prio    = prio;
1099
1100         return __mlx5_create_flow_table(ns, &ft_attr, FS_FT_OP_MOD_NORMAL, vport);
1101 }
1102
1103 struct mlx5_flow_table*
1104 mlx5_create_lag_demux_flow_table(struct mlx5_flow_namespace *ns,
1105                                  int prio, u32 level)
1106 {
1107         struct mlx5_flow_table_attr ft_attr = {};
1108
1109         ft_attr.level = level;
1110         ft_attr.prio  = prio;
1111         return __mlx5_create_flow_table(ns, &ft_attr, FS_FT_OP_MOD_LAG_DEMUX, 0);
1112 }
1113 EXPORT_SYMBOL(mlx5_create_lag_demux_flow_table);
1114
1115 struct mlx5_flow_table*
1116 mlx5_create_auto_grouped_flow_table(struct mlx5_flow_namespace *ns,
1117                                     int prio,
1118                                     int num_flow_table_entries,
1119                                     int max_num_groups,
1120                                     u32 level,
1121                                     u32 flags)
1122 {
1123         struct mlx5_flow_table_attr ft_attr = {};
1124         struct mlx5_flow_table *ft;
1125
1126         if (max_num_groups > num_flow_table_entries)
1127                 return ERR_PTR(-EINVAL);
1128
1129         ft_attr.max_fte = num_flow_table_entries;
1130         ft_attr.prio    = prio;
1131         ft_attr.level   = level;
1132         ft_attr.flags   = flags;
1133
1134         ft = mlx5_create_flow_table(ns, &ft_attr);
1135         if (IS_ERR(ft))
1136                 return ft;
1137
1138         ft->autogroup.active = true;
1139         ft->autogroup.required_groups = max_num_groups;
1140
1141         return ft;
1142 }
1143 EXPORT_SYMBOL(mlx5_create_auto_grouped_flow_table);
1144
1145 struct mlx5_flow_group *mlx5_create_flow_group(struct mlx5_flow_table *ft,
1146                                                u32 *fg_in)
1147 {
1148         struct mlx5_flow_root_namespace *root = find_root(&ft->node);
1149         void *match_criteria = MLX5_ADDR_OF(create_flow_group_in,
1150                                             fg_in, match_criteria);
1151         u8 match_criteria_enable = MLX5_GET(create_flow_group_in,
1152                                             fg_in,
1153                                             match_criteria_enable);
1154         int start_index = MLX5_GET(create_flow_group_in, fg_in,
1155                                    start_flow_index);
1156         int end_index = MLX5_GET(create_flow_group_in, fg_in,
1157                                  end_flow_index);
1158         struct mlx5_core_dev *dev = get_dev(&ft->node);
1159         struct mlx5_flow_group *fg;
1160         int err;
1161
1162         if (!check_valid_mask(match_criteria_enable, match_criteria))
1163                 return ERR_PTR(-EINVAL);
1164
1165         if (ft->autogroup.active)
1166                 return ERR_PTR(-EPERM);
1167
1168         down_write_ref_node(&ft->node);
1169         fg = alloc_insert_flow_group(ft, match_criteria_enable, match_criteria,
1170                                      start_index, end_index,
1171                                      ft->node.children.prev);
1172         up_write_ref_node(&ft->node);
1173         if (IS_ERR(fg))
1174                 return fg;
1175
1176         err = root->cmds->create_flow_group(dev, ft, fg_in, &fg->id);
1177         if (err) {
1178                 tree_put_node(&fg->node);
1179                 return ERR_PTR(err);
1180         }
1181         trace_mlx5_fs_add_fg(fg);
1182         fg->node.active = true;
1183
1184         return fg;
1185 }
1186
1187 static struct mlx5_flow_rule *alloc_rule(struct mlx5_flow_destination *dest)
1188 {
1189         struct mlx5_flow_rule *rule;
1190
1191         rule = kzalloc(sizeof(*rule), GFP_KERNEL);
1192         if (!rule)
1193                 return NULL;
1194
1195         INIT_LIST_HEAD(&rule->next_ft);
1196         rule->node.type = FS_TYPE_FLOW_DEST;
1197         if (dest)
1198                 memcpy(&rule->dest_attr, dest, sizeof(*dest));
1199
1200         return rule;
1201 }
1202
1203 static struct mlx5_flow_handle *alloc_handle(int num_rules)
1204 {
1205         struct mlx5_flow_handle *handle;
1206
1207         handle = kzalloc(struct_size(handle, rule, num_rules), GFP_KERNEL);
1208         if (!handle)
1209                 return NULL;
1210
1211         handle->num_rules = num_rules;
1212
1213         return handle;
1214 }
1215
1216 static void destroy_flow_handle(struct fs_fte *fte,
1217                                 struct mlx5_flow_handle *handle,
1218                                 struct mlx5_flow_destination *dest,
1219                                 int i)
1220 {
1221         for (; --i >= 0;) {
1222                 if (refcount_dec_and_test(&handle->rule[i]->node.refcount)) {
1223                         fte->dests_size--;
1224                         list_del(&handle->rule[i]->node.list);
1225                         kfree(handle->rule[i]);
1226                 }
1227         }
1228         kfree(handle);
1229 }
1230
1231 static struct mlx5_flow_handle *
1232 create_flow_handle(struct fs_fte *fte,
1233                    struct mlx5_flow_destination *dest,
1234                    int dest_num,
1235                    int *modify_mask,
1236                    bool *new_rule)
1237 {
1238         struct mlx5_flow_handle *handle;
1239         struct mlx5_flow_rule *rule = NULL;
1240         static int count = BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_FLOW_COUNTERS);
1241         static int dst = BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_DESTINATION_LIST);
1242         int type;
1243         int i = 0;
1244
1245         handle = alloc_handle((dest_num) ? dest_num : 1);
1246         if (!handle)
1247                 return ERR_PTR(-ENOMEM);
1248
1249         do {
1250                 if (dest) {
1251                         rule = find_flow_rule(fte, dest + i);
1252                         if (rule) {
1253                                 refcount_inc(&rule->node.refcount);
1254                                 goto rule_found;
1255                         }
1256                 }
1257
1258                 *new_rule = true;
1259                 rule = alloc_rule(dest + i);
1260                 if (!rule)
1261                         goto free_rules;
1262
1263                 /* Add dest to dests list- we need flow tables to be in the
1264                  * end of the list for forward to next prio rules.
1265                  */
1266                 tree_init_node(&rule->node, NULL, del_sw_hw_rule);
1267                 if (dest &&
1268                     dest[i].type != MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE)
1269                         list_add(&rule->node.list, &fte->node.children);
1270                 else
1271                         list_add_tail(&rule->node.list, &fte->node.children);
1272                 if (dest) {
1273                         fte->dests_size++;
1274
1275                         type = dest[i].type ==
1276                                 MLX5_FLOW_DESTINATION_TYPE_COUNTER;
1277                         *modify_mask |= type ? count : dst;
1278                 }
1279 rule_found:
1280                 handle->rule[i] = rule;
1281         } while (++i < dest_num);
1282
1283         return handle;
1284
1285 free_rules:
1286         destroy_flow_handle(fte, handle, dest, i);
1287         return ERR_PTR(-ENOMEM);
1288 }
1289
1290 /* fte should not be deleted while calling this function */
1291 static struct mlx5_flow_handle *
1292 add_rule_fte(struct fs_fte *fte,
1293              struct mlx5_flow_group *fg,
1294              struct mlx5_flow_destination *dest,
1295              int dest_num,
1296              bool update_action)
1297 {
1298         struct mlx5_flow_root_namespace *root;
1299         struct mlx5_flow_handle *handle;
1300         struct mlx5_flow_table *ft;
1301         int modify_mask = 0;
1302         int err;
1303         bool new_rule = false;
1304
1305         handle = create_flow_handle(fte, dest, dest_num, &modify_mask,
1306                                     &new_rule);
1307         if (IS_ERR(handle) || !new_rule)
1308                 goto out;
1309
1310         if (update_action)
1311                 modify_mask |= BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_ACTION);
1312
1313         fs_get_obj(ft, fg->node.parent);
1314         root = find_root(&fg->node);
1315         if (!(fte->status & FS_FTE_STATUS_EXISTING))
1316                 err = root->cmds->create_fte(get_dev(&ft->node),
1317                                              ft, fg, fte);
1318         else
1319                 err = root->cmds->update_fte(get_dev(&ft->node), ft, fg->id,
1320                                                      modify_mask, fte);
1321         if (err)
1322                 goto free_handle;
1323
1324         fte->node.active = true;
1325         fte->status |= FS_FTE_STATUS_EXISTING;
1326         atomic_inc(&fte->node.version);
1327
1328 out:
1329         return handle;
1330
1331 free_handle:
1332         destroy_flow_handle(fte, handle, dest, handle->num_rules);
1333         return ERR_PTR(err);
1334 }
1335
1336 static struct mlx5_flow_group *alloc_auto_flow_group(struct mlx5_flow_table  *ft,
1337                                                      struct mlx5_flow_spec *spec)
1338 {
1339         struct list_head *prev = &ft->node.children;
1340         struct mlx5_flow_group *fg;
1341         unsigned int candidate_index = 0;
1342         unsigned int group_size = 0;
1343
1344         if (!ft->autogroup.active)
1345                 return ERR_PTR(-ENOENT);
1346
1347         if (ft->autogroup.num_groups < ft->autogroup.required_groups)
1348                 /* We save place for flow groups in addition to max types */
1349                 group_size = ft->max_fte / (ft->autogroup.required_groups + 1);
1350
1351         /*  ft->max_fte == ft->autogroup.max_types */
1352         if (group_size == 0)
1353                 group_size = 1;
1354
1355         /* sorted by start_index */
1356         fs_for_each_fg(fg, ft) {
1357                 if (candidate_index + group_size > fg->start_index)
1358                         candidate_index = fg->start_index + fg->max_ftes;
1359                 else
1360                         break;
1361                 prev = &fg->node.list;
1362         }
1363
1364         if (candidate_index + group_size > ft->max_fte)
1365                 return ERR_PTR(-ENOSPC);
1366
1367         fg = alloc_insert_flow_group(ft,
1368                                      spec->match_criteria_enable,
1369                                      spec->match_criteria,
1370                                      candidate_index,
1371                                      candidate_index + group_size - 1,
1372                                      prev);
1373         if (IS_ERR(fg))
1374                 goto out;
1375
1376         ft->autogroup.num_groups++;
1377
1378 out:
1379         return fg;
1380 }
1381
1382 static int create_auto_flow_group(struct mlx5_flow_table *ft,
1383                                   struct mlx5_flow_group *fg)
1384 {
1385         struct mlx5_flow_root_namespace *root = find_root(&ft->node);
1386         struct mlx5_core_dev *dev = get_dev(&ft->node);
1387         int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
1388         void *match_criteria_addr;
1389         u8 src_esw_owner_mask_on;
1390         void *misc;
1391         int err;
1392         u32 *in;
1393
1394         in = kvzalloc(inlen, GFP_KERNEL);
1395         if (!in)
1396                 return -ENOMEM;
1397
1398         MLX5_SET(create_flow_group_in, in, match_criteria_enable,
1399                  fg->mask.match_criteria_enable);
1400         MLX5_SET(create_flow_group_in, in, start_flow_index, fg->start_index);
1401         MLX5_SET(create_flow_group_in, in, end_flow_index,   fg->start_index +
1402                  fg->max_ftes - 1);
1403
1404         misc = MLX5_ADDR_OF(fte_match_param, fg->mask.match_criteria,
1405                             misc_parameters);
1406         src_esw_owner_mask_on = !!MLX5_GET(fte_match_set_misc, misc,
1407                                          source_eswitch_owner_vhca_id);
1408         MLX5_SET(create_flow_group_in, in,
1409                  source_eswitch_owner_vhca_id_valid, src_esw_owner_mask_on);
1410
1411         match_criteria_addr = MLX5_ADDR_OF(create_flow_group_in,
1412                                            in, match_criteria);
1413         memcpy(match_criteria_addr, fg->mask.match_criteria,
1414                sizeof(fg->mask.match_criteria));
1415
1416         err = root->cmds->create_flow_group(dev, ft, in, &fg->id);
1417         if (!err) {
1418                 fg->node.active = true;
1419                 trace_mlx5_fs_add_fg(fg);
1420         }
1421
1422         kvfree(in);
1423         return err;
1424 }
1425
1426 static bool mlx5_flow_dests_cmp(struct mlx5_flow_destination *d1,
1427                                 struct mlx5_flow_destination *d2)
1428 {
1429         if (d1->type == d2->type) {
1430                 if ((d1->type == MLX5_FLOW_DESTINATION_TYPE_VPORT &&
1431                      d1->vport.num == d2->vport.num) ||
1432                     (d1->type == MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE &&
1433                      d1->ft == d2->ft) ||
1434                     (d1->type == MLX5_FLOW_DESTINATION_TYPE_TIR &&
1435                      d1->tir_num == d2->tir_num))
1436                         return true;
1437         }
1438
1439         return false;
1440 }
1441
1442 static struct mlx5_flow_rule *find_flow_rule(struct fs_fte *fte,
1443                                              struct mlx5_flow_destination *dest)
1444 {
1445         struct mlx5_flow_rule *rule;
1446
1447         list_for_each_entry(rule, &fte->node.children, node.list) {
1448                 if (mlx5_flow_dests_cmp(&rule->dest_attr, dest))
1449                         return rule;
1450         }
1451         return NULL;
1452 }
1453
1454 static bool check_conflicting_actions(u32 action1, u32 action2)
1455 {
1456         u32 xored_actions = action1 ^ action2;
1457
1458         /* if one rule only wants to count, it's ok */
1459         if (action1 == MLX5_FLOW_CONTEXT_ACTION_COUNT ||
1460             action2 == MLX5_FLOW_CONTEXT_ACTION_COUNT)
1461                 return false;
1462
1463         if (xored_actions & (MLX5_FLOW_CONTEXT_ACTION_DROP  |
1464                              MLX5_FLOW_CONTEXT_ACTION_ENCAP |
1465                              MLX5_FLOW_CONTEXT_ACTION_DECAP |
1466                              MLX5_FLOW_CONTEXT_ACTION_MOD_HDR  |
1467                              MLX5_FLOW_CONTEXT_ACTION_VLAN_POP |
1468                              MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH |
1469                              MLX5_FLOW_CONTEXT_ACTION_VLAN_POP_2 |
1470                              MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH_2))
1471                 return true;
1472
1473         return false;
1474 }
1475
1476 static int check_conflicting_ftes(struct fs_fte *fte, const struct mlx5_flow_act *flow_act)
1477 {
1478         if (check_conflicting_actions(flow_act->action, fte->action.action)) {
1479                 mlx5_core_warn(get_dev(&fte->node),
1480                                "Found two FTEs with conflicting actions\n");
1481                 return -EEXIST;
1482         }
1483
1484         if (flow_act->has_flow_tag &&
1485             fte->action.flow_tag != flow_act->flow_tag) {
1486                 mlx5_core_warn(get_dev(&fte->node),
1487                                "FTE flow tag %u already exists with different flow tag %u\n",
1488                                fte->action.flow_tag,
1489                                flow_act->flow_tag);
1490                 return -EEXIST;
1491         }
1492
1493         return 0;
1494 }
1495
1496 static struct mlx5_flow_handle *add_rule_fg(struct mlx5_flow_group *fg,
1497                                             u32 *match_value,
1498                                             struct mlx5_flow_act *flow_act,
1499                                             struct mlx5_flow_destination *dest,
1500                                             int dest_num,
1501                                             struct fs_fte *fte)
1502 {
1503         struct mlx5_flow_handle *handle;
1504         int old_action;
1505         int i;
1506         int ret;
1507
1508         ret = check_conflicting_ftes(fte, flow_act);
1509         if (ret)
1510                 return ERR_PTR(ret);
1511
1512         old_action = fte->action.action;
1513         fte->action.action |= flow_act->action;
1514         handle = add_rule_fte(fte, fg, dest, dest_num,
1515                               old_action != flow_act->action);
1516         if (IS_ERR(handle)) {
1517                 fte->action.action = old_action;
1518                 return handle;
1519         }
1520         trace_mlx5_fs_set_fte(fte, false);
1521
1522         for (i = 0; i < handle->num_rules; i++) {
1523                 if (refcount_read(&handle->rule[i]->node.refcount) == 1) {
1524                         tree_add_node(&handle->rule[i]->node, &fte->node);
1525                         trace_mlx5_fs_add_rule(handle->rule[i]);
1526                 }
1527         }
1528         return handle;
1529 }
1530
1531 struct mlx5_fc *mlx5_flow_rule_counter(struct mlx5_flow_handle *handle)
1532 {
1533         struct mlx5_flow_rule *dst;
1534         struct fs_fte *fte;
1535
1536         fs_get_obj(fte, handle->rule[0]->node.parent);
1537
1538         fs_for_each_dst(dst, fte) {
1539                 if (dst->dest_attr.type == MLX5_FLOW_DESTINATION_TYPE_COUNTER)
1540                         return dst->dest_attr.counter;
1541         }
1542
1543         return NULL;
1544 }
1545
1546 static bool counter_is_valid(struct mlx5_fc *counter, u32 action)
1547 {
1548         if (!(action & MLX5_FLOW_CONTEXT_ACTION_COUNT))
1549                 return !counter;
1550
1551         if (!counter)
1552                 return false;
1553
1554         return (action & (MLX5_FLOW_CONTEXT_ACTION_DROP |
1555                           MLX5_FLOW_CONTEXT_ACTION_FWD_DEST));
1556 }
1557
1558 static bool dest_is_valid(struct mlx5_flow_destination *dest,
1559                           u32 action,
1560                           struct mlx5_flow_table *ft)
1561 {
1562         if (dest && (dest->type == MLX5_FLOW_DESTINATION_TYPE_COUNTER))
1563                 return counter_is_valid(dest->counter, action);
1564
1565         if (!(action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST))
1566                 return true;
1567
1568         if (!dest || ((dest->type ==
1569             MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE) &&
1570             (dest->ft->level <= ft->level)))
1571                 return false;
1572         return true;
1573 }
1574
1575 struct match_list {
1576         struct list_head        list;
1577         struct mlx5_flow_group *g;
1578 };
1579
1580 struct match_list_head {
1581         struct list_head  list;
1582         struct match_list first;
1583 };
1584
1585 static void free_match_list(struct match_list_head *head)
1586 {
1587         if (!list_empty(&head->list)) {
1588                 struct match_list *iter, *match_tmp;
1589
1590                 list_del(&head->first.list);
1591                 tree_put_node(&head->first.g->node);
1592                 list_for_each_entry_safe(iter, match_tmp, &head->list,
1593                                          list) {
1594                         tree_put_node(&iter->g->node);
1595                         list_del(&iter->list);
1596                         kfree(iter);
1597                 }
1598         }
1599 }
1600
1601 static int build_match_list(struct match_list_head *match_head,
1602                             struct mlx5_flow_table *ft,
1603                             struct mlx5_flow_spec *spec)
1604 {
1605         struct rhlist_head *tmp, *list;
1606         struct mlx5_flow_group *g;
1607         int err = 0;
1608
1609         rcu_read_lock();
1610         INIT_LIST_HEAD(&match_head->list);
1611         /* Collect all fgs which has a matching match_criteria */
1612         list = rhltable_lookup(&ft->fgs_hash, spec, rhash_fg);
1613         /* RCU is atomic, we can't execute FW commands here */
1614         rhl_for_each_entry_rcu(g, tmp, list, hash) {
1615                 struct match_list *curr_match;
1616
1617                 if (likely(list_empty(&match_head->list))) {
1618                         if (!tree_get_node(&g->node))
1619                                 continue;
1620                         match_head->first.g = g;
1621                         list_add_tail(&match_head->first.list,
1622                                       &match_head->list);
1623                         continue;
1624                 }
1625
1626                 curr_match = kmalloc(sizeof(*curr_match), GFP_ATOMIC);
1627                 if (!curr_match) {
1628                         free_match_list(match_head);
1629                         err = -ENOMEM;
1630                         goto out;
1631                 }
1632                 if (!tree_get_node(&g->node)) {
1633                         kfree(curr_match);
1634                         continue;
1635                 }
1636                 curr_match->g = g;
1637                 list_add_tail(&curr_match->list, &match_head->list);
1638         }
1639 out:
1640         rcu_read_unlock();
1641         return err;
1642 }
1643
1644 static u64 matched_fgs_get_version(struct list_head *match_head)
1645 {
1646         struct match_list *iter;
1647         u64 version = 0;
1648
1649         list_for_each_entry(iter, match_head, list)
1650                 version += (u64)atomic_read(&iter->g->node.version);
1651         return version;
1652 }
1653
1654 static struct mlx5_flow_handle *
1655 try_add_to_existing_fg(struct mlx5_flow_table *ft,
1656                        struct list_head *match_head,
1657                        struct mlx5_flow_spec *spec,
1658                        struct mlx5_flow_act *flow_act,
1659                        struct mlx5_flow_destination *dest,
1660                        int dest_num,
1661                        int ft_version)
1662 {
1663         struct mlx5_flow_steering *steering = get_steering(&ft->node);
1664         struct mlx5_flow_group *g;
1665         struct mlx5_flow_handle *rule;
1666         struct match_list *iter;
1667         bool take_write = false;
1668         struct fs_fte *fte;
1669         u64  version;
1670         int err;
1671
1672         fte = alloc_fte(ft, spec->match_value, flow_act);
1673         if (IS_ERR(fte))
1674                 return  ERR_PTR(-ENOMEM);
1675
1676         list_for_each_entry(iter, match_head, list) {
1677                 nested_down_read_ref_node(&iter->g->node, FS_LOCK_PARENT);
1678         }
1679
1680 search_again_locked:
1681         version = matched_fgs_get_version(match_head);
1682         /* Try to find a fg that already contains a matching fte */
1683         list_for_each_entry(iter, match_head, list) {
1684                 struct fs_fte *fte_tmp;
1685
1686                 g = iter->g;
1687                 fte_tmp = rhashtable_lookup_fast(&g->ftes_hash, spec->match_value,
1688                                                  rhash_fte);
1689                 if (!fte_tmp || !tree_get_node(&fte_tmp->node))
1690                         continue;
1691
1692                 nested_down_write_ref_node(&fte_tmp->node, FS_LOCK_CHILD);
1693                 if (!take_write) {
1694                         list_for_each_entry(iter, match_head, list)
1695                                 up_read_ref_node(&iter->g->node);
1696                 } else {
1697                         list_for_each_entry(iter, match_head, list)
1698                                 up_write_ref_node(&iter->g->node);
1699                 }
1700
1701                 rule = add_rule_fg(g, spec->match_value,
1702                                    flow_act, dest, dest_num, fte_tmp);
1703                 up_write_ref_node(&fte_tmp->node);
1704                 tree_put_node(&fte_tmp->node);
1705                 kmem_cache_free(steering->ftes_cache, fte);
1706                 return rule;
1707         }
1708
1709         /* No group with matching fte found. Try to add a new fte to any
1710          * matching fg.
1711          */
1712
1713         if (!take_write) {
1714                 list_for_each_entry(iter, match_head, list)
1715                         up_read_ref_node(&iter->g->node);
1716                 list_for_each_entry(iter, match_head, list)
1717                         nested_down_write_ref_node(&iter->g->node,
1718                                                    FS_LOCK_PARENT);
1719                 take_write = true;
1720         }
1721
1722         /* Check the ft version, for case that new flow group
1723          * was added while the fgs weren't locked
1724          */
1725         if (atomic_read(&ft->node.version) != ft_version) {
1726                 rule = ERR_PTR(-EAGAIN);
1727                 goto out;
1728         }
1729
1730         /* Check the fgs version, for case the new FTE with the
1731          * same values was added while the fgs weren't locked
1732          */
1733         if (version != matched_fgs_get_version(match_head))
1734                 goto search_again_locked;
1735
1736         list_for_each_entry(iter, match_head, list) {
1737                 g = iter->g;
1738
1739                 if (!g->node.active)
1740                         continue;
1741                 err = insert_fte(g, fte);
1742                 if (err) {
1743                         if (err == -ENOSPC)
1744                                 continue;
1745                         list_for_each_entry(iter, match_head, list)
1746                                 up_write_ref_node(&iter->g->node);
1747                         kmem_cache_free(steering->ftes_cache, fte);
1748                         return ERR_PTR(err);
1749                 }
1750
1751                 nested_down_write_ref_node(&fte->node, FS_LOCK_CHILD);
1752                 list_for_each_entry(iter, match_head, list)
1753                         up_write_ref_node(&iter->g->node);
1754                 rule = add_rule_fg(g, spec->match_value,
1755                                    flow_act, dest, dest_num, fte);
1756                 up_write_ref_node(&fte->node);
1757                 tree_put_node(&fte->node);
1758                 return rule;
1759         }
1760         rule = ERR_PTR(-ENOENT);
1761 out:
1762         list_for_each_entry(iter, match_head, list)
1763                 up_write_ref_node(&iter->g->node);
1764         kmem_cache_free(steering->ftes_cache, fte);
1765         return rule;
1766 }
1767
1768 static struct mlx5_flow_handle *
1769 _mlx5_add_flow_rules(struct mlx5_flow_table *ft,
1770                      struct mlx5_flow_spec *spec,
1771                      struct mlx5_flow_act *flow_act,
1772                      struct mlx5_flow_destination *dest,
1773                      int dest_num)
1774
1775 {
1776         struct mlx5_flow_steering *steering = get_steering(&ft->node);
1777         struct mlx5_flow_group *g;
1778         struct mlx5_flow_handle *rule;
1779         struct match_list_head match_head;
1780         bool take_write = false;
1781         struct fs_fte *fte;
1782         int version;
1783         int err;
1784         int i;
1785
1786         if (!check_valid_spec(spec))
1787                 return ERR_PTR(-EINVAL);
1788
1789         for (i = 0; i < dest_num; i++) {
1790                 if (!dest_is_valid(&dest[i], flow_act->action, ft))
1791                         return ERR_PTR(-EINVAL);
1792         }
1793         nested_down_read_ref_node(&ft->node, FS_LOCK_GRANDPARENT);
1794 search_again_locked:
1795         version = atomic_read(&ft->node.version);
1796
1797         /* Collect all fgs which has a matching match_criteria */
1798         err = build_match_list(&match_head, ft, spec);
1799         if (err) {
1800                 if (take_write)
1801                         up_write_ref_node(&ft->node);
1802                 return ERR_PTR(err);
1803         }
1804
1805         if (!take_write)
1806                 up_read_ref_node(&ft->node);
1807
1808         rule = try_add_to_existing_fg(ft, &match_head.list, spec, flow_act, dest,
1809                                       dest_num, version);
1810         free_match_list(&match_head);
1811         if (!IS_ERR(rule) ||
1812             (PTR_ERR(rule) != -ENOENT && PTR_ERR(rule) != -EAGAIN)) {
1813                 if (take_write)
1814                         up_write_ref_node(&ft->node);
1815                 return rule;
1816         }
1817
1818         if (!take_write) {
1819                 nested_down_write_ref_node(&ft->node, FS_LOCK_GRANDPARENT);
1820                 take_write = true;
1821         }
1822
1823         if (PTR_ERR(rule) == -EAGAIN ||
1824             version != atomic_read(&ft->node.version))
1825                 goto search_again_locked;
1826
1827         g = alloc_auto_flow_group(ft, spec);
1828         if (IS_ERR(g)) {
1829                 rule = ERR_CAST(g);
1830                 up_write_ref_node(&ft->node);
1831                 return rule;
1832         }
1833
1834         nested_down_write_ref_node(&g->node, FS_LOCK_PARENT);
1835         up_write_ref_node(&ft->node);
1836
1837         err = create_auto_flow_group(ft, g);
1838         if (err)
1839                 goto err_release_fg;
1840
1841         fte = alloc_fte(ft, spec->match_value, flow_act);
1842         if (IS_ERR(fte)) {
1843                 err = PTR_ERR(fte);
1844                 goto err_release_fg;
1845         }
1846
1847         err = insert_fte(g, fte);
1848         if (err) {
1849                 kmem_cache_free(steering->ftes_cache, fte);
1850                 goto err_release_fg;
1851         }
1852
1853         nested_down_write_ref_node(&fte->node, FS_LOCK_CHILD);
1854         up_write_ref_node(&g->node);
1855         rule = add_rule_fg(g, spec->match_value, flow_act, dest,
1856                            dest_num, fte);
1857         up_write_ref_node(&fte->node);
1858         tree_put_node(&fte->node);
1859         tree_put_node(&g->node);
1860         return rule;
1861
1862 err_release_fg:
1863         up_write_ref_node(&g->node);
1864         tree_put_node(&g->node);
1865         return ERR_PTR(err);
1866 }
1867
1868 static bool fwd_next_prio_supported(struct mlx5_flow_table *ft)
1869 {
1870         return ((ft->type == FS_FT_NIC_RX) &&
1871                 (MLX5_CAP_FLOWTABLE(get_dev(&ft->node), nic_rx_multi_path_tirs)));
1872 }
1873
1874 struct mlx5_flow_handle *
1875 mlx5_add_flow_rules(struct mlx5_flow_table *ft,
1876                     struct mlx5_flow_spec *spec,
1877                     struct mlx5_flow_act *flow_act,
1878                     struct mlx5_flow_destination *dest,
1879                     int dest_num)
1880 {
1881         struct mlx5_flow_root_namespace *root = find_root(&ft->node);
1882         struct mlx5_flow_destination gen_dest = {};
1883         struct mlx5_flow_table *next_ft = NULL;
1884         struct mlx5_flow_handle *handle = NULL;
1885         u32 sw_action = flow_act->action;
1886         struct fs_prio *prio;
1887
1888         fs_get_obj(prio, ft->node.parent);
1889         if (flow_act->action == MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO) {
1890                 if (!fwd_next_prio_supported(ft))
1891                         return ERR_PTR(-EOPNOTSUPP);
1892                 if (dest)
1893                         return ERR_PTR(-EINVAL);
1894                 mutex_lock(&root->chain_lock);
1895                 next_ft = find_next_chained_ft(prio);
1896                 if (next_ft) {
1897                         gen_dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
1898                         gen_dest.ft = next_ft;
1899                         dest = &gen_dest;
1900                         dest_num = 1;
1901                         flow_act->action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
1902                 } else {
1903                         mutex_unlock(&root->chain_lock);
1904                         return ERR_PTR(-EOPNOTSUPP);
1905                 }
1906         }
1907
1908         handle = _mlx5_add_flow_rules(ft, spec, flow_act, dest, dest_num);
1909
1910         if (sw_action == MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO) {
1911                 if (!IS_ERR_OR_NULL(handle) &&
1912                     (list_empty(&handle->rule[0]->next_ft))) {
1913                         mutex_lock(&next_ft->lock);
1914                         list_add(&handle->rule[0]->next_ft,
1915                                  &next_ft->fwd_rules);
1916                         mutex_unlock(&next_ft->lock);
1917                         handle->rule[0]->sw_action = MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO;
1918                 }
1919                 mutex_unlock(&root->chain_lock);
1920         }
1921         return handle;
1922 }
1923 EXPORT_SYMBOL(mlx5_add_flow_rules);
1924
1925 void mlx5_del_flow_rules(struct mlx5_flow_handle *handle)
1926 {
1927         int i;
1928
1929         for (i = handle->num_rules - 1; i >= 0; i--)
1930                 tree_remove_node(&handle->rule[i]->node);
1931         kfree(handle);
1932 }
1933 EXPORT_SYMBOL(mlx5_del_flow_rules);
1934
1935 /* Assuming prio->node.children(flow tables) is sorted by level */
1936 static struct mlx5_flow_table *find_next_ft(struct mlx5_flow_table *ft)
1937 {
1938         struct fs_prio *prio;
1939
1940         fs_get_obj(prio, ft->node.parent);
1941
1942         if (!list_is_last(&ft->node.list, &prio->node.children))
1943                 return list_next_entry(ft, node.list);
1944         return find_next_chained_ft(prio);
1945 }
1946
1947 static int update_root_ft_destroy(struct mlx5_flow_table *ft)
1948 {
1949         struct mlx5_flow_root_namespace *root = find_root(&ft->node);
1950         struct mlx5_ft_underlay_qp *uqp;
1951         struct mlx5_flow_table *new_root_ft = NULL;
1952         int err = 0;
1953         u32 qpn;
1954
1955         if (root->root_ft != ft)
1956                 return 0;
1957
1958         new_root_ft = find_next_ft(ft);
1959         if (!new_root_ft) {
1960                 root->root_ft = NULL;
1961                 return 0;
1962         }
1963
1964         if (list_empty(&root->underlay_qpns)) {
1965                 /* Don't set any QPN (zero) in case QPN list is empty */
1966                 qpn = 0;
1967                 err = root->cmds->update_root_ft(root->dev, new_root_ft,
1968                                                  qpn, false);
1969         } else {
1970                 list_for_each_entry(uqp, &root->underlay_qpns, list) {
1971                         qpn = uqp->qpn;
1972                         err = root->cmds->update_root_ft(root->dev,
1973                                                          new_root_ft, qpn,
1974                                                          false);
1975                         if (err)
1976                                 break;
1977                 }
1978         }
1979
1980         if (err)
1981                 mlx5_core_warn(root->dev,
1982                                "Update root flow table of id(%u) qpn(%d) failed\n",
1983                                ft->id, qpn);
1984         else
1985                 root->root_ft = new_root_ft;
1986
1987         return 0;
1988 }
1989
1990 /* Connect flow table from previous priority to
1991  * the next flow table.
1992  */
1993 static int disconnect_flow_table(struct mlx5_flow_table *ft)
1994 {
1995         struct mlx5_core_dev *dev = get_dev(&ft->node);
1996         struct mlx5_flow_table *next_ft;
1997         struct fs_prio *prio;
1998         int err = 0;
1999
2000         err = update_root_ft_destroy(ft);
2001         if (err)
2002                 return err;
2003
2004         fs_get_obj(prio, ft->node.parent);
2005         if  (!(list_first_entry(&prio->node.children,
2006                                 struct mlx5_flow_table,
2007                                 node.list) == ft))
2008                 return 0;
2009
2010         next_ft = find_next_chained_ft(prio);
2011         err = connect_fwd_rules(dev, next_ft, ft);
2012         if (err)
2013                 return err;
2014
2015         err = connect_prev_fts(dev, next_ft, prio);
2016         if (err)
2017                 mlx5_core_warn(dev, "Failed to disconnect flow table %d\n",
2018                                ft->id);
2019         return err;
2020 }
2021
2022 int mlx5_destroy_flow_table(struct mlx5_flow_table *ft)
2023 {
2024         struct mlx5_flow_root_namespace *root = find_root(&ft->node);
2025         int err = 0;
2026
2027         mutex_lock(&root->chain_lock);
2028         err = disconnect_flow_table(ft);
2029         if (err) {
2030                 mutex_unlock(&root->chain_lock);
2031                 return err;
2032         }
2033         if (tree_remove_node(&ft->node))
2034                 mlx5_core_warn(get_dev(&ft->node), "Flow table %d wasn't destroyed, refcount > 1\n",
2035                                ft->id);
2036         mutex_unlock(&root->chain_lock);
2037
2038         return err;
2039 }
2040 EXPORT_SYMBOL(mlx5_destroy_flow_table);
2041
2042 void mlx5_destroy_flow_group(struct mlx5_flow_group *fg)
2043 {
2044         if (tree_remove_node(&fg->node))
2045                 mlx5_core_warn(get_dev(&fg->node), "Flow group %d wasn't destroyed, refcount > 1\n",
2046                                fg->id);
2047 }
2048
2049 struct mlx5_flow_namespace *mlx5_get_flow_namespace(struct mlx5_core_dev *dev,
2050                                                     enum mlx5_flow_namespace_type type)
2051 {
2052         struct mlx5_flow_steering *steering = dev->priv.steering;
2053         struct mlx5_flow_root_namespace *root_ns;
2054         int prio;
2055         struct fs_prio *fs_prio;
2056         struct mlx5_flow_namespace *ns;
2057
2058         if (!steering)
2059                 return NULL;
2060
2061         switch (type) {
2062         case MLX5_FLOW_NAMESPACE_BYPASS:
2063         case MLX5_FLOW_NAMESPACE_LAG:
2064         case MLX5_FLOW_NAMESPACE_OFFLOADS:
2065         case MLX5_FLOW_NAMESPACE_ETHTOOL:
2066         case MLX5_FLOW_NAMESPACE_KERNEL:
2067         case MLX5_FLOW_NAMESPACE_LEFTOVERS:
2068         case MLX5_FLOW_NAMESPACE_ANCHOR:
2069                 prio = type;
2070                 break;
2071         case MLX5_FLOW_NAMESPACE_FDB:
2072                 if (steering->fdb_root_ns)
2073                         return &steering->fdb_root_ns->ns;
2074                 else
2075                         return NULL;
2076         case MLX5_FLOW_NAMESPACE_SNIFFER_RX:
2077                 if (steering->sniffer_rx_root_ns)
2078                         return &steering->sniffer_rx_root_ns->ns;
2079                 else
2080                         return NULL;
2081         case MLX5_FLOW_NAMESPACE_SNIFFER_TX:
2082                 if (steering->sniffer_tx_root_ns)
2083                         return &steering->sniffer_tx_root_ns->ns;
2084                 else
2085                         return NULL;
2086         case MLX5_FLOW_NAMESPACE_EGRESS:
2087                 if (steering->egress_root_ns)
2088                         return &steering->egress_root_ns->ns;
2089                 else
2090                         return NULL;
2091         default:
2092                 return NULL;
2093         }
2094
2095         root_ns = steering->root_ns;
2096         if (!root_ns)
2097                 return NULL;
2098
2099         fs_prio = find_prio(&root_ns->ns, prio);
2100         if (!fs_prio)
2101                 return NULL;
2102
2103         ns = list_first_entry(&fs_prio->node.children,
2104                               typeof(*ns),
2105                               node.list);
2106
2107         return ns;
2108 }
2109 EXPORT_SYMBOL(mlx5_get_flow_namespace);
2110
2111 struct mlx5_flow_namespace *mlx5_get_flow_vport_acl_namespace(struct mlx5_core_dev *dev,
2112                                                               enum mlx5_flow_namespace_type type,
2113                                                               int vport)
2114 {
2115         struct mlx5_flow_steering *steering = dev->priv.steering;
2116
2117         if (!steering || vport >= MLX5_TOTAL_VPORTS(dev))
2118                 return NULL;
2119
2120         switch (type) {
2121         case MLX5_FLOW_NAMESPACE_ESW_EGRESS:
2122                 if (steering->esw_egress_root_ns &&
2123                     steering->esw_egress_root_ns[vport])
2124                         return &steering->esw_egress_root_ns[vport]->ns;
2125                 else
2126                         return NULL;
2127         case MLX5_FLOW_NAMESPACE_ESW_INGRESS:
2128                 if (steering->esw_ingress_root_ns &&
2129                     steering->esw_ingress_root_ns[vport])
2130                         return &steering->esw_ingress_root_ns[vport]->ns;
2131                 else
2132                         return NULL;
2133         default:
2134                 return NULL;
2135         }
2136 }
2137
2138 static struct fs_prio *fs_create_prio(struct mlx5_flow_namespace *ns,
2139                                       unsigned int prio, int num_levels)
2140 {
2141         struct fs_prio *fs_prio;
2142
2143         fs_prio = kzalloc(sizeof(*fs_prio), GFP_KERNEL);
2144         if (!fs_prio)
2145                 return ERR_PTR(-ENOMEM);
2146
2147         fs_prio->node.type = FS_TYPE_PRIO;
2148         tree_init_node(&fs_prio->node, NULL, del_sw_prio);
2149         tree_add_node(&fs_prio->node, &ns->node);
2150         fs_prio->num_levels = num_levels;
2151         fs_prio->prio = prio;
2152         list_add_tail(&fs_prio->node.list, &ns->node.children);
2153
2154         return fs_prio;
2155 }
2156
2157 static struct mlx5_flow_namespace *fs_init_namespace(struct mlx5_flow_namespace
2158                                                      *ns)
2159 {
2160         ns->node.type = FS_TYPE_NAMESPACE;
2161
2162         return ns;
2163 }
2164
2165 static struct mlx5_flow_namespace *fs_create_namespace(struct fs_prio *prio)
2166 {
2167         struct mlx5_flow_namespace      *ns;
2168
2169         ns = kzalloc(sizeof(*ns), GFP_KERNEL);
2170         if (!ns)
2171                 return ERR_PTR(-ENOMEM);
2172
2173         fs_init_namespace(ns);
2174         tree_init_node(&ns->node, NULL, del_sw_ns);
2175         tree_add_node(&ns->node, &prio->node);
2176         list_add_tail(&ns->node.list, &prio->node.children);
2177
2178         return ns;
2179 }
2180
2181 static int create_leaf_prios(struct mlx5_flow_namespace *ns, int prio,
2182                              struct init_tree_node *prio_metadata)
2183 {
2184         struct fs_prio *fs_prio;
2185         int i;
2186
2187         for (i = 0; i < prio_metadata->num_leaf_prios; i++) {
2188                 fs_prio = fs_create_prio(ns, prio++, prio_metadata->num_levels);
2189                 if (IS_ERR(fs_prio))
2190                         return PTR_ERR(fs_prio);
2191         }
2192         return 0;
2193 }
2194
2195 #define FLOW_TABLE_BIT_SZ 1
2196 #define GET_FLOW_TABLE_CAP(dev, offset) \
2197         ((be32_to_cpu(*((__be32 *)(dev->caps.hca_cur[MLX5_CAP_FLOW_TABLE]) +    \
2198                         offset / 32)) >>                                        \
2199           (32 - FLOW_TABLE_BIT_SZ - (offset & 0x1f))) & FLOW_TABLE_BIT_SZ)
2200 static bool has_required_caps(struct mlx5_core_dev *dev, struct node_caps *caps)
2201 {
2202         int i;
2203
2204         for (i = 0; i < caps->arr_sz; i++) {
2205                 if (!GET_FLOW_TABLE_CAP(dev, caps->caps[i]))
2206                         return false;
2207         }
2208         return true;
2209 }
2210
2211 static int init_root_tree_recursive(struct mlx5_flow_steering *steering,
2212                                     struct init_tree_node *init_node,
2213                                     struct fs_node *fs_parent_node,
2214                                     struct init_tree_node *init_parent_node,
2215                                     int prio)
2216 {
2217         int max_ft_level = MLX5_CAP_FLOWTABLE(steering->dev,
2218                                               flow_table_properties_nic_receive.
2219                                               max_ft_level);
2220         struct mlx5_flow_namespace *fs_ns;
2221         struct fs_prio *fs_prio;
2222         struct fs_node *base;
2223         int i;
2224         int err;
2225
2226         if (init_node->type == FS_TYPE_PRIO) {
2227                 if ((init_node->min_ft_level > max_ft_level) ||
2228                     !has_required_caps(steering->dev, &init_node->caps))
2229                         return 0;
2230
2231                 fs_get_obj(fs_ns, fs_parent_node);
2232                 if (init_node->num_leaf_prios)
2233                         return create_leaf_prios(fs_ns, prio, init_node);
2234                 fs_prio = fs_create_prio(fs_ns, prio, init_node->num_levels);
2235                 if (IS_ERR(fs_prio))
2236                         return PTR_ERR(fs_prio);
2237                 base = &fs_prio->node;
2238         } else if (init_node->type == FS_TYPE_NAMESPACE) {
2239                 fs_get_obj(fs_prio, fs_parent_node);
2240                 fs_ns = fs_create_namespace(fs_prio);
2241                 if (IS_ERR(fs_ns))
2242                         return PTR_ERR(fs_ns);
2243                 base = &fs_ns->node;
2244         } else {
2245                 return -EINVAL;
2246         }
2247         prio = 0;
2248         for (i = 0; i < init_node->ar_size; i++) {
2249                 err = init_root_tree_recursive(steering, &init_node->children[i],
2250                                                base, init_node, prio);
2251                 if (err)
2252                         return err;
2253                 if (init_node->children[i].type == FS_TYPE_PRIO &&
2254                     init_node->children[i].num_leaf_prios) {
2255                         prio += init_node->children[i].num_leaf_prios;
2256                 }
2257         }
2258
2259         return 0;
2260 }
2261
2262 static int init_root_tree(struct mlx5_flow_steering *steering,
2263                           struct init_tree_node *init_node,
2264                           struct fs_node *fs_parent_node)
2265 {
2266         int i;
2267         struct mlx5_flow_namespace *fs_ns;
2268         int err;
2269
2270         fs_get_obj(fs_ns, fs_parent_node);
2271         for (i = 0; i < init_node->ar_size; i++) {
2272                 err = init_root_tree_recursive(steering, &init_node->children[i],
2273                                                &fs_ns->node,
2274                                                init_node, i);
2275                 if (err)
2276                         return err;
2277         }
2278         return 0;
2279 }
2280
2281 static struct mlx5_flow_root_namespace
2282 *create_root_ns(struct mlx5_flow_steering *steering,
2283                 enum fs_flow_table_type table_type)
2284 {
2285         const struct mlx5_flow_cmds *cmds = mlx5_fs_cmd_get_default(table_type);
2286         struct mlx5_flow_root_namespace *root_ns;
2287         struct mlx5_flow_namespace *ns;
2288
2289         if (mlx5_accel_ipsec_device_caps(steering->dev) & MLX5_ACCEL_IPSEC_CAP_DEVICE &&
2290             (table_type == FS_FT_NIC_RX || table_type == FS_FT_NIC_TX))
2291                 cmds = mlx5_fs_cmd_get_default_ipsec_fpga_cmds(table_type);
2292
2293         /* Create the root namespace */
2294         root_ns = kvzalloc(sizeof(*root_ns), GFP_KERNEL);
2295         if (!root_ns)
2296                 return NULL;
2297
2298         root_ns->dev = steering->dev;
2299         root_ns->table_type = table_type;
2300         root_ns->cmds = cmds;
2301
2302         INIT_LIST_HEAD(&root_ns->underlay_qpns);
2303
2304         ns = &root_ns->ns;
2305         fs_init_namespace(ns);
2306         mutex_init(&root_ns->chain_lock);
2307         tree_init_node(&ns->node, NULL, NULL);
2308         tree_add_node(&ns->node, NULL);
2309
2310         return root_ns;
2311 }
2312
2313 static void set_prio_attrs_in_prio(struct fs_prio *prio, int acc_level);
2314
2315 static int set_prio_attrs_in_ns(struct mlx5_flow_namespace *ns, int acc_level)
2316 {
2317         struct fs_prio *prio;
2318
2319         fs_for_each_prio(prio, ns) {
2320                  /* This updates prio start_level and num_levels */
2321                 set_prio_attrs_in_prio(prio, acc_level);
2322                 acc_level += prio->num_levels;
2323         }
2324         return acc_level;
2325 }
2326
2327 static void set_prio_attrs_in_prio(struct fs_prio *prio, int acc_level)
2328 {
2329         struct mlx5_flow_namespace *ns;
2330         int acc_level_ns = acc_level;
2331
2332         prio->start_level = acc_level;
2333         fs_for_each_ns(ns, prio)
2334                 /* This updates start_level and num_levels of ns's priority descendants */
2335                 acc_level_ns = set_prio_attrs_in_ns(ns, acc_level);
2336         if (!prio->num_levels)
2337                 prio->num_levels = acc_level_ns - prio->start_level;
2338         WARN_ON(prio->num_levels < acc_level_ns - prio->start_level);
2339 }
2340
2341 static void set_prio_attrs(struct mlx5_flow_root_namespace *root_ns)
2342 {
2343         struct mlx5_flow_namespace *ns = &root_ns->ns;
2344         struct fs_prio *prio;
2345         int start_level = 0;
2346
2347         fs_for_each_prio(prio, ns) {
2348                 set_prio_attrs_in_prio(prio, start_level);
2349                 start_level += prio->num_levels;
2350         }
2351 }
2352
2353 #define ANCHOR_PRIO 0
2354 #define ANCHOR_SIZE 1
2355 #define ANCHOR_LEVEL 0
2356 static int create_anchor_flow_table(struct mlx5_flow_steering *steering)
2357 {
2358         struct mlx5_flow_namespace *ns = NULL;
2359         struct mlx5_flow_table_attr ft_attr = {};
2360         struct mlx5_flow_table *ft;
2361
2362         ns = mlx5_get_flow_namespace(steering->dev, MLX5_FLOW_NAMESPACE_ANCHOR);
2363         if (WARN_ON(!ns))
2364                 return -EINVAL;
2365
2366         ft_attr.max_fte = ANCHOR_SIZE;
2367         ft_attr.level   = ANCHOR_LEVEL;
2368         ft_attr.prio    = ANCHOR_PRIO;
2369
2370         ft = mlx5_create_flow_table(ns, &ft_attr);
2371         if (IS_ERR(ft)) {
2372                 mlx5_core_err(steering->dev, "Failed to create last anchor flow table");
2373                 return PTR_ERR(ft);
2374         }
2375         return 0;
2376 }
2377
2378 static int init_root_ns(struct mlx5_flow_steering *steering)
2379 {
2380         int err;
2381
2382         steering->root_ns = create_root_ns(steering, FS_FT_NIC_RX);
2383         if (!steering->root_ns)
2384                 return -ENOMEM;
2385
2386         err = init_root_tree(steering, &root_fs, &steering->root_ns->ns.node);
2387         if (err)
2388                 goto out_err;
2389
2390         set_prio_attrs(steering->root_ns);
2391         err = create_anchor_flow_table(steering);
2392         if (err)
2393                 goto out_err;
2394
2395         return 0;
2396
2397 out_err:
2398         cleanup_root_ns(steering->root_ns);
2399         steering->root_ns = NULL;
2400         return err;
2401 }
2402
2403 static void clean_tree(struct fs_node *node)
2404 {
2405         if (node) {
2406                 struct fs_node *iter;
2407                 struct fs_node *temp;
2408
2409                 tree_get_node(node);
2410                 list_for_each_entry_safe(iter, temp, &node->children, list)
2411                         clean_tree(iter);
2412                 tree_put_node(node);
2413                 tree_remove_node(node);
2414         }
2415 }
2416
2417 static void cleanup_root_ns(struct mlx5_flow_root_namespace *root_ns)
2418 {
2419         if (!root_ns)
2420                 return;
2421
2422         clean_tree(&root_ns->ns.node);
2423 }
2424
2425 static void cleanup_egress_acls_root_ns(struct mlx5_core_dev *dev)
2426 {
2427         struct mlx5_flow_steering *steering = dev->priv.steering;
2428         int i;
2429
2430         if (!steering->esw_egress_root_ns)
2431                 return;
2432
2433         for (i = 0; i < MLX5_TOTAL_VPORTS(dev); i++)
2434                 cleanup_root_ns(steering->esw_egress_root_ns[i]);
2435
2436         kfree(steering->esw_egress_root_ns);
2437 }
2438
2439 static void cleanup_ingress_acls_root_ns(struct mlx5_core_dev *dev)
2440 {
2441         struct mlx5_flow_steering *steering = dev->priv.steering;
2442         int i;
2443
2444         if (!steering->esw_ingress_root_ns)
2445                 return;
2446
2447         for (i = 0; i < MLX5_TOTAL_VPORTS(dev); i++)
2448                 cleanup_root_ns(steering->esw_ingress_root_ns[i]);
2449
2450         kfree(steering->esw_ingress_root_ns);
2451 }
2452
2453 void mlx5_cleanup_fs(struct mlx5_core_dev *dev)
2454 {
2455         struct mlx5_flow_steering *steering = dev->priv.steering;
2456
2457         cleanup_root_ns(steering->root_ns);
2458         cleanup_egress_acls_root_ns(dev);
2459         cleanup_ingress_acls_root_ns(dev);
2460         cleanup_root_ns(steering->fdb_root_ns);
2461         cleanup_root_ns(steering->sniffer_rx_root_ns);
2462         cleanup_root_ns(steering->sniffer_tx_root_ns);
2463         cleanup_root_ns(steering->egress_root_ns);
2464         mlx5_cleanup_fc_stats(dev);
2465         kmem_cache_destroy(steering->ftes_cache);
2466         kmem_cache_destroy(steering->fgs_cache);
2467         kfree(steering);
2468 }
2469
2470 static int init_sniffer_tx_root_ns(struct mlx5_flow_steering *steering)
2471 {
2472         struct fs_prio *prio;
2473
2474         steering->sniffer_tx_root_ns = create_root_ns(steering, FS_FT_SNIFFER_TX);
2475         if (!steering->sniffer_tx_root_ns)
2476                 return -ENOMEM;
2477
2478         /* Create single prio */
2479         prio = fs_create_prio(&steering->sniffer_tx_root_ns->ns, 0, 1);
2480         if (IS_ERR(prio)) {
2481                 cleanup_root_ns(steering->sniffer_tx_root_ns);
2482                 return PTR_ERR(prio);
2483         }
2484         return 0;
2485 }
2486
2487 static int init_sniffer_rx_root_ns(struct mlx5_flow_steering *steering)
2488 {
2489         struct fs_prio *prio;
2490
2491         steering->sniffer_rx_root_ns = create_root_ns(steering, FS_FT_SNIFFER_RX);
2492         if (!steering->sniffer_rx_root_ns)
2493                 return -ENOMEM;
2494
2495         /* Create single prio */
2496         prio = fs_create_prio(&steering->sniffer_rx_root_ns->ns, 0, 1);
2497         if (IS_ERR(prio)) {
2498                 cleanup_root_ns(steering->sniffer_rx_root_ns);
2499                 return PTR_ERR(prio);
2500         }
2501         return 0;
2502 }
2503
2504 static int init_fdb_root_ns(struct mlx5_flow_steering *steering)
2505 {
2506         struct fs_prio *prio;
2507
2508         steering->fdb_root_ns = create_root_ns(steering, FS_FT_FDB);
2509         if (!steering->fdb_root_ns)
2510                 return -ENOMEM;
2511
2512         prio = fs_create_prio(&steering->fdb_root_ns->ns, 0, 2);
2513         if (IS_ERR(prio))
2514                 goto out_err;
2515
2516         prio = fs_create_prio(&steering->fdb_root_ns->ns, 1, 1);
2517         if (IS_ERR(prio))
2518                 goto out_err;
2519
2520         set_prio_attrs(steering->fdb_root_ns);
2521         return 0;
2522
2523 out_err:
2524         cleanup_root_ns(steering->fdb_root_ns);
2525         steering->fdb_root_ns = NULL;
2526         return PTR_ERR(prio);
2527 }
2528
2529 static int init_egress_acl_root_ns(struct mlx5_flow_steering *steering, int vport)
2530 {
2531         struct fs_prio *prio;
2532
2533         steering->esw_egress_root_ns[vport] = create_root_ns(steering, FS_FT_ESW_EGRESS_ACL);
2534         if (!steering->esw_egress_root_ns[vport])
2535                 return -ENOMEM;
2536
2537         /* create 1 prio*/
2538         prio = fs_create_prio(&steering->esw_egress_root_ns[vport]->ns, 0, 1);
2539         return PTR_ERR_OR_ZERO(prio);
2540 }
2541
2542 static int init_ingress_acl_root_ns(struct mlx5_flow_steering *steering, int vport)
2543 {
2544         struct fs_prio *prio;
2545
2546         steering->esw_ingress_root_ns[vport] = create_root_ns(steering, FS_FT_ESW_INGRESS_ACL);
2547         if (!steering->esw_ingress_root_ns[vport])
2548                 return -ENOMEM;
2549
2550         /* create 1 prio*/
2551         prio = fs_create_prio(&steering->esw_ingress_root_ns[vport]->ns, 0, 1);
2552         return PTR_ERR_OR_ZERO(prio);
2553 }
2554
2555 static int init_egress_acls_root_ns(struct mlx5_core_dev *dev)
2556 {
2557         struct mlx5_flow_steering *steering = dev->priv.steering;
2558         int err;
2559         int i;
2560
2561         steering->esw_egress_root_ns = kcalloc(MLX5_TOTAL_VPORTS(dev),
2562                                                sizeof(*steering->esw_egress_root_ns),
2563                                                GFP_KERNEL);
2564         if (!steering->esw_egress_root_ns)
2565                 return -ENOMEM;
2566
2567         for (i = 0; i < MLX5_TOTAL_VPORTS(dev); i++) {
2568                 err = init_egress_acl_root_ns(steering, i);
2569                 if (err)
2570                         goto cleanup_root_ns;
2571         }
2572
2573         return 0;
2574
2575 cleanup_root_ns:
2576         for (i--; i >= 0; i--)
2577                 cleanup_root_ns(steering->esw_egress_root_ns[i]);
2578         kfree(steering->esw_egress_root_ns);
2579         return err;
2580 }
2581
2582 static int init_ingress_acls_root_ns(struct mlx5_core_dev *dev)
2583 {
2584         struct mlx5_flow_steering *steering = dev->priv.steering;
2585         int err;
2586         int i;
2587
2588         steering->esw_ingress_root_ns = kcalloc(MLX5_TOTAL_VPORTS(dev),
2589                                                 sizeof(*steering->esw_ingress_root_ns),
2590                                                 GFP_KERNEL);
2591         if (!steering->esw_ingress_root_ns)
2592                 return -ENOMEM;
2593
2594         for (i = 0; i < MLX5_TOTAL_VPORTS(dev); i++) {
2595                 err = init_ingress_acl_root_ns(steering, i);
2596                 if (err)
2597                         goto cleanup_root_ns;
2598         }
2599
2600         return 0;
2601
2602 cleanup_root_ns:
2603         for (i--; i >= 0; i--)
2604                 cleanup_root_ns(steering->esw_ingress_root_ns[i]);
2605         kfree(steering->esw_ingress_root_ns);
2606         return err;
2607 }
2608
2609 static int init_egress_root_ns(struct mlx5_flow_steering *steering)
2610 {
2611         struct fs_prio *prio;
2612
2613         steering->egress_root_ns = create_root_ns(steering,
2614                                                   FS_FT_NIC_TX);
2615         if (!steering->egress_root_ns)
2616                 return -ENOMEM;
2617
2618         /* create 1 prio*/
2619         prio = fs_create_prio(&steering->egress_root_ns->ns, 0, 1);
2620         return PTR_ERR_OR_ZERO(prio);
2621 }
2622
2623 int mlx5_init_fs(struct mlx5_core_dev *dev)
2624 {
2625         struct mlx5_flow_steering *steering;
2626         int err = 0;
2627
2628         err = mlx5_init_fc_stats(dev);
2629         if (err)
2630                 return err;
2631
2632         steering = kzalloc(sizeof(*steering), GFP_KERNEL);
2633         if (!steering)
2634                 return -ENOMEM;
2635         steering->dev = dev;
2636         dev->priv.steering = steering;
2637
2638         steering->fgs_cache = kmem_cache_create("mlx5_fs_fgs",
2639                                                 sizeof(struct mlx5_flow_group), 0,
2640                                                 0, NULL);
2641         steering->ftes_cache = kmem_cache_create("mlx5_fs_ftes", sizeof(struct fs_fte), 0,
2642                                                  0, NULL);
2643         if (!steering->ftes_cache || !steering->fgs_cache) {
2644                 err = -ENOMEM;
2645                 goto err;
2646         }
2647
2648         if ((((MLX5_CAP_GEN(dev, port_type) == MLX5_CAP_PORT_TYPE_ETH) &&
2649               (MLX5_CAP_GEN(dev, nic_flow_table))) ||
2650              ((MLX5_CAP_GEN(dev, port_type) == MLX5_CAP_PORT_TYPE_IB) &&
2651               MLX5_CAP_GEN(dev, ipoib_enhanced_offloads))) &&
2652             MLX5_CAP_FLOWTABLE_NIC_RX(dev, ft_support)) {
2653                 err = init_root_ns(steering);
2654                 if (err)
2655                         goto err;
2656         }
2657
2658         if (MLX5_ESWITCH_MANAGER(dev)) {
2659                 if (MLX5_CAP_ESW_FLOWTABLE_FDB(dev, ft_support)) {
2660                         err = init_fdb_root_ns(steering);
2661                         if (err)
2662                                 goto err;
2663                 }
2664                 if (MLX5_CAP_ESW_EGRESS_ACL(dev, ft_support)) {
2665                         err = init_egress_acls_root_ns(dev);
2666                         if (err)
2667                                 goto err;
2668                 }
2669                 if (MLX5_CAP_ESW_INGRESS_ACL(dev, ft_support)) {
2670                         err = init_ingress_acls_root_ns(dev);
2671                         if (err)
2672                                 goto err;
2673                 }
2674         }
2675
2676         if (MLX5_CAP_FLOWTABLE_SNIFFER_RX(dev, ft_support)) {
2677                 err = init_sniffer_rx_root_ns(steering);
2678                 if (err)
2679                         goto err;
2680         }
2681
2682         if (MLX5_CAP_FLOWTABLE_SNIFFER_TX(dev, ft_support)) {
2683                 err = init_sniffer_tx_root_ns(steering);
2684                 if (err)
2685                         goto err;
2686         }
2687
2688         if (MLX5_IPSEC_DEV(dev)) {
2689                 err = init_egress_root_ns(steering);
2690                 if (err)
2691                         goto err;
2692         }
2693
2694         return 0;
2695 err:
2696         mlx5_cleanup_fs(dev);
2697         return err;
2698 }
2699
2700 int mlx5_fs_add_rx_underlay_qpn(struct mlx5_core_dev *dev, u32 underlay_qpn)
2701 {
2702         struct mlx5_flow_root_namespace *root = dev->priv.steering->root_ns;
2703         struct mlx5_ft_underlay_qp *new_uqp;
2704         int err = 0;
2705
2706         new_uqp = kzalloc(sizeof(*new_uqp), GFP_KERNEL);
2707         if (!new_uqp)
2708                 return -ENOMEM;
2709
2710         mutex_lock(&root->chain_lock);
2711
2712         if (!root->root_ft) {
2713                 err = -EINVAL;
2714                 goto update_ft_fail;
2715         }
2716
2717         err = root->cmds->update_root_ft(dev, root->root_ft, underlay_qpn,
2718                                          false);
2719         if (err) {
2720                 mlx5_core_warn(dev, "Failed adding underlay QPN (%u) to root FT err(%d)\n",
2721                                underlay_qpn, err);
2722                 goto update_ft_fail;
2723         }
2724
2725         new_uqp->qpn = underlay_qpn;
2726         list_add_tail(&new_uqp->list, &root->underlay_qpns);
2727
2728         mutex_unlock(&root->chain_lock);
2729
2730         return 0;
2731
2732 update_ft_fail:
2733         mutex_unlock(&root->chain_lock);
2734         kfree(new_uqp);
2735         return err;
2736 }
2737 EXPORT_SYMBOL(mlx5_fs_add_rx_underlay_qpn);
2738
2739 int mlx5_fs_remove_rx_underlay_qpn(struct mlx5_core_dev *dev, u32 underlay_qpn)
2740 {
2741         struct mlx5_flow_root_namespace *root = dev->priv.steering->root_ns;
2742         struct mlx5_ft_underlay_qp *uqp;
2743         bool found = false;
2744         int err = 0;
2745
2746         mutex_lock(&root->chain_lock);
2747         list_for_each_entry(uqp, &root->underlay_qpns, list) {
2748                 if (uqp->qpn == underlay_qpn) {
2749                         found = true;
2750                         break;
2751                 }
2752         }
2753
2754         if (!found) {
2755                 mlx5_core_warn(dev, "Failed finding underlay qp (%u) in qpn list\n",
2756                                underlay_qpn);
2757                 err = -EINVAL;
2758                 goto out;
2759         }
2760
2761         err = root->cmds->update_root_ft(dev, root->root_ft, underlay_qpn,
2762                                          true);
2763         if (err)
2764                 mlx5_core_warn(dev, "Failed removing underlay QPN (%u) from root FT err(%d)\n",
2765                                underlay_qpn, err);
2766
2767         list_del(&uqp->list);
2768         mutex_unlock(&root->chain_lock);
2769         kfree(uqp);
2770
2771         return 0;
2772
2773 out:
2774         mutex_unlock(&root->chain_lock);
2775         return err;
2776 }
2777 EXPORT_SYMBOL(mlx5_fs_remove_rx_underlay_qpn);