linux/drivers/net/ethernet/mellanox/mlxsw/spectrum_kvdl.c
<<
>>
Prefs
   1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
   2/* Copyright (c) 2016-2018 Mellanox Technologies. All rights reserved */
   3
   4#include <linux/kernel.h>
   5#include <linux/mutex.h>
   6#include <linux/slab.h>
   7
   8#include "spectrum.h"
   9
  10struct mlxsw_sp_kvdl {
  11        const struct mlxsw_sp_kvdl_ops *kvdl_ops;
  12        struct mutex kvdl_lock; /* Protects kvdl allocations */
  13        unsigned long priv[];
  14        /* priv has to be always the last item */
  15};
  16
  17int mlxsw_sp_kvdl_init(struct mlxsw_sp *mlxsw_sp)
  18{
  19        const struct mlxsw_sp_kvdl_ops *kvdl_ops = mlxsw_sp->kvdl_ops;
  20        struct mlxsw_sp_kvdl *kvdl;
  21        int err;
  22
  23        kvdl = kzalloc(sizeof(*mlxsw_sp->kvdl) + kvdl_ops->priv_size,
  24                       GFP_KERNEL);
  25        if (!kvdl)
  26                return -ENOMEM;
  27        mutex_init(&kvdl->kvdl_lock);
  28        kvdl->kvdl_ops = kvdl_ops;
  29        mlxsw_sp->kvdl = kvdl;
  30
  31        err = kvdl_ops->init(mlxsw_sp, kvdl->priv);
  32        if (err)
  33                goto err_init;
  34        return 0;
  35
  36err_init:
  37        mutex_destroy(&kvdl->kvdl_lock);
  38        kfree(kvdl);
  39        return err;
  40}
  41
  42void mlxsw_sp_kvdl_fini(struct mlxsw_sp *mlxsw_sp)
  43{
  44        struct mlxsw_sp_kvdl *kvdl = mlxsw_sp->kvdl;
  45
  46        kvdl->kvdl_ops->fini(mlxsw_sp, kvdl->priv);
  47        mutex_destroy(&kvdl->kvdl_lock);
  48        kfree(kvdl);
  49}
  50
  51int mlxsw_sp_kvdl_alloc(struct mlxsw_sp *mlxsw_sp,
  52                        enum mlxsw_sp_kvdl_entry_type type,
  53                        unsigned int entry_count, u32 *p_entry_index)
  54{
  55        struct mlxsw_sp_kvdl *kvdl = mlxsw_sp->kvdl;
  56        int err;
  57
  58        mutex_lock(&kvdl->kvdl_lock);
  59        err = kvdl->kvdl_ops->alloc(mlxsw_sp, kvdl->priv, type,
  60                                    entry_count, p_entry_index);
  61        mutex_unlock(&kvdl->kvdl_lock);
  62
  63        return err;
  64}
  65
  66void mlxsw_sp_kvdl_free(struct mlxsw_sp *mlxsw_sp,
  67                        enum mlxsw_sp_kvdl_entry_type type,
  68                        unsigned int entry_count, int entry_index)
  69{
  70        struct mlxsw_sp_kvdl *kvdl = mlxsw_sp->kvdl;
  71
  72        mutex_lock(&kvdl->kvdl_lock);
  73        kvdl->kvdl_ops->free(mlxsw_sp, kvdl->priv, type,
  74                             entry_count, entry_index);
  75        mutex_unlock(&kvdl->kvdl_lock);
  76}
  77
  78int mlxsw_sp_kvdl_alloc_count_query(struct mlxsw_sp *mlxsw_sp,
  79                                    enum mlxsw_sp_kvdl_entry_type type,
  80                                    unsigned int entry_count,
  81                                    unsigned int *p_alloc_count)
  82{
  83        struct mlxsw_sp_kvdl *kvdl = mlxsw_sp->kvdl;
  84
  85        return kvdl->kvdl_ops->alloc_size_query(mlxsw_sp, kvdl->priv, type,
  86                                                entry_count, p_alloc_count);
  87}
  88