0001
0002
0003
0004 #include <linux/kernel.h>
0005 #include <linux/mutex.h>
0006 #include <linux/slab.h>
0007
0008 #include "spectrum.h"
0009
0010 struct mlxsw_sp_kvdl {
0011 const struct mlxsw_sp_kvdl_ops *kvdl_ops;
0012 struct mutex kvdl_lock;
0013 unsigned long priv[];
0014
0015 };
0016
0017 int mlxsw_sp_kvdl_init(struct mlxsw_sp *mlxsw_sp)
0018 {
0019 const struct mlxsw_sp_kvdl_ops *kvdl_ops = mlxsw_sp->kvdl_ops;
0020 struct mlxsw_sp_kvdl *kvdl;
0021 int err;
0022
0023 kvdl = kzalloc(sizeof(*mlxsw_sp->kvdl) + kvdl_ops->priv_size,
0024 GFP_KERNEL);
0025 if (!kvdl)
0026 return -ENOMEM;
0027 mutex_init(&kvdl->kvdl_lock);
0028 kvdl->kvdl_ops = kvdl_ops;
0029 mlxsw_sp->kvdl = kvdl;
0030
0031 err = kvdl_ops->init(mlxsw_sp, kvdl->priv);
0032 if (err)
0033 goto err_init;
0034 return 0;
0035
0036 err_init:
0037 mutex_destroy(&kvdl->kvdl_lock);
0038 kfree(kvdl);
0039 return err;
0040 }
0041
0042 void mlxsw_sp_kvdl_fini(struct mlxsw_sp *mlxsw_sp)
0043 {
0044 struct mlxsw_sp_kvdl *kvdl = mlxsw_sp->kvdl;
0045
0046 kvdl->kvdl_ops->fini(mlxsw_sp, kvdl->priv);
0047 mutex_destroy(&kvdl->kvdl_lock);
0048 kfree(kvdl);
0049 }
0050
0051 int mlxsw_sp_kvdl_alloc(struct mlxsw_sp *mlxsw_sp,
0052 enum mlxsw_sp_kvdl_entry_type type,
0053 unsigned int entry_count, u32 *p_entry_index)
0054 {
0055 struct mlxsw_sp_kvdl *kvdl = mlxsw_sp->kvdl;
0056 int err;
0057
0058 mutex_lock(&kvdl->kvdl_lock);
0059 err = kvdl->kvdl_ops->alloc(mlxsw_sp, kvdl->priv, type,
0060 entry_count, p_entry_index);
0061 mutex_unlock(&kvdl->kvdl_lock);
0062
0063 return err;
0064 }
0065
0066 void mlxsw_sp_kvdl_free(struct mlxsw_sp *mlxsw_sp,
0067 enum mlxsw_sp_kvdl_entry_type type,
0068 unsigned int entry_count, int entry_index)
0069 {
0070 struct mlxsw_sp_kvdl *kvdl = mlxsw_sp->kvdl;
0071
0072 mutex_lock(&kvdl->kvdl_lock);
0073 kvdl->kvdl_ops->free(mlxsw_sp, kvdl->priv, type,
0074 entry_count, entry_index);
0075 mutex_unlock(&kvdl->kvdl_lock);
0076 }
0077
0078 int mlxsw_sp_kvdl_alloc_count_query(struct mlxsw_sp *mlxsw_sp,
0079 enum mlxsw_sp_kvdl_entry_type type,
0080 unsigned int entry_count,
0081 unsigned int *p_alloc_count)
0082 {
0083 struct mlxsw_sp_kvdl *kvdl = mlxsw_sp->kvdl;
0084
0085 return kvdl->kvdl_ops->alloc_size_query(mlxsw_sp, kvdl->priv, type,
0086 entry_count, p_alloc_count);
0087 }