mirror of https://github.com/F-Stack/f-stack.git
665 lines
16 KiB
C
665 lines
16 KiB
C
/* SPDX-License-Identifier: BSD-3-Clause
|
|
* Copyright (c) 2022 NVIDIA Corporation & Affiliates
|
|
*/
|
|
|
|
#include <rte_bitmap.h>
|
|
#include <rte_malloc.h>
|
|
#include "mlx5dr_buddy.h"
|
|
#include "mlx5dr_internal.h"
|
|
|
|
static void mlx5dr_pool_free_one_resource(struct mlx5dr_pool_resource *resource)
|
|
{
|
|
mlx5dr_cmd_destroy_obj(resource->devx_obj);
|
|
|
|
simple_free(resource);
|
|
}
|
|
|
|
static void mlx5dr_pool_resource_free(struct mlx5dr_pool *pool,
|
|
int resource_idx)
|
|
{
|
|
mlx5dr_pool_free_one_resource(pool->resource[resource_idx]);
|
|
pool->resource[resource_idx] = NULL;
|
|
|
|
if (pool->tbl_type == MLX5DR_TABLE_TYPE_FDB) {
|
|
mlx5dr_pool_free_one_resource(pool->mirror_resource[resource_idx]);
|
|
pool->mirror_resource[resource_idx] = NULL;
|
|
}
|
|
}
|
|
|
|
static struct mlx5dr_pool_resource *
|
|
mlx5dr_pool_create_one_resource(struct mlx5dr_pool *pool, uint32_t log_range,
|
|
uint32_t fw_ft_type)
|
|
{
|
|
struct mlx5dr_cmd_ste_create_attr ste_attr;
|
|
struct mlx5dr_cmd_stc_create_attr stc_attr;
|
|
struct mlx5dr_pool_resource *resource;
|
|
struct mlx5dr_devx_obj *devx_obj;
|
|
|
|
resource = simple_malloc(sizeof(*resource));
|
|
if (!resource) {
|
|
rte_errno = ENOMEM;
|
|
return NULL;
|
|
}
|
|
|
|
switch (pool->type) {
|
|
case MLX5DR_POOL_TYPE_STE:
|
|
ste_attr.log_obj_range = log_range;
|
|
ste_attr.table_type = fw_ft_type;
|
|
devx_obj = mlx5dr_cmd_ste_create(pool->ctx->ibv_ctx, &ste_attr);
|
|
break;
|
|
case MLX5DR_POOL_TYPE_STC:
|
|
stc_attr.log_obj_range = log_range;
|
|
stc_attr.table_type = fw_ft_type;
|
|
devx_obj = mlx5dr_cmd_stc_create(pool->ctx->ibv_ctx, &stc_attr);
|
|
break;
|
|
default:
|
|
assert(0);
|
|
break;
|
|
}
|
|
|
|
if (!devx_obj) {
|
|
DR_LOG(ERR, "Failed to allocate resource objects");
|
|
goto free_resource;
|
|
}
|
|
|
|
resource->pool = pool;
|
|
resource->devx_obj = devx_obj;
|
|
resource->range = 1 << log_range;
|
|
resource->base_id = devx_obj->id;
|
|
|
|
return resource;
|
|
|
|
free_resource:
|
|
simple_free(resource);
|
|
return NULL;
|
|
}
|
|
|
|
static int
|
|
mlx5dr_pool_resource_alloc(struct mlx5dr_pool *pool, uint32_t log_range, int idx)
|
|
{
|
|
struct mlx5dr_pool_resource *resource;
|
|
uint32_t fw_ft_type, opt_log_range;
|
|
|
|
fw_ft_type = mlx5dr_table_get_res_fw_ft_type(pool->tbl_type, false);
|
|
opt_log_range = pool->opt_type == MLX5DR_POOL_OPTIMIZE_ORIG ? 0 : log_range;
|
|
resource = mlx5dr_pool_create_one_resource(pool, opt_log_range, fw_ft_type);
|
|
if (!resource) {
|
|
DR_LOG(ERR, "Failed allocating resource");
|
|
return rte_errno;
|
|
}
|
|
pool->resource[idx] = resource;
|
|
|
|
if (pool->tbl_type == MLX5DR_TABLE_TYPE_FDB) {
|
|
struct mlx5dr_pool_resource *mir_resource;
|
|
|
|
fw_ft_type = mlx5dr_table_get_res_fw_ft_type(pool->tbl_type, true);
|
|
opt_log_range = pool->opt_type == MLX5DR_POOL_OPTIMIZE_MIRROR ? 0 : log_range;
|
|
mir_resource = mlx5dr_pool_create_one_resource(pool, opt_log_range, fw_ft_type);
|
|
if (!mir_resource) {
|
|
DR_LOG(ERR, "Failed allocating mirrored resource");
|
|
mlx5dr_pool_free_one_resource(resource);
|
|
pool->resource[idx] = NULL;
|
|
return rte_errno;
|
|
}
|
|
pool->mirror_resource[idx] = mir_resource;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int mlx5dr_pool_bitmap_get_free_slot(struct rte_bitmap *bitmap, uint32_t *iidx)
|
|
{
|
|
uint64_t slab = 0;
|
|
|
|
__rte_bitmap_scan_init(bitmap);
|
|
|
|
if (!rte_bitmap_scan(bitmap, iidx, &slab))
|
|
return ENOMEM;
|
|
|
|
*iidx += __builtin_ctzll(slab);
|
|
|
|
rte_bitmap_clear(bitmap, *iidx);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static struct rte_bitmap *mlx5dr_pool_create_and_init_bitmap(uint32_t log_range)
|
|
{
|
|
struct rte_bitmap *cur_bmp;
|
|
uint32_t bmp_size;
|
|
void *mem;
|
|
|
|
bmp_size = rte_bitmap_get_memory_footprint(1 << log_range);
|
|
mem = rte_zmalloc("create_stc_bmap", bmp_size, RTE_CACHE_LINE_SIZE);
|
|
if (!mem) {
|
|
DR_LOG(ERR, "No mem for bitmap");
|
|
rte_errno = ENOMEM;
|
|
return NULL;
|
|
}
|
|
|
|
cur_bmp = rte_bitmap_init_with_all_set(1 << log_range, mem, bmp_size);
|
|
if (!cur_bmp) {
|
|
rte_free(mem);
|
|
DR_LOG(ERR, "Failed to initialize stc bitmap.");
|
|
rte_errno = ENOMEM;
|
|
return NULL;
|
|
}
|
|
|
|
return cur_bmp;
|
|
}
|
|
|
|
static void mlx5dr_pool_buddy_db_put_chunk(struct mlx5dr_pool *pool,
|
|
struct mlx5dr_pool_chunk *chunk)
|
|
{
|
|
struct mlx5dr_buddy_mem *buddy;
|
|
|
|
buddy = pool->db.buddy_manager->buddies[chunk->resource_idx];
|
|
if (!buddy) {
|
|
assert(false);
|
|
DR_LOG(ERR, "No such buddy (%d)", chunk->resource_idx);
|
|
return;
|
|
}
|
|
|
|
mlx5dr_buddy_free_mem(buddy, chunk->offset, chunk->order);
|
|
}
|
|
|
|
static struct mlx5dr_buddy_mem *
|
|
mlx5dr_pool_buddy_get_next_buddy(struct mlx5dr_pool *pool, int idx,
|
|
uint32_t order, bool *is_new_buddy)
|
|
{
|
|
static struct mlx5dr_buddy_mem *buddy;
|
|
uint32_t new_buddy_size;
|
|
|
|
buddy = pool->db.buddy_manager->buddies[idx];
|
|
if (buddy)
|
|
return buddy;
|
|
|
|
new_buddy_size = RTE_MAX(pool->alloc_log_sz, order);
|
|
*is_new_buddy = true;
|
|
buddy = mlx5dr_buddy_create(new_buddy_size);
|
|
if (!buddy) {
|
|
DR_LOG(ERR, "Failed to create buddy order: %d index: %d",
|
|
new_buddy_size, idx);
|
|
return NULL;
|
|
}
|
|
|
|
if (mlx5dr_pool_resource_alloc(pool, new_buddy_size, idx) != 0) {
|
|
DR_LOG(ERR, "Failed to create resource type: %d: size %d index: %d",
|
|
pool->type, new_buddy_size, idx);
|
|
mlx5dr_buddy_cleanup(buddy);
|
|
return NULL;
|
|
}
|
|
|
|
pool->db.buddy_manager->buddies[idx] = buddy;
|
|
|
|
return buddy;
|
|
}
|
|
|
|
static int mlx5dr_pool_buddy_get_mem_chunk(struct mlx5dr_pool *pool,
|
|
int order,
|
|
uint32_t *buddy_idx,
|
|
int *seg)
|
|
{
|
|
struct mlx5dr_buddy_mem *buddy;
|
|
bool new_mem = false;
|
|
int err = 0;
|
|
int i;
|
|
|
|
*seg = -1;
|
|
|
|
/* Find the next free place from the buddy array */
|
|
while (*seg == -1) {
|
|
for (i = 0; i < MLX5DR_POOL_RESOURCE_ARR_SZ; i++) {
|
|
buddy = mlx5dr_pool_buddy_get_next_buddy(pool, i,
|
|
order,
|
|
&new_mem);
|
|
if (!buddy) {
|
|
err = rte_errno;
|
|
goto out;
|
|
}
|
|
|
|
*seg = mlx5dr_buddy_alloc_mem(buddy, order);
|
|
if (*seg != -1)
|
|
goto found;
|
|
|
|
if (pool->flags & MLX5DR_POOL_FLAGS_ONE_RESOURCE) {
|
|
DR_LOG(ERR, "Fail to allocate seg for one resource pool");
|
|
err = rte_errno;
|
|
goto out;
|
|
}
|
|
|
|
if (new_mem) {
|
|
/* We have new memory pool, should be place for us */
|
|
assert(false);
|
|
DR_LOG(ERR, "No memory for order: %d with buddy no: %d",
|
|
order, i);
|
|
rte_errno = ENOMEM;
|
|
err = ENOMEM;
|
|
goto out;
|
|
}
|
|
}
|
|
}
|
|
|
|
found:
|
|
*buddy_idx = i;
|
|
out:
|
|
return err;
|
|
}
|
|
|
|
static int mlx5dr_pool_buddy_db_get_chunk(struct mlx5dr_pool *pool,
|
|
struct mlx5dr_pool_chunk *chunk)
|
|
{
|
|
int ret = 0;
|
|
|
|
/* Go over the buddies and find next free slot */
|
|
ret = mlx5dr_pool_buddy_get_mem_chunk(pool, chunk->order,
|
|
&chunk->resource_idx,
|
|
&chunk->offset);
|
|
if (ret)
|
|
DR_LOG(ERR, "Failed to get free slot for chunk with order: %d",
|
|
chunk->order);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void mlx5dr_pool_buddy_db_uninit(struct mlx5dr_pool *pool)
|
|
{
|
|
struct mlx5dr_buddy_mem *buddy;
|
|
int i;
|
|
|
|
for (i = 0; i < MLX5DR_POOL_RESOURCE_ARR_SZ; i++) {
|
|
buddy = pool->db.buddy_manager->buddies[i];
|
|
if (buddy) {
|
|
mlx5dr_buddy_cleanup(buddy);
|
|
simple_free(buddy);
|
|
pool->db.buddy_manager->buddies[i] = NULL;
|
|
}
|
|
}
|
|
|
|
simple_free(pool->db.buddy_manager);
|
|
}
|
|
|
|
static int mlx5dr_pool_buddy_db_init(struct mlx5dr_pool *pool, uint32_t log_range)
|
|
{
|
|
pool->db.buddy_manager = simple_calloc(1, sizeof(*pool->db.buddy_manager));
|
|
if (!pool->db.buddy_manager) {
|
|
DR_LOG(ERR, "No mem for buddy_manager with log_range: %d", log_range);
|
|
rte_errno = ENOMEM;
|
|
return rte_errno;
|
|
}
|
|
|
|
if (pool->flags & MLX5DR_POOL_FLAGS_ALLOC_MEM_ON_CREATE) {
|
|
bool new_buddy;
|
|
|
|
if (!mlx5dr_pool_buddy_get_next_buddy(pool, 0, log_range, &new_buddy)) {
|
|
DR_LOG(ERR, "Failed allocating memory on create log_sz: %d", log_range);
|
|
simple_free(pool->db.buddy_manager);
|
|
return rte_errno;
|
|
}
|
|
}
|
|
|
|
pool->p_db_uninit = &mlx5dr_pool_buddy_db_uninit;
|
|
pool->p_get_chunk = &mlx5dr_pool_buddy_db_get_chunk;
|
|
pool->p_put_chunk = &mlx5dr_pool_buddy_db_put_chunk;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int mlx5dr_pool_create_resource_on_index(struct mlx5dr_pool *pool,
|
|
uint32_t alloc_size, int idx)
|
|
{
|
|
if (mlx5dr_pool_resource_alloc(pool, alloc_size, idx) != 0) {
|
|
DR_LOG(ERR, "Failed to create resource type: %d: size %d index: %d",
|
|
pool->type, alloc_size, idx);
|
|
return rte_errno;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static struct mlx5dr_pool_elements *
|
|
mlx5dr_pool_element_create_new_elem(struct mlx5dr_pool *pool, uint32_t order, int idx)
|
|
{
|
|
struct mlx5dr_pool_elements *elem;
|
|
uint32_t alloc_size;
|
|
|
|
alloc_size = pool->alloc_log_sz;
|
|
|
|
elem = simple_calloc(1, sizeof(*elem));
|
|
if (!elem) {
|
|
DR_LOG(ERR, "Failed to create elem order: %d index: %d",
|
|
order, idx);
|
|
rte_errno = ENOMEM;
|
|
return NULL;
|
|
}
|
|
/*sharing the same resource, also means that all the elements are with size 1*/
|
|
if ((pool->flags & MLX5DR_POOL_FLAGS_FIXED_SIZE_OBJECTS) &&
|
|
!(pool->flags & MLX5DR_POOL_FLAGS_RESOURCE_PER_CHUNK)) {
|
|
/* Currently all chunks in size 1 */
|
|
elem->bitmap = mlx5dr_pool_create_and_init_bitmap(alloc_size - order);
|
|
if (!elem->bitmap) {
|
|
DR_LOG(ERR, "Failed to create bitmap type: %d: size %d index: %d",
|
|
pool->type, alloc_size, idx);
|
|
goto free_elem;
|
|
}
|
|
}
|
|
|
|
if (mlx5dr_pool_create_resource_on_index(pool, alloc_size, idx)) {
|
|
DR_LOG(ERR, "Failed to create resource type: %d: size %d index: %d",
|
|
pool->type, alloc_size, idx);
|
|
goto free_db;
|
|
}
|
|
|
|
pool->db.element_manager->elements[idx] = elem;
|
|
|
|
return elem;
|
|
|
|
free_db:
|
|
rte_free(elem->bitmap);
|
|
free_elem:
|
|
simple_free(elem);
|
|
return NULL;
|
|
}
|
|
|
|
static int mlx5dr_pool_element_find_seg(struct mlx5dr_pool_elements *elem, int *seg)
|
|
{
|
|
if (mlx5dr_pool_bitmap_get_free_slot(elem->bitmap, (uint32_t *)seg)) {
|
|
elem->is_full = true;
|
|
return ENOMEM;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
mlx5dr_pool_onesize_element_get_mem_chunk(struct mlx5dr_pool *pool, uint32_t order,
|
|
uint32_t *idx, int *seg)
|
|
{
|
|
struct mlx5dr_pool_elements *elem;
|
|
|
|
elem = pool->db.element_manager->elements[0];
|
|
if (!elem)
|
|
elem = mlx5dr_pool_element_create_new_elem(pool, order, 0);
|
|
if (!elem)
|
|
goto err_no_elem;
|
|
|
|
*idx = 0;
|
|
|
|
if (mlx5dr_pool_element_find_seg(elem, seg) != 0) {
|
|
DR_LOG(ERR, "No more resources (last request order: %d)", order);
|
|
rte_errno = ENOMEM;
|
|
return ENOMEM;
|
|
}
|
|
|
|
elem->num_of_elements++;
|
|
return 0;
|
|
|
|
err_no_elem:
|
|
DR_LOG(ERR, "Failed to allocate element for order: %d", order);
|
|
return ENOMEM;
|
|
}
|
|
|
|
static int
|
|
mlx5dr_pool_general_element_get_mem_chunk(struct mlx5dr_pool *pool, uint32_t order,
|
|
uint32_t *idx, int *seg)
|
|
{
|
|
int ret;
|
|
int i;
|
|
|
|
for (i = 0; i < MLX5DR_POOL_RESOURCE_ARR_SZ; i++) {
|
|
if (!pool->resource[i]) {
|
|
ret = mlx5dr_pool_create_resource_on_index(pool, order, i);
|
|
if (ret)
|
|
goto err_no_res;
|
|
*idx = i;
|
|
*seg = 0; /* One memory slot in that element */
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
rte_errno = ENOMEM;
|
|
DR_LOG(ERR, "No more resources (last request order: %d)", order);
|
|
return ENOMEM;
|
|
|
|
err_no_res:
|
|
DR_LOG(ERR, "Failed to allocate element for order: %d", order);
|
|
return ENOMEM;
|
|
}
|
|
|
|
static int mlx5dr_pool_general_element_db_get_chunk(struct mlx5dr_pool *pool,
|
|
struct mlx5dr_pool_chunk *chunk)
|
|
{
|
|
int ret;
|
|
|
|
/* Go over all memory elements and find/allocate free slot */
|
|
ret = mlx5dr_pool_general_element_get_mem_chunk(pool, chunk->order,
|
|
&chunk->resource_idx,
|
|
&chunk->offset);
|
|
if (ret)
|
|
DR_LOG(ERR, "Failed to get free slot for chunk with order: %d",
|
|
chunk->order);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void mlx5dr_pool_general_element_db_put_chunk(struct mlx5dr_pool *pool,
|
|
struct mlx5dr_pool_chunk *chunk)
|
|
{
|
|
assert(pool->resource[chunk->resource_idx]);
|
|
|
|
if (pool->flags & MLX5DR_POOL_FLAGS_RELEASE_FREE_RESOURCE)
|
|
mlx5dr_pool_resource_free(pool, chunk->resource_idx);
|
|
}
|
|
|
|
static void mlx5dr_pool_general_element_db_uninit(struct mlx5dr_pool *pool)
|
|
{
|
|
(void)pool;
|
|
}
|
|
|
|
/* This memory management works as the following:
|
|
* - At start doesn't allocate no mem at all.
|
|
* - When new request for chunk arrived:
|
|
* allocate resource and give it.
|
|
* - When free that chunk:
|
|
* the resource is freed.
|
|
*/
|
|
static int mlx5dr_pool_general_element_db_init(struct mlx5dr_pool *pool)
|
|
{
|
|
pool->p_db_uninit = &mlx5dr_pool_general_element_db_uninit;
|
|
pool->p_get_chunk = &mlx5dr_pool_general_element_db_get_chunk;
|
|
pool->p_put_chunk = &mlx5dr_pool_general_element_db_put_chunk;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void mlx5dr_onesize_element_db_destroy_element(struct mlx5dr_pool *pool,
|
|
struct mlx5dr_pool_elements *elem,
|
|
struct mlx5dr_pool_chunk *chunk)
|
|
{
|
|
assert(pool->resource[chunk->resource_idx]);
|
|
|
|
mlx5dr_pool_resource_free(pool, chunk->resource_idx);
|
|
|
|
simple_free(elem);
|
|
pool->db.element_manager->elements[chunk->resource_idx] = NULL;
|
|
}
|
|
|
|
static void mlx5dr_onesize_element_db_put_chunk(struct mlx5dr_pool *pool,
|
|
struct mlx5dr_pool_chunk *chunk)
|
|
{
|
|
struct mlx5dr_pool_elements *elem;
|
|
|
|
assert(chunk->resource_idx == 0);
|
|
|
|
elem = pool->db.element_manager->elements[chunk->resource_idx];
|
|
if (!elem) {
|
|
assert(false);
|
|
DR_LOG(ERR, "No such element (%d)", chunk->resource_idx);
|
|
return;
|
|
}
|
|
|
|
rte_bitmap_set(elem->bitmap, chunk->offset);
|
|
elem->is_full = false;
|
|
elem->num_of_elements--;
|
|
|
|
if (pool->flags & MLX5DR_POOL_FLAGS_RELEASE_FREE_RESOURCE &&
|
|
!elem->num_of_elements)
|
|
mlx5dr_onesize_element_db_destroy_element(pool, elem, chunk);
|
|
}
|
|
|
|
static int mlx5dr_onesize_element_db_get_chunk(struct mlx5dr_pool *pool,
|
|
struct mlx5dr_pool_chunk *chunk)
|
|
{
|
|
int ret = 0;
|
|
|
|
/* Go over all memory elements and find/allocate free slot */
|
|
ret = mlx5dr_pool_onesize_element_get_mem_chunk(pool, chunk->order,
|
|
&chunk->resource_idx,
|
|
&chunk->offset);
|
|
if (ret)
|
|
DR_LOG(ERR, "Failed to get free slot for chunk with order: %d",
|
|
chunk->order);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void mlx5dr_onesize_element_db_uninit(struct mlx5dr_pool *pool)
|
|
{
|
|
struct mlx5dr_pool_elements *elem;
|
|
int i;
|
|
|
|
for (i = 0; i < MLX5DR_POOL_RESOURCE_ARR_SZ; i++) {
|
|
elem = pool->db.element_manager->elements[i];
|
|
if (elem) {
|
|
rte_free(elem->bitmap);
|
|
simple_free(elem);
|
|
pool->db.element_manager->elements[i] = NULL;
|
|
}
|
|
}
|
|
simple_free(pool->db.element_manager);
|
|
}
|
|
|
|
/* This memory management works as the following:
|
|
* - At start doesn't allocate no mem at all.
|
|
* - When new request for chunk arrived:
|
|
* aloocate the first and only slot of memory/resource
|
|
* when it ended return error.
|
|
*/
|
|
static int mlx5dr_pool_onesize_element_db_init(struct mlx5dr_pool *pool)
|
|
{
|
|
pool->db.element_manager = simple_calloc(1, sizeof(*pool->db.element_manager));
|
|
if (!pool->db.element_manager) {
|
|
DR_LOG(ERR, "No mem for general elemnt_manager");
|
|
rte_errno = ENOMEM;
|
|
return rte_errno;
|
|
}
|
|
|
|
pool->p_db_uninit = &mlx5dr_onesize_element_db_uninit;
|
|
pool->p_get_chunk = &mlx5dr_onesize_element_db_get_chunk;
|
|
pool->p_put_chunk = &mlx5dr_onesize_element_db_put_chunk;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int mlx5dr_pool_db_init(struct mlx5dr_pool *pool,
|
|
enum mlx5dr_db_type db_type)
|
|
{
|
|
int ret;
|
|
|
|
if (db_type == MLX5DR_POOL_DB_TYPE_GENERAL_SIZE)
|
|
ret = mlx5dr_pool_general_element_db_init(pool);
|
|
else if (db_type == MLX5DR_POOL_DB_TYPE_ONE_SIZE_RESOURCE)
|
|
ret = mlx5dr_pool_onesize_element_db_init(pool);
|
|
else
|
|
ret = mlx5dr_pool_buddy_db_init(pool, pool->alloc_log_sz);
|
|
|
|
if (ret) {
|
|
DR_LOG(ERR, "Failed to init general db : %d (ret: %d)", db_type, ret);
|
|
return ret;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void mlx5dr_pool_db_unint(struct mlx5dr_pool *pool)
|
|
{
|
|
pool->p_db_uninit(pool);
|
|
}
|
|
|
|
int
|
|
mlx5dr_pool_chunk_alloc(struct mlx5dr_pool *pool,
|
|
struct mlx5dr_pool_chunk *chunk)
|
|
{
|
|
int ret;
|
|
|
|
pthread_spin_lock(&pool->lock);
|
|
ret = pool->p_get_chunk(pool, chunk);
|
|
pthread_spin_unlock(&pool->lock);
|
|
|
|
return ret;
|
|
}
|
|
|
|
void mlx5dr_pool_chunk_free(struct mlx5dr_pool *pool,
|
|
struct mlx5dr_pool_chunk *chunk)
|
|
{
|
|
pthread_spin_lock(&pool->lock);
|
|
pool->p_put_chunk(pool, chunk);
|
|
pthread_spin_unlock(&pool->lock);
|
|
}
|
|
|
|
struct mlx5dr_pool *
|
|
mlx5dr_pool_create(struct mlx5dr_context *ctx, struct mlx5dr_pool_attr *pool_attr)
|
|
{
|
|
enum mlx5dr_db_type res_db_type;
|
|
struct mlx5dr_pool *pool;
|
|
|
|
pool = simple_calloc(1, sizeof(*pool));
|
|
if (!pool)
|
|
return NULL;
|
|
|
|
pool->ctx = ctx;
|
|
pool->type = pool_attr->pool_type;
|
|
pool->alloc_log_sz = pool_attr->alloc_log_sz;
|
|
pool->flags = pool_attr->flags;
|
|
pool->tbl_type = pool_attr->table_type;
|
|
pool->opt_type = pool_attr->opt_type;
|
|
|
|
pthread_spin_init(&pool->lock, PTHREAD_PROCESS_PRIVATE);
|
|
|
|
/* Support general db */
|
|
if (pool->flags == (MLX5DR_POOL_FLAGS_RELEASE_FREE_RESOURCE |
|
|
MLX5DR_POOL_FLAGS_RESOURCE_PER_CHUNK))
|
|
res_db_type = MLX5DR_POOL_DB_TYPE_GENERAL_SIZE;
|
|
else if (pool->flags == (MLX5DR_POOL_FLAGS_ONE_RESOURCE |
|
|
MLX5DR_POOL_FLAGS_FIXED_SIZE_OBJECTS))
|
|
res_db_type = MLX5DR_POOL_DB_TYPE_ONE_SIZE_RESOURCE;
|
|
else
|
|
res_db_type = MLX5DR_POOL_DB_TYPE_BUDDY;
|
|
|
|
pool->alloc_log_sz = pool_attr->alloc_log_sz;
|
|
|
|
if (mlx5dr_pool_db_init(pool, res_db_type))
|
|
goto free_pool;
|
|
|
|
return pool;
|
|
|
|
free_pool:
|
|
pthread_spin_destroy(&pool->lock);
|
|
simple_free(pool);
|
|
return NULL;
|
|
}
|
|
|
|
int mlx5dr_pool_destroy(struct mlx5dr_pool *pool)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < MLX5DR_POOL_RESOURCE_ARR_SZ; i++)
|
|
if (pool->resource[i])
|
|
mlx5dr_pool_resource_free(pool, i);
|
|
|
|
mlx5dr_pool_db_unint(pool);
|
|
|
|
pthread_spin_destroy(&pool->lock);
|
|
simple_free(pool);
|
|
return 0;
|
|
}
|