Linux Audio

Check our new training course

Linux BSP upgrade and security maintenance

Need help to get security updates for your Linux BSP?
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}