Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
0002 /* Copyright (c) 2016-2018 Mellanox Technologies. All rights reserved */
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; /* Protects kvdl allocations */
0013     unsigned long priv[];
0014     /* priv has to be always the last item */
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 }