18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
28c2ecf20Sopenharmony_ci/* Copyright (c) 2018 Mellanox Technologies. All rights reserved */
38c2ecf20Sopenharmony_ci
48c2ecf20Sopenharmony_ci#include <linux/kernel.h>
58c2ecf20Sopenharmony_ci#include <linux/bitops.h>
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#include "spectrum.h"
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#define MLXSW_SP1_KVDL_SINGLE_BASE 0
108c2ecf20Sopenharmony_ci#define MLXSW_SP1_KVDL_SINGLE_SIZE 16384
118c2ecf20Sopenharmony_ci#define MLXSW_SP1_KVDL_SINGLE_END \
128c2ecf20Sopenharmony_ci	(MLXSW_SP1_KVDL_SINGLE_SIZE + MLXSW_SP1_KVDL_SINGLE_BASE - 1)
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#define MLXSW_SP1_KVDL_CHUNKS_BASE \
158c2ecf20Sopenharmony_ci	(MLXSW_SP1_KVDL_SINGLE_BASE + MLXSW_SP1_KVDL_SINGLE_SIZE)
168c2ecf20Sopenharmony_ci#define MLXSW_SP1_KVDL_CHUNKS_SIZE 49152
178c2ecf20Sopenharmony_ci#define MLXSW_SP1_KVDL_CHUNKS_END \
188c2ecf20Sopenharmony_ci	(MLXSW_SP1_KVDL_CHUNKS_SIZE + MLXSW_SP1_KVDL_CHUNKS_BASE - 1)
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci#define MLXSW_SP1_KVDL_LARGE_CHUNKS_BASE \
218c2ecf20Sopenharmony_ci	(MLXSW_SP1_KVDL_CHUNKS_BASE + MLXSW_SP1_KVDL_CHUNKS_SIZE)
228c2ecf20Sopenharmony_ci#define MLXSW_SP1_KVDL_LARGE_CHUNKS_SIZE \
238c2ecf20Sopenharmony_ci	(MLXSW_SP_KVD_LINEAR_SIZE - MLXSW_SP1_KVDL_LARGE_CHUNKS_BASE)
248c2ecf20Sopenharmony_ci#define MLXSW_SP1_KVDL_LARGE_CHUNKS_END \
258c2ecf20Sopenharmony_ci	(MLXSW_SP1_KVDL_LARGE_CHUNKS_SIZE + MLXSW_SP1_KVDL_LARGE_CHUNKS_BASE - 1)
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci#define MLXSW_SP1_KVDL_SINGLE_ALLOC_SIZE 1
288c2ecf20Sopenharmony_ci#define MLXSW_SP1_KVDL_CHUNKS_ALLOC_SIZE 32
298c2ecf20Sopenharmony_ci#define MLXSW_SP1_KVDL_LARGE_CHUNKS_ALLOC_SIZE 512
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_cistruct mlxsw_sp1_kvdl_part_info {
328c2ecf20Sopenharmony_ci	unsigned int part_index;
338c2ecf20Sopenharmony_ci	unsigned int start_index;
348c2ecf20Sopenharmony_ci	unsigned int end_index;
358c2ecf20Sopenharmony_ci	unsigned int alloc_size;
368c2ecf20Sopenharmony_ci	enum mlxsw_sp_resource_id resource_id;
378c2ecf20Sopenharmony_ci};
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_cienum mlxsw_sp1_kvdl_part_id {
408c2ecf20Sopenharmony_ci	MLXSW_SP1_KVDL_PART_ID_SINGLE,
418c2ecf20Sopenharmony_ci	MLXSW_SP1_KVDL_PART_ID_CHUNKS,
428c2ecf20Sopenharmony_ci	MLXSW_SP1_KVDL_PART_ID_LARGE_CHUNKS,
438c2ecf20Sopenharmony_ci};
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci#define MLXSW_SP1_KVDL_PART_INFO(id)				\
468c2ecf20Sopenharmony_ci[MLXSW_SP1_KVDL_PART_ID_##id] = {				\
478c2ecf20Sopenharmony_ci	.start_index = MLXSW_SP1_KVDL_##id##_BASE,		\
488c2ecf20Sopenharmony_ci	.end_index = MLXSW_SP1_KVDL_##id##_END,			\
498c2ecf20Sopenharmony_ci	.alloc_size = MLXSW_SP1_KVDL_##id##_ALLOC_SIZE,		\
508c2ecf20Sopenharmony_ci	.resource_id = MLXSW_SP_RESOURCE_KVD_LINEAR_##id,	\
518c2ecf20Sopenharmony_ci}
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_cistatic const struct mlxsw_sp1_kvdl_part_info mlxsw_sp1_kvdl_parts_info[] = {
548c2ecf20Sopenharmony_ci	MLXSW_SP1_KVDL_PART_INFO(SINGLE),
558c2ecf20Sopenharmony_ci	MLXSW_SP1_KVDL_PART_INFO(CHUNKS),
568c2ecf20Sopenharmony_ci	MLXSW_SP1_KVDL_PART_INFO(LARGE_CHUNKS),
578c2ecf20Sopenharmony_ci};
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci#define MLXSW_SP1_KVDL_PARTS_INFO_LEN ARRAY_SIZE(mlxsw_sp1_kvdl_parts_info)
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_cistruct mlxsw_sp1_kvdl_part {
628c2ecf20Sopenharmony_ci	struct mlxsw_sp1_kvdl_part_info info;
638c2ecf20Sopenharmony_ci	unsigned long usage[];	/* Entries */
648c2ecf20Sopenharmony_ci};
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_cistruct mlxsw_sp1_kvdl {
678c2ecf20Sopenharmony_ci	struct mlxsw_sp1_kvdl_part *parts[MLXSW_SP1_KVDL_PARTS_INFO_LEN];
688c2ecf20Sopenharmony_ci};
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_cistatic struct mlxsw_sp1_kvdl_part *
718c2ecf20Sopenharmony_cimlxsw_sp1_kvdl_alloc_size_part(struct mlxsw_sp1_kvdl *kvdl,
728c2ecf20Sopenharmony_ci			       unsigned int alloc_size)
738c2ecf20Sopenharmony_ci{
748c2ecf20Sopenharmony_ci	struct mlxsw_sp1_kvdl_part *part, *min_part = NULL;
758c2ecf20Sopenharmony_ci	int i;
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci	for (i = 0; i < MLXSW_SP1_KVDL_PARTS_INFO_LEN; i++) {
788c2ecf20Sopenharmony_ci		part = kvdl->parts[i];
798c2ecf20Sopenharmony_ci		if (alloc_size <= part->info.alloc_size &&
808c2ecf20Sopenharmony_ci		    (!min_part ||
818c2ecf20Sopenharmony_ci		     part->info.alloc_size <= min_part->info.alloc_size))
828c2ecf20Sopenharmony_ci			min_part = part;
838c2ecf20Sopenharmony_ci	}
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci	return min_part ?: ERR_PTR(-ENOBUFS);
868c2ecf20Sopenharmony_ci}
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_cistatic struct mlxsw_sp1_kvdl_part *
898c2ecf20Sopenharmony_cimlxsw_sp1_kvdl_index_part(struct mlxsw_sp1_kvdl *kvdl, u32 kvdl_index)
908c2ecf20Sopenharmony_ci{
918c2ecf20Sopenharmony_ci	struct mlxsw_sp1_kvdl_part *part;
928c2ecf20Sopenharmony_ci	int i;
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci	for (i = 0; i < MLXSW_SP1_KVDL_PARTS_INFO_LEN; i++) {
958c2ecf20Sopenharmony_ci		part = kvdl->parts[i];
968c2ecf20Sopenharmony_ci		if (kvdl_index >= part->info.start_index &&
978c2ecf20Sopenharmony_ci		    kvdl_index <= part->info.end_index)
988c2ecf20Sopenharmony_ci			return part;
998c2ecf20Sopenharmony_ci	}
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci	return ERR_PTR(-EINVAL);
1028c2ecf20Sopenharmony_ci}
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_cistatic u32
1058c2ecf20Sopenharmony_cimlxsw_sp1_kvdl_to_kvdl_index(const struct mlxsw_sp1_kvdl_part_info *info,
1068c2ecf20Sopenharmony_ci			     unsigned int entry_index)
1078c2ecf20Sopenharmony_ci{
1088c2ecf20Sopenharmony_ci	return info->start_index + entry_index * info->alloc_size;
1098c2ecf20Sopenharmony_ci}
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_cistatic unsigned int
1128c2ecf20Sopenharmony_cimlxsw_sp1_kvdl_to_entry_index(const struct mlxsw_sp1_kvdl_part_info *info,
1138c2ecf20Sopenharmony_ci			      u32 kvdl_index)
1148c2ecf20Sopenharmony_ci{
1158c2ecf20Sopenharmony_ci	return (kvdl_index - info->start_index) / info->alloc_size;
1168c2ecf20Sopenharmony_ci}
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_cistatic int mlxsw_sp1_kvdl_part_alloc(struct mlxsw_sp1_kvdl_part *part,
1198c2ecf20Sopenharmony_ci				     u32 *p_kvdl_index)
1208c2ecf20Sopenharmony_ci{
1218c2ecf20Sopenharmony_ci	const struct mlxsw_sp1_kvdl_part_info *info = &part->info;
1228c2ecf20Sopenharmony_ci	unsigned int entry_index, nr_entries;
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci	nr_entries = (info->end_index - info->start_index + 1) /
1258c2ecf20Sopenharmony_ci		     info->alloc_size;
1268c2ecf20Sopenharmony_ci	entry_index = find_first_zero_bit(part->usage, nr_entries);
1278c2ecf20Sopenharmony_ci	if (entry_index == nr_entries)
1288c2ecf20Sopenharmony_ci		return -ENOBUFS;
1298c2ecf20Sopenharmony_ci	__set_bit(entry_index, part->usage);
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci	*p_kvdl_index = mlxsw_sp1_kvdl_to_kvdl_index(info, entry_index);
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ci	return 0;
1348c2ecf20Sopenharmony_ci}
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_cistatic void mlxsw_sp1_kvdl_part_free(struct mlxsw_sp1_kvdl_part *part,
1378c2ecf20Sopenharmony_ci				     u32 kvdl_index)
1388c2ecf20Sopenharmony_ci{
1398c2ecf20Sopenharmony_ci	const struct mlxsw_sp1_kvdl_part_info *info = &part->info;
1408c2ecf20Sopenharmony_ci	unsigned int entry_index;
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci	entry_index = mlxsw_sp1_kvdl_to_entry_index(info, kvdl_index);
1438c2ecf20Sopenharmony_ci	__clear_bit(entry_index, part->usage);
1448c2ecf20Sopenharmony_ci}
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_cistatic int mlxsw_sp1_kvdl_alloc(struct mlxsw_sp *mlxsw_sp, void *priv,
1478c2ecf20Sopenharmony_ci				enum mlxsw_sp_kvdl_entry_type type,
1488c2ecf20Sopenharmony_ci				unsigned int entry_count,
1498c2ecf20Sopenharmony_ci				u32 *p_entry_index)
1508c2ecf20Sopenharmony_ci{
1518c2ecf20Sopenharmony_ci	struct mlxsw_sp1_kvdl *kvdl = priv;
1528c2ecf20Sopenharmony_ci	struct mlxsw_sp1_kvdl_part *part;
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ci	/* Find partition with smallest allocation size satisfying the
1558c2ecf20Sopenharmony_ci	 * requested size.
1568c2ecf20Sopenharmony_ci	 */
1578c2ecf20Sopenharmony_ci	part = mlxsw_sp1_kvdl_alloc_size_part(kvdl, entry_count);
1588c2ecf20Sopenharmony_ci	if (IS_ERR(part))
1598c2ecf20Sopenharmony_ci		return PTR_ERR(part);
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_ci	return mlxsw_sp1_kvdl_part_alloc(part, p_entry_index);
1628c2ecf20Sopenharmony_ci}
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_cistatic void mlxsw_sp1_kvdl_free(struct mlxsw_sp *mlxsw_sp, void *priv,
1658c2ecf20Sopenharmony_ci				enum mlxsw_sp_kvdl_entry_type type,
1668c2ecf20Sopenharmony_ci				unsigned int entry_count, int entry_index)
1678c2ecf20Sopenharmony_ci{
1688c2ecf20Sopenharmony_ci	struct mlxsw_sp1_kvdl *kvdl = priv;
1698c2ecf20Sopenharmony_ci	struct mlxsw_sp1_kvdl_part *part;
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci	part = mlxsw_sp1_kvdl_index_part(kvdl, entry_index);
1728c2ecf20Sopenharmony_ci	if (IS_ERR(part))
1738c2ecf20Sopenharmony_ci		return;
1748c2ecf20Sopenharmony_ci	mlxsw_sp1_kvdl_part_free(part, entry_index);
1758c2ecf20Sopenharmony_ci}
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_cistatic int mlxsw_sp1_kvdl_alloc_size_query(struct mlxsw_sp *mlxsw_sp,
1788c2ecf20Sopenharmony_ci					   void *priv,
1798c2ecf20Sopenharmony_ci					   enum mlxsw_sp_kvdl_entry_type type,
1808c2ecf20Sopenharmony_ci					   unsigned int entry_count,
1818c2ecf20Sopenharmony_ci					   unsigned int *p_alloc_size)
1828c2ecf20Sopenharmony_ci{
1838c2ecf20Sopenharmony_ci	struct mlxsw_sp1_kvdl *kvdl = priv;
1848c2ecf20Sopenharmony_ci	struct mlxsw_sp1_kvdl_part *part;
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_ci	part = mlxsw_sp1_kvdl_alloc_size_part(kvdl, entry_count);
1878c2ecf20Sopenharmony_ci	if (IS_ERR(part))
1888c2ecf20Sopenharmony_ci		return PTR_ERR(part);
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_ci	*p_alloc_size = part->info.alloc_size;
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ci	return 0;
1938c2ecf20Sopenharmony_ci}
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_cistatic void mlxsw_sp1_kvdl_part_update(struct mlxsw_sp1_kvdl_part *part,
1968c2ecf20Sopenharmony_ci				       struct mlxsw_sp1_kvdl_part *part_prev,
1978c2ecf20Sopenharmony_ci				       unsigned int size)
1988c2ecf20Sopenharmony_ci{
1998c2ecf20Sopenharmony_ci	if (!part_prev) {
2008c2ecf20Sopenharmony_ci		part->info.end_index = size - 1;
2018c2ecf20Sopenharmony_ci	} else {
2028c2ecf20Sopenharmony_ci		part->info.start_index = part_prev->info.end_index + 1;
2038c2ecf20Sopenharmony_ci		part->info.end_index = part->info.start_index + size - 1;
2048c2ecf20Sopenharmony_ci	}
2058c2ecf20Sopenharmony_ci}
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_cistatic struct mlxsw_sp1_kvdl_part *
2088c2ecf20Sopenharmony_cimlxsw_sp1_kvdl_part_init(struct mlxsw_sp *mlxsw_sp,
2098c2ecf20Sopenharmony_ci			 const struct mlxsw_sp1_kvdl_part_info *info,
2108c2ecf20Sopenharmony_ci			 struct mlxsw_sp1_kvdl_part *part_prev)
2118c2ecf20Sopenharmony_ci{
2128c2ecf20Sopenharmony_ci	struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
2138c2ecf20Sopenharmony_ci	struct mlxsw_sp1_kvdl_part *part;
2148c2ecf20Sopenharmony_ci	bool need_update = true;
2158c2ecf20Sopenharmony_ci	unsigned int nr_entries;
2168c2ecf20Sopenharmony_ci	size_t usage_size;
2178c2ecf20Sopenharmony_ci	u64 resource_size;
2188c2ecf20Sopenharmony_ci	int err;
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ci	err = devlink_resource_size_get(devlink, info->resource_id,
2218c2ecf20Sopenharmony_ci					&resource_size);
2228c2ecf20Sopenharmony_ci	if (err) {
2238c2ecf20Sopenharmony_ci		need_update = false;
2248c2ecf20Sopenharmony_ci		resource_size = info->end_index - info->start_index + 1;
2258c2ecf20Sopenharmony_ci	}
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_ci	nr_entries = div_u64(resource_size, info->alloc_size);
2288c2ecf20Sopenharmony_ci	usage_size = BITS_TO_LONGS(nr_entries) * sizeof(unsigned long);
2298c2ecf20Sopenharmony_ci	part = kzalloc(sizeof(*part) + usage_size, GFP_KERNEL);
2308c2ecf20Sopenharmony_ci	if (!part)
2318c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci	memcpy(&part->info, info, sizeof(part->info));
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ci	if (need_update)
2368c2ecf20Sopenharmony_ci		mlxsw_sp1_kvdl_part_update(part, part_prev, resource_size);
2378c2ecf20Sopenharmony_ci	return part;
2388c2ecf20Sopenharmony_ci}
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_cistatic void mlxsw_sp1_kvdl_part_fini(struct mlxsw_sp1_kvdl_part *part)
2418c2ecf20Sopenharmony_ci{
2428c2ecf20Sopenharmony_ci	kfree(part);
2438c2ecf20Sopenharmony_ci}
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_cistatic int mlxsw_sp1_kvdl_parts_init(struct mlxsw_sp *mlxsw_sp,
2468c2ecf20Sopenharmony_ci				     struct mlxsw_sp1_kvdl *kvdl)
2478c2ecf20Sopenharmony_ci{
2488c2ecf20Sopenharmony_ci	const struct mlxsw_sp1_kvdl_part_info *info;
2498c2ecf20Sopenharmony_ci	struct mlxsw_sp1_kvdl_part *part_prev = NULL;
2508c2ecf20Sopenharmony_ci	int err, i;
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_ci	for (i = 0; i < MLXSW_SP1_KVDL_PARTS_INFO_LEN; i++) {
2538c2ecf20Sopenharmony_ci		info = &mlxsw_sp1_kvdl_parts_info[i];
2548c2ecf20Sopenharmony_ci		kvdl->parts[i] = mlxsw_sp1_kvdl_part_init(mlxsw_sp, info,
2558c2ecf20Sopenharmony_ci							  part_prev);
2568c2ecf20Sopenharmony_ci		if (IS_ERR(kvdl->parts[i])) {
2578c2ecf20Sopenharmony_ci			err = PTR_ERR(kvdl->parts[i]);
2588c2ecf20Sopenharmony_ci			goto err_kvdl_part_init;
2598c2ecf20Sopenharmony_ci		}
2608c2ecf20Sopenharmony_ci		part_prev = kvdl->parts[i];
2618c2ecf20Sopenharmony_ci	}
2628c2ecf20Sopenharmony_ci	return 0;
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_cierr_kvdl_part_init:
2658c2ecf20Sopenharmony_ci	for (i--; i >= 0; i--)
2668c2ecf20Sopenharmony_ci		mlxsw_sp1_kvdl_part_fini(kvdl->parts[i]);
2678c2ecf20Sopenharmony_ci	return err;
2688c2ecf20Sopenharmony_ci}
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_cistatic void mlxsw_sp1_kvdl_parts_fini(struct mlxsw_sp1_kvdl *kvdl)
2718c2ecf20Sopenharmony_ci{
2728c2ecf20Sopenharmony_ci	int i;
2738c2ecf20Sopenharmony_ci
2748c2ecf20Sopenharmony_ci	for (i = 0; i < MLXSW_SP1_KVDL_PARTS_INFO_LEN; i++)
2758c2ecf20Sopenharmony_ci		mlxsw_sp1_kvdl_part_fini(kvdl->parts[i]);
2768c2ecf20Sopenharmony_ci}
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_cistatic u64 mlxsw_sp1_kvdl_part_occ(struct mlxsw_sp1_kvdl_part *part)
2798c2ecf20Sopenharmony_ci{
2808c2ecf20Sopenharmony_ci	const struct mlxsw_sp1_kvdl_part_info *info = &part->info;
2818c2ecf20Sopenharmony_ci	unsigned int nr_entries;
2828c2ecf20Sopenharmony_ci	int bit = -1;
2838c2ecf20Sopenharmony_ci	u64 occ = 0;
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_ci	nr_entries = (info->end_index -
2868c2ecf20Sopenharmony_ci		      info->start_index + 1) /
2878c2ecf20Sopenharmony_ci		      info->alloc_size;
2888c2ecf20Sopenharmony_ci	while ((bit = find_next_bit(part->usage, nr_entries, bit + 1))
2898c2ecf20Sopenharmony_ci		< nr_entries)
2908c2ecf20Sopenharmony_ci		occ += info->alloc_size;
2918c2ecf20Sopenharmony_ci	return occ;
2928c2ecf20Sopenharmony_ci}
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_cistatic u64 mlxsw_sp1_kvdl_occ_get(void *priv)
2958c2ecf20Sopenharmony_ci{
2968c2ecf20Sopenharmony_ci	const struct mlxsw_sp1_kvdl *kvdl = priv;
2978c2ecf20Sopenharmony_ci	u64 occ = 0;
2988c2ecf20Sopenharmony_ci	int i;
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_ci	for (i = 0; i < MLXSW_SP1_KVDL_PARTS_INFO_LEN; i++)
3018c2ecf20Sopenharmony_ci		occ += mlxsw_sp1_kvdl_part_occ(kvdl->parts[i]);
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_ci	return occ;
3048c2ecf20Sopenharmony_ci}
3058c2ecf20Sopenharmony_ci
3068c2ecf20Sopenharmony_cistatic u64 mlxsw_sp1_kvdl_single_occ_get(void *priv)
3078c2ecf20Sopenharmony_ci{
3088c2ecf20Sopenharmony_ci	const struct mlxsw_sp1_kvdl *kvdl = priv;
3098c2ecf20Sopenharmony_ci	struct mlxsw_sp1_kvdl_part *part;
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_ci	part = kvdl->parts[MLXSW_SP1_KVDL_PART_ID_SINGLE];
3128c2ecf20Sopenharmony_ci	return mlxsw_sp1_kvdl_part_occ(part);
3138c2ecf20Sopenharmony_ci}
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_cistatic u64 mlxsw_sp1_kvdl_chunks_occ_get(void *priv)
3168c2ecf20Sopenharmony_ci{
3178c2ecf20Sopenharmony_ci	const struct mlxsw_sp1_kvdl *kvdl = priv;
3188c2ecf20Sopenharmony_ci	struct mlxsw_sp1_kvdl_part *part;
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_ci	part = kvdl->parts[MLXSW_SP1_KVDL_PART_ID_CHUNKS];
3218c2ecf20Sopenharmony_ci	return mlxsw_sp1_kvdl_part_occ(part);
3228c2ecf20Sopenharmony_ci}
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_cistatic u64 mlxsw_sp1_kvdl_large_chunks_occ_get(void *priv)
3258c2ecf20Sopenharmony_ci{
3268c2ecf20Sopenharmony_ci	const struct mlxsw_sp1_kvdl *kvdl = priv;
3278c2ecf20Sopenharmony_ci	struct mlxsw_sp1_kvdl_part *part;
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_ci	part = kvdl->parts[MLXSW_SP1_KVDL_PART_ID_LARGE_CHUNKS];
3308c2ecf20Sopenharmony_ci	return mlxsw_sp1_kvdl_part_occ(part);
3318c2ecf20Sopenharmony_ci}
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_cistatic int mlxsw_sp1_kvdl_init(struct mlxsw_sp *mlxsw_sp, void *priv)
3348c2ecf20Sopenharmony_ci{
3358c2ecf20Sopenharmony_ci	struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
3368c2ecf20Sopenharmony_ci	struct mlxsw_sp1_kvdl *kvdl = priv;
3378c2ecf20Sopenharmony_ci	int err;
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_ci	err = mlxsw_sp1_kvdl_parts_init(mlxsw_sp, kvdl);
3408c2ecf20Sopenharmony_ci	if (err)
3418c2ecf20Sopenharmony_ci		return err;
3428c2ecf20Sopenharmony_ci	devlink_resource_occ_get_register(devlink,
3438c2ecf20Sopenharmony_ci					  MLXSW_SP_RESOURCE_KVD_LINEAR,
3448c2ecf20Sopenharmony_ci					  mlxsw_sp1_kvdl_occ_get,
3458c2ecf20Sopenharmony_ci					  kvdl);
3468c2ecf20Sopenharmony_ci	devlink_resource_occ_get_register(devlink,
3478c2ecf20Sopenharmony_ci					  MLXSW_SP_RESOURCE_KVD_LINEAR_SINGLE,
3488c2ecf20Sopenharmony_ci					  mlxsw_sp1_kvdl_single_occ_get,
3498c2ecf20Sopenharmony_ci					  kvdl);
3508c2ecf20Sopenharmony_ci	devlink_resource_occ_get_register(devlink,
3518c2ecf20Sopenharmony_ci					  MLXSW_SP_RESOURCE_KVD_LINEAR_CHUNKS,
3528c2ecf20Sopenharmony_ci					  mlxsw_sp1_kvdl_chunks_occ_get,
3538c2ecf20Sopenharmony_ci					  kvdl);
3548c2ecf20Sopenharmony_ci	devlink_resource_occ_get_register(devlink,
3558c2ecf20Sopenharmony_ci					  MLXSW_SP_RESOURCE_KVD_LINEAR_LARGE_CHUNKS,
3568c2ecf20Sopenharmony_ci					  mlxsw_sp1_kvdl_large_chunks_occ_get,
3578c2ecf20Sopenharmony_ci					  kvdl);
3588c2ecf20Sopenharmony_ci	return 0;
3598c2ecf20Sopenharmony_ci}
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_cistatic void mlxsw_sp1_kvdl_fini(struct mlxsw_sp *mlxsw_sp, void *priv)
3628c2ecf20Sopenharmony_ci{
3638c2ecf20Sopenharmony_ci	struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
3648c2ecf20Sopenharmony_ci	struct mlxsw_sp1_kvdl *kvdl = priv;
3658c2ecf20Sopenharmony_ci
3668c2ecf20Sopenharmony_ci	devlink_resource_occ_get_unregister(devlink,
3678c2ecf20Sopenharmony_ci					    MLXSW_SP_RESOURCE_KVD_LINEAR_LARGE_CHUNKS);
3688c2ecf20Sopenharmony_ci	devlink_resource_occ_get_unregister(devlink,
3698c2ecf20Sopenharmony_ci					    MLXSW_SP_RESOURCE_KVD_LINEAR_CHUNKS);
3708c2ecf20Sopenharmony_ci	devlink_resource_occ_get_unregister(devlink,
3718c2ecf20Sopenharmony_ci					    MLXSW_SP_RESOURCE_KVD_LINEAR_SINGLE);
3728c2ecf20Sopenharmony_ci	devlink_resource_occ_get_unregister(devlink,
3738c2ecf20Sopenharmony_ci					    MLXSW_SP_RESOURCE_KVD_LINEAR);
3748c2ecf20Sopenharmony_ci	mlxsw_sp1_kvdl_parts_fini(kvdl);
3758c2ecf20Sopenharmony_ci}
3768c2ecf20Sopenharmony_ci
3778c2ecf20Sopenharmony_ciconst struct mlxsw_sp_kvdl_ops mlxsw_sp1_kvdl_ops = {
3788c2ecf20Sopenharmony_ci	.priv_size = sizeof(struct mlxsw_sp1_kvdl),
3798c2ecf20Sopenharmony_ci	.init = mlxsw_sp1_kvdl_init,
3808c2ecf20Sopenharmony_ci	.fini = mlxsw_sp1_kvdl_fini,
3818c2ecf20Sopenharmony_ci	.alloc = mlxsw_sp1_kvdl_alloc,
3828c2ecf20Sopenharmony_ci	.free = mlxsw_sp1_kvdl_free,
3838c2ecf20Sopenharmony_ci	.alloc_size_query = mlxsw_sp1_kvdl_alloc_size_query,
3848c2ecf20Sopenharmony_ci};
3858c2ecf20Sopenharmony_ci
3868c2ecf20Sopenharmony_ciint mlxsw_sp1_kvdl_resources_register(struct mlxsw_core *mlxsw_core)
3878c2ecf20Sopenharmony_ci{
3888c2ecf20Sopenharmony_ci	struct devlink *devlink = priv_to_devlink(mlxsw_core);
3898c2ecf20Sopenharmony_ci	static struct devlink_resource_size_params size_params;
3908c2ecf20Sopenharmony_ci	u32 kvdl_max_size;
3918c2ecf20Sopenharmony_ci	int err;
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_ci	kvdl_max_size = MLXSW_CORE_RES_GET(mlxsw_core, KVD_SIZE) -
3948c2ecf20Sopenharmony_ci			MLXSW_CORE_RES_GET(mlxsw_core, KVD_SINGLE_MIN_SIZE) -
3958c2ecf20Sopenharmony_ci			MLXSW_CORE_RES_GET(mlxsw_core, KVD_DOUBLE_MIN_SIZE);
3968c2ecf20Sopenharmony_ci
3978c2ecf20Sopenharmony_ci	devlink_resource_size_params_init(&size_params, 0, kvdl_max_size,
3988c2ecf20Sopenharmony_ci					  MLXSW_SP1_KVDL_SINGLE_ALLOC_SIZE,
3998c2ecf20Sopenharmony_ci					  DEVLINK_RESOURCE_UNIT_ENTRY);
4008c2ecf20Sopenharmony_ci	err = devlink_resource_register(devlink, MLXSW_SP_RESOURCE_NAME_KVD_LINEAR_SINGLES,
4018c2ecf20Sopenharmony_ci					MLXSW_SP1_KVDL_SINGLE_SIZE,
4028c2ecf20Sopenharmony_ci					MLXSW_SP_RESOURCE_KVD_LINEAR_SINGLE,
4038c2ecf20Sopenharmony_ci					MLXSW_SP_RESOURCE_KVD_LINEAR,
4048c2ecf20Sopenharmony_ci					&size_params);
4058c2ecf20Sopenharmony_ci	if (err)
4068c2ecf20Sopenharmony_ci		return err;
4078c2ecf20Sopenharmony_ci
4088c2ecf20Sopenharmony_ci	devlink_resource_size_params_init(&size_params, 0, kvdl_max_size,
4098c2ecf20Sopenharmony_ci					  MLXSW_SP1_KVDL_CHUNKS_ALLOC_SIZE,
4108c2ecf20Sopenharmony_ci					  DEVLINK_RESOURCE_UNIT_ENTRY);
4118c2ecf20Sopenharmony_ci	err = devlink_resource_register(devlink, MLXSW_SP_RESOURCE_NAME_KVD_LINEAR_CHUNKS,
4128c2ecf20Sopenharmony_ci					MLXSW_SP1_KVDL_CHUNKS_SIZE,
4138c2ecf20Sopenharmony_ci					MLXSW_SP_RESOURCE_KVD_LINEAR_CHUNKS,
4148c2ecf20Sopenharmony_ci					MLXSW_SP_RESOURCE_KVD_LINEAR,
4158c2ecf20Sopenharmony_ci					&size_params);
4168c2ecf20Sopenharmony_ci	if (err)
4178c2ecf20Sopenharmony_ci		return err;
4188c2ecf20Sopenharmony_ci
4198c2ecf20Sopenharmony_ci	devlink_resource_size_params_init(&size_params, 0, kvdl_max_size,
4208c2ecf20Sopenharmony_ci					  MLXSW_SP1_KVDL_LARGE_CHUNKS_ALLOC_SIZE,
4218c2ecf20Sopenharmony_ci					  DEVLINK_RESOURCE_UNIT_ENTRY);
4228c2ecf20Sopenharmony_ci	err = devlink_resource_register(devlink, MLXSW_SP_RESOURCE_NAME_KVD_LINEAR_LARGE_CHUNKS,
4238c2ecf20Sopenharmony_ci					MLXSW_SP1_KVDL_LARGE_CHUNKS_SIZE,
4248c2ecf20Sopenharmony_ci					MLXSW_SP_RESOURCE_KVD_LINEAR_LARGE_CHUNKS,
4258c2ecf20Sopenharmony_ci					MLXSW_SP_RESOURCE_KVD_LINEAR,
4268c2ecf20Sopenharmony_ci					&size_params);
4278c2ecf20Sopenharmony_ci	return err;
4288c2ecf20Sopenharmony_ci}
429