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