]> git.hungrycats.org Git - linux/commitdiff
net/mlx5_core: Fix soft lockup in steering error flow
authorMaor Gottlieb <maorg@mellanox.com>
Thu, 21 Apr 2016 21:33:00 +0000 (00:33 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 19 May 2016 01:35:02 +0000 (18:35 -0700)
[ Upstream commit c3f9bf628bc7edda298897d952f5e761137229c9 ]

In the error flow of adding flow rule to auto-grouped flow
table, we call to tree_remove_node.

tree_remove_node locks the node's parent, however the node's parent
is already locked by mlx5_add_flow_rule and this causes a deadlock.
After this patch, if we failed to add the flow rule, we unlock the
flow table before calling to tree_remove_node.

fixes: f0d22d187473 ('net/mlx5_core: Introduce flow steering autogrouped
flow table')
Signed-off-by: Maor Gottlieb <maorg@mellanox.com>
Reported-by: Amir Vadai <amir@vadai.me>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/net/ethernet/mellanox/mlx5/core/fs_core.c

index 6f68dba8d7edcfb212e23461d20b8bd24a3d6723..cc901852f1a9a4411d3332d52bcb822d2cde4416 100644 (file)
@@ -957,33 +957,6 @@ unlock_fg:
        return rule;
 }
 
-static struct mlx5_flow_rule *add_rule_to_auto_fg(struct mlx5_flow_table *ft,
-                                                 u8 match_criteria_enable,
-                                                 u32 *match_criteria,
-                                                 u32 *match_value,
-                                                 u8 action,
-                                                 u32 flow_tag,
-                                                 struct mlx5_flow_destination *dest)
-{
-       struct mlx5_flow_rule *rule;
-       struct mlx5_flow_group *g;
-
-       g = create_autogroup(ft, match_criteria_enable, match_criteria);
-       if (IS_ERR(g))
-               return (void *)g;
-
-       rule = add_rule_fg(g, match_value,
-                          action, flow_tag, dest);
-       if (IS_ERR(rule)) {
-               /* Remove assumes refcount > 0 and autogroup creates a group
-                * with a refcount = 0.
-                */
-               tree_get_node(&g->node);
-               tree_remove_node(&g->node);
-       }
-       return rule;
-}
-
 struct mlx5_flow_rule *
 mlx5_add_flow_rule(struct mlx5_flow_table *ft,
                   u8 match_criteria_enable,
@@ -1008,8 +981,23 @@ mlx5_add_flow_rule(struct mlx5_flow_table *ft,
                                goto unlock;
                }
 
-       rule = add_rule_to_auto_fg(ft, match_criteria_enable, match_criteria,
-                                  match_value, action, flow_tag, dest);
+       g = create_autogroup(ft, match_criteria_enable, match_criteria);
+       if (IS_ERR(g)) {
+               rule = (void *)g;
+               goto unlock;
+       }
+
+       rule = add_rule_fg(g, match_value,
+                          action, flow_tag, dest);
+       if (IS_ERR(rule)) {
+               /* Remove assumes refcount > 0 and autogroup creates a group
+                * with a refcount = 0.
+                */
+               unlock_ref_node(&ft->node);
+               tree_get_node(&g->node);
+               tree_remove_node(&g->node);
+               return rule;
+       }
 unlock:
        unlock_ref_node(&ft->node);
        return rule;