Loading...
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}
1/*
2 * drivers/net/ethernet/mellanox/mlxsw/spectrum_kvdl.c
3 * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
4 * Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com>
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the names of the copyright holders nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * Alternatively, this software may be distributed under the terms of the
19 * GNU General Public License ("GPL") version 2 as published by the Free
20 * Software Foundation.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 */
34
35#include <linux/kernel.h>
36#include <linux/bitops.h>
37
38#include "spectrum.h"
39
40#define MLXSW_SP_KVDL_SINGLE_BASE 0
41#define MLXSW_SP_KVDL_SINGLE_SIZE 16384
42#define MLXSW_SP_KVDL_CHUNKS_BASE \
43 (MLXSW_SP_KVDL_SINGLE_BASE + MLXSW_SP_KVDL_SINGLE_SIZE)
44#define MLXSW_SP_KVDL_CHUNKS_SIZE \
45 (MLXSW_SP_KVD_LINEAR_SIZE - MLXSW_SP_KVDL_CHUNKS_BASE)
46#define MLXSW_SP_CHUNK_MAX 32
47
48int mlxsw_sp_kvdl_alloc(struct mlxsw_sp *mlxsw_sp, unsigned int entry_count)
49{
50 int entry_index;
51 int size;
52 int type_base;
53 int type_size;
54 int type_entries;
55
56 if (entry_count == 0 || entry_count > MLXSW_SP_CHUNK_MAX) {
57 return -EINVAL;
58 } else if (entry_count == 1) {
59 type_base = MLXSW_SP_KVDL_SINGLE_BASE;
60 type_size = MLXSW_SP_KVDL_SINGLE_SIZE;
61 type_entries = 1;
62 } else {
63 type_base = MLXSW_SP_KVDL_CHUNKS_BASE;
64 type_size = MLXSW_SP_KVDL_CHUNKS_SIZE;
65 type_entries = MLXSW_SP_CHUNK_MAX;
66 }
67
68 entry_index = type_base;
69 size = type_base + type_size;
70 for_each_clear_bit_from(entry_index, mlxsw_sp->kvdl.usage, size) {
71 int i;
72
73 for (i = 0; i < type_entries; i++)
74 set_bit(entry_index + i, mlxsw_sp->kvdl.usage);
75 return entry_index;
76 }
77 return -ENOBUFS;
78}
79
80void mlxsw_sp_kvdl_free(struct mlxsw_sp *mlxsw_sp, int entry_index)
81{
82 int type_entries;
83 int i;
84
85 if (entry_index < MLXSW_SP_KVDL_CHUNKS_BASE)
86 type_entries = 1;
87 else
88 type_entries = MLXSW_SP_CHUNK_MAX;
89 for (i = 0; i < type_entries; i++)
90 clear_bit(entry_index + i, mlxsw_sp->kvdl.usage);
91}