| // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 |
| /* Copyright (c) 2016-2018 Mellanox Technologies. All rights reserved */ |
| |
| #include <linux/kernel.h> |
| #include <linux/slab.h> |
| |
| #include "spectrum.h" |
| |
| struct mlxsw_sp_kvdl { |
| const struct mlxsw_sp_kvdl_ops *kvdl_ops; |
| unsigned long priv[0]; |
| /* priv has to be always the last item */ |
| }; |
| |
| int mlxsw_sp_kvdl_init(struct mlxsw_sp *mlxsw_sp) |
| { |
| const struct mlxsw_sp_kvdl_ops *kvdl_ops = mlxsw_sp->kvdl_ops; |
| struct mlxsw_sp_kvdl *kvdl; |
| int err; |
| |
| kvdl = kzalloc(sizeof(*mlxsw_sp->kvdl) + kvdl_ops->priv_size, |
| GFP_KERNEL); |
| if (!kvdl) |
| return -ENOMEM; |
| kvdl->kvdl_ops = kvdl_ops; |
| mlxsw_sp->kvdl = kvdl; |
| |
| err = kvdl_ops->init(mlxsw_sp, kvdl->priv); |
| if (err) |
| goto err_init; |
| return 0; |
| |
| err_init: |
| kfree(kvdl); |
| return err; |
| } |
| |
| 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); |
| kfree(kvdl); |
| } |
| |
| int mlxsw_sp_kvdl_alloc(struct mlxsw_sp *mlxsw_sp, |
| enum mlxsw_sp_kvdl_entry_type type, |
| unsigned int entry_count, u32 *p_entry_index) |
| { |
| struct mlxsw_sp_kvdl *kvdl = mlxsw_sp->kvdl; |
| |
| return kvdl->kvdl_ops->alloc(mlxsw_sp, kvdl->priv, type, |
| entry_count, p_entry_index); |
| } |
| |
| void mlxsw_sp_kvdl_free(struct mlxsw_sp *mlxsw_sp, |
| enum mlxsw_sp_kvdl_entry_type type, |
| unsigned int entry_count, int entry_index) |
| { |
| struct mlxsw_sp_kvdl *kvdl = mlxsw_sp->kvdl; |
| |
| kvdl->kvdl_ops->free(mlxsw_sp, kvdl->priv, type, |
| entry_count, entry_index); |
| } |
| |
| int mlxsw_sp_kvdl_alloc_count_query(struct mlxsw_sp *mlxsw_sp, |
| enum mlxsw_sp_kvdl_entry_type type, |
| unsigned int entry_count, |
| unsigned int *p_alloc_count) |
| { |
| struct mlxsw_sp_kvdl *kvdl = mlxsw_sp->kvdl; |
| |
| return kvdl->kvdl_ops->alloc_size_query(mlxsw_sp, kvdl->priv, type, |
| entry_count, p_alloc_count); |
| } |