Merge tag 'pci-v4.18-fixes-3' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaa...
[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                 return true;
1470
1471         return false;
1472 }
1473
1474 static int check_conflicting_ftes(struct fs_fte *fte, const struct mlx5_flow_act *flow_act)
1475 {
1476         if (check_conflicting_actions(flow_act->action, fte->action.action)) {
1477                 mlx5_core_warn(get_dev(&fte->node),
1478                                "Found two FTEs with conflicting actions\n");
1479                 return -EEXIST;
1480         }
1481
1482         if (flow_act->has_flow_tag &&
1483             fte->action.flow_tag != flow_act->flow_tag) {
1484                 mlx5_core_warn(get_dev(&fte->node),
1485                                "FTE flow tag %u already exists with different flow tag %u\n",
1486                                fte->action.flow_tag,
1487                                flow_act->flow_tag);
1488                 return -EEXIST;
1489         }
1490
1491         return 0;
1492 }
1493
1494 static struct mlx5_flow_handle *add_rule_fg(struct mlx5_flow_group *fg,
1495                                             u32 *match_value,
1496                                             struct mlx5_flow_act *flow_act,
1497                                             struct mlx5_flow_destination *dest,
1498                                             int dest_num,
1499                                             struct fs_fte *fte)
1500 {
1501         struct mlx5_flow_handle *handle;
1502         int old_action;
1503         int i;
1504         int ret;
1505
1506         ret = check_conflicting_ftes(fte, flow_act);
1507         if (ret)
1508                 return ERR_PTR(ret);
1509
1510         old_action = fte->action.action;
1511         fte->action.action |= flow_act->action;
1512         handle = add_rule_fte(fte, fg, dest, dest_num,
1513                               old_action != flow_act->action);
1514         if (IS_ERR(handle)) {
1515                 fte->action.action = old_action;
1516                 return handle;
1517         }
1518         trace_mlx5_fs_set_fte(fte, false);
1519
1520         for (i = 0; i < handle->num_rules; i++) {
1521                 if (refcount_read(&handle->rule[i]->node.refcount) == 1) {
1522                         tree_add_node(&handle->rule[i]->node, &fte->node);
1523                         trace_mlx5_fs_add_rule(handle->rule[i]);
1524                 }
1525         }
1526         return handle;
1527 }
1528
1529 struct mlx5_fc *mlx5_flow_rule_counter(struct mlx5_flow_handle *handle)
1530 {
1531         struct mlx5_flow_rule *dst;
1532         struct fs_fte *fte;
1533
1534         fs_get_obj(fte, handle->rule[0]->node.parent);
1535
1536         fs_for_each_dst(dst, fte) {
1537                 if (dst->dest_attr.type == MLX5_FLOW_DESTINATION_TYPE_COUNTER)
1538                         return dst->dest_attr.counter;
1539         }
1540
1541         return NULL;
1542 }
1543
1544 static bool counter_is_valid(struct mlx5_fc *counter, u32 action)
1545 {
1546         if (!(action & MLX5_FLOW_CONTEXT_ACTION_COUNT))
1547                 return !counter;
1548
1549         if (!counter)
1550                 return false;
1551
1552         return (action & (MLX5_FLOW_CONTEXT_ACTION_DROP |
1553                           MLX5_FLOW_CONTEXT_ACTION_FWD_DEST));
1554 }
1555
1556 static bool dest_is_valid(struct mlx5_flow_destination *dest,
1557                           u32 action,
1558                           struct mlx5_flow_table *ft)
1559 {
1560         if (dest && (dest->type == MLX5_FLOW_DESTINATION_TYPE_COUNTER))
1561                 return counter_is_valid(dest->counter, action);
1562
1563         if (!(action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST))
1564                 return true;
1565
1566         if (!dest || ((dest->type ==
1567             MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE) &&
1568             (dest->ft->level <= ft->level)))
1569                 return false;
1570         return true;
1571 }
1572
1573 struct match_list {
1574         struct list_head        list;
1575         struct mlx5_flow_group *g;
1576 };
1577
1578 struct match_list_head {
1579         struct list_head  list;
1580         struct match_list first;
1581 };
1582
1583 static void free_match_list(struct match_list_head *head)
1584 {
1585         if (!list_empty(&head->list)) {
1586                 struct match_list *iter, *match_tmp;
1587
1588                 list_del(&head->first.list);
1589                 tree_put_node(&head->first.g->node);
1590                 list_for_each_entry_safe(iter, match_tmp, &head->list,
1591                                          list) {
1592                         tree_put_node(&iter->g->node);
1593                         list_del(&iter->list);
1594                         kfree(iter);
1595                 }
1596         }
1597 }
1598
1599 static int build_match_list(struct match_list_head *match_head,
1600                             struct mlx5_flow_table *ft,
1601                             struct mlx5_flow_spec *spec)
1602 {
1603         struct rhlist_head *tmp, *list;
1604         struct mlx5_flow_group *g;
1605         int err = 0;
1606
1607         rcu_read_lock();
1608         INIT_LIST_HEAD(&match_head->list);
1609         /* Collect all fgs which has a matching match_criteria */
1610         list = rhltable_lookup(&ft->fgs_hash, spec, rhash_fg);
1611         /* RCU is atomic, we can't execute FW commands here */
1612         rhl_for_each_entry_rcu(g, tmp, list, hash) {
1613                 struct match_list *curr_match;
1614
1615                 if (likely(list_empty(&match_head->list))) {
1616                         if (!tree_get_node(&g->node))
1617                                 continue;
1618                         match_head->first.g = g;
1619                         list_add_tail(&match_head->first.list,
1620                                       &match_head->list);
1621                         continue;
1622                 }
1623
1624                 curr_match = kmalloc(sizeof(*curr_match), GFP_ATOMIC);
1625                 if (!curr_match) {
1626                         free_match_list(match_head);
1627                         err = -ENOMEM;
1628                         goto out;
1629                 }
1630                 if (!tree_get_node(&g->node)) {
1631                         kfree(curr_match);
1632                         continue;
1633                 }
1634                 curr_match->g = g;
1635                 list_add_tail(&curr_match->list, &match_head->list);
1636         }
1637 out:
1638         rcu_read_unlock();
1639         return err;
1640 }
1641
1642 static u64 matched_fgs_get_version(struct list_head *match_head)
1643 {
1644         struct match_list *iter;
1645         u64 version = 0;
1646
1647         list_for_each_entry(iter, match_head, list)
1648                 version += (u64)atomic_read(&iter->g->node.version);
1649         return version;
1650 }
1651
1652 static struct mlx5_flow_handle *
1653 try_add_to_existing_fg(struct mlx5_flow_table *ft,
1654                        struct list_head *match_head,
1655                        struct mlx5_flow_spec *spec,
1656                        struct mlx5_flow_act *flow_act,
1657                        struct mlx5_flow_destination *dest,
1658                        int dest_num,
1659                        int ft_version)
1660 {
1661         struct mlx5_flow_steering *steering = get_steering(&ft->node);
1662         struct mlx5_flow_group *g;
1663         struct mlx5_flow_handle *rule;
1664         struct match_list *iter;
1665         bool take_write = false;
1666         struct fs_fte *fte;
1667         u64  version;
1668         int err;
1669
1670         fte = alloc_fte(ft, spec->match_value, flow_act);
1671         if (IS_ERR(fte))
1672                 return  ERR_PTR(-ENOMEM);
1673
1674         list_for_each_entry(iter, match_head, list) {
1675                 nested_down_read_ref_node(&iter->g->node, FS_LOCK_PARENT);
1676         }
1677
1678 search_again_locked:
1679         version = matched_fgs_get_version(match_head);
1680         /* Try to find a fg that already contains a matching fte */
1681         list_for_each_entry(iter, match_head, list) {
1682                 struct fs_fte *fte_tmp;
1683
1684                 g = iter->g;
1685                 fte_tmp = rhashtable_lookup_fast(&g->ftes_hash, spec->match_value,
1686                                                  rhash_fte);
1687                 if (!fte_tmp || !tree_get_node(&fte_tmp->node))
1688                         continue;
1689
1690                 nested_down_write_ref_node(&fte_tmp->node, FS_LOCK_CHILD);
1691                 if (!take_write) {
1692                         list_for_each_entry(iter, match_head, list)
1693                                 up_read_ref_node(&iter->g->node);
1694                 } else {
1695                         list_for_each_entry(iter, match_head, list)
1696                                 up_write_ref_node(&iter->g->node);
1697                 }
1698
1699                 rule = add_rule_fg(g, spec->match_value,
1700                                    flow_act, dest, dest_num, fte_tmp);
1701                 up_write_ref_node(&fte_tmp->node);
1702                 tree_put_node(&fte_tmp->node);
1703                 kmem_cache_free(steering->ftes_cache, fte);
1704                 return rule;
1705         }
1706
1707         /* No group with matching fte found. Try to add a new fte to any
1708          * matching fg.
1709          */
1710
1711         if (!take_write) {
1712                 list_for_each_entry(iter, match_head, list)
1713                         up_read_ref_node(&iter->g->node);
1714                 list_for_each_entry(iter, match_head, list)
1715                         nested_down_write_ref_node(&iter->g->node,
1716                                                    FS_LOCK_PARENT);
1717                 take_write = true;
1718         }
1719
1720         /* Check the ft version, for case that new flow group
1721          * was added while the fgs weren't locked
1722          */
1723         if (atomic_read(&ft->node.version) != ft_version) {
1724                 rule = ERR_PTR(-EAGAIN);
1725                 goto out;
1726         }
1727
1728         /* Check the fgs version, for case the new FTE with the
1729          * same values was added while the fgs weren't locked
1730          */
1731         if (version != matched_fgs_get_version(match_head))
1732                 goto search_again_locked;
1733
1734         list_for_each_entry(iter, match_head, list) {
1735                 g = iter->g;
1736
1737                 if (!g->node.active)
1738                         continue;
1739                 err = insert_fte(g, fte);
1740                 if (err) {
1741                         if (err == -ENOSPC)
1742                                 continue;
1743                         list_for_each_entry(iter, match_head, list)
1744                                 up_write_ref_node(&iter->g->node);
1745                         kmem_cache_free(steering->ftes_cache, fte);
1746                         return ERR_PTR(err);
1747                 }
1748
1749                 nested_down_write_ref_node(&fte->node, FS_LOCK_CHILD);
1750                 list_for_each_entry(iter, match_head, list)
1751                         up_write_ref_node(&iter->g->node);
1752                 rule = add_rule_fg(g, spec->match_value,
1753                                    flow_act, dest, dest_num, fte);
1754                 up_write_ref_node(&fte->node);
1755                 tree_put_node(&fte->node);
1756                 return rule;
1757         }
1758         rule = ERR_PTR(-ENOENT);
1759 out:
1760         list_for_each_entry(iter, match_head, list)
1761                 up_write_ref_node(&iter->g->node);
1762         kmem_cache_free(steering->ftes_cache, fte);
1763         return rule;
1764 }
1765
1766 static struct mlx5_flow_handle *
1767 _mlx5_add_flow_rules(struct mlx5_flow_table *ft,
1768                      struct mlx5_flow_spec *spec,
1769                      struct mlx5_flow_act *flow_act,
1770                      struct mlx5_flow_destination *dest,
1771                      int dest_num)
1772
1773 {
1774         struct mlx5_flow_steering *steering = get_steering(&ft->node);
1775         struct mlx5_flow_group *g;
1776         struct mlx5_flow_handle *rule;
1777         struct match_list_head match_head;
1778         bool take_write = false;
1779         struct fs_fte *fte;
1780         int version;
1781         int err;
1782         int i;
1783
1784         if (!check_valid_spec(spec))
1785                 return ERR_PTR(-EINVAL);
1786
1787         for (i = 0; i < dest_num; i++) {
1788                 if (!dest_is_valid(&dest[i], flow_act->action, ft))
1789                         return ERR_PTR(-EINVAL);
1790         }
1791         nested_down_read_ref_node(&ft->node, FS_LOCK_GRANDPARENT);
1792 search_again_locked:
1793         version = atomic_read(&ft->node.version);
1794
1795         /* Collect all fgs which has a matching match_criteria */
1796         err = build_match_list(&match_head, ft, spec);
1797         if (err) {
1798                 if (take_write)
1799                         up_write_ref_node(&ft->node);
1800                 return ERR_PTR(err);
1801         }
1802
1803         if (!take_write)
1804                 up_read_ref_node(&ft->node);
1805
1806         rule = try_add_to_existing_fg(ft, &match_head.list, spec, flow_act, dest,
1807                                       dest_num, version);
1808         free_match_list(&match_head);
1809         if (!IS_ERR(rule) ||
1810             (PTR_ERR(rule) != -ENOENT && PTR_ERR(rule) != -EAGAIN)) {
1811                 if (take_write)
1812                         up_write_ref_node(&ft->node);
1813                 return rule;
1814         }
1815
1816         if (!take_write) {
1817                 nested_down_write_ref_node(&ft->node, FS_LOCK_GRANDPARENT);
1818                 take_write = true;
1819         }
1820
1821         if (PTR_ERR(rule) == -EAGAIN ||
1822             version != atomic_read(&ft->node.version))
1823                 goto search_again_locked;
1824
1825         g = alloc_auto_flow_group(ft, spec);
1826         if (IS_ERR(g)) {
1827                 rule = (void *)g;
1828                 up_write_ref_node(&ft->node);
1829                 return rule;
1830         }
1831
1832         nested_down_write_ref_node(&g->node, FS_LOCK_PARENT);
1833         up_write_ref_node(&ft->node);
1834
1835         err = create_auto_flow_group(ft, g);
1836         if (err)
1837                 goto err_release_fg;
1838
1839         fte = alloc_fte(ft, spec->match_value, flow_act);
1840         if (IS_ERR(fte)) {
1841                 err = PTR_ERR(fte);
1842                 goto err_release_fg;
1843         }
1844
1845         err = insert_fte(g, fte);
1846         if (err) {
1847                 kmem_cache_free(steering->ftes_cache, fte);
1848                 goto err_release_fg;
1849         }
1850
1851         nested_down_write_ref_node(&fte->node, FS_LOCK_CHILD);
1852         up_write_ref_node(&g->node);
1853         rule = add_rule_fg(g, spec->match_value, flow_act, dest,
1854                            dest_num, fte);
1855         up_write_ref_node(&fte->node);
1856         tree_put_node(&fte->node);
1857         tree_put_node(&g->node);
1858         return rule;
1859
1860 err_release_fg:
1861         up_write_ref_node(&g->node);
1862         tree_put_node(&g->node);
1863         return ERR_PTR(err);
1864 }
1865
1866 static bool fwd_next_prio_supported(struct mlx5_flow_table *ft)
1867 {
1868         return ((ft->type == FS_FT_NIC_RX) &&
1869                 (MLX5_CAP_FLOWTABLE(get_dev(&ft->node), nic_rx_multi_path_tirs)));
1870 }
1871
1872 struct mlx5_flow_handle *
1873 mlx5_add_flow_rules(struct mlx5_flow_table *ft,
1874                     struct mlx5_flow_spec *spec,
1875                     struct mlx5_flow_act *flow_act,
1876                     struct mlx5_flow_destination *dest,
1877                     int dest_num)
1878 {
1879         struct mlx5_flow_root_namespace *root = find_root(&ft->node);
1880         struct mlx5_flow_destination gen_dest = {};
1881         struct mlx5_flow_table *next_ft = NULL;
1882         struct mlx5_flow_handle *handle = NULL;
1883         u32 sw_action = flow_act->action;
1884         struct fs_prio *prio;
1885
1886         fs_get_obj(prio, ft->node.parent);
1887         if (flow_act->action == MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO) {
1888                 if (!fwd_next_prio_supported(ft))
1889                         return ERR_PTR(-EOPNOTSUPP);
1890                 if (dest)
1891                         return ERR_PTR(-EINVAL);
1892                 mutex_lock(&root->chain_lock);
1893                 next_ft = find_next_chained_ft(prio);
1894                 if (next_ft) {
1895                         gen_dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
1896                         gen_dest.ft = next_ft;
1897                         dest = &gen_dest;
1898                         dest_num = 1;
1899                         flow_act->action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
1900                 } else {
1901                         mutex_unlock(&root->chain_lock);
1902                         return ERR_PTR(-EOPNOTSUPP);
1903                 }
1904         }
1905
1906         handle = _mlx5_add_flow_rules(ft, spec, flow_act, dest, dest_num);
1907
1908         if (sw_action == MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO) {
1909                 if (!IS_ERR_OR_NULL(handle) &&
1910                     (list_empty(&handle->rule[0]->next_ft))) {
1911                         mutex_lock(&next_ft->lock);
1912                         list_add(&handle->rule[0]->next_ft,
1913                                  &next_ft->fwd_rules);
1914                         mutex_unlock(&next_ft->lock);
1915                         handle->rule[0]->sw_action = MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO;
1916                 }
1917                 mutex_unlock(&root->chain_lock);
1918         }
1919         return handle;
1920 }
1921 EXPORT_SYMBOL(mlx5_add_flow_rules);
1922
1923 void mlx5_del_flow_rules(struct mlx5_flow_handle *handle)
1924 {
1925         int i;
1926
1927         for (i = handle->num_rules - 1; i >= 0; i--)
1928                 tree_remove_node(&handle->rule[i]->node);
1929         kfree(handle);
1930 }
1931 EXPORT_SYMBOL(mlx5_del_flow_rules);
1932
1933 /* Assuming prio->node.children(flow tables) is sorted by level */
1934 static struct mlx5_flow_table *find_next_ft(struct mlx5_flow_table *ft)
1935 {
1936         struct fs_prio *prio;
1937
1938         fs_get_obj(prio, ft->node.parent);
1939
1940         if (!list_is_last(&ft->node.list, &prio->node.children))
1941                 return list_next_entry(ft, node.list);
1942         return find_next_chained_ft(prio);
1943 }
1944
1945 static int update_root_ft_destroy(struct mlx5_flow_table *ft)
1946 {
1947         struct mlx5_flow_root_namespace *root = find_root(&ft->node);
1948         struct mlx5_ft_underlay_qp *uqp;
1949         struct mlx5_flow_table *new_root_ft = NULL;
1950         int err = 0;
1951         u32 qpn;
1952
1953         if (root->root_ft != ft)
1954                 return 0;
1955
1956         new_root_ft = find_next_ft(ft);
1957         if (!new_root_ft) {
1958                 root->root_ft = NULL;
1959                 return 0;
1960         }
1961
1962         if (list_empty(&root->underlay_qpns)) {
1963                 /* Don't set any QPN (zero) in case QPN list is empty */
1964                 qpn = 0;
1965                 err = root->cmds->update_root_ft(root->dev, new_root_ft,
1966                                                  qpn, false);
1967         } else {
1968                 list_for_each_entry(uqp, &root->underlay_qpns, list) {
1969                         qpn = uqp->qpn;
1970                         err = root->cmds->update_root_ft(root->dev,
1971                                                          new_root_ft, qpn,
1972                                                          false);
1973                         if (err)
1974                                 break;
1975                 }
1976         }
1977
1978         if (err)
1979                 mlx5_core_warn(root->dev,
1980                                "Update root flow table of id(%u) qpn(%d) failed\n",
1981                                ft->id, qpn);
1982         else
1983                 root->root_ft = new_root_ft;
1984
1985         return 0;
1986 }
1987
1988 /* Connect flow table from previous priority to
1989  * the next flow table.
1990  */
1991 static int disconnect_flow_table(struct mlx5_flow_table *ft)
1992 {
1993         struct mlx5_core_dev *dev = get_dev(&ft->node);
1994         struct mlx5_flow_table *next_ft;
1995         struct fs_prio *prio;
1996         int err = 0;
1997
1998         err = update_root_ft_destroy(ft);
1999         if (err)
2000                 return err;
2001
2002         fs_get_obj(prio, ft->node.parent);
2003         if  (!(list_first_entry(&prio->node.children,
2004                                 struct mlx5_flow_table,
2005                                 node.list) == ft))
2006                 return 0;
2007
2008         next_ft = find_next_chained_ft(prio);
2009         err = connect_fwd_rules(dev, next_ft, ft);
2010         if (err)
2011                 return err;
2012
2013         err = connect_prev_fts(dev, next_ft, prio);
2014         if (err)
2015                 mlx5_core_warn(dev, "Failed to disconnect flow table %d\n",
2016                                ft->id);
2017         return err;
2018 }
2019
2020 int mlx5_destroy_flow_table(struct mlx5_flow_table *ft)
2021 {
2022         struct mlx5_flow_root_namespace *root = find_root(&ft->node);
2023         int err = 0;
2024
2025         mutex_lock(&root->chain_lock);
2026         err = disconnect_flow_table(ft);
2027         if (err) {
2028                 mutex_unlock(&root->chain_lock);
2029                 return err;
2030         }
2031         if (tree_remove_node(&ft->node))
2032                 mlx5_core_warn(get_dev(&ft->node), "Flow table %d wasn't destroyed, refcount > 1\n",
2033                                ft->id);
2034         mutex_unlock(&root->chain_lock);
2035
2036         return err;
2037 }
2038 EXPORT_SYMBOL(mlx5_destroy_flow_table);
2039
2040 void mlx5_destroy_flow_group(struct mlx5_flow_group *fg)
2041 {
2042         if (tree_remove_node(&fg->node))
2043                 mlx5_core_warn(get_dev(&fg->node), "Flow group %d wasn't destroyed, refcount > 1\n",
2044                                fg->id);
2045 }
2046
2047 struct mlx5_flow_namespace *mlx5_get_flow_namespace(struct mlx5_core_dev *dev,
2048                                                     enum mlx5_flow_namespace_type type)
2049 {
2050         struct mlx5_flow_steering *steering = dev->priv.steering;
2051         struct mlx5_flow_root_namespace *root_ns;
2052         int prio;
2053         struct fs_prio *fs_prio;
2054         struct mlx5_flow_namespace *ns;
2055
2056         if (!steering)
2057                 return NULL;
2058
2059         switch (type) {
2060         case MLX5_FLOW_NAMESPACE_BYPASS:
2061         case MLX5_FLOW_NAMESPACE_LAG:
2062         case MLX5_FLOW_NAMESPACE_OFFLOADS:
2063         case MLX5_FLOW_NAMESPACE_ETHTOOL:
2064         case MLX5_FLOW_NAMESPACE_KERNEL:
2065         case MLX5_FLOW_NAMESPACE_LEFTOVERS:
2066         case MLX5_FLOW_NAMESPACE_ANCHOR:
2067                 prio = type;
2068                 break;
2069         case MLX5_FLOW_NAMESPACE_FDB:
2070                 if (steering->fdb_root_ns)
2071                         return &steering->fdb_root_ns->ns;
2072                 else
2073                         return NULL;
2074         case MLX5_FLOW_NAMESPACE_SNIFFER_RX:
2075                 if (steering->sniffer_rx_root_ns)
2076                         return &steering->sniffer_rx_root_ns->ns;
2077                 else
2078                         return NULL;
2079         case MLX5_FLOW_NAMESPACE_SNIFFER_TX:
2080                 if (steering->sniffer_tx_root_ns)
2081                         return &steering->sniffer_tx_root_ns->ns;
2082                 else
2083                         return NULL;
2084         case MLX5_FLOW_NAMESPACE_EGRESS:
2085                 if (steering->egress_root_ns)
2086                         return &steering->egress_root_ns->ns;
2087                 else
2088                         return NULL;
2089         default:
2090                 return NULL;
2091         }
2092
2093         root_ns = steering->root_ns;
2094         if (!root_ns)
2095                 return NULL;
2096
2097         fs_prio = find_prio(&root_ns->ns, prio);
2098         if (!fs_prio)
2099                 return NULL;
2100
2101         ns = list_first_entry(&fs_prio->node.children,
2102                               typeof(*ns),
2103                               node.list);
2104
2105         return ns;
2106 }
2107 EXPORT_SYMBOL(mlx5_get_flow_namespace);
2108
2109 struct mlx5_flow_namespace *mlx5_get_flow_vport_acl_namespace(struct mlx5_core_dev *dev,
2110                                                               enum mlx5_flow_namespace_type type,
2111                                                               int vport)
2112 {
2113         struct mlx5_flow_steering *steering = dev->priv.steering;
2114
2115         if (!steering || vport >= MLX5_TOTAL_VPORTS(dev))
2116                 return NULL;
2117
2118         switch (type) {
2119         case MLX5_FLOW_NAMESPACE_ESW_EGRESS:
2120                 if (steering->esw_egress_root_ns &&
2121                     steering->esw_egress_root_ns[vport])
2122                         return &steering->esw_egress_root_ns[vport]->ns;
2123                 else
2124                         return NULL;
2125         case MLX5_FLOW_NAMESPACE_ESW_INGRESS:
2126                 if (steering->esw_ingress_root_ns &&
2127                     steering->esw_ingress_root_ns[vport])
2128                         return &steering->esw_ingress_root_ns[vport]->ns;
2129                 else
2130                         return NULL;
2131         default:
2132                 return NULL;
2133         }
2134 }
2135
2136 static struct fs_prio *fs_create_prio(struct mlx5_flow_namespace *ns,
2137                                       unsigned int prio, int num_levels)
2138 {
2139         struct fs_prio *fs_prio;
2140
2141         fs_prio = kzalloc(sizeof(*fs_prio), GFP_KERNEL);
2142         if (!fs_prio)
2143                 return ERR_PTR(-ENOMEM);
2144
2145         fs_prio->node.type = FS_TYPE_PRIO;
2146         tree_init_node(&fs_prio->node, NULL, del_sw_prio);
2147         tree_add_node(&fs_prio->node, &ns->node);
2148         fs_prio->num_levels = num_levels;
2149         fs_prio->prio = prio;
2150         list_add_tail(&fs_prio->node.list, &ns->node.children);
2151
2152         return fs_prio;
2153 }
2154
2155 static struct mlx5_flow_namespace *fs_init_namespace(struct mlx5_flow_namespace
2156                                                      *ns)
2157 {
2158         ns->node.type = FS_TYPE_NAMESPACE;
2159
2160         return ns;
2161 }
2162
2163 static struct mlx5_flow_namespace *fs_create_namespace(struct fs_prio *prio)
2164 {
2165         struct mlx5_flow_namespace      *ns;
2166
2167         ns = kzalloc(sizeof(*ns), GFP_KERNEL);
2168         if (!ns)
2169                 return ERR_PTR(-ENOMEM);
2170
2171         fs_init_namespace(ns);
2172         tree_init_node(&ns->node, NULL, del_sw_ns);
2173         tree_add_node(&ns->node, &prio->node);
2174         list_add_tail(&ns->node.list, &prio->node.children);
2175
2176         return ns;
2177 }
2178
2179 static int create_leaf_prios(struct mlx5_flow_namespace *ns, int prio,
2180                              struct init_tree_node *prio_metadata)
2181 {
2182         struct fs_prio *fs_prio;
2183         int i;
2184
2185         for (i = 0; i < prio_metadata->num_leaf_prios; i++) {
2186                 fs_prio = fs_create_prio(ns, prio++, prio_metadata->num_levels);
2187                 if (IS_ERR(fs_prio))
2188                         return PTR_ERR(fs_prio);
2189         }
2190         return 0;
2191 }
2192
2193 #define FLOW_TABLE_BIT_SZ 1
2194 #define GET_FLOW_TABLE_CAP(dev, offset) \
2195         ((be32_to_cpu(*((__be32 *)(dev->caps.hca_cur[MLX5_CAP_FLOW_TABLE]) +    \
2196                         offset / 32)) >>                                        \
2197           (32 - FLOW_TABLE_BIT_SZ - (offset & 0x1f))) & FLOW_TABLE_BIT_SZ)
2198 static bool has_required_caps(struct mlx5_core_dev *dev, struct node_caps *caps)
2199 {
2200         int i;
2201
2202         for (i = 0; i < caps->arr_sz; i++) {
2203                 if (!GET_FLOW_TABLE_CAP(dev, caps->caps[i]))
2204                         return false;
2205         }
2206         return true;
2207 }
2208
2209 static int init_root_tree_recursive(struct mlx5_flow_steering *steering,
2210                                     struct init_tree_node *init_node,
2211                                     struct fs_node *fs_parent_node,
2212                                     struct init_tree_node *init_parent_node,
2213                                     int prio)
2214 {
2215         int max_ft_level = MLX5_CAP_FLOWTABLE(steering->dev,
2216                                               flow_table_properties_nic_receive.
2217                                               max_ft_level);
2218         struct mlx5_flow_namespace *fs_ns;
2219         struct fs_prio *fs_prio;
2220         struct fs_node *base;
2221         int i;
2222         int err;
2223
2224         if (init_node->type == FS_TYPE_PRIO) {
2225                 if ((init_node->min_ft_level > max_ft_level) ||
2226                     !has_required_caps(steering->dev, &init_node->caps))
2227                         return 0;
2228
2229                 fs_get_obj(fs_ns, fs_parent_node);
2230                 if (init_node->num_leaf_prios)
2231                         return create_leaf_prios(fs_ns, prio, init_node);
2232                 fs_prio = fs_create_prio(fs_ns, prio, init_node->num_levels);
2233                 if (IS_ERR(fs_prio))
2234                         return PTR_ERR(fs_prio);
2235                 base = &fs_prio->node;
2236         } else if (init_node->type == FS_TYPE_NAMESPACE) {
2237                 fs_get_obj(fs_prio, fs_parent_node);
2238                 fs_ns = fs_create_namespace(fs_prio);
2239                 if (IS_ERR(fs_ns))
2240                         return PTR_ERR(fs_ns);
2241                 base = &fs_ns->node;
2242         } else {
2243                 return -EINVAL;
2244         }
2245         prio = 0;
2246         for (i = 0; i < init_node->ar_size; i++) {
2247                 err = init_root_tree_recursive(steering, &init_node->children[i],
2248                                                base, init_node, prio);
2249                 if (err)
2250                         return err;
2251                 if (init_node->children[i].type == FS_TYPE_PRIO &&
2252                     init_node->children[i].num_leaf_prios) {
2253                         prio += init_node->children[i].num_leaf_prios;
2254                 }
2255         }
2256
2257         return 0;
2258 }
2259
2260 static int init_root_tree(struct mlx5_flow_steering *steering,
2261                           struct init_tree_node *init_node,
2262                           struct fs_node *fs_parent_node)
2263 {
2264         int i;
2265         struct mlx5_flow_namespace *fs_ns;
2266         int err;
2267
2268         fs_get_obj(fs_ns, fs_parent_node);
2269         for (i = 0; i < init_node->ar_size; i++) {
2270                 err = init_root_tree_recursive(steering, &init_node->children[i],
2271                                                &fs_ns->node,
2272                                                init_node, i);
2273                 if (err)
2274                         return err;
2275         }
2276         return 0;
2277 }
2278
2279 static struct mlx5_flow_root_namespace
2280 *create_root_ns(struct mlx5_flow_steering *steering,
2281                 enum fs_flow_table_type table_type)
2282 {
2283         const struct mlx5_flow_cmds *cmds = mlx5_fs_cmd_get_default(table_type);
2284         struct mlx5_flow_root_namespace *root_ns;
2285         struct mlx5_flow_namespace *ns;
2286
2287         if (mlx5_accel_ipsec_device_caps(steering->dev) & MLX5_ACCEL_IPSEC_CAP_DEVICE &&
2288             (table_type == FS_FT_NIC_RX || table_type == FS_FT_NIC_TX))
2289                 cmds = mlx5_fs_cmd_get_default_ipsec_fpga_cmds(table_type);
2290
2291         /* Create the root namespace */
2292         root_ns = kvzalloc(sizeof(*root_ns), GFP_KERNEL);
2293         if (!root_ns)
2294                 return NULL;
2295
2296         root_ns->dev = steering->dev;
2297         root_ns->table_type = table_type;
2298         root_ns->cmds = cmds;
2299
2300         INIT_LIST_HEAD(&root_ns->underlay_qpns);
2301
2302         ns = &root_ns->ns;
2303         fs_init_namespace(ns);
2304         mutex_init(&root_ns->chain_lock);
2305         tree_init_node(&ns->node, NULL, NULL);
2306         tree_add_node(&ns->node, NULL);
2307
2308         return root_ns;
2309 }
2310
2311 static void set_prio_attrs_in_prio(struct fs_prio *prio, int acc_level);
2312
2313 static int set_prio_attrs_in_ns(struct mlx5_flow_namespace *ns, int acc_level)
2314 {
2315         struct fs_prio *prio;
2316
2317         fs_for_each_prio(prio, ns) {
2318                  /* This updates prio start_level and num_levels */
2319                 set_prio_attrs_in_prio(prio, acc_level);
2320                 acc_level += prio->num_levels;
2321         }
2322         return acc_level;
2323 }
2324
2325 static void set_prio_attrs_in_prio(struct fs_prio *prio, int acc_level)
2326 {
2327         struct mlx5_flow_namespace *ns;
2328         int acc_level_ns = acc_level;
2329
2330         prio->start_level = acc_level;
2331         fs_for_each_ns(ns, prio)
2332                 /* This updates start_level and num_levels of ns's priority descendants */
2333                 acc_level_ns = set_prio_attrs_in_ns(ns, acc_level);
2334         if (!prio->num_levels)
2335                 prio->num_levels = acc_level_ns - prio->start_level;
2336         WARN_ON(prio->num_levels < acc_level_ns - prio->start_level);
2337 }
2338
2339 static void set_prio_attrs(struct mlx5_flow_root_namespace *root_ns)
2340 {
2341         struct mlx5_flow_namespace *ns = &root_ns->ns;
2342         struct fs_prio *prio;
2343         int start_level = 0;
2344
2345         fs_for_each_prio(prio, ns) {
2346                 set_prio_attrs_in_prio(prio, start_level);
2347                 start_level += prio->num_levels;
2348         }
2349 }
2350
2351 #define ANCHOR_PRIO 0
2352 #define ANCHOR_SIZE 1
2353 #define ANCHOR_LEVEL 0
2354 static int create_anchor_flow_table(struct mlx5_flow_steering *steering)
2355 {
2356         struct mlx5_flow_namespace *ns = NULL;
2357         struct mlx5_flow_table_attr ft_attr = {};
2358         struct mlx5_flow_table *ft;
2359
2360         ns = mlx5_get_flow_namespace(steering->dev, MLX5_FLOW_NAMESPACE_ANCHOR);
2361         if (WARN_ON(!ns))
2362                 return -EINVAL;
2363
2364         ft_attr.max_fte = ANCHOR_SIZE;
2365         ft_attr.level   = ANCHOR_LEVEL;
2366         ft_attr.prio    = ANCHOR_PRIO;
2367
2368         ft = mlx5_create_flow_table(ns, &ft_attr);
2369         if (IS_ERR(ft)) {
2370                 mlx5_core_err(steering->dev, "Failed to create last anchor flow table");
2371                 return PTR_ERR(ft);
2372         }
2373         return 0;
2374 }
2375
2376 static int init_root_ns(struct mlx5_flow_steering *steering)
2377 {
2378         int err;
2379
2380         steering->root_ns = create_root_ns(steering, FS_FT_NIC_RX);
2381         if (!steering->root_ns)
2382                 return -ENOMEM;
2383
2384         err = init_root_tree(steering, &root_fs, &steering->root_ns->ns.node);
2385         if (err)
2386                 goto out_err;
2387
2388         set_prio_attrs(steering->root_ns);
2389         err = create_anchor_flow_table(steering);
2390         if (err)
2391                 goto out_err;
2392
2393         return 0;
2394
2395 out_err:
2396         cleanup_root_ns(steering->root_ns);
2397         steering->root_ns = NULL;
2398         return err;
2399 }
2400
2401 static void clean_tree(struct fs_node *node)
2402 {
2403         if (node) {
2404                 struct fs_node *iter;
2405                 struct fs_node *temp;
2406
2407                 tree_get_node(node);
2408                 list_for_each_entry_safe(iter, temp, &node->children, list)
2409                         clean_tree(iter);
2410                 tree_put_node(node);
2411                 tree_remove_node(node);
2412         }
2413 }
2414
2415 static void cleanup_root_ns(struct mlx5_flow_root_namespace *root_ns)
2416 {
2417         if (!root_ns)
2418                 return;
2419
2420         clean_tree(&root_ns->ns.node);
2421 }
2422
2423 static void cleanup_egress_acls_root_ns(struct mlx5_core_dev *dev)
2424 {
2425         struct mlx5_flow_steering *steering = dev->priv.steering;
2426         int i;
2427
2428         if (!steering->esw_egress_root_ns)
2429                 return;
2430
2431         for (i = 0; i < MLX5_TOTAL_VPORTS(dev); i++)
2432                 cleanup_root_ns(steering->esw_egress_root_ns[i]);
2433
2434         kfree(steering->esw_egress_root_ns);
2435 }
2436
2437 static void cleanup_ingress_acls_root_ns(struct mlx5_core_dev *dev)
2438 {
2439         struct mlx5_flow_steering *steering = dev->priv.steering;
2440         int i;
2441
2442         if (!steering->esw_ingress_root_ns)
2443                 return;
2444
2445         for (i = 0; i < MLX5_TOTAL_VPORTS(dev); i++)
2446                 cleanup_root_ns(steering->esw_ingress_root_ns[i]);
2447
2448         kfree(steering->esw_ingress_root_ns);
2449 }
2450
2451 void mlx5_cleanup_fs(struct mlx5_core_dev *dev)
2452 {
2453         struct mlx5_flow_steering *steering = dev->priv.steering;
2454
2455         cleanup_root_ns(steering->root_ns);
2456         cleanup_egress_acls_root_ns(dev);
2457         cleanup_ingress_acls_root_ns(dev);
2458         cleanup_root_ns(steering->fdb_root_ns);
2459         cleanup_root_ns(steering->sniffer_rx_root_ns);
2460         cleanup_root_ns(steering->sniffer_tx_root_ns);
2461         cleanup_root_ns(steering->egress_root_ns);
2462         mlx5_cleanup_fc_stats(dev);
2463         kmem_cache_destroy(steering->ftes_cache);
2464         kmem_cache_destroy(steering->fgs_cache);
2465         kfree(steering);
2466 }
2467
2468 static int init_sniffer_tx_root_ns(struct mlx5_flow_steering *steering)
2469 {
2470         struct fs_prio *prio;
2471
2472         steering->sniffer_tx_root_ns = create_root_ns(steering, FS_FT_SNIFFER_TX);
2473         if (!steering->sniffer_tx_root_ns)
2474                 return -ENOMEM;
2475
2476         /* Create single prio */
2477         prio = fs_create_prio(&steering->sniffer_tx_root_ns->ns, 0, 1);
2478         if (IS_ERR(prio)) {
2479                 cleanup_root_ns(steering->sniffer_tx_root_ns);
2480                 return PTR_ERR(prio);
2481         }
2482         return 0;
2483 }
2484
2485 static int init_sniffer_rx_root_ns(struct mlx5_flow_steering *steering)
2486 {
2487         struct fs_prio *prio;
2488
2489         steering->sniffer_rx_root_ns = create_root_ns(steering, FS_FT_SNIFFER_RX);
2490         if (!steering->sniffer_rx_root_ns)
2491                 return -ENOMEM;
2492
2493         /* Create single prio */
2494         prio = fs_create_prio(&steering->sniffer_rx_root_ns->ns, 0, 1);
2495         if (IS_ERR(prio)) {
2496                 cleanup_root_ns(steering->sniffer_rx_root_ns);
2497                 return PTR_ERR(prio);
2498         }
2499         return 0;
2500 }
2501
2502 static int init_fdb_root_ns(struct mlx5_flow_steering *steering)
2503 {
2504         struct fs_prio *prio;
2505
2506         steering->fdb_root_ns = create_root_ns(steering, FS_FT_FDB);
2507         if (!steering->fdb_root_ns)
2508                 return -ENOMEM;
2509
2510         prio = fs_create_prio(&steering->fdb_root_ns->ns, 0, 2);
2511         if (IS_ERR(prio))
2512                 goto out_err;
2513
2514         prio = fs_create_prio(&steering->fdb_root_ns->ns, 1, 1);
2515         if (IS_ERR(prio))
2516                 goto out_err;
2517
2518         set_prio_attrs(steering->fdb_root_ns);
2519         return 0;
2520
2521 out_err:
2522         cleanup_root_ns(steering->fdb_root_ns);
2523         steering->fdb_root_ns = NULL;
2524         return PTR_ERR(prio);
2525 }
2526
2527 static int init_egress_acl_root_ns(struct mlx5_flow_steering *steering, int vport)
2528 {
2529         struct fs_prio *prio;
2530
2531         steering->esw_egress_root_ns[vport] = create_root_ns(steering, FS_FT_ESW_EGRESS_ACL);
2532         if (!steering->esw_egress_root_ns[vport])
2533                 return -ENOMEM;
2534
2535         /* create 1 prio*/
2536         prio = fs_create_prio(&steering->esw_egress_root_ns[vport]->ns, 0, 1);
2537         return PTR_ERR_OR_ZERO(prio);
2538 }
2539
2540 static int init_ingress_acl_root_ns(struct mlx5_flow_steering *steering, int vport)
2541 {
2542         struct fs_prio *prio;
2543
2544         steering->esw_ingress_root_ns[vport] = create_root_ns(steering, FS_FT_ESW_INGRESS_ACL);
2545         if (!steering->esw_ingress_root_ns[vport])
2546                 return -ENOMEM;
2547
2548         /* create 1 prio*/
2549         prio = fs_create_prio(&steering->esw_ingress_root_ns[vport]->ns, 0, 1);
2550         return PTR_ERR_OR_ZERO(prio);
2551 }
2552
2553 static int init_egress_acls_root_ns(struct mlx5_core_dev *dev)
2554 {
2555         struct mlx5_flow_steering *steering = dev->priv.steering;
2556         int err;
2557         int i;
2558
2559         steering->esw_egress_root_ns = kcalloc(MLX5_TOTAL_VPORTS(dev),
2560                                                sizeof(*steering->esw_egress_root_ns),
2561                                                GFP_KERNEL);
2562         if (!steering->esw_egress_root_ns)
2563                 return -ENOMEM;
2564
2565         for (i = 0; i < MLX5_TOTAL_VPORTS(dev); i++) {
2566                 err = init_egress_acl_root_ns(steering, i);
2567                 if (err)
2568                         goto cleanup_root_ns;
2569         }
2570
2571         return 0;
2572
2573 cleanup_root_ns:
2574         for (i--; i >= 0; i--)
2575                 cleanup_root_ns(steering->esw_egress_root_ns[i]);
2576         kfree(steering->esw_egress_root_ns);
2577         return err;
2578 }
2579
2580 static int init_ingress_acls_root_ns(struct mlx5_core_dev *dev)
2581 {
2582         struct mlx5_flow_steering *steering = dev->priv.steering;
2583         int err;
2584         int i;
2585
2586         steering->esw_ingress_root_ns = kcalloc(MLX5_TOTAL_VPORTS(dev),
2587                                                 sizeof(*steering->esw_ingress_root_ns),
2588                                                 GFP_KERNEL);
2589         if (!steering->esw_ingress_root_ns)
2590                 return -ENOMEM;
2591
2592         for (i = 0; i < MLX5_TOTAL_VPORTS(dev); i++) {
2593                 err = init_ingress_acl_root_ns(steering, i);
2594                 if (err)
2595                         goto cleanup_root_ns;
2596         }
2597
2598         return 0;
2599
2600 cleanup_root_ns:
2601         for (i--; i >= 0; i--)
2602                 cleanup_root_ns(steering->esw_ingress_root_ns[i]);
2603         kfree(steering->esw_ingress_root_ns);
2604         return err;
2605 }
2606
2607 static int init_egress_root_ns(struct mlx5_flow_steering *steering)
2608 {
2609         struct fs_prio *prio;
2610
2611         steering->egress_root_ns = create_root_ns(steering,
2612                                                   FS_FT_NIC_TX);
2613         if (!steering->egress_root_ns)
2614                 return -ENOMEM;
2615
2616         /* create 1 prio*/
2617         prio = fs_create_prio(&steering->egress_root_ns->ns, 0, 1);
2618         return PTR_ERR_OR_ZERO(prio);
2619 }
2620
2621 int mlx5_init_fs(struct mlx5_core_dev *dev)
2622 {
2623         struct mlx5_flow_steering *steering;
2624         int err = 0;
2625
2626         err = mlx5_init_fc_stats(dev);
2627         if (err)
2628                 return err;
2629
2630         steering = kzalloc(sizeof(*steering), GFP_KERNEL);
2631         if (!steering)
2632                 return -ENOMEM;
2633         steering->dev = dev;
2634         dev->priv.steering = steering;
2635
2636         steering->fgs_cache = kmem_cache_create("mlx5_fs_fgs",
2637                                                 sizeof(struct mlx5_flow_group), 0,
2638                                                 0, NULL);
2639         steering->ftes_cache = kmem_cache_create("mlx5_fs_ftes", sizeof(struct fs_fte), 0,
2640                                                  0, NULL);
2641         if (!steering->ftes_cache || !steering->fgs_cache) {
2642                 err = -ENOMEM;
2643                 goto err;
2644         }
2645
2646         if ((((MLX5_CAP_GEN(dev, port_type) == MLX5_CAP_PORT_TYPE_ETH) &&
2647               (MLX5_CAP_GEN(dev, nic_flow_table))) ||
2648              ((MLX5_CAP_GEN(dev, port_type) == MLX5_CAP_PORT_TYPE_IB) &&
2649               MLX5_CAP_GEN(dev, ipoib_enhanced_offloads))) &&
2650             MLX5_CAP_FLOWTABLE_NIC_RX(dev, ft_support)) {
2651                 err = init_root_ns(steering);
2652                 if (err)
2653                         goto err;
2654         }
2655
2656         if (MLX5_ESWITCH_MANAGER(dev)) {
2657                 if (MLX5_CAP_ESW_FLOWTABLE_FDB(dev, ft_support)) {
2658                         err = init_fdb_root_ns(steering);
2659                         if (err)
2660                                 goto err;
2661                 }
2662                 if (MLX5_CAP_ESW_EGRESS_ACL(dev, ft_support)) {
2663                         err = init_egress_acls_root_ns(dev);
2664                         if (err)
2665                                 goto err;
2666                 }
2667                 if (MLX5_CAP_ESW_INGRESS_ACL(dev, ft_support)) {
2668                         err = init_ingress_acls_root_ns(dev);
2669                         if (err)
2670                                 goto err;
2671                 }
2672         }
2673
2674         if (MLX5_CAP_FLOWTABLE_SNIFFER_RX(dev, ft_support)) {
2675                 err = init_sniffer_rx_root_ns(steering);
2676                 if (err)
2677                         goto err;
2678         }
2679
2680         if (MLX5_CAP_FLOWTABLE_SNIFFER_TX(dev, ft_support)) {
2681                 err = init_sniffer_tx_root_ns(steering);
2682                 if (err)
2683                         goto err;
2684         }
2685
2686         if (MLX5_IPSEC_DEV(dev)) {
2687                 err = init_egress_root_ns(steering);
2688                 if (err)
2689                         goto err;
2690         }
2691
2692         return 0;
2693 err:
2694         mlx5_cleanup_fs(dev);
2695         return err;
2696 }
2697
2698 int mlx5_fs_add_rx_underlay_qpn(struct mlx5_core_dev *dev, u32 underlay_qpn)
2699 {
2700         struct mlx5_flow_root_namespace *root = dev->priv.steering->root_ns;
2701         struct mlx5_ft_underlay_qp *new_uqp;
2702         int err = 0;
2703
2704         new_uqp = kzalloc(sizeof(*new_uqp), GFP_KERNEL);
2705         if (!new_uqp)
2706                 return -ENOMEM;
2707
2708         mutex_lock(&root->chain_lock);
2709
2710         if (!root->root_ft) {
2711                 err = -EINVAL;
2712                 goto update_ft_fail;
2713         }
2714
2715         err = root->cmds->update_root_ft(dev, root->root_ft, underlay_qpn,
2716                                          false);
2717         if (err) {
2718                 mlx5_core_warn(dev, "Failed adding underlay QPN (%u) to root FT err(%d)\n",
2719                                underlay_qpn, err);
2720                 goto update_ft_fail;
2721         }
2722
2723         new_uqp->qpn = underlay_qpn;
2724         list_add_tail(&new_uqp->list, &root->underlay_qpns);
2725
2726         mutex_unlock(&root->chain_lock);
2727
2728         return 0;
2729
2730 update_ft_fail:
2731         mutex_unlock(&root->chain_lock);
2732         kfree(new_uqp);
2733         return err;
2734 }
2735 EXPORT_SYMBOL(mlx5_fs_add_rx_underlay_qpn);
2736
2737 int mlx5_fs_remove_rx_underlay_qpn(struct mlx5_core_dev *dev, u32 underlay_qpn)
2738 {
2739         struct mlx5_flow_root_namespace *root = dev->priv.steering->root_ns;
2740         struct mlx5_ft_underlay_qp *uqp;
2741         bool found = false;
2742         int err = 0;
2743
2744         mutex_lock(&root->chain_lock);
2745         list_for_each_entry(uqp, &root->underlay_qpns, list) {
2746                 if (uqp->qpn == underlay_qpn) {
2747                         found = true;
2748                         break;
2749                 }
2750         }
2751
2752         if (!found) {
2753                 mlx5_core_warn(dev, "Failed finding underlay qp (%u) in qpn list\n",
2754                                underlay_qpn);
2755                 err = -EINVAL;
2756                 goto out;
2757         }
2758
2759         err = root->cmds->update_root_ft(dev, root->root_ft, underlay_qpn,
2760                                          true);
2761         if (err)
2762                 mlx5_core_warn(dev, "Failed removing underlay QPN (%u) from root FT err(%d)\n",
2763                                underlay_qpn, err);
2764
2765         list_del(&uqp->list);
2766         mutex_unlock(&root->chain_lock);
2767         kfree(uqp);
2768
2769         return 0;
2770
2771 out:
2772         mutex_unlock(&root->chain_lock);
2773         return err;
2774 }
2775 EXPORT_SYMBOL(mlx5_fs_remove_rx_underlay_qpn);