Commit 70e83bd3 authored by Vlad Buslov's avatar Vlad Buslov Committed by Saeed Mahameed

net/mlx5e: Refactor mlx5e_neigh_update_table->encap_lock

To remove dependency on rtnl lock, always take neigh update encap lock when
modifying neigh update hash table and list. Originally, this lock was only
used to synchronize with netevent handler function, which is called from bh
context and cannot use rtnl lock for synchronization. Take lock in encap
entry attach function to prevent concurrent modifications of neigh update
hash table and list.

Taking the encap lock when creating new nhe introduces a problem that we
need to allocate new entry with sleeping GFP_KERNEL flag while holding a
spinlock. However, since previous patch in this series has already
converted lookup in netevent handler function to user rcu read lock instead
of encap lock, we can safely convert the lock type to mutex.
Signed-off-by: default avatarVlad Buslov <vladbu@mellanox.com>
Reviewed-by: default avatarJianbo Liu <jianbol@mellanox.com>
Reviewed-by: default avatarRoi Dayan <roid@mellanox.com>
Signed-off-by: default avatarSaeed Mahameed <saeedm@mellanox.com>
parent 1216ce9d
...@@ -973,7 +973,7 @@ static int mlx5e_rep_neigh_init(struct mlx5e_rep_priv *rpriv) ...@@ -973,7 +973,7 @@ static int mlx5e_rep_neigh_init(struct mlx5e_rep_priv *rpriv)
return err; return err;
INIT_LIST_HEAD(&neigh_update->neigh_list); INIT_LIST_HEAD(&neigh_update->neigh_list);
spin_lock_init(&neigh_update->encap_lock); mutex_init(&neigh_update->encap_lock);
INIT_DELAYED_WORK(&neigh_update->neigh_stats_work, INIT_DELAYED_WORK(&neigh_update->neigh_stats_work,
mlx5e_rep_neigh_stats_work); mlx5e_rep_neigh_stats_work);
mlx5e_rep_neigh_update_init_interval(rpriv); mlx5e_rep_neigh_update_init_interval(rpriv);
...@@ -1000,6 +1000,7 @@ static void mlx5e_rep_neigh_cleanup(struct mlx5e_rep_priv *rpriv) ...@@ -1000,6 +1000,7 @@ static void mlx5e_rep_neigh_cleanup(struct mlx5e_rep_priv *rpriv)
cancel_delayed_work_sync(&rpriv->neigh_update.neigh_stats_work); cancel_delayed_work_sync(&rpriv->neigh_update.neigh_stats_work);
mutex_destroy(&neigh_update->encap_lock);
rhashtable_destroy(&neigh_update->neigh_ht); rhashtable_destroy(&neigh_update->neigh_ht);
} }
...@@ -1024,18 +1025,18 @@ static void mlx5e_rep_neigh_entry_remove(struct mlx5e_neigh_hash_entry *nhe) ...@@ -1024,18 +1025,18 @@ static void mlx5e_rep_neigh_entry_remove(struct mlx5e_neigh_hash_entry *nhe)
{ {
struct mlx5e_rep_priv *rpriv = nhe->priv->ppriv; struct mlx5e_rep_priv *rpriv = nhe->priv->ppriv;
spin_lock_bh(&rpriv->neigh_update.encap_lock); mutex_lock(&rpriv->neigh_update.encap_lock);
list_del_rcu(&nhe->neigh_list); list_del_rcu(&nhe->neigh_list);
rhashtable_remove_fast(&rpriv->neigh_update.neigh_ht, rhashtable_remove_fast(&rpriv->neigh_update.neigh_ht,
&nhe->rhash_node, &nhe->rhash_node,
mlx5e_neigh_ht_params); mlx5e_neigh_ht_params);
spin_unlock_bh(&rpriv->neigh_update.encap_lock); mutex_unlock(&rpriv->neigh_update.encap_lock);
} }
/* This function must only be called under RTNL lock or under the /* This function must only be called under the representor's encap_lock or
* representor's encap_lock in case RTNL mutex can't be held. * inside rcu read lock section.
*/ */
static struct mlx5e_neigh_hash_entry * static struct mlx5e_neigh_hash_entry *
mlx5e_rep_neigh_entry_lookup(struct mlx5e_priv *priv, mlx5e_rep_neigh_entry_lookup(struct mlx5e_priv *priv,
...@@ -1088,17 +1089,23 @@ int mlx5e_rep_encap_entry_attach(struct mlx5e_priv *priv, ...@@ -1088,17 +1089,23 @@ int mlx5e_rep_encap_entry_attach(struct mlx5e_priv *priv,
err = mlx5_tun_entropy_refcount_inc(tun_entropy, e->reformat_type); err = mlx5_tun_entropy_refcount_inc(tun_entropy, e->reformat_type);
if (err) if (err)
return err; return err;
mutex_lock(&rpriv->neigh_update.encap_lock);
nhe = mlx5e_rep_neigh_entry_lookup(priv, &e->m_neigh); nhe = mlx5e_rep_neigh_entry_lookup(priv, &e->m_neigh);
if (!nhe) { if (!nhe) {
err = mlx5e_rep_neigh_entry_create(priv, e, &nhe); err = mlx5e_rep_neigh_entry_create(priv, e, &nhe);
if (err) { if (err) {
mutex_unlock(&rpriv->neigh_update.encap_lock);
mlx5_tun_entropy_refcount_dec(tun_entropy, mlx5_tun_entropy_refcount_dec(tun_entropy,
e->reformat_type); e->reformat_type);
return err; return err;
} }
} }
e->nhe = nhe; e->nhe = nhe;
list_add(&e->encap_list, &nhe->encap_list); list_add(&e->encap_list, &nhe->encap_list);
mutex_unlock(&rpriv->neigh_update.encap_lock);
return 0; return 0;
} }
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include <net/ip_tunnels.h> #include <net/ip_tunnels.h>
#include <linux/rhashtable.h> #include <linux/rhashtable.h>
#include <linux/mutex.h>
#include "eswitch.h" #include "eswitch.h"
#include "en.h" #include "en.h"
#include "lib/port_tun.h" #include "lib/port_tun.h"
...@@ -48,7 +49,7 @@ struct mlx5e_neigh_update_table { ...@@ -48,7 +49,7 @@ struct mlx5e_neigh_update_table {
*/ */
struct list_head neigh_list; struct list_head neigh_list;
/* protect lookup/remove operations */ /* protect lookup/remove operations */
spinlock_t encap_lock; struct mutex encap_lock;
struct notifier_block netevent_nb; struct notifier_block netevent_nb;
struct delayed_work neigh_stats_work; struct delayed_work neigh_stats_work;
unsigned long min_interval; /* jiffies */ unsigned long min_interval; /* jiffies */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment