net/mlx5: fs_core: Introduce unmanaged flow tables
[linux-2.6-microblaze.git] / drivers / net / ethernet / mellanox / mlx5 / core / fs_core.c
index 51913e2..456d373 100644 (file)
@@ -1006,7 +1006,8 @@ static struct mlx5_flow_table *__mlx5_create_flow_table(struct mlx5_flow_namespa
                                                        u16 vport)
 {
        struct mlx5_flow_root_namespace *root = find_root(&ns->node);
-       struct mlx5_flow_table *next_ft = NULL;
+       bool unmanaged = ft_attr->flags & MLX5_FLOW_TABLE_UNMANAGED;
+       struct mlx5_flow_table *next_ft;
        struct fs_prio *fs_prio = NULL;
        struct mlx5_flow_table *ft;
        int log_table_sz;
@@ -1023,14 +1024,21 @@ static struct mlx5_flow_table *__mlx5_create_flow_table(struct mlx5_flow_namespa
                err = -EINVAL;
                goto unlock_root;
        }
-       if (ft_attr->level >= fs_prio->num_levels) {
-               err = -ENOSPC;
-               goto unlock_root;
+       if (!unmanaged) {
+               /* The level is related to the
+                * priority level range.
+                */
+               if (ft_attr->level >= fs_prio->num_levels) {
+                       err = -ENOSPC;
+                       goto unlock_root;
+               }
+
+               ft_attr->level += fs_prio->start_level;
        }
+
        /* The level is related to the
         * priority level range.
         */
-       ft_attr->level += fs_prio->start_level;
        ft = alloc_flow_table(ft_attr->level,
                              vport,
                              ft_attr->max_fte ? roundup_pow_of_two(ft_attr->max_fte) : 0,
@@ -1043,19 +1051,27 @@ static struct mlx5_flow_table *__mlx5_create_flow_table(struct mlx5_flow_namespa
 
        tree_init_node(&ft->node, del_hw_flow_table, del_sw_flow_table);
        log_table_sz = ft->max_fte ? ilog2(ft->max_fte) : 0;
-       next_ft = find_next_chained_ft(fs_prio);
+       next_ft = unmanaged ? ft_attr->next_ft :
+                             find_next_chained_ft(fs_prio);
        ft->def_miss_action = ns->def_miss_action;
        err = root->cmds->create_flow_table(root, ft, log_table_sz, next_ft);
        if (err)
                goto free_ft;
 
-       err = connect_flow_table(root->dev, ft, fs_prio);
-       if (err)
-               goto destroy_ft;
+       if (!unmanaged) {
+               err = connect_flow_table(root->dev, ft, fs_prio);
+               if (err)
+                       goto destroy_ft;
+       }
+
        ft->node.active = true;
        down_write_ref_node(&fs_prio->node, false);
-       tree_add_node(&ft->node, &fs_prio->node);
-       list_add_flow_table(ft, fs_prio);
+       if (!unmanaged) {
+               tree_add_node(&ft->node, &fs_prio->node);
+               list_add_flow_table(ft, fs_prio);
+       } else {
+               ft->node.root = fs_prio->node.root;
+       }
        fs_prio->num_ft++;
        up_write_ref_node(&fs_prio->node, false);
        mutex_unlock(&root->chain_lock);
@@ -2024,7 +2040,8 @@ int mlx5_destroy_flow_table(struct mlx5_flow_table *ft)
        int err = 0;
 
        mutex_lock(&root->chain_lock);
-       err = disconnect_flow_table(ft);
+       if (!(ft->flags & MLX5_FLOW_TABLE_UNMANAGED))
+               err = disconnect_flow_table(ft);
        if (err) {
                mutex_unlock(&root->chain_lock);
                return err;