GNU Linux-libre 4.14.266-gnu1
[releases.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
36 #include "mlx5_core.h"
37 #include "fs_core.h"
38 #include "fs_cmd.h"
39 #include "eswitch.h"
40 #include "diag/fs_tracepoint.h"
41
42 #define INIT_TREE_NODE_ARRAY_SIZE(...)  (sizeof((struct init_tree_node[]){__VA_ARGS__}) /\
43                                          sizeof(struct init_tree_node))
44
45 #define ADD_PRIO(num_prios_val, min_level_val, num_levels_val, caps_val,\
46                  ...) {.type = FS_TYPE_PRIO,\
47         .min_ft_level = min_level_val,\
48         .num_levels = num_levels_val,\
49         .num_leaf_prios = num_prios_val,\
50         .caps = caps_val,\
51         .children = (struct init_tree_node[]) {__VA_ARGS__},\
52         .ar_size = INIT_TREE_NODE_ARRAY_SIZE(__VA_ARGS__) \
53 }
54
55 #define ADD_MULTIPLE_PRIO(num_prios_val, num_levels_val, ...)\
56         ADD_PRIO(num_prios_val, 0, num_levels_val, {},\
57                  __VA_ARGS__)\
58
59 #define ADD_NS(...) {.type = FS_TYPE_NAMESPACE,\
60         .children = (struct init_tree_node[]) {__VA_ARGS__},\
61         .ar_size = INIT_TREE_NODE_ARRAY_SIZE(__VA_ARGS__) \
62 }
63
64 #define INIT_CAPS_ARRAY_SIZE(...) (sizeof((long[]){__VA_ARGS__}) /\
65                                    sizeof(long))
66
67 #define FS_CAP(cap) (__mlx5_bit_off(flow_table_nic_cap, cap))
68
69 #define FS_REQUIRED_CAPS(...) {.arr_sz = INIT_CAPS_ARRAY_SIZE(__VA_ARGS__), \
70                                .caps = (long[]) {__VA_ARGS__} }
71
72 #define FS_CHAINING_CAPS  FS_REQUIRED_CAPS(FS_CAP(flow_table_properties_nic_receive.flow_modify_en), \
73                                            FS_CAP(flow_table_properties_nic_receive.modify_root), \
74                                            FS_CAP(flow_table_properties_nic_receive.identified_miss_table_mode), \
75                                            FS_CAP(flow_table_properties_nic_receive.flow_table_modify))
76
77 #define LEFTOVERS_NUM_LEVELS 1
78 #define LEFTOVERS_NUM_PRIOS 1
79
80 #define BY_PASS_PRIO_NUM_LEVELS 1
81 #define BY_PASS_MIN_LEVEL (ETHTOOL_MIN_LEVEL + MLX5_BY_PASS_NUM_PRIOS +\
82                            LEFTOVERS_NUM_PRIOS)
83
84 #define ETHTOOL_PRIO_NUM_LEVELS 1
85 #define ETHTOOL_NUM_PRIOS 11
86 #define ETHTOOL_MIN_LEVEL (KERNEL_MIN_LEVEL + ETHTOOL_NUM_PRIOS)
87 /* Vlan, mac, ttc, inner ttc, aRFS */
88 #define KERNEL_NIC_PRIO_NUM_LEVELS 5
89 #define KERNEL_NIC_NUM_PRIOS 1
90 /* One more level for tc */
91 #define KERNEL_MIN_LEVEL (KERNEL_NIC_PRIO_NUM_LEVELS + 1)
92
93 #define ANCHOR_NUM_LEVELS 1
94 #define ANCHOR_NUM_PRIOS 1
95 #define ANCHOR_MIN_LEVEL (BY_PASS_MIN_LEVEL + 1)
96
97 #define OFFLOADS_MAX_FT 1
98 #define OFFLOADS_NUM_PRIOS 1
99 #define OFFLOADS_MIN_LEVEL (ANCHOR_MIN_LEVEL + 1)
100
101 #define LAG_PRIO_NUM_LEVELS 1
102 #define LAG_NUM_PRIOS 1
103 #define LAG_MIN_LEVEL (OFFLOADS_MIN_LEVEL + 1)
104
105 struct node_caps {
106         size_t  arr_sz;
107         long    *caps;
108 };
109
110 static struct init_tree_node {
111         enum fs_node_type       type;
112         struct init_tree_node *children;
113         int ar_size;
114         struct node_caps caps;
115         int min_ft_level;
116         int num_leaf_prios;
117         int prio;
118         int num_levels;
119 } root_fs = {
120         .type = FS_TYPE_NAMESPACE,
121         .ar_size = 7,
122         .children = (struct init_tree_node[]) {
123                 ADD_PRIO(0, BY_PASS_MIN_LEVEL, 0,
124                          FS_CHAINING_CAPS,
125                          ADD_NS(ADD_MULTIPLE_PRIO(MLX5_BY_PASS_NUM_PRIOS,
126                                                   BY_PASS_PRIO_NUM_LEVELS))),
127                 ADD_PRIO(0, LAG_MIN_LEVEL, 0,
128                          FS_CHAINING_CAPS,
129                          ADD_NS(ADD_MULTIPLE_PRIO(LAG_NUM_PRIOS,
130                                                   LAG_PRIO_NUM_LEVELS))),
131                 ADD_PRIO(0, OFFLOADS_MIN_LEVEL, 0, {},
132                          ADD_NS(ADD_MULTIPLE_PRIO(OFFLOADS_NUM_PRIOS, OFFLOADS_MAX_FT))),
133                 ADD_PRIO(0, ETHTOOL_MIN_LEVEL, 0,
134                          FS_CHAINING_CAPS,
135                          ADD_NS(ADD_MULTIPLE_PRIO(ETHTOOL_NUM_PRIOS,
136                                                   ETHTOOL_PRIO_NUM_LEVELS))),
137                 ADD_PRIO(0, KERNEL_MIN_LEVEL, 0, {},
138                          ADD_NS(ADD_MULTIPLE_PRIO(1, 1),
139                                 ADD_MULTIPLE_PRIO(KERNEL_NIC_NUM_PRIOS,
140                                                   KERNEL_NIC_PRIO_NUM_LEVELS))),
141                 ADD_PRIO(0, BY_PASS_MIN_LEVEL, 0,
142                          FS_CHAINING_CAPS,
143                          ADD_NS(ADD_MULTIPLE_PRIO(LEFTOVERS_NUM_PRIOS, LEFTOVERS_NUM_LEVELS))),
144                 ADD_PRIO(0, ANCHOR_MIN_LEVEL, 0, {},
145                          ADD_NS(ADD_MULTIPLE_PRIO(ANCHOR_NUM_PRIOS, ANCHOR_NUM_LEVELS))),
146         }
147 };
148
149 enum fs_i_mutex_lock_class {
150         FS_MUTEX_GRANDPARENT,
151         FS_MUTEX_PARENT,
152         FS_MUTEX_CHILD
153 };
154
155 static const struct rhashtable_params rhash_fte = {
156         .key_len = FIELD_SIZEOF(struct fs_fte, val),
157         .key_offset = offsetof(struct fs_fte, val),
158         .head_offset = offsetof(struct fs_fte, hash),
159         .automatic_shrinking = true,
160         .min_size = 1,
161 };
162
163 static const struct rhashtable_params rhash_fg = {
164         .key_len = FIELD_SIZEOF(struct mlx5_flow_group, mask),
165         .key_offset = offsetof(struct mlx5_flow_group, mask),
166         .head_offset = offsetof(struct mlx5_flow_group, hash),
167         .automatic_shrinking = true,
168         .min_size = 1,
169
170 };
171
172 static void del_rule(struct fs_node *node);
173 static void del_flow_table(struct fs_node *node);
174 static void del_flow_group(struct fs_node *node);
175 static void del_fte(struct fs_node *node);
176 static bool mlx5_flow_dests_cmp(struct mlx5_flow_destination *d1,
177                                 struct mlx5_flow_destination *d2);
178 static void cleanup_root_ns(struct mlx5_flow_root_namespace *root_ns);
179 static struct mlx5_flow_rule *
180 find_flow_rule(struct fs_fte *fte,
181                struct mlx5_flow_destination *dest);
182
183 static void tree_init_node(struct fs_node *node,
184                            unsigned int refcount,
185                            void (*remove_func)(struct fs_node *))
186 {
187         atomic_set(&node->refcount, refcount);
188         INIT_LIST_HEAD(&node->list);
189         INIT_LIST_HEAD(&node->children);
190         mutex_init(&node->lock);
191         node->remove_func = remove_func;
192 }
193
194 static void tree_add_node(struct fs_node *node, struct fs_node *parent)
195 {
196         if (parent)
197                 atomic_inc(&parent->refcount);
198         node->parent = parent;
199
200         /* Parent is the root */
201         if (!parent)
202                 node->root = node;
203         else
204                 node->root = parent->root;
205 }
206
207 static void tree_get_node(struct fs_node *node)
208 {
209         atomic_inc(&node->refcount);
210 }
211
212 static void nested_lock_ref_node(struct fs_node *node,
213                                  enum fs_i_mutex_lock_class class)
214 {
215         if (node) {
216                 mutex_lock_nested(&node->lock, class);
217                 atomic_inc(&node->refcount);
218         }
219 }
220
221 static void lock_ref_node(struct fs_node *node)
222 {
223         if (node) {
224                 mutex_lock(&node->lock);
225                 atomic_inc(&node->refcount);
226         }
227 }
228
229 static void unlock_ref_node(struct fs_node *node)
230 {
231         if (node) {
232                 atomic_dec(&node->refcount);
233                 mutex_unlock(&node->lock);
234         }
235 }
236
237 static void tree_put_node(struct fs_node *node)
238 {
239         struct fs_node *parent_node = node->parent;
240
241         lock_ref_node(parent_node);
242         if (atomic_dec_and_test(&node->refcount)) {
243                 if (parent_node)
244                         list_del_init(&node->list);
245                 if (node->remove_func)
246                         node->remove_func(node);
247                 kfree(node);
248                 node = NULL;
249         }
250         unlock_ref_node(parent_node);
251         if (!node && parent_node)
252                 tree_put_node(parent_node);
253 }
254
255 static int tree_remove_node(struct fs_node *node)
256 {
257         if (atomic_read(&node->refcount) > 1) {
258                 atomic_dec(&node->refcount);
259                 return -EEXIST;
260         }
261         tree_put_node(node);
262         return 0;
263 }
264
265 static struct fs_prio *find_prio(struct mlx5_flow_namespace *ns,
266                                  unsigned int prio)
267 {
268         struct fs_prio *iter_prio;
269
270         fs_for_each_prio(iter_prio, ns) {
271                 if (iter_prio->prio == prio)
272                         return iter_prio;
273         }
274
275         return NULL;
276 }
277
278 static bool check_last_reserved(const u32 *match_criteria)
279 {
280         char *match_criteria_reserved =
281                 MLX5_ADDR_OF(fte_match_param, match_criteria, MLX5_FTE_MATCH_PARAM_RESERVED);
282
283         return  !match_criteria_reserved[0] &&
284                 !memcmp(match_criteria_reserved, match_criteria_reserved + 1,
285                         MLX5_FLD_SZ_BYTES(fte_match_param,
286                                           MLX5_FTE_MATCH_PARAM_RESERVED) - 1);
287 }
288
289 static bool check_valid_mask(u8 match_criteria_enable, const u32 *match_criteria)
290 {
291         if (match_criteria_enable & ~(
292                 (1 << MLX5_CREATE_FLOW_GROUP_IN_MATCH_CRITERIA_ENABLE_OUTER_HEADERS)   |
293                 (1 << MLX5_CREATE_FLOW_GROUP_IN_MATCH_CRITERIA_ENABLE_MISC_PARAMETERS) |
294                 (1 << MLX5_CREATE_FLOW_GROUP_IN_MATCH_CRITERIA_ENABLE_INNER_HEADERS)))
295                 return false;
296
297         if (!(match_criteria_enable &
298               1 << MLX5_CREATE_FLOW_GROUP_IN_MATCH_CRITERIA_ENABLE_OUTER_HEADERS)) {
299                 char *fg_type_mask = MLX5_ADDR_OF(fte_match_param,
300                                                   match_criteria, outer_headers);
301
302                 if (fg_type_mask[0] ||
303                     memcmp(fg_type_mask, fg_type_mask + 1,
304                            MLX5_ST_SZ_BYTES(fte_match_set_lyr_2_4) - 1))
305                         return false;
306         }
307
308         if (!(match_criteria_enable &
309               1 << MLX5_CREATE_FLOW_GROUP_IN_MATCH_CRITERIA_ENABLE_MISC_PARAMETERS)) {
310                 char *fg_type_mask = MLX5_ADDR_OF(fte_match_param,
311                                                   match_criteria, misc_parameters);
312
313                 if (fg_type_mask[0] ||
314                     memcmp(fg_type_mask, fg_type_mask + 1,
315                            MLX5_ST_SZ_BYTES(fte_match_set_misc) - 1))
316                         return false;
317         }
318
319         if (!(match_criteria_enable &
320               1 << MLX5_CREATE_FLOW_GROUP_IN_MATCH_CRITERIA_ENABLE_INNER_HEADERS)) {
321                 char *fg_type_mask = MLX5_ADDR_OF(fte_match_param,
322                                                   match_criteria, inner_headers);
323
324                 if (fg_type_mask[0] ||
325                     memcmp(fg_type_mask, fg_type_mask + 1,
326                            MLX5_ST_SZ_BYTES(fte_match_set_lyr_2_4) - 1))
327                         return false;
328         }
329
330         return check_last_reserved(match_criteria);
331 }
332
333 static bool check_valid_spec(const struct mlx5_flow_spec *spec)
334 {
335         int i;
336
337         if (!check_valid_mask(spec->match_criteria_enable, spec->match_criteria)) {
338                 pr_warn("mlx5_core: Match criteria given mismatches match_criteria_enable\n");
339                 return false;
340         }
341
342         for (i = 0; i < MLX5_ST_SZ_DW_MATCH_PARAM; i++)
343                 if (spec->match_value[i] & ~spec->match_criteria[i]) {
344                         pr_warn("mlx5_core: match_value differs from match_criteria\n");
345                         return false;
346                 }
347
348         return check_last_reserved(spec->match_value);
349 }
350
351 static struct mlx5_flow_root_namespace *find_root(struct fs_node *node)
352 {
353         struct fs_node *root;
354         struct mlx5_flow_namespace *ns;
355
356         root = node->root;
357
358         if (WARN_ON(root->type != FS_TYPE_NAMESPACE)) {
359                 pr_warn("mlx5: flow steering node is not in tree or garbaged\n");
360                 return NULL;
361         }
362
363         ns = container_of(root, struct mlx5_flow_namespace, node);
364         return container_of(ns, struct mlx5_flow_root_namespace, ns);
365 }
366
367 static inline struct mlx5_core_dev *get_dev(struct fs_node *node)
368 {
369         struct mlx5_flow_root_namespace *root = find_root(node);
370
371         if (root)
372                 return root->dev;
373         return NULL;
374 }
375
376 static void del_flow_table(struct fs_node *node)
377 {
378         struct mlx5_flow_table *ft;
379         struct mlx5_core_dev *dev;
380         struct fs_prio *prio;
381         int err;
382
383         fs_get_obj(ft, node);
384         dev = get_dev(&ft->node);
385
386         err = mlx5_cmd_destroy_flow_table(dev, ft);
387         if (err)
388                 mlx5_core_warn(dev, "flow steering can't destroy ft\n");
389         ida_destroy(&ft->fte_allocator);
390         rhltable_destroy(&ft->fgs_hash);
391         fs_get_obj(prio, ft->node.parent);
392         prio->num_ft--;
393 }
394
395 static void del_rule(struct fs_node *node)
396 {
397         struct mlx5_flow_rule *rule;
398         struct mlx5_flow_table *ft;
399         struct mlx5_flow_group *fg;
400         struct fs_fte *fte;
401         int modify_mask;
402         struct mlx5_core_dev *dev = get_dev(node);
403         int err;
404         bool update_fte = false;
405
406         fs_get_obj(rule, node);
407         fs_get_obj(fte, rule->node.parent);
408         fs_get_obj(fg, fte->node.parent);
409         fs_get_obj(ft, fg->node.parent);
410         trace_mlx5_fs_del_rule(rule);
411         list_del(&rule->node.list);
412         if (rule->sw_action == MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO) {
413                 mutex_lock(&rule->dest_attr.ft->lock);
414                 list_del(&rule->next_ft);
415                 mutex_unlock(&rule->dest_attr.ft->lock);
416         }
417
418         if (rule->dest_attr.type == MLX5_FLOW_DESTINATION_TYPE_COUNTER  &&
419             --fte->dests_size) {
420                 modify_mask = BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_ACTION);
421                 fte->action &= ~MLX5_FLOW_CONTEXT_ACTION_COUNT;
422                 update_fte = true;
423                 goto out;
424         }
425
426         if ((fte->action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) &&
427             --fte->dests_size) {
428                 modify_mask = BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_DESTINATION_LIST);
429                 update_fte = true;
430         }
431 out:
432         if (update_fte && fte->dests_size) {
433                 err = mlx5_cmd_update_fte(dev, ft, fg->id, modify_mask, fte);
434                 if (err)
435                         mlx5_core_warn(dev,
436                                        "%s can't del rule fg id=%d fte_index=%d\n",
437                                        __func__, fg->id, fte->index);
438         }
439 }
440
441 static void destroy_fte(struct fs_fte *fte, struct mlx5_flow_group *fg)
442 {
443         struct mlx5_flow_table *ft;
444         int ret;
445
446         ret = rhashtable_remove_fast(&fg->ftes_hash, &fte->hash, rhash_fte);
447         WARN_ON(ret);
448         fte->status = 0;
449         fs_get_obj(ft, fg->node.parent);
450         ida_simple_remove(&ft->fte_allocator, fte->index);
451 }
452
453 static void del_fte(struct fs_node *node)
454 {
455         struct mlx5_flow_table *ft;
456         struct mlx5_flow_group *fg;
457         struct mlx5_core_dev *dev;
458         struct fs_fte *fte;
459         int err;
460
461         fs_get_obj(fte, node);
462         fs_get_obj(fg, fte->node.parent);
463         fs_get_obj(ft, fg->node.parent);
464         trace_mlx5_fs_del_fte(fte);
465
466         dev = get_dev(&ft->node);
467         err = mlx5_cmd_delete_fte(dev, ft,
468                                   fte->index);
469         if (err)
470                 mlx5_core_warn(dev,
471                                "flow steering can't delete fte in index %d of flow group id %d\n",
472                                fte->index, fg->id);
473
474         destroy_fte(fte, fg);
475 }
476
477 static void del_flow_group(struct fs_node *node)
478 {
479         struct mlx5_flow_group *fg;
480         struct mlx5_flow_table *ft;
481         struct mlx5_core_dev *dev;
482         int err;
483
484         fs_get_obj(fg, node);
485         fs_get_obj(ft, fg->node.parent);
486         dev = get_dev(&ft->node);
487         trace_mlx5_fs_del_fg(fg);
488
489         if (ft->autogroup.active)
490                 ft->autogroup.num_groups--;
491
492         rhashtable_destroy(&fg->ftes_hash);
493         err = rhltable_remove(&ft->fgs_hash,
494                               &fg->hash,
495                               rhash_fg);
496         WARN_ON(err);
497         if (mlx5_cmd_destroy_flow_group(dev, ft, fg->id))
498                 mlx5_core_warn(dev, "flow steering can't destroy fg %d of ft %d\n",
499                                fg->id, ft->id);
500 }
501
502 static struct fs_fte *alloc_fte(struct mlx5_flow_act *flow_act,
503                                 u32 *match_value,
504                                 unsigned int index)
505 {
506         struct fs_fte *fte;
507
508         fte = kzalloc(sizeof(*fte), GFP_KERNEL);
509         if (!fte)
510                 return ERR_PTR(-ENOMEM);
511
512         memcpy(fte->val, match_value, sizeof(fte->val));
513         fte->node.type =  FS_TYPE_FLOW_ENTRY;
514         fte->flow_tag = flow_act->flow_tag;
515         fte->index = index;
516         fte->action = flow_act->action;
517         fte->encap_id = flow_act->encap_id;
518         fte->modify_id = flow_act->modify_id;
519
520         return fte;
521 }
522
523 static struct mlx5_flow_group *alloc_flow_group(u32 *create_fg_in)
524 {
525         struct mlx5_flow_group *fg;
526         void *match_criteria = MLX5_ADDR_OF(create_flow_group_in,
527                                             create_fg_in, match_criteria);
528         u8 match_criteria_enable = MLX5_GET(create_flow_group_in,
529                                             create_fg_in,
530                                             match_criteria_enable);
531         int ret;
532
533         fg = kzalloc(sizeof(*fg), GFP_KERNEL);
534         if (!fg)
535                 return ERR_PTR(-ENOMEM);
536
537         ret = rhashtable_init(&fg->ftes_hash, &rhash_fte);
538         if (ret) {
539                 kfree(fg);
540                 return ERR_PTR(ret);
541         }
542         fg->mask.match_criteria_enable = match_criteria_enable;
543         memcpy(&fg->mask.match_criteria, match_criteria,
544                sizeof(fg->mask.match_criteria));
545         fg->node.type =  FS_TYPE_FLOW_GROUP;
546         fg->start_index = MLX5_GET(create_flow_group_in, create_fg_in,
547                                    start_flow_index);
548         fg->max_ftes = MLX5_GET(create_flow_group_in, create_fg_in,
549                                 end_flow_index) - fg->start_index + 1;
550         return fg;
551 }
552
553 static struct mlx5_flow_table *alloc_flow_table(int level, u16 vport, int max_fte,
554                                                 enum fs_flow_table_type table_type,
555                                                 enum fs_flow_table_op_mod op_mod,
556                                                 u32 flags)
557 {
558         struct mlx5_flow_table *ft;
559         int ret;
560
561         ft  = kzalloc(sizeof(*ft), GFP_KERNEL);
562         if (!ft)
563                 return ERR_PTR(-ENOMEM);
564
565         ret = rhltable_init(&ft->fgs_hash, &rhash_fg);
566         if (ret) {
567                 kfree(ft);
568                 return ERR_PTR(ret);
569         }
570
571         ft->level = level;
572         ft->node.type = FS_TYPE_FLOW_TABLE;
573         ft->op_mod = op_mod;
574         ft->type = table_type;
575         ft->vport = vport;
576         ft->max_fte = max_fte;
577         ft->flags = flags;
578         INIT_LIST_HEAD(&ft->fwd_rules);
579         mutex_init(&ft->lock);
580         ida_init(&ft->fte_allocator);
581
582         return ft;
583 }
584
585 /* If reverse is false, then we search for the first flow table in the
586  * root sub-tree from start(closest from right), else we search for the
587  * last flow table in the root sub-tree till start(closest from left).
588  */
589 static struct mlx5_flow_table *find_closest_ft_recursive(struct fs_node  *root,
590                                                          struct list_head *start,
591                                                          bool reverse)
592 {
593 #define list_advance_entry(pos, reverse)                \
594         ((reverse) ? list_prev_entry(pos, list) : list_next_entry(pos, list))
595
596 #define list_for_each_advance_continue(pos, head, reverse)      \
597         for (pos = list_advance_entry(pos, reverse);            \
598              &pos->list != (head);                              \
599              pos = list_advance_entry(pos, reverse))
600
601         struct fs_node *iter = list_entry(start, struct fs_node, list);
602         struct mlx5_flow_table *ft = NULL;
603
604         if (!root)
605                 return NULL;
606
607         list_for_each_advance_continue(iter, &root->children, reverse) {
608                 if (iter->type == FS_TYPE_FLOW_TABLE) {
609                         fs_get_obj(ft, iter);
610                         return ft;
611                 }
612                 ft = find_closest_ft_recursive(iter, &iter->children, reverse);
613                 if (ft)
614                         return ft;
615         }
616
617         return ft;
618 }
619
620 /* If reverse if false then return the first flow table in next priority of
621  * prio in the tree, else return the last flow table in the previous priority
622  * of prio in the tree.
623  */
624 static struct mlx5_flow_table *find_closest_ft(struct fs_prio *prio, bool reverse)
625 {
626         struct mlx5_flow_table *ft = NULL;
627         struct fs_node *curr_node;
628         struct fs_node *parent;
629
630         parent = prio->node.parent;
631         curr_node = &prio->node;
632         while (!ft && parent) {
633                 ft = find_closest_ft_recursive(parent, &curr_node->list, reverse);
634                 curr_node = parent;
635                 parent = curr_node->parent;
636         }
637         return ft;
638 }
639
640 /* Assuming all the tree is locked by mutex chain lock */
641 static struct mlx5_flow_table *find_next_chained_ft(struct fs_prio *prio)
642 {
643         return find_closest_ft(prio, false);
644 }
645
646 /* Assuming all the tree is locked by mutex chain lock */
647 static struct mlx5_flow_table *find_prev_chained_ft(struct fs_prio *prio)
648 {
649         return find_closest_ft(prio, true);
650 }
651
652 static int connect_fts_in_prio(struct mlx5_core_dev *dev,
653                                struct fs_prio *prio,
654                                struct mlx5_flow_table *ft)
655 {
656         struct mlx5_flow_table *iter;
657         int i = 0;
658         int err;
659
660         fs_for_each_ft(iter, prio) {
661                 i++;
662                 err = mlx5_cmd_modify_flow_table(dev,
663                                                  iter,
664                                                  ft);
665                 if (err) {
666                         mlx5_core_warn(dev, "Failed to modify flow table %d\n",
667                                        iter->id);
668                         /* The driver is out of sync with the FW */
669                         if (i > 1)
670                                 WARN_ON(true);
671                         return err;
672                 }
673         }
674         return 0;
675 }
676
677 /* Connect flow tables from previous priority of prio to ft */
678 static int connect_prev_fts(struct mlx5_core_dev *dev,
679                             struct mlx5_flow_table *ft,
680                             struct fs_prio *prio)
681 {
682         struct mlx5_flow_table *prev_ft;
683
684         prev_ft = find_prev_chained_ft(prio);
685         if (prev_ft) {
686                 struct fs_prio *prev_prio;
687
688                 fs_get_obj(prev_prio, prev_ft->node.parent);
689                 return connect_fts_in_prio(dev, prev_prio, ft);
690         }
691         return 0;
692 }
693
694 static int update_root_ft_create(struct mlx5_flow_table *ft, struct fs_prio
695                                  *prio)
696 {
697         struct mlx5_flow_root_namespace *root = find_root(&prio->node);
698         int min_level = INT_MAX;
699         int err;
700
701         if (root->root_ft)
702                 min_level = root->root_ft->level;
703
704         if (ft->level >= min_level)
705                 return 0;
706
707         err = mlx5_cmd_update_root_ft(root->dev, ft, root->underlay_qpn);
708         if (err)
709                 mlx5_core_warn(root->dev, "Update root flow table of id=%u failed\n",
710                                ft->id);
711         else
712                 root->root_ft = ft;
713
714         return err;
715 }
716
717 static int _mlx5_modify_rule_destination(struct mlx5_flow_rule *rule,
718                                          struct mlx5_flow_destination *dest)
719 {
720         struct mlx5_flow_table *ft;
721         struct mlx5_flow_group *fg;
722         struct fs_fte *fte;
723         int modify_mask = BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_DESTINATION_LIST);
724         int err = 0;
725
726         fs_get_obj(fte, rule->node.parent);
727         if (!(fte->action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST))
728                 return -EINVAL;
729         lock_ref_node(&fte->node);
730         fs_get_obj(fg, fte->node.parent);
731         fs_get_obj(ft, fg->node.parent);
732
733         memcpy(&rule->dest_attr, dest, sizeof(*dest));
734         err = mlx5_cmd_update_fte(get_dev(&ft->node),
735                                   ft, fg->id,
736                                   modify_mask,
737                                   fte);
738         unlock_ref_node(&fte->node);
739
740         return err;
741 }
742
743 int mlx5_modify_rule_destination(struct mlx5_flow_handle *handle,
744                                  struct mlx5_flow_destination *new_dest,
745                                  struct mlx5_flow_destination *old_dest)
746 {
747         int i;
748
749         if (!old_dest) {
750                 if (handle->num_rules != 1)
751                         return -EINVAL;
752                 return _mlx5_modify_rule_destination(handle->rule[0],
753                                                      new_dest);
754         }
755
756         for (i = 0; i < handle->num_rules; i++) {
757                 if (mlx5_flow_dests_cmp(new_dest, &handle->rule[i]->dest_attr))
758                         return _mlx5_modify_rule_destination(handle->rule[i],
759                                                              new_dest);
760         }
761
762         return -EINVAL;
763 }
764
765 /* Modify/set FWD rules that point on old_next_ft to point on new_next_ft  */
766 static int connect_fwd_rules(struct mlx5_core_dev *dev,
767                              struct mlx5_flow_table *new_next_ft,
768                              struct mlx5_flow_table *old_next_ft)
769 {
770         struct mlx5_flow_destination dest;
771         struct mlx5_flow_rule *iter;
772         int err = 0;
773
774         /* new_next_ft and old_next_ft could be NULL only
775          * when we create/destroy the anchor flow table.
776          */
777         if (!new_next_ft || !old_next_ft)
778                 return 0;
779
780         dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
781         dest.ft = new_next_ft;
782
783         mutex_lock(&old_next_ft->lock);
784         list_splice_init(&old_next_ft->fwd_rules, &new_next_ft->fwd_rules);
785         mutex_unlock(&old_next_ft->lock);
786         list_for_each_entry(iter, &new_next_ft->fwd_rules, next_ft) {
787                 err = _mlx5_modify_rule_destination(iter, &dest);
788                 if (err)
789                         pr_err("mlx5_core: failed to modify rule to point on flow table %d\n",
790                                new_next_ft->id);
791         }
792         return 0;
793 }
794
795 static int connect_flow_table(struct mlx5_core_dev *dev, struct mlx5_flow_table *ft,
796                               struct fs_prio *prio)
797 {
798         struct mlx5_flow_table *next_ft, *first_ft;
799         int err = 0;
800
801         /* Connect_prev_fts and update_root_ft_create are mutually exclusive */
802
803         first_ft = list_first_entry_or_null(&prio->node.children,
804                                             struct mlx5_flow_table, node.list);
805         if (!first_ft || first_ft->level > ft->level) {
806                 err = connect_prev_fts(dev, ft, prio);
807                 if (err)
808                         return err;
809
810                 next_ft = first_ft ? first_ft : find_next_chained_ft(prio);
811                 err = connect_fwd_rules(dev, ft, next_ft);
812                 if (err)
813                         return err;
814         }
815
816         if (MLX5_CAP_FLOWTABLE(dev,
817                                flow_table_properties_nic_receive.modify_root))
818                 err = update_root_ft_create(ft, prio);
819         return err;
820 }
821
822 static void list_add_flow_table(struct mlx5_flow_table *ft,
823                                 struct fs_prio *prio)
824 {
825         struct list_head *prev = &prio->node.children;
826         struct mlx5_flow_table *iter;
827
828         fs_for_each_ft(iter, prio) {
829                 if (iter->level > ft->level)
830                         break;
831                 prev = &iter->node.list;
832         }
833         list_add(&ft->node.list, prev);
834 }
835
836 static struct mlx5_flow_table *__mlx5_create_flow_table(struct mlx5_flow_namespace *ns,
837                                                         struct mlx5_flow_table_attr *ft_attr,
838                                                         enum fs_flow_table_op_mod op_mod,
839                                                         u16 vport)
840 {
841         struct mlx5_flow_root_namespace *root = find_root(&ns->node);
842         struct mlx5_flow_table *next_ft = NULL;
843         struct fs_prio *fs_prio = NULL;
844         struct mlx5_flow_table *ft;
845         int log_table_sz;
846         int err;
847
848         if (!root) {
849                 pr_err("mlx5: flow steering failed to find root of namespace\n");
850                 return ERR_PTR(-ENODEV);
851         }
852
853         mutex_lock(&root->chain_lock);
854         fs_prio = find_prio(ns, ft_attr->prio);
855         if (!fs_prio) {
856                 err = -EINVAL;
857                 goto unlock_root;
858         }
859         if (ft_attr->level >= fs_prio->num_levels) {
860                 err = -ENOSPC;
861                 goto unlock_root;
862         }
863         /* The level is related to the
864          * priority level range.
865          */
866         ft_attr->level += fs_prio->start_level;
867         ft = alloc_flow_table(ft_attr->level,
868                               vport,
869                               ft_attr->max_fte ? roundup_pow_of_two(ft_attr->max_fte) : 0,
870                               root->table_type,
871                               op_mod, ft_attr->flags);
872         if (IS_ERR(ft)) {
873                 err = PTR_ERR(ft);
874                 goto unlock_root;
875         }
876
877         tree_init_node(&ft->node, 1, del_flow_table);
878         log_table_sz = ft->max_fte ? ilog2(ft->max_fte) : 0;
879         next_ft = find_next_chained_ft(fs_prio);
880         err = mlx5_cmd_create_flow_table(root->dev, ft->vport, ft->op_mod, ft->type,
881                                          ft->level, log_table_sz, next_ft, &ft->id,
882                                          ft->flags);
883         if (err)
884                 goto free_ft;
885
886         err = connect_flow_table(root->dev, ft, fs_prio);
887         if (err)
888                 goto destroy_ft;
889         lock_ref_node(&fs_prio->node);
890         tree_add_node(&ft->node, &fs_prio->node);
891         list_add_flow_table(ft, fs_prio);
892         fs_prio->num_ft++;
893         unlock_ref_node(&fs_prio->node);
894         mutex_unlock(&root->chain_lock);
895         return ft;
896 destroy_ft:
897         mlx5_cmd_destroy_flow_table(root->dev, ft);
898 free_ft:
899         ida_destroy(&ft->fte_allocator);
900         kfree(ft);
901 unlock_root:
902         mutex_unlock(&root->chain_lock);
903         return ERR_PTR(err);
904 }
905
906 struct mlx5_flow_table *mlx5_create_flow_table(struct mlx5_flow_namespace *ns,
907                                                struct mlx5_flow_table_attr *ft_attr)
908 {
909         return __mlx5_create_flow_table(ns, ft_attr, FS_FT_OP_MOD_NORMAL, 0);
910 }
911
912 struct mlx5_flow_table *mlx5_create_vport_flow_table(struct mlx5_flow_namespace *ns,
913                                                      int prio, int max_fte,
914                                                      u32 level, u16 vport)
915 {
916         struct mlx5_flow_table_attr ft_attr = {};
917
918         ft_attr.max_fte = max_fte;
919         ft_attr.level   = level;
920         ft_attr.prio    = prio;
921
922         return __mlx5_create_flow_table(ns, &ft_attr, FS_FT_OP_MOD_NORMAL, vport);
923 }
924
925 struct mlx5_flow_table*
926 mlx5_create_lag_demux_flow_table(struct mlx5_flow_namespace *ns,
927                                  int prio, u32 level)
928 {
929         struct mlx5_flow_table_attr ft_attr = {};
930
931         ft_attr.level = level;
932         ft_attr.prio  = prio;
933         return __mlx5_create_flow_table(ns, &ft_attr, FS_FT_OP_MOD_LAG_DEMUX, 0);
934 }
935 EXPORT_SYMBOL(mlx5_create_lag_demux_flow_table);
936
937 struct mlx5_flow_table*
938 mlx5_create_auto_grouped_flow_table(struct mlx5_flow_namespace *ns,
939                                     int prio,
940                                     int num_flow_table_entries,
941                                     int max_num_groups,
942                                     u32 level,
943                                     u32 flags)
944 {
945         struct mlx5_flow_table_attr ft_attr = {};
946         struct mlx5_flow_table *ft;
947
948         if (max_num_groups > num_flow_table_entries)
949                 return ERR_PTR(-EINVAL);
950
951         ft_attr.max_fte = num_flow_table_entries;
952         ft_attr.prio    = prio;
953         ft_attr.level   = level;
954         ft_attr.flags   = flags;
955
956         ft = mlx5_create_flow_table(ns, &ft_attr);
957         if (IS_ERR(ft))
958                 return ft;
959
960         ft->autogroup.active = true;
961         ft->autogroup.required_groups = max_num_groups;
962
963         return ft;
964 }
965 EXPORT_SYMBOL(mlx5_create_auto_grouped_flow_table);
966
967 /* Flow table should be locked */
968 static struct mlx5_flow_group *create_flow_group_common(struct mlx5_flow_table *ft,
969                                                         u32 *fg_in,
970                                                         struct list_head
971                                                         *prev_fg,
972                                                         bool is_auto_fg)
973 {
974         struct mlx5_flow_group *fg;
975         struct mlx5_core_dev *dev = get_dev(&ft->node);
976         int err;
977
978         if (!dev)
979                 return ERR_PTR(-ENODEV);
980
981         fg = alloc_flow_group(fg_in);
982         if (IS_ERR(fg))
983                 return fg;
984
985         err = rhltable_insert(&ft->fgs_hash, &fg->hash, rhash_fg);
986         if (err)
987                 goto err_free_fg;
988
989         err = mlx5_cmd_create_flow_group(dev, ft, fg_in, &fg->id);
990         if (err)
991                 goto err_remove_fg;
992
993         if (ft->autogroup.active)
994                 ft->autogroup.num_groups++;
995         /* Add node to tree */
996         tree_init_node(&fg->node, !is_auto_fg, del_flow_group);
997         tree_add_node(&fg->node, &ft->node);
998         /* Add node to group list */
999         list_add(&fg->node.list, prev_fg);
1000
1001         trace_mlx5_fs_add_fg(fg);
1002         return fg;
1003
1004 err_remove_fg:
1005         WARN_ON(rhltable_remove(&ft->fgs_hash,
1006                                 &fg->hash,
1007                                 rhash_fg));
1008 err_free_fg:
1009         rhashtable_destroy(&fg->ftes_hash);
1010         kfree(fg);
1011
1012         return ERR_PTR(err);
1013 }
1014
1015 struct mlx5_flow_group *mlx5_create_flow_group(struct mlx5_flow_table *ft,
1016                                                u32 *fg_in)
1017 {
1018         void *match_criteria = MLX5_ADDR_OF(create_flow_group_in,
1019                                             fg_in, match_criteria);
1020         u8 match_criteria_enable = MLX5_GET(create_flow_group_in,
1021                                             fg_in,
1022                                             match_criteria_enable);
1023         struct mlx5_flow_group *fg;
1024
1025         if (!check_valid_mask(match_criteria_enable, match_criteria))
1026                 return ERR_PTR(-EINVAL);
1027
1028         if (ft->autogroup.active)
1029                 return ERR_PTR(-EPERM);
1030
1031         lock_ref_node(&ft->node);
1032         fg = create_flow_group_common(ft, fg_in, ft->node.children.prev, false);
1033         unlock_ref_node(&ft->node);
1034
1035         return fg;
1036 }
1037
1038 static struct mlx5_flow_rule *alloc_rule(struct mlx5_flow_destination *dest)
1039 {
1040         struct mlx5_flow_rule *rule;
1041
1042         rule = kzalloc(sizeof(*rule), GFP_KERNEL);
1043         if (!rule)
1044                 return NULL;
1045
1046         INIT_LIST_HEAD(&rule->next_ft);
1047         rule->node.type = FS_TYPE_FLOW_DEST;
1048         if (dest)
1049                 memcpy(&rule->dest_attr, dest, sizeof(*dest));
1050
1051         return rule;
1052 }
1053
1054 static struct mlx5_flow_handle *alloc_handle(int num_rules)
1055 {
1056         struct mlx5_flow_handle *handle;
1057
1058         handle = kzalloc(sizeof(*handle) + sizeof(handle->rule[0]) *
1059                           num_rules, GFP_KERNEL);
1060         if (!handle)
1061                 return NULL;
1062
1063         handle->num_rules = num_rules;
1064
1065         return handle;
1066 }
1067
1068 static void destroy_flow_handle(struct fs_fte *fte,
1069                                 struct mlx5_flow_handle *handle,
1070                                 struct mlx5_flow_destination *dest,
1071                                 int i)
1072 {
1073         for (; --i >= 0;) {
1074                 if (atomic_dec_and_test(&handle->rule[i]->node.refcount)) {
1075                         fte->dests_size--;
1076                         list_del(&handle->rule[i]->node.list);
1077                         kfree(handle->rule[i]);
1078                 }
1079         }
1080         kfree(handle);
1081 }
1082
1083 static struct mlx5_flow_handle *
1084 create_flow_handle(struct fs_fte *fte,
1085                    struct mlx5_flow_destination *dest,
1086                    int dest_num,
1087                    int *modify_mask,
1088                    bool *new_rule)
1089 {
1090         struct mlx5_flow_handle *handle;
1091         struct mlx5_flow_rule *rule = NULL;
1092         static int count = BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_FLOW_COUNTERS);
1093         static int dst = BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_DESTINATION_LIST);
1094         int type;
1095         int i = 0;
1096
1097         handle = alloc_handle((dest_num) ? dest_num : 1);
1098         if (!handle)
1099                 return ERR_PTR(-ENOMEM);
1100
1101         do {
1102                 if (dest) {
1103                         rule = find_flow_rule(fte, dest + i);
1104                         if (rule) {
1105                                 atomic_inc(&rule->node.refcount);
1106                                 goto rule_found;
1107                         }
1108                 }
1109
1110                 *new_rule = true;
1111                 rule = alloc_rule(dest + i);
1112                 if (!rule)
1113                         goto free_rules;
1114
1115                 /* Add dest to dests list- we need flow tables to be in the
1116                  * end of the list for forward to next prio rules.
1117                  */
1118                 tree_init_node(&rule->node, 1, del_rule);
1119                 if (dest &&
1120                     dest[i].type != MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE)
1121                         list_add(&rule->node.list, &fte->node.children);
1122                 else
1123                         list_add_tail(&rule->node.list, &fte->node.children);
1124                 if (dest) {
1125                         fte->dests_size++;
1126
1127                         type = dest[i].type ==
1128                                 MLX5_FLOW_DESTINATION_TYPE_COUNTER;
1129                         *modify_mask |= type ? count : dst;
1130                 }
1131 rule_found:
1132                 handle->rule[i] = rule;
1133         } while (++i < dest_num);
1134
1135         return handle;
1136
1137 free_rules:
1138         destroy_flow_handle(fte, handle, dest, i);
1139         return ERR_PTR(-ENOMEM);
1140 }
1141
1142 /* fte should not be deleted while calling this function */
1143 static struct mlx5_flow_handle *
1144 add_rule_fte(struct fs_fte *fte,
1145              struct mlx5_flow_group *fg,
1146              struct mlx5_flow_destination *dest,
1147              int dest_num,
1148              bool update_action)
1149 {
1150         struct mlx5_flow_handle *handle;
1151         struct mlx5_flow_table *ft;
1152         int modify_mask = 0;
1153         int err;
1154         bool new_rule = false;
1155
1156         handle = create_flow_handle(fte, dest, dest_num, &modify_mask,
1157                                     &new_rule);
1158         if (IS_ERR(handle) || !new_rule)
1159                 goto out;
1160
1161         if (update_action)
1162                 modify_mask |= BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_ACTION);
1163
1164         fs_get_obj(ft, fg->node.parent);
1165         if (!(fte->status & FS_FTE_STATUS_EXISTING))
1166                 err = mlx5_cmd_create_fte(get_dev(&ft->node),
1167                                           ft, fg->id, fte);
1168         else
1169                 err = mlx5_cmd_update_fte(get_dev(&ft->node),
1170                                           ft, fg->id, modify_mask, fte);
1171         if (err)
1172                 goto free_handle;
1173
1174         fte->status |= FS_FTE_STATUS_EXISTING;
1175
1176 out:
1177         return handle;
1178
1179 free_handle:
1180         destroy_flow_handle(fte, handle, dest, handle->num_rules);
1181         return ERR_PTR(err);
1182 }
1183
1184 static struct fs_fte *create_fte(struct mlx5_flow_group *fg,
1185                                  u32 *match_value,
1186                                  struct mlx5_flow_act *flow_act)
1187 {
1188         struct mlx5_flow_table *ft;
1189         struct fs_fte *fte;
1190         int index;
1191         int ret;
1192
1193         fs_get_obj(ft, fg->node.parent);
1194         index = ida_simple_get(&ft->fte_allocator, fg->start_index,
1195                                fg->start_index + fg->max_ftes,
1196                                GFP_KERNEL);
1197         if (index < 0)
1198                 return ERR_PTR(index);
1199
1200         fte = alloc_fte(flow_act, match_value, index);
1201         if (IS_ERR(fte)) {
1202                 ret = PTR_ERR(fte);
1203                 goto err_alloc;
1204         }
1205         ret = rhashtable_insert_fast(&fg->ftes_hash, &fte->hash, rhash_fte);
1206         if (ret)
1207                 goto err_hash;
1208
1209         return fte;
1210
1211 err_hash:
1212         kfree(fte);
1213 err_alloc:
1214         ida_simple_remove(&ft->fte_allocator, index);
1215         return ERR_PTR(ret);
1216 }
1217
1218 static struct mlx5_flow_group *create_autogroup(struct mlx5_flow_table *ft,
1219                                                 u8 match_criteria_enable,
1220                                                 u32 *match_criteria)
1221 {
1222         int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
1223         struct list_head *prev = &ft->node.children;
1224         unsigned int candidate_index = 0;
1225         struct mlx5_flow_group *fg;
1226         void *match_criteria_addr;
1227         unsigned int group_size = 0;
1228         u32 *in;
1229
1230         if (!ft->autogroup.active)
1231                 return ERR_PTR(-ENOENT);
1232
1233         in = kvzalloc(inlen, GFP_KERNEL);
1234         if (!in)
1235                 return ERR_PTR(-ENOMEM);
1236
1237         if (ft->autogroup.num_groups < ft->autogroup.required_groups)
1238                 /* We save place for flow groups in addition to max types */
1239                 group_size = ft->max_fte / (ft->autogroup.required_groups + 1);
1240
1241         /*  ft->max_fte == ft->autogroup.max_types */
1242         if (group_size == 0)
1243                 group_size = 1;
1244
1245         /* sorted by start_index */
1246         fs_for_each_fg(fg, ft) {
1247                 if (candidate_index + group_size > fg->start_index)
1248                         candidate_index = fg->start_index + fg->max_ftes;
1249                 else
1250                         break;
1251                 prev = &fg->node.list;
1252         }
1253
1254         if (candidate_index + group_size > ft->max_fte) {
1255                 fg = ERR_PTR(-ENOSPC);
1256                 goto out;
1257         }
1258
1259         MLX5_SET(create_flow_group_in, in, match_criteria_enable,
1260                  match_criteria_enable);
1261         MLX5_SET(create_flow_group_in, in, start_flow_index, candidate_index);
1262         MLX5_SET(create_flow_group_in, in, end_flow_index,   candidate_index +
1263                  group_size - 1);
1264         match_criteria_addr = MLX5_ADDR_OF(create_flow_group_in,
1265                                            in, match_criteria);
1266         memcpy(match_criteria_addr, match_criteria,
1267                MLX5_ST_SZ_BYTES(fte_match_param));
1268
1269         fg = create_flow_group_common(ft, in, prev, true);
1270 out:
1271         kvfree(in);
1272         return fg;
1273 }
1274
1275 static bool mlx5_flow_dests_cmp(struct mlx5_flow_destination *d1,
1276                                 struct mlx5_flow_destination *d2)
1277 {
1278         if (d1->type == d2->type) {
1279                 if ((d1->type == MLX5_FLOW_DESTINATION_TYPE_VPORT &&
1280                      d1->vport_num == d2->vport_num) ||
1281                     (d1->type == MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE &&
1282                      d1->ft == d2->ft) ||
1283                     (d1->type == MLX5_FLOW_DESTINATION_TYPE_TIR &&
1284                      d1->tir_num == d2->tir_num))
1285                         return true;
1286         }
1287
1288         return false;
1289 }
1290
1291 static struct mlx5_flow_rule *find_flow_rule(struct fs_fte *fte,
1292                                              struct mlx5_flow_destination *dest)
1293 {
1294         struct mlx5_flow_rule *rule;
1295
1296         list_for_each_entry(rule, &fte->node.children, node.list) {
1297                 if (mlx5_flow_dests_cmp(&rule->dest_attr, dest))
1298                         return rule;
1299         }
1300         return NULL;
1301 }
1302
1303 static bool check_conflicting_actions(u32 action1, u32 action2)
1304 {
1305         u32 xored_actions = action1 ^ action2;
1306
1307         /* if one rule only wants to count, it's ok */
1308         if (action1 == MLX5_FLOW_CONTEXT_ACTION_COUNT ||
1309             action2 == MLX5_FLOW_CONTEXT_ACTION_COUNT)
1310                 return false;
1311
1312         if (xored_actions & (MLX5_FLOW_CONTEXT_ACTION_DROP  |
1313                              MLX5_FLOW_CONTEXT_ACTION_ENCAP |
1314                              MLX5_FLOW_CONTEXT_ACTION_DECAP))
1315                 return true;
1316
1317         return false;
1318 }
1319
1320 static int check_conflicting_ftes(struct fs_fte *fte, const struct mlx5_flow_act *flow_act)
1321 {
1322         if (check_conflicting_actions(flow_act->action, fte->action)) {
1323                 mlx5_core_warn(get_dev(&fte->node),
1324                                "Found two FTEs with conflicting actions\n");
1325                 return -EEXIST;
1326         }
1327
1328         if (fte->flow_tag != flow_act->flow_tag) {
1329                 mlx5_core_warn(get_dev(&fte->node),
1330                                "FTE flow tag %u already exists with different flow tag %u\n",
1331                                fte->flow_tag,
1332                                flow_act->flow_tag);
1333                 return -EEXIST;
1334         }
1335
1336         return 0;
1337 }
1338
1339 static struct mlx5_flow_handle *add_rule_fg(struct mlx5_flow_group *fg,
1340                                             u32 *match_value,
1341                                             struct mlx5_flow_act *flow_act,
1342                                             struct mlx5_flow_destination *dest,
1343                                             int dest_num,
1344                                             struct fs_fte *fte)
1345 {
1346         struct mlx5_flow_handle *handle;
1347         struct mlx5_flow_table *ft;
1348         int i;
1349
1350         if (fte) {
1351                 int old_action;
1352                 int ret;
1353
1354                 nested_lock_ref_node(&fte->node, FS_MUTEX_CHILD);
1355                 ret = check_conflicting_ftes(fte, flow_act);
1356                 if (ret) {
1357                         handle = ERR_PTR(ret);
1358                         goto unlock_fte;
1359                 }
1360
1361                 old_action = fte->action;
1362                 fte->action |= flow_act->action;
1363                 handle = add_rule_fte(fte, fg, dest, dest_num,
1364                                       old_action != flow_act->action);
1365                 if (IS_ERR(handle)) {
1366                         fte->action = old_action;
1367                         goto unlock_fte;
1368                 } else {
1369                         trace_mlx5_fs_set_fte(fte, false);
1370                         goto add_rules;
1371                 }
1372         }
1373         fs_get_obj(ft, fg->node.parent);
1374
1375         fte = create_fte(fg, match_value, flow_act);
1376         if (IS_ERR(fte))
1377                 return (void *)fte;
1378         tree_init_node(&fte->node, 0, del_fte);
1379         nested_lock_ref_node(&fte->node, FS_MUTEX_CHILD);
1380         handle = add_rule_fte(fte, fg, dest, dest_num, false);
1381         if (IS_ERR(handle)) {
1382                 unlock_ref_node(&fte->node);
1383                 destroy_fte(fte, fg);
1384                 kfree(fte);
1385                 return handle;
1386         }
1387
1388         tree_add_node(&fte->node, &fg->node);
1389         /* fte list isn't sorted */
1390         list_add_tail(&fte->node.list, &fg->node.children);
1391         trace_mlx5_fs_set_fte(fte, true);
1392 add_rules:
1393         for (i = 0; i < handle->num_rules; i++) {
1394                 if (atomic_read(&handle->rule[i]->node.refcount) == 1) {
1395                         tree_add_node(&handle->rule[i]->node, &fte->node);
1396                         trace_mlx5_fs_add_rule(handle->rule[i]);
1397                 }
1398         }
1399 unlock_fte:
1400         unlock_ref_node(&fte->node);
1401         return handle;
1402 }
1403
1404 struct mlx5_fc *mlx5_flow_rule_counter(struct mlx5_flow_handle *handle)
1405 {
1406         struct mlx5_flow_rule *dst;
1407         struct fs_fte *fte;
1408
1409         fs_get_obj(fte, handle->rule[0]->node.parent);
1410
1411         fs_for_each_dst(dst, fte) {
1412                 if (dst->dest_attr.type == MLX5_FLOW_DESTINATION_TYPE_COUNTER)
1413                         return dst->dest_attr.counter;
1414         }
1415
1416         return NULL;
1417 }
1418
1419 static bool counter_is_valid(struct mlx5_fc *counter, u32 action)
1420 {
1421         if (!(action & MLX5_FLOW_CONTEXT_ACTION_COUNT))
1422                 return !counter;
1423
1424         if (!counter)
1425                 return false;
1426
1427         return (action & (MLX5_FLOW_CONTEXT_ACTION_DROP |
1428                           MLX5_FLOW_CONTEXT_ACTION_FWD_DEST));
1429 }
1430
1431 static bool dest_is_valid(struct mlx5_flow_destination *dest,
1432                           u32 action,
1433                           struct mlx5_flow_table *ft)
1434 {
1435         if (dest && (dest->type == MLX5_FLOW_DESTINATION_TYPE_COUNTER))
1436                 return counter_is_valid(dest->counter, action);
1437
1438         if (!(action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST))
1439                 return true;
1440
1441         if (!dest || ((dest->type ==
1442             MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE) &&
1443             (dest->ft->level <= ft->level)))
1444                 return false;
1445         return true;
1446 }
1447
1448 static struct mlx5_flow_handle *
1449 try_add_to_existing_fg(struct mlx5_flow_table *ft,
1450                        struct mlx5_flow_spec *spec,
1451                        struct mlx5_flow_act *flow_act,
1452                        struct mlx5_flow_destination *dest,
1453                        int dest_num)
1454 {
1455         struct mlx5_flow_group *g;
1456         struct mlx5_flow_handle *rule = ERR_PTR(-ENOENT);
1457         struct rhlist_head *tmp, *list;
1458         struct match_list {
1459                 struct list_head        list;
1460                 struct mlx5_flow_group *g;
1461         } match_list, *iter;
1462         LIST_HEAD(match_head);
1463
1464         rcu_read_lock();
1465         /* Collect all fgs which has a matching match_criteria */
1466         list = rhltable_lookup(&ft->fgs_hash, spec, rhash_fg);
1467         rhl_for_each_entry_rcu(g, tmp, list, hash) {
1468                 struct match_list *curr_match;
1469
1470                 if (likely(list_empty(&match_head))) {
1471                         match_list.g = g;
1472                         list_add_tail(&match_list.list, &match_head);
1473                         continue;
1474                 }
1475                 curr_match = kmalloc(sizeof(*curr_match), GFP_ATOMIC);
1476
1477                 if (!curr_match) {
1478                         rcu_read_unlock();
1479                         rule = ERR_PTR(-ENOMEM);
1480                         goto free_list;
1481                 }
1482                 curr_match->g = g;
1483                 list_add_tail(&curr_match->list, &match_head);
1484         }
1485         rcu_read_unlock();
1486
1487         /* Try to find a fg that already contains a matching fte */
1488         list_for_each_entry(iter, &match_head, list) {
1489                 struct fs_fte *fte;
1490
1491                 g = iter->g;
1492                 nested_lock_ref_node(&g->node, FS_MUTEX_PARENT);
1493                 fte = rhashtable_lookup_fast(&g->ftes_hash, spec->match_value,
1494                                              rhash_fte);
1495                 if (fte) {
1496                         rule = add_rule_fg(g, spec->match_value,
1497                                            flow_act, dest, dest_num, fte);
1498                         unlock_ref_node(&g->node);
1499                         goto free_list;
1500                 }
1501                 unlock_ref_node(&g->node);
1502         }
1503
1504         /* No group with matching fte found. Try to add a new fte to any
1505          * matching fg.
1506          */
1507         list_for_each_entry(iter, &match_head, list) {
1508                 g = iter->g;
1509
1510                 nested_lock_ref_node(&g->node, FS_MUTEX_PARENT);
1511                 rule = add_rule_fg(g, spec->match_value,
1512                                    flow_act, dest, dest_num, NULL);
1513                 if (!IS_ERR(rule) || PTR_ERR(rule) != -ENOSPC) {
1514                         unlock_ref_node(&g->node);
1515                         goto free_list;
1516                 }
1517                 unlock_ref_node(&g->node);
1518         }
1519
1520 free_list:
1521         if (!list_empty(&match_head)) {
1522                 struct match_list *match_tmp;
1523
1524                 /* The most common case is having one FG. Since we want to
1525                  * optimize this case, we save the first on the stack.
1526                  * Therefore, no need to free it.
1527                  */
1528                 list_del(&list_first_entry(&match_head, typeof(*iter), list)->list);
1529                 list_for_each_entry_safe(iter, match_tmp, &match_head, list) {
1530                         list_del(&iter->list);
1531                         kfree(iter);
1532                 }
1533         }
1534
1535         return rule;
1536 }
1537
1538 static struct mlx5_flow_handle *
1539 _mlx5_add_flow_rules(struct mlx5_flow_table *ft,
1540                      struct mlx5_flow_spec *spec,
1541                      struct mlx5_flow_act *flow_act,
1542                      struct mlx5_flow_destination *dest,
1543                      int dest_num)
1544
1545 {
1546         struct mlx5_flow_group *g;
1547         struct mlx5_flow_handle *rule;
1548         int i;
1549
1550         if (!check_valid_spec(spec))
1551                 return ERR_PTR(-EINVAL);
1552
1553         for (i = 0; i < dest_num; i++) {
1554                 if (!dest_is_valid(&dest[i], flow_act->action, ft))
1555                         return ERR_PTR(-EINVAL);
1556         }
1557
1558         nested_lock_ref_node(&ft->node, FS_MUTEX_GRANDPARENT);
1559         rule = try_add_to_existing_fg(ft, spec, flow_act, dest, dest_num);
1560         if (!IS_ERR(rule))
1561                 goto unlock;
1562
1563         g = create_autogroup(ft, spec->match_criteria_enable,
1564                              spec->match_criteria);
1565         if (IS_ERR(g)) {
1566                 rule = (void *)g;
1567                 goto unlock;
1568         }
1569
1570         rule = add_rule_fg(g, spec->match_value, flow_act, dest,
1571                            dest_num, NULL);
1572         if (IS_ERR(rule)) {
1573                 /* Remove assumes refcount > 0 and autogroup creates a group
1574                  * with a refcount = 0.
1575                  */
1576                 unlock_ref_node(&ft->node);
1577                 tree_get_node(&g->node);
1578                 tree_remove_node(&g->node);
1579                 return rule;
1580         }
1581 unlock:
1582         unlock_ref_node(&ft->node);
1583         return rule;
1584 }
1585
1586 static bool fwd_next_prio_supported(struct mlx5_flow_table *ft)
1587 {
1588         return ((ft->type == FS_FT_NIC_RX) &&
1589                 (MLX5_CAP_FLOWTABLE(get_dev(&ft->node), nic_rx_multi_path_tirs)));
1590 }
1591
1592 struct mlx5_flow_handle *
1593 mlx5_add_flow_rules(struct mlx5_flow_table *ft,
1594                     struct mlx5_flow_spec *spec,
1595                     struct mlx5_flow_act *flow_act,
1596                     struct mlx5_flow_destination *dest,
1597                     int dest_num)
1598 {
1599         struct mlx5_flow_root_namespace *root = find_root(&ft->node);
1600         struct mlx5_flow_destination gen_dest;
1601         struct mlx5_flow_table *next_ft = NULL;
1602         struct mlx5_flow_handle *handle = NULL;
1603         u32 sw_action = flow_act->action;
1604         struct fs_prio *prio;
1605
1606         fs_get_obj(prio, ft->node.parent);
1607         if (flow_act->action == MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO) {
1608                 if (!fwd_next_prio_supported(ft))
1609                         return ERR_PTR(-EOPNOTSUPP);
1610                 if (dest)
1611                         return ERR_PTR(-EINVAL);
1612                 mutex_lock(&root->chain_lock);
1613                 next_ft = find_next_chained_ft(prio);
1614                 if (next_ft) {
1615                         gen_dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
1616                         gen_dest.ft = next_ft;
1617                         dest = &gen_dest;
1618                         dest_num = 1;
1619                         flow_act->action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
1620                 } else {
1621                         mutex_unlock(&root->chain_lock);
1622                         return ERR_PTR(-EOPNOTSUPP);
1623                 }
1624         }
1625
1626         handle = _mlx5_add_flow_rules(ft, spec, flow_act, dest, dest_num);
1627
1628         if (sw_action == MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO) {
1629                 if (!IS_ERR_OR_NULL(handle) &&
1630                     (list_empty(&handle->rule[0]->next_ft))) {
1631                         mutex_lock(&next_ft->lock);
1632                         list_add(&handle->rule[0]->next_ft,
1633                                  &next_ft->fwd_rules);
1634                         mutex_unlock(&next_ft->lock);
1635                         handle->rule[0]->sw_action = MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO;
1636                 }
1637                 mutex_unlock(&root->chain_lock);
1638         }
1639         return handle;
1640 }
1641 EXPORT_SYMBOL(mlx5_add_flow_rules);
1642
1643 void mlx5_del_flow_rules(struct mlx5_flow_handle *handle)
1644 {
1645         int i;
1646
1647         for (i = handle->num_rules - 1; i >= 0; i--)
1648                 tree_remove_node(&handle->rule[i]->node);
1649         kfree(handle);
1650 }
1651 EXPORT_SYMBOL(mlx5_del_flow_rules);
1652
1653 /* Assuming prio->node.children(flow tables) is sorted by level */
1654 static struct mlx5_flow_table *find_next_ft(struct mlx5_flow_table *ft)
1655 {
1656         struct fs_prio *prio;
1657
1658         fs_get_obj(prio, ft->node.parent);
1659
1660         if (!list_is_last(&ft->node.list, &prio->node.children))
1661                 return list_next_entry(ft, node.list);
1662         return find_next_chained_ft(prio);
1663 }
1664
1665 static int update_root_ft_destroy(struct mlx5_flow_table *ft)
1666 {
1667         struct mlx5_flow_root_namespace *root = find_root(&ft->node);
1668         struct mlx5_flow_table *new_root_ft = NULL;
1669
1670         if (root->root_ft != ft)
1671                 return 0;
1672
1673         new_root_ft = find_next_ft(ft);
1674         if (new_root_ft) {
1675                 int err = mlx5_cmd_update_root_ft(root->dev, new_root_ft,
1676                                                   root->underlay_qpn);
1677
1678                 if (err) {
1679                         mlx5_core_warn(root->dev, "Update root flow table of id=%u failed\n",
1680                                        ft->id);
1681                         return err;
1682                 }
1683         }
1684         root->root_ft = new_root_ft;
1685         return 0;
1686 }
1687
1688 /* Connect flow table from previous priority to
1689  * the next flow table.
1690  */
1691 static int disconnect_flow_table(struct mlx5_flow_table *ft)
1692 {
1693         struct mlx5_core_dev *dev = get_dev(&ft->node);
1694         struct mlx5_flow_table *next_ft;
1695         struct fs_prio *prio;
1696         int err = 0;
1697
1698         err = update_root_ft_destroy(ft);
1699         if (err)
1700                 return err;
1701
1702         fs_get_obj(prio, ft->node.parent);
1703         if  (!(list_first_entry(&prio->node.children,
1704                                 struct mlx5_flow_table,
1705                                 node.list) == ft))
1706                 return 0;
1707
1708         next_ft = find_next_ft(ft);
1709         err = connect_fwd_rules(dev, next_ft, ft);
1710         if (err)
1711                 return err;
1712
1713         err = connect_prev_fts(dev, next_ft, prio);
1714         if (err)
1715                 mlx5_core_warn(dev, "Failed to disconnect flow table %d\n",
1716                                ft->id);
1717         return err;
1718 }
1719
1720 int mlx5_destroy_flow_table(struct mlx5_flow_table *ft)
1721 {
1722         struct mlx5_flow_root_namespace *root = find_root(&ft->node);
1723         int err = 0;
1724
1725         mutex_lock(&root->chain_lock);
1726         err = disconnect_flow_table(ft);
1727         if (err) {
1728                 mutex_unlock(&root->chain_lock);
1729                 return err;
1730         }
1731         if (tree_remove_node(&ft->node))
1732                 mlx5_core_warn(get_dev(&ft->node), "Flow table %d wasn't destroyed, refcount > 1\n",
1733                                ft->id);
1734         mutex_unlock(&root->chain_lock);
1735
1736         return err;
1737 }
1738 EXPORT_SYMBOL(mlx5_destroy_flow_table);
1739
1740 void mlx5_destroy_flow_group(struct mlx5_flow_group *fg)
1741 {
1742         if (tree_remove_node(&fg->node))
1743                 mlx5_core_warn(get_dev(&fg->node), "Flow group %d wasn't destroyed, refcount > 1\n",
1744                                fg->id);
1745 }
1746
1747 struct mlx5_flow_namespace *mlx5_get_flow_namespace(struct mlx5_core_dev *dev,
1748                                                     enum mlx5_flow_namespace_type type)
1749 {
1750         struct mlx5_flow_steering *steering = dev->priv.steering;
1751         struct mlx5_flow_root_namespace *root_ns;
1752         int prio;
1753         struct fs_prio *fs_prio;
1754         struct mlx5_flow_namespace *ns;
1755
1756         if (!steering)
1757                 return NULL;
1758
1759         switch (type) {
1760         case MLX5_FLOW_NAMESPACE_BYPASS:
1761         case MLX5_FLOW_NAMESPACE_LAG:
1762         case MLX5_FLOW_NAMESPACE_OFFLOADS:
1763         case MLX5_FLOW_NAMESPACE_ETHTOOL:
1764         case MLX5_FLOW_NAMESPACE_KERNEL:
1765         case MLX5_FLOW_NAMESPACE_LEFTOVERS:
1766         case MLX5_FLOW_NAMESPACE_ANCHOR:
1767                 prio = type;
1768                 break;
1769         case MLX5_FLOW_NAMESPACE_FDB:
1770                 if (steering->fdb_root_ns)
1771                         return &steering->fdb_root_ns->ns;
1772                 else
1773                         return NULL;
1774         case MLX5_FLOW_NAMESPACE_ESW_EGRESS:
1775                 if (steering->esw_egress_root_ns)
1776                         return &steering->esw_egress_root_ns->ns;
1777                 else
1778                         return NULL;
1779         case MLX5_FLOW_NAMESPACE_ESW_INGRESS:
1780                 if (steering->esw_ingress_root_ns)
1781                         return &steering->esw_ingress_root_ns->ns;
1782                 else
1783                         return NULL;
1784         case MLX5_FLOW_NAMESPACE_SNIFFER_RX:
1785                 if (steering->sniffer_rx_root_ns)
1786                         return &steering->sniffer_rx_root_ns->ns;
1787                 else
1788                         return NULL;
1789         case MLX5_FLOW_NAMESPACE_SNIFFER_TX:
1790                 if (steering->sniffer_tx_root_ns)
1791                         return &steering->sniffer_tx_root_ns->ns;
1792                 else
1793                         return NULL;
1794         default:
1795                 return NULL;
1796         }
1797
1798         root_ns = steering->root_ns;
1799         if (!root_ns)
1800                 return NULL;
1801
1802         fs_prio = find_prio(&root_ns->ns, prio);
1803         if (!fs_prio)
1804                 return NULL;
1805
1806         ns = list_first_entry(&fs_prio->node.children,
1807                               typeof(*ns),
1808                               node.list);
1809
1810         return ns;
1811 }
1812 EXPORT_SYMBOL(mlx5_get_flow_namespace);
1813
1814 static struct fs_prio *fs_create_prio(struct mlx5_flow_namespace *ns,
1815                                       unsigned int prio, int num_levels)
1816 {
1817         struct fs_prio *fs_prio;
1818
1819         fs_prio = kzalloc(sizeof(*fs_prio), GFP_KERNEL);
1820         if (!fs_prio)
1821                 return ERR_PTR(-ENOMEM);
1822
1823         fs_prio->node.type = FS_TYPE_PRIO;
1824         tree_init_node(&fs_prio->node, 1, NULL);
1825         tree_add_node(&fs_prio->node, &ns->node);
1826         fs_prio->num_levels = num_levels;
1827         fs_prio->prio = prio;
1828         list_add_tail(&fs_prio->node.list, &ns->node.children);
1829
1830         return fs_prio;
1831 }
1832
1833 static struct mlx5_flow_namespace *fs_init_namespace(struct mlx5_flow_namespace
1834                                                      *ns)
1835 {
1836         ns->node.type = FS_TYPE_NAMESPACE;
1837
1838         return ns;
1839 }
1840
1841 static struct mlx5_flow_namespace *fs_create_namespace(struct fs_prio *prio)
1842 {
1843         struct mlx5_flow_namespace      *ns;
1844
1845         ns = kzalloc(sizeof(*ns), GFP_KERNEL);
1846         if (!ns)
1847                 return ERR_PTR(-ENOMEM);
1848
1849         fs_init_namespace(ns);
1850         tree_init_node(&ns->node, 1, NULL);
1851         tree_add_node(&ns->node, &prio->node);
1852         list_add_tail(&ns->node.list, &prio->node.children);
1853
1854         return ns;
1855 }
1856
1857 static int create_leaf_prios(struct mlx5_flow_namespace *ns, int prio,
1858                              struct init_tree_node *prio_metadata)
1859 {
1860         struct fs_prio *fs_prio;
1861         int i;
1862
1863         for (i = 0; i < prio_metadata->num_leaf_prios; i++) {
1864                 fs_prio = fs_create_prio(ns, prio++, prio_metadata->num_levels);
1865                 if (IS_ERR(fs_prio))
1866                         return PTR_ERR(fs_prio);
1867         }
1868         return 0;
1869 }
1870
1871 #define FLOW_TABLE_BIT_SZ 1
1872 #define GET_FLOW_TABLE_CAP(dev, offset) \
1873         ((be32_to_cpu(*((__be32 *)(dev->caps.hca_cur[MLX5_CAP_FLOW_TABLE]) +    \
1874                         offset / 32)) >>                                        \
1875           (32 - FLOW_TABLE_BIT_SZ - (offset & 0x1f))) & FLOW_TABLE_BIT_SZ)
1876 static bool has_required_caps(struct mlx5_core_dev *dev, struct node_caps *caps)
1877 {
1878         int i;
1879
1880         for (i = 0; i < caps->arr_sz; i++) {
1881                 if (!GET_FLOW_TABLE_CAP(dev, caps->caps[i]))
1882                         return false;
1883         }
1884         return true;
1885 }
1886
1887 static int init_root_tree_recursive(struct mlx5_flow_steering *steering,
1888                                     struct init_tree_node *init_node,
1889                                     struct fs_node *fs_parent_node,
1890                                     struct init_tree_node *init_parent_node,
1891                                     int prio)
1892 {
1893         int max_ft_level = MLX5_CAP_FLOWTABLE(steering->dev,
1894                                               flow_table_properties_nic_receive.
1895                                               max_ft_level);
1896         struct mlx5_flow_namespace *fs_ns;
1897         struct fs_prio *fs_prio;
1898         struct fs_node *base;
1899         int i;
1900         int err;
1901
1902         if (init_node->type == FS_TYPE_PRIO) {
1903                 if ((init_node->min_ft_level > max_ft_level) ||
1904                     !has_required_caps(steering->dev, &init_node->caps))
1905                         return 0;
1906
1907                 fs_get_obj(fs_ns, fs_parent_node);
1908                 if (init_node->num_leaf_prios)
1909                         return create_leaf_prios(fs_ns, prio, init_node);
1910                 fs_prio = fs_create_prio(fs_ns, prio, init_node->num_levels);
1911                 if (IS_ERR(fs_prio))
1912                         return PTR_ERR(fs_prio);
1913                 base = &fs_prio->node;
1914         } else if (init_node->type == FS_TYPE_NAMESPACE) {
1915                 fs_get_obj(fs_prio, fs_parent_node);
1916                 fs_ns = fs_create_namespace(fs_prio);
1917                 if (IS_ERR(fs_ns))
1918                         return PTR_ERR(fs_ns);
1919                 base = &fs_ns->node;
1920         } else {
1921                 return -EINVAL;
1922         }
1923         prio = 0;
1924         for (i = 0; i < init_node->ar_size; i++) {
1925                 err = init_root_tree_recursive(steering, &init_node->children[i],
1926                                                base, init_node, prio);
1927                 if (err)
1928                         return err;
1929                 if (init_node->children[i].type == FS_TYPE_PRIO &&
1930                     init_node->children[i].num_leaf_prios) {
1931                         prio += init_node->children[i].num_leaf_prios;
1932                 }
1933         }
1934
1935         return 0;
1936 }
1937
1938 static int init_root_tree(struct mlx5_flow_steering *steering,
1939                           struct init_tree_node *init_node,
1940                           struct fs_node *fs_parent_node)
1941 {
1942         int i;
1943         struct mlx5_flow_namespace *fs_ns;
1944         int err;
1945
1946         fs_get_obj(fs_ns, fs_parent_node);
1947         for (i = 0; i < init_node->ar_size; i++) {
1948                 err = init_root_tree_recursive(steering, &init_node->children[i],
1949                                                &fs_ns->node,
1950                                                init_node, i);
1951                 if (err)
1952                         return err;
1953         }
1954         return 0;
1955 }
1956
1957 static struct mlx5_flow_root_namespace *create_root_ns(struct mlx5_flow_steering *steering,
1958                                                        enum fs_flow_table_type
1959                                                        table_type)
1960 {
1961         struct mlx5_flow_root_namespace *root_ns;
1962         struct mlx5_flow_namespace *ns;
1963
1964         /* Create the root namespace */
1965         root_ns = kzalloc(sizeof(*root_ns), GFP_KERNEL);
1966         if (!root_ns)
1967                 return NULL;
1968
1969         root_ns->dev = steering->dev;
1970         root_ns->table_type = table_type;
1971
1972         ns = &root_ns->ns;
1973         fs_init_namespace(ns);
1974         mutex_init(&root_ns->chain_lock);
1975         tree_init_node(&ns->node, 1, NULL);
1976         tree_add_node(&ns->node, NULL);
1977
1978         return root_ns;
1979 }
1980
1981 static void set_prio_attrs_in_prio(struct fs_prio *prio, int acc_level);
1982
1983 static int set_prio_attrs_in_ns(struct mlx5_flow_namespace *ns, int acc_level)
1984 {
1985         struct fs_prio *prio;
1986
1987         fs_for_each_prio(prio, ns) {
1988                  /* This updates prio start_level and num_levels */
1989                 set_prio_attrs_in_prio(prio, acc_level);
1990                 acc_level += prio->num_levels;
1991         }
1992         return acc_level;
1993 }
1994
1995 static void set_prio_attrs_in_prio(struct fs_prio *prio, int acc_level)
1996 {
1997         struct mlx5_flow_namespace *ns;
1998         int acc_level_ns = acc_level;
1999
2000         prio->start_level = acc_level;
2001         fs_for_each_ns(ns, prio)
2002                 /* This updates start_level and num_levels of ns's priority descendants */
2003                 acc_level_ns = set_prio_attrs_in_ns(ns, acc_level);
2004         if (!prio->num_levels)
2005                 prio->num_levels = acc_level_ns - prio->start_level;
2006         WARN_ON(prio->num_levels < acc_level_ns - prio->start_level);
2007 }
2008
2009 static void set_prio_attrs(struct mlx5_flow_root_namespace *root_ns)
2010 {
2011         struct mlx5_flow_namespace *ns = &root_ns->ns;
2012         struct fs_prio *prio;
2013         int start_level = 0;
2014
2015         fs_for_each_prio(prio, ns) {
2016                 set_prio_attrs_in_prio(prio, start_level);
2017                 start_level += prio->num_levels;
2018         }
2019 }
2020
2021 #define ANCHOR_PRIO 0
2022 #define ANCHOR_SIZE 1
2023 #define ANCHOR_LEVEL 0
2024 static int create_anchor_flow_table(struct mlx5_flow_steering *steering)
2025 {
2026         struct mlx5_flow_namespace *ns = NULL;
2027         struct mlx5_flow_table_attr ft_attr = {};
2028         struct mlx5_flow_table *ft;
2029
2030         ns = mlx5_get_flow_namespace(steering->dev, MLX5_FLOW_NAMESPACE_ANCHOR);
2031         if (WARN_ON(!ns))
2032                 return -EINVAL;
2033
2034         ft_attr.max_fte = ANCHOR_SIZE;
2035         ft_attr.level   = ANCHOR_LEVEL;
2036         ft_attr.prio    = ANCHOR_PRIO;
2037
2038         ft = mlx5_create_flow_table(ns, &ft_attr);
2039         if (IS_ERR(ft)) {
2040                 mlx5_core_err(steering->dev, "Failed to create last anchor flow table");
2041                 return PTR_ERR(ft);
2042         }
2043         return 0;
2044 }
2045
2046 static int init_root_ns(struct mlx5_flow_steering *steering)
2047 {
2048         int err;
2049
2050         steering->root_ns = create_root_ns(steering, FS_FT_NIC_RX);
2051         if (!steering->root_ns)
2052                 return -ENOMEM;
2053
2054         err = init_root_tree(steering, &root_fs, &steering->root_ns->ns.node);
2055         if (err)
2056                 goto out_err;
2057
2058         set_prio_attrs(steering->root_ns);
2059         err = create_anchor_flow_table(steering);
2060         if (err)
2061                 goto out_err;
2062
2063         return 0;
2064
2065 out_err:
2066         cleanup_root_ns(steering->root_ns);
2067         steering->root_ns = NULL;
2068         return err;
2069 }
2070
2071 static void clean_tree(struct fs_node *node)
2072 {
2073         if (node) {
2074                 struct fs_node *iter;
2075                 struct fs_node *temp;
2076
2077                 list_for_each_entry_safe(iter, temp, &node->children, list)
2078                         clean_tree(iter);
2079                 tree_remove_node(node);
2080         }
2081 }
2082
2083 static void cleanup_root_ns(struct mlx5_flow_root_namespace *root_ns)
2084 {
2085         if (!root_ns)
2086                 return;
2087
2088         clean_tree(&root_ns->ns.node);
2089 }
2090
2091 void mlx5_cleanup_fs(struct mlx5_core_dev *dev)
2092 {
2093         struct mlx5_flow_steering *steering = dev->priv.steering;
2094
2095         cleanup_root_ns(steering->root_ns);
2096         cleanup_root_ns(steering->esw_egress_root_ns);
2097         cleanup_root_ns(steering->esw_ingress_root_ns);
2098         cleanup_root_ns(steering->fdb_root_ns);
2099         cleanup_root_ns(steering->sniffer_rx_root_ns);
2100         cleanup_root_ns(steering->sniffer_tx_root_ns);
2101         mlx5_cleanup_fc_stats(dev);
2102         kfree(steering);
2103 }
2104
2105 static int init_sniffer_tx_root_ns(struct mlx5_flow_steering *steering)
2106 {
2107         struct fs_prio *prio;
2108
2109         steering->sniffer_tx_root_ns = create_root_ns(steering, FS_FT_SNIFFER_TX);
2110         if (!steering->sniffer_tx_root_ns)
2111                 return -ENOMEM;
2112
2113         /* Create single prio */
2114         prio = fs_create_prio(&steering->sniffer_tx_root_ns->ns, 0, 1);
2115         if (IS_ERR(prio)) {
2116                 cleanup_root_ns(steering->sniffer_tx_root_ns);
2117                 return PTR_ERR(prio);
2118         }
2119         return 0;
2120 }
2121
2122 static int init_sniffer_rx_root_ns(struct mlx5_flow_steering *steering)
2123 {
2124         struct fs_prio *prio;
2125
2126         steering->sniffer_rx_root_ns = create_root_ns(steering, FS_FT_SNIFFER_RX);
2127         if (!steering->sniffer_rx_root_ns)
2128                 return -ENOMEM;
2129
2130         /* Create single prio */
2131         prio = fs_create_prio(&steering->sniffer_rx_root_ns->ns, 0, 1);
2132         if (IS_ERR(prio)) {
2133                 cleanup_root_ns(steering->sniffer_rx_root_ns);
2134                 return PTR_ERR(prio);
2135         }
2136         return 0;
2137 }
2138
2139 static int init_fdb_root_ns(struct mlx5_flow_steering *steering)
2140 {
2141         struct fs_prio *prio;
2142
2143         steering->fdb_root_ns = create_root_ns(steering, FS_FT_FDB);
2144         if (!steering->fdb_root_ns)
2145                 return -ENOMEM;
2146
2147         prio = fs_create_prio(&steering->fdb_root_ns->ns, 0, 1);
2148         if (IS_ERR(prio))
2149                 goto out_err;
2150
2151         prio = fs_create_prio(&steering->fdb_root_ns->ns, 1, 1);
2152         if (IS_ERR(prio))
2153                 goto out_err;
2154
2155         set_prio_attrs(steering->fdb_root_ns);
2156         return 0;
2157
2158 out_err:
2159         cleanup_root_ns(steering->fdb_root_ns);
2160         steering->fdb_root_ns = NULL;
2161         return PTR_ERR(prio);
2162 }
2163
2164 static int init_ingress_acl_root_ns(struct mlx5_flow_steering *steering)
2165 {
2166         struct fs_prio *prio;
2167
2168         steering->esw_egress_root_ns = create_root_ns(steering, FS_FT_ESW_EGRESS_ACL);
2169         if (!steering->esw_egress_root_ns)
2170                 return -ENOMEM;
2171
2172         /* create 1 prio*/
2173         prio = fs_create_prio(&steering->esw_egress_root_ns->ns, 0,
2174                               MLX5_TOTAL_VPORTS(steering->dev));
2175         return PTR_ERR_OR_ZERO(prio);
2176 }
2177
2178 static int init_egress_acl_root_ns(struct mlx5_flow_steering *steering)
2179 {
2180         struct fs_prio *prio;
2181
2182         steering->esw_ingress_root_ns = create_root_ns(steering, FS_FT_ESW_INGRESS_ACL);
2183         if (!steering->esw_ingress_root_ns)
2184                 return -ENOMEM;
2185
2186         /* create 1 prio*/
2187         prio = fs_create_prio(&steering->esw_ingress_root_ns->ns, 0,
2188                               MLX5_TOTAL_VPORTS(steering->dev));
2189         return PTR_ERR_OR_ZERO(prio);
2190 }
2191
2192 int mlx5_init_fs(struct mlx5_core_dev *dev)
2193 {
2194         struct mlx5_flow_steering *steering;
2195         int err = 0;
2196
2197         err = mlx5_init_fc_stats(dev);
2198         if (err)
2199                 return err;
2200
2201         steering = kzalloc(sizeof(*steering), GFP_KERNEL);
2202         if (!steering)
2203                 return -ENOMEM;
2204         steering->dev = dev;
2205         dev->priv.steering = steering;
2206
2207         if ((((MLX5_CAP_GEN(dev, port_type) == MLX5_CAP_PORT_TYPE_ETH) &&
2208               (MLX5_CAP_GEN(dev, nic_flow_table))) ||
2209              ((MLX5_CAP_GEN(dev, port_type) == MLX5_CAP_PORT_TYPE_IB) &&
2210               MLX5_CAP_GEN(dev, ipoib_enhanced_offloads))) &&
2211             MLX5_CAP_FLOWTABLE_NIC_RX(dev, ft_support)) {
2212                 err = init_root_ns(steering);
2213                 if (err)
2214                         goto err;
2215         }
2216
2217         if (MLX5_ESWITCH_MANAGER(dev)) {
2218                 if (MLX5_CAP_ESW_FLOWTABLE_FDB(dev, ft_support)) {
2219                         err = init_fdb_root_ns(steering);
2220                         if (err)
2221                                 goto err;
2222                 }
2223                 if (MLX5_CAP_ESW_EGRESS_ACL(dev, ft_support)) {
2224                         err = init_egress_acl_root_ns(steering);
2225                         if (err)
2226                                 goto err;
2227                 }
2228                 if (MLX5_CAP_ESW_INGRESS_ACL(dev, ft_support)) {
2229                         err = init_ingress_acl_root_ns(steering);
2230                         if (err)
2231                                 goto err;
2232                 }
2233         }
2234
2235         if (MLX5_CAP_FLOWTABLE_SNIFFER_RX(dev, ft_support)) {
2236                 err = init_sniffer_rx_root_ns(steering);
2237                 if (err)
2238                         goto err;
2239         }
2240
2241         if (MLX5_CAP_FLOWTABLE_SNIFFER_TX(dev, ft_support)) {
2242                 err = init_sniffer_tx_root_ns(steering);
2243                 if (err)
2244                         goto err;
2245         }
2246
2247         return 0;
2248 err:
2249         mlx5_cleanup_fs(dev);
2250         return err;
2251 }
2252
2253 int mlx5_fs_add_rx_underlay_qpn(struct mlx5_core_dev *dev, u32 underlay_qpn)
2254 {
2255         struct mlx5_flow_root_namespace *root = dev->priv.steering->root_ns;
2256
2257         root->underlay_qpn = underlay_qpn;
2258         return 0;
2259 }
2260 EXPORT_SYMBOL(mlx5_fs_add_rx_underlay_qpn);
2261
2262 int mlx5_fs_remove_rx_underlay_qpn(struct mlx5_core_dev *dev, u32 underlay_qpn)
2263 {
2264         struct mlx5_flow_root_namespace *root = dev->priv.steering->root_ns;
2265
2266         root->underlay_qpn = 0;
2267         return 0;
2268 }
2269 EXPORT_SYMBOL(mlx5_fs_remove_rx_underlay_qpn);