aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
diff options
context:
space:
mode:
authorVlad Buslov <vladbu@mellanox.com>2019-07-31 18:19:06 +0300
committerSaeed Mahameed <saeedm@mellanox.com>2019-08-09 14:54:08 -0700
commitb32accda8afd36d7de1581375467fd3642d3c73e (patch)
tree948768d121b0c6dc17c0d9cad3dd9fdc9c61d1dd /drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
parentnet/mlx5e: Protect hairpin entry flows list with spinlock (diff)
downloadlinux-dev-b32accda8afd36d7de1581375467fd3642d3c73e.tar.xz
linux-dev-b32accda8afd36d7de1581375467fd3642d3c73e.zip
net/mlx5e: Protect hairpin hash table with mutex
To remove dependency on rtnl lock, protect hairpin hash table from concurrent modifications with new "hairpin_tbl_lock" mutex. Signed-off-by: Vlad Buslov <vladbu@mellanox.com> Reviewed-by: Roi Dayan <roid@mellanox.com> Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
Diffstat (limited to 'drivers/net/ethernet/mellanox/mlx5/core/en_tc.c')
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_tc.c21
1 files changed, 17 insertions, 4 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
index 0abfa9b3ec54..a7acb7fcbf5a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
@@ -652,15 +652,16 @@ static void mlx5e_hairpin_put(struct mlx5e_priv *priv,
struct mlx5e_hairpin_entry *hpe)
{
/* no more hairpin flows for us, release the hairpin pair */
- if (!refcount_dec_and_test(&hpe->refcnt))
+ if (!refcount_dec_and_mutex_lock(&hpe->refcnt, &priv->fs.tc.hairpin_tbl_lock))
return;
+ hash_del(&hpe->hairpin_hlist);
+ mutex_unlock(&priv->fs.tc.hairpin_tbl_lock);
netdev_dbg(priv->netdev, "del hairpin: peer %s\n",
dev_name(hpe->hp->pair->peer_mdev->device));
WARN_ON(!list_empty(&hpe->flows));
mlx5e_hairpin_destroy(hpe->hp);
- hash_del(&hpe->hairpin_hlist);
kfree(hpe);
}
@@ -729,13 +730,17 @@ static int mlx5e_hairpin_flow_add(struct mlx5e_priv *priv,
extack);
if (err)
return err;
+
+ mutex_lock(&priv->fs.tc.hairpin_tbl_lock);
hpe = mlx5e_hairpin_get(priv, peer_id, match_prio);
if (hpe)
goto attach_flow;
hpe = kzalloc(sizeof(*hpe), GFP_KERNEL);
- if (!hpe)
- return -ENOMEM;
+ if (!hpe) {
+ err = -ENOMEM;
+ goto create_hairpin_err;
+ }
spin_lock_init(&hpe->flows_lock);
INIT_LIST_HEAD(&hpe->flows);
@@ -784,6 +789,8 @@ attach_flow:
} else {
flow->nic_attr->hairpin_tirn = hpe->hp->tirn;
}
+ mutex_unlock(&priv->fs.tc.hairpin_tbl_lock);
+
flow->hpe = hpe;
spin_lock(&hpe->flows_lock);
list_add(&flow->hairpin, &hpe->flows);
@@ -792,6 +799,7 @@ attach_flow:
return 0;
create_hairpin_err:
+ mutex_unlock(&priv->fs.tc.hairpin_tbl_lock);
kfree(hpe);
return err;
}
@@ -3768,10 +3776,12 @@ static void mlx5e_tc_hairpin_update_dead_peer(struct mlx5e_priv *priv,
peer_vhca_id = MLX5_CAP_GEN(peer_mdev, vhca_id);
+ mutex_lock(&priv->fs.tc.hairpin_tbl_lock);
hash_for_each(priv->fs.tc.hairpin_tbl, bkt, hpe, hairpin_hlist) {
if (hpe->peer_vhca_id == peer_vhca_id)
hpe->hp->pair->peer_gone = true;
}
+ mutex_unlock(&priv->fs.tc.hairpin_tbl_lock);
}
static int mlx5e_tc_netdev_event(struct notifier_block *this,
@@ -3808,6 +3818,7 @@ int mlx5e_tc_nic_init(struct mlx5e_priv *priv)
mutex_init(&tc->t_lock);
hash_init(tc->mod_hdr_tbl);
+ mutex_init(&tc->hairpin_tbl_lock);
hash_init(tc->hairpin_tbl);
err = rhashtable_init(&tc->ht, &tc_ht_params);
@@ -3839,6 +3850,8 @@ void mlx5e_tc_nic_cleanup(struct mlx5e_priv *priv)
if (tc->netdevice_nb.notifier_call)
unregister_netdevice_notifier(&tc->netdevice_nb);
+ mutex_destroy(&tc->hairpin_tbl_lock);
+
rhashtable_destroy(&tc->ht);
if (!IS_ERR_OR_NULL(tc->t)) {