Commit 48fe78ce authored by Ido Schimmel's avatar Ido Schimmel Committed by David S. Miller

mlxsw: spectrum_kvdl: Protect allocations with a lock

The KVDL is used to store objects allocated throughout various places
in the driver. For example, both nexthops (adjacency entries) and ACL
actions are stored in the KVDL.

Currently, all allocations are protected by RTNL, but this is going to
change with the removal of RTNL from the routing code.

Therefore, protect KVDL allocations with a lock. A mutex is used since
the free operation can block in Spectrum-2.
Signed-off-by: default avatarIdo Schimmel <idosch@mellanox.com>
Acked-by: default avatarJiri Pirko <jiri@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 807ea870
...@@ -2,12 +2,14 @@ ...@@ -2,12 +2,14 @@
/* Copyright (c) 2016-2018 Mellanox Technologies. All rights reserved */ /* Copyright (c) 2016-2018 Mellanox Technologies. All rights reserved */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/mutex.h>
#include <linux/slab.h> #include <linux/slab.h>
#include "spectrum.h" #include "spectrum.h"
struct mlxsw_sp_kvdl { struct mlxsw_sp_kvdl {
const struct mlxsw_sp_kvdl_ops *kvdl_ops; const struct mlxsw_sp_kvdl_ops *kvdl_ops;
struct mutex kvdl_lock; /* Protects kvdl allocations */
unsigned long priv[]; unsigned long priv[];
/* priv has to be always the last item */ /* priv has to be always the last item */
}; };
...@@ -22,6 +24,7 @@ int mlxsw_sp_kvdl_init(struct mlxsw_sp *mlxsw_sp) ...@@ -22,6 +24,7 @@ int mlxsw_sp_kvdl_init(struct mlxsw_sp *mlxsw_sp)
GFP_KERNEL); GFP_KERNEL);
if (!kvdl) if (!kvdl)
return -ENOMEM; return -ENOMEM;
mutex_init(&kvdl->kvdl_lock);
kvdl->kvdl_ops = kvdl_ops; kvdl->kvdl_ops = kvdl_ops;
mlxsw_sp->kvdl = kvdl; mlxsw_sp->kvdl = kvdl;
...@@ -31,6 +34,7 @@ int mlxsw_sp_kvdl_init(struct mlxsw_sp *mlxsw_sp) ...@@ -31,6 +34,7 @@ int mlxsw_sp_kvdl_init(struct mlxsw_sp *mlxsw_sp)
return 0; return 0;
err_init: err_init:
mutex_destroy(&kvdl->kvdl_lock);
kfree(kvdl); kfree(kvdl);
return err; return err;
} }
...@@ -40,6 +44,7 @@ void mlxsw_sp_kvdl_fini(struct mlxsw_sp *mlxsw_sp) ...@@ -40,6 +44,7 @@ void mlxsw_sp_kvdl_fini(struct mlxsw_sp *mlxsw_sp)
struct mlxsw_sp_kvdl *kvdl = mlxsw_sp->kvdl; struct mlxsw_sp_kvdl *kvdl = mlxsw_sp->kvdl;
kvdl->kvdl_ops->fini(mlxsw_sp, kvdl->priv); kvdl->kvdl_ops->fini(mlxsw_sp, kvdl->priv);
mutex_destroy(&kvdl->kvdl_lock);
kfree(kvdl); kfree(kvdl);
} }
...@@ -48,9 +53,14 @@ int mlxsw_sp_kvdl_alloc(struct mlxsw_sp *mlxsw_sp, ...@@ -48,9 +53,14 @@ int mlxsw_sp_kvdl_alloc(struct mlxsw_sp *mlxsw_sp,
unsigned int entry_count, u32 *p_entry_index) unsigned int entry_count, u32 *p_entry_index)
{ {
struct mlxsw_sp_kvdl *kvdl = mlxsw_sp->kvdl; struct mlxsw_sp_kvdl *kvdl = mlxsw_sp->kvdl;
int err;
return kvdl->kvdl_ops->alloc(mlxsw_sp, kvdl->priv, type, mutex_lock(&kvdl->kvdl_lock);
err = kvdl->kvdl_ops->alloc(mlxsw_sp, kvdl->priv, type,
entry_count, p_entry_index); entry_count, p_entry_index);
mutex_unlock(&kvdl->kvdl_lock);
return err;
} }
void mlxsw_sp_kvdl_free(struct mlxsw_sp *mlxsw_sp, void mlxsw_sp_kvdl_free(struct mlxsw_sp *mlxsw_sp,
...@@ -59,8 +69,10 @@ void mlxsw_sp_kvdl_free(struct mlxsw_sp *mlxsw_sp, ...@@ -59,8 +69,10 @@ void mlxsw_sp_kvdl_free(struct mlxsw_sp *mlxsw_sp,
{ {
struct mlxsw_sp_kvdl *kvdl = mlxsw_sp->kvdl; struct mlxsw_sp_kvdl *kvdl = mlxsw_sp->kvdl;
mutex_lock(&kvdl->kvdl_lock);
kvdl->kvdl_ops->free(mlxsw_sp, kvdl->priv, type, kvdl->kvdl_ops->free(mlxsw_sp, kvdl->priv, type,
entry_count, entry_index); entry_count, entry_index);
mutex_unlock(&kvdl->kvdl_lock);
} }
int mlxsw_sp_kvdl_alloc_count_query(struct mlxsw_sp *mlxsw_sp, int mlxsw_sp_kvdl_alloc_count_query(struct mlxsw_sp *mlxsw_sp,
......
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