aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
diff options
context:
space:
mode:
authorVlad Buslov <vladbu@mellanox.com>2019-08-08 17:01:33 +0300
committerSaeed Mahameed <saeedm@mellanox.com>2019-08-09 14:54:10 -0700
commitd589e785baf5e48ee80a4fbfed96661a4c7c8c8d (patch)
tree7f2324fc85658f4d9591142d09645bb51afeb311 /drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
parentnet/mlx5e: Protect encap hash table with mutex (diff)
downloadlinux-dev-d589e785baf5e48ee80a4fbfed96661a4c7c8c8d.tar.xz
linux-dev-d589e785baf5e48ee80a4fbfed96661a4c7c8c8d.zip
net/mlx5e: Allow concurrent creation of encap entries
Encap entries creation is fully synchronized by encap_tbl_lock. In order to allow concurrent allocation of hardware resources used to offload encapsulation, extend mlx5e_encap_entry with 'res_ready' completion. Move call to mlx5e_tc_tun_create_header_ipv{4|6}() out of encap_tbl_lock critical section. Modify code that attaches new flows to existing encap to wait for 'res_ready' completion before using the entry. Insert encap entry to table before provisioning it to hardware and modify all users of the encap table to verify that encap was fully initialized by checking completion result for non-zero value (and to wait for 'res_ready' completion, if necessary). 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.c33
1 files changed, 27 insertions, 6 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
index c13db9bc1f9b..5be3da621499 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
@@ -2904,8 +2904,18 @@ static int mlx5e_attach_encap(struct mlx5e_priv *priv,
e = mlx5e_encap_get(priv, &key, hash_key);
/* must verify if encap is valid or not */
- if (e)
+ if (e) {
+ mutex_unlock(&esw->offloads.encap_tbl_lock);
+ wait_for_completion(&e->res_ready);
+
+ /* Protect against concurrent neigh update. */
+ mutex_lock(&esw->offloads.encap_tbl_lock);
+ if (e->compl_result) {
+ err = -EREMOTEIO;
+ goto out_err;
+ }
goto attach_flow;
+ }
e = kzalloc(sizeof(*e), GFP_KERNEL);
if (!e) {
@@ -2914,22 +2924,32 @@ static int mlx5e_attach_encap(struct mlx5e_priv *priv,
}
refcount_set(&e->refcnt, 1);
+ init_completion(&e->res_ready);
+
e->tun_info = tun_info;
err = mlx5e_tc_tun_init_encap_attr(mirred_dev, priv, e, extack);
- if (err)
+ if (err) {
+ kfree(e);
+ e = NULL;
goto out_err;
+ }
INIT_LIST_HEAD(&e->flows);
+ hash_add_rcu(esw->offloads.encap_tbl, &e->encap_hlist, hash_key);
+ mutex_unlock(&esw->offloads.encap_tbl_lock);
if (family == AF_INET)
err = mlx5e_tc_tun_create_header_ipv4(priv, mirred_dev, e);
else if (family == AF_INET6)
err = mlx5e_tc_tun_create_header_ipv6(priv, mirred_dev, e);
- if (err)
+ /* Protect against concurrent neigh update. */
+ mutex_lock(&esw->offloads.encap_tbl_lock);
+ complete_all(&e->res_ready);
+ if (err) {
+ e->compl_result = err;
goto out_err;
-
- hash_add_rcu(esw->offloads.encap_tbl, &e->encap_hlist, hash_key);
+ }
attach_flow:
flow->encaps[out_index].e = e;
@@ -2949,7 +2969,8 @@ attach_flow:
out_err:
mutex_unlock(&esw->offloads.encap_tbl_lock);
- kfree(e);
+ if (e)
+ mlx5e_encap_put(priv, e);
return err;
}