aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaor Gottlieb <maorg@mellanox.com>2016-04-21 17:33:00 -0400
committerDavid S. Miller <davem@davemloft.net>2016-04-24 14:51:38 -0400
commitc3f9bf628bc7edda298897d952f5e761137229c9 (patch)
tree0e82ce86364cd38cfd80f19010e6b9b04294c907
parent45c78e0219405af1b0f31b06952dfd9bcf7ad1f6 (diff)
net/mlx5_core: Fix soft lockup in steering error flow
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>
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/fs_core.c46
1 files changed, 17 insertions, 29 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
index 5121be4675d1..3c7e3e581835 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
@@ -1065,33 +1065,6 @@ unlock_fg:
1065 return rule; 1065 return rule;
1066} 1066}
1067 1067
1068static struct mlx5_flow_rule *add_rule_to_auto_fg(struct mlx5_flow_table *ft,
1069 u8 match_criteria_enable,
1070 u32 *match_criteria,
1071 u32 *match_value,
1072 u8 action,
1073 u32 flow_tag,
1074 struct mlx5_flow_destination *dest)
1075{
1076 struct mlx5_flow_rule *rule;
1077 struct mlx5_flow_group *g;
1078
1079 g = create_autogroup(ft, match_criteria_enable, match_criteria);
1080 if (IS_ERR(g))
1081 return (void *)g;
1082
1083 rule = add_rule_fg(g, match_value,
1084 action, flow_tag, dest);
1085 if (IS_ERR(rule)) {
1086 /* Remove assumes refcount > 0 and autogroup creates a group
1087 * with a refcount = 0.
1088 */
1089 tree_get_node(&g->node);
1090 tree_remove_node(&g->node);
1091 }
1092 return rule;
1093}
1094
1095static struct mlx5_flow_rule * 1068static struct mlx5_flow_rule *
1096_mlx5_add_flow_rule(struct mlx5_flow_table *ft, 1069_mlx5_add_flow_rule(struct mlx5_flow_table *ft,
1097 u8 match_criteria_enable, 1070 u8 match_criteria_enable,
@@ -1119,8 +1092,23 @@ _mlx5_add_flow_rule(struct mlx5_flow_table *ft,
1119 goto unlock; 1092 goto unlock;
1120 } 1093 }
1121 1094
1122 rule = add_rule_to_auto_fg(ft, match_criteria_enable, match_criteria, 1095 g = create_autogroup(ft, match_criteria_enable, match_criteria);
1123 match_value, action, flow_tag, dest); 1096 if (IS_ERR(g)) {
1097 rule = (void *)g;
1098 goto unlock;
1099 }
1100
1101 rule = add_rule_fg(g, match_value,
1102 action, flow_tag, dest);
1103 if (IS_ERR(rule)) {
1104 /* Remove assumes refcount > 0 and autogroup creates a group
1105 * with a refcount = 0.
1106 */
1107 unlock_ref_node(&ft->node);
1108 tree_get_node(&g->node);
1109 tree_remove_node(&g->node);
1110 return rule;
1111 }
1124unlock: 1112unlock:
1125 unlock_ref_node(&ft->node); 1113 unlock_ref_node(&ft->node);
1126 return rule; 1114 return rule;