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: Ido Schimmel <idosch@mellanox.com> Acked-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Родитель
807ea87032
Коммит
48fe78cebd
|
@ -2,12 +2,14 @@
|
|||
/* Copyright (c) 2016-2018 Mellanox Technologies. All rights reserved */
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "spectrum.h"
|
||||
|
||||
struct mlxsw_sp_kvdl {
|
||||
const struct mlxsw_sp_kvdl_ops *kvdl_ops;
|
||||
struct mutex kvdl_lock; /* Protects kvdl allocations */
|
||||
unsigned long priv[];
|
||||
/* priv has to be always the last item */
|
||||
};
|
||||
|
@ -22,6 +24,7 @@ int mlxsw_sp_kvdl_init(struct mlxsw_sp *mlxsw_sp)
|
|||
GFP_KERNEL);
|
||||
if (!kvdl)
|
||||
return -ENOMEM;
|
||||
mutex_init(&kvdl->kvdl_lock);
|
||||
kvdl->kvdl_ops = kvdl_ops;
|
||||
mlxsw_sp->kvdl = kvdl;
|
||||
|
||||
|
@ -31,6 +34,7 @@ int mlxsw_sp_kvdl_init(struct mlxsw_sp *mlxsw_sp)
|
|||
return 0;
|
||||
|
||||
err_init:
|
||||
mutex_destroy(&kvdl->kvdl_lock);
|
||||
kfree(kvdl);
|
||||
return err;
|
||||
}
|
||||
|
@ -40,6 +44,7 @@ void mlxsw_sp_kvdl_fini(struct mlxsw_sp *mlxsw_sp)
|
|||
struct mlxsw_sp_kvdl *kvdl = mlxsw_sp->kvdl;
|
||||
|
||||
kvdl->kvdl_ops->fini(mlxsw_sp, kvdl->priv);
|
||||
mutex_destroy(&kvdl->kvdl_lock);
|
||||
kfree(kvdl);
|
||||
}
|
||||
|
||||
|
@ -48,9 +53,14 @@ int mlxsw_sp_kvdl_alloc(struct mlxsw_sp *mlxsw_sp,
|
|||
unsigned int entry_count, u32 *p_entry_index)
|
||||
{
|
||||
struct mlxsw_sp_kvdl *kvdl = mlxsw_sp->kvdl;
|
||||
int err;
|
||||
|
||||
return kvdl->kvdl_ops->alloc(mlxsw_sp, kvdl->priv, type,
|
||||
entry_count, p_entry_index);
|
||||
mutex_lock(&kvdl->kvdl_lock);
|
||||
err = kvdl->kvdl_ops->alloc(mlxsw_sp, kvdl->priv, type,
|
||||
entry_count, p_entry_index);
|
||||
mutex_unlock(&kvdl->kvdl_lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
mutex_lock(&kvdl->kvdl_lock);
|
||||
kvdl->kvdl_ops->free(mlxsw_sp, kvdl->priv, type,
|
||||
entry_count, entry_index);
|
||||
mutex_unlock(&kvdl->kvdl_lock);
|
||||
}
|
||||
|
||||
int mlxsw_sp_kvdl_alloc_count_query(struct mlxsw_sp *mlxsw_sp,
|
||||
|
|
Загрузка…
Ссылка в новой задаче