162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+
262306a36Sopenharmony_ci/* Microchip Sparx5 Switch driver
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Copyright (c) 2023 Microchip Technology Inc. and its subsidiaries.
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#include "sparx5_main_regs.h"
862306a36Sopenharmony_ci#include "sparx5_main.h"
962306a36Sopenharmony_ci
1062306a36Sopenharmony_cistatic u32 sparx5_pool_id_to_idx(u32 id)
1162306a36Sopenharmony_ci{
1262306a36Sopenharmony_ci	return --id;
1362306a36Sopenharmony_ci}
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ciu32 sparx5_pool_idx_to_id(u32 idx)
1662306a36Sopenharmony_ci{
1762306a36Sopenharmony_ci	return ++idx;
1862306a36Sopenharmony_ci}
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci/* Release resource from pool.
2162306a36Sopenharmony_ci * Return reference count on success, otherwise return error.
2262306a36Sopenharmony_ci */
2362306a36Sopenharmony_ciint sparx5_pool_put(struct sparx5_pool_entry *pool, int size, u32 id)
2462306a36Sopenharmony_ci{
2562306a36Sopenharmony_ci	struct sparx5_pool_entry *e_itr;
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci	e_itr = (pool + sparx5_pool_id_to_idx(id));
2862306a36Sopenharmony_ci	if (e_itr->ref_cnt == 0)
2962306a36Sopenharmony_ci		return -EINVAL;
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci	return --e_itr->ref_cnt;
3262306a36Sopenharmony_ci}
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci/* Get resource from pool.
3562306a36Sopenharmony_ci * Return reference count on success, otherwise return error.
3662306a36Sopenharmony_ci */
3762306a36Sopenharmony_ciint sparx5_pool_get(struct sparx5_pool_entry *pool, int size, u32 *id)
3862306a36Sopenharmony_ci{
3962306a36Sopenharmony_ci	struct sparx5_pool_entry *e_itr;
4062306a36Sopenharmony_ci	int i;
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci	for (i = 0, e_itr = pool; i < size; i++, e_itr++) {
4362306a36Sopenharmony_ci		if (e_itr->ref_cnt == 0) {
4462306a36Sopenharmony_ci			*id = sparx5_pool_idx_to_id(i);
4562306a36Sopenharmony_ci			return ++e_itr->ref_cnt;
4662306a36Sopenharmony_ci		}
4762306a36Sopenharmony_ci	}
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci	return -ENOSPC;
5062306a36Sopenharmony_ci}
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci/* Get resource from pool that matches index.
5362306a36Sopenharmony_ci * Return reference count on success, otherwise return error.
5462306a36Sopenharmony_ci */
5562306a36Sopenharmony_ciint sparx5_pool_get_with_idx(struct sparx5_pool_entry *pool, int size, u32 idx,
5662306a36Sopenharmony_ci			     u32 *id)
5762306a36Sopenharmony_ci{
5862306a36Sopenharmony_ci	struct sparx5_pool_entry *e_itr;
5962306a36Sopenharmony_ci	int i, ret = -ENOSPC;
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci	for (i = 0, e_itr = pool; i < size; i++, e_itr++) {
6262306a36Sopenharmony_ci		/* Pool index of first free entry */
6362306a36Sopenharmony_ci		if (e_itr->ref_cnt == 0 && ret == -ENOSPC)
6462306a36Sopenharmony_ci			ret = i;
6562306a36Sopenharmony_ci		/* Tc index already in use ? */
6662306a36Sopenharmony_ci		if (e_itr->idx == idx && e_itr->ref_cnt > 0) {
6762306a36Sopenharmony_ci			ret = i;
6862306a36Sopenharmony_ci			break;
6962306a36Sopenharmony_ci		}
7062306a36Sopenharmony_ci	}
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci	/* Did we find a free entry? */
7362306a36Sopenharmony_ci	if (ret >= 0) {
7462306a36Sopenharmony_ci		*id = sparx5_pool_idx_to_id(ret);
7562306a36Sopenharmony_ci		e_itr = (pool + ret);
7662306a36Sopenharmony_ci		e_itr->idx = idx;
7762306a36Sopenharmony_ci		return ++e_itr->ref_cnt;
7862306a36Sopenharmony_ci	}
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci	return ret;
8162306a36Sopenharmony_ci}
82