xref: /dpdk/drivers/net/mlx5/hws/mlx5dr_pool.c (revision 3d4e27fd7ff050d565c7450930c92fb945706518)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright (c) 2022 NVIDIA Corporation & Affiliates
3  */
4 
5 #include <rte_bitmap.h>
6 #include <rte_malloc.h>
7 #include "mlx5dr_buddy.h"
8 #include "mlx5dr_internal.h"
9 
mlx5dr_pool_free_one_resource(struct mlx5dr_pool_resource * resource)10 static void mlx5dr_pool_free_one_resource(struct mlx5dr_pool_resource *resource)
11 {
12 	mlx5dr_cmd_destroy_obj(resource->devx_obj);
13 
14 	simple_free(resource);
15 }
16 
mlx5dr_pool_resource_free(struct mlx5dr_pool * pool,int resource_idx)17 static void mlx5dr_pool_resource_free(struct mlx5dr_pool *pool,
18 				      int resource_idx)
19 {
20 	mlx5dr_pool_free_one_resource(pool->resource[resource_idx]);
21 	pool->resource[resource_idx] = NULL;
22 
23 	if (pool->tbl_type == MLX5DR_TABLE_TYPE_FDB) {
24 		mlx5dr_pool_free_one_resource(pool->mirror_resource[resource_idx]);
25 		pool->mirror_resource[resource_idx] = NULL;
26 	}
27 }
28 
29 static struct mlx5dr_pool_resource *
mlx5dr_pool_create_one_resource(struct mlx5dr_pool * pool,uint32_t log_range,uint32_t fw_ft_type)30 mlx5dr_pool_create_one_resource(struct mlx5dr_pool *pool, uint32_t log_range,
31 				uint32_t fw_ft_type)
32 {
33 	struct mlx5dr_cmd_ste_create_attr ste_attr;
34 	struct mlx5dr_cmd_stc_create_attr stc_attr;
35 	struct mlx5dr_pool_resource *resource;
36 	struct mlx5dr_devx_obj *devx_obj;
37 
38 	resource = simple_malloc(sizeof(*resource));
39 	if (!resource) {
40 		rte_errno = ENOMEM;
41 		return NULL;
42 	}
43 
44 	switch (pool->type) {
45 	case MLX5DR_POOL_TYPE_STE:
46 		ste_attr.log_obj_range = log_range;
47 		ste_attr.table_type = fw_ft_type;
48 		devx_obj = mlx5dr_cmd_ste_create(pool->ctx->ibv_ctx, &ste_attr);
49 		break;
50 	case MLX5DR_POOL_TYPE_STC:
51 		stc_attr.log_obj_range = log_range;
52 		stc_attr.table_type = fw_ft_type;
53 		devx_obj = mlx5dr_cmd_stc_create(pool->ctx->ibv_ctx, &stc_attr);
54 		break;
55 	default:
56 		assert(0);
57 		break;
58 	}
59 
60 	if (!devx_obj) {
61 		DR_LOG(ERR, "Failed to allocate resource objects");
62 		goto free_resource;
63 	}
64 
65 	resource->pool = pool;
66 	resource->devx_obj = devx_obj;
67 	resource->range = 1 << log_range;
68 	resource->base_id = devx_obj->id;
69 
70 	return resource;
71 
72 free_resource:
73 	simple_free(resource);
74 	return NULL;
75 }
76 
77 static int
mlx5dr_pool_resource_alloc(struct mlx5dr_pool * pool,uint32_t log_range,int idx)78 mlx5dr_pool_resource_alloc(struct mlx5dr_pool *pool, uint32_t log_range, int idx)
79 {
80 	struct mlx5dr_pool_resource *resource;
81 	uint32_t fw_ft_type, opt_log_range;
82 
83 	fw_ft_type = mlx5dr_table_get_res_fw_ft_type(pool->tbl_type, false);
84 	opt_log_range = pool->opt_type == MLX5DR_POOL_OPTIMIZE_ORIG ? 0 : log_range;
85 	resource = mlx5dr_pool_create_one_resource(pool, opt_log_range, fw_ft_type);
86 	if (!resource) {
87 		DR_LOG(ERR, "Failed allocating resource");
88 		return rte_errno;
89 	}
90 	pool->resource[idx] = resource;
91 
92 	if (pool->tbl_type == MLX5DR_TABLE_TYPE_FDB) {
93 		struct mlx5dr_pool_resource *mir_resource;
94 
95 		fw_ft_type = mlx5dr_table_get_res_fw_ft_type(pool->tbl_type, true);
96 		opt_log_range = pool->opt_type == MLX5DR_POOL_OPTIMIZE_MIRROR ? 0 : log_range;
97 		mir_resource = mlx5dr_pool_create_one_resource(pool, opt_log_range, fw_ft_type);
98 		if (!mir_resource) {
99 			DR_LOG(ERR, "Failed allocating mirrored resource");
100 			mlx5dr_pool_free_one_resource(resource);
101 			pool->resource[idx] = NULL;
102 			return rte_errno;
103 		}
104 		pool->mirror_resource[idx] = mir_resource;
105 	}
106 
107 	return 0;
108 }
109 
mlx5dr_pool_bitmap_get_free_slot(struct rte_bitmap * bitmap,uint32_t * iidx)110 static int mlx5dr_pool_bitmap_get_free_slot(struct rte_bitmap *bitmap, uint32_t *iidx)
111 {
112 	uint64_t slab = 0;
113 
114 	__rte_bitmap_scan_init(bitmap);
115 
116 	if (!rte_bitmap_scan(bitmap, iidx, &slab))
117 		return ENOMEM;
118 
119 	*iidx += rte_ctz64(slab);
120 
121 	rte_bitmap_clear(bitmap, *iidx);
122 
123 	return 0;
124 }
125 
mlx5dr_pool_create_and_init_bitmap(uint32_t log_range)126 static struct rte_bitmap *mlx5dr_pool_create_and_init_bitmap(uint32_t log_range)
127 {
128 	struct rte_bitmap *cur_bmp;
129 	uint32_t bmp_size;
130 	void *mem;
131 
132 	bmp_size = rte_bitmap_get_memory_footprint(1 << log_range);
133 	mem = rte_zmalloc("create_stc_bmap", bmp_size, RTE_CACHE_LINE_SIZE);
134 	if (!mem) {
135 		DR_LOG(ERR, "No mem for bitmap");
136 		rte_errno = ENOMEM;
137 		return NULL;
138 	}
139 
140 	cur_bmp = rte_bitmap_init_with_all_set(1 << log_range, mem, bmp_size);
141 	if (!cur_bmp) {
142 		rte_free(mem);
143 		DR_LOG(ERR, "Failed to initialize stc bitmap.");
144 		rte_errno = ENOMEM;
145 		return NULL;
146 	}
147 
148 	return cur_bmp;
149 }
150 
mlx5dr_pool_buddy_db_put_chunk(struct mlx5dr_pool * pool,struct mlx5dr_pool_chunk * chunk)151 static void mlx5dr_pool_buddy_db_put_chunk(struct mlx5dr_pool *pool,
152 				      struct mlx5dr_pool_chunk *chunk)
153 {
154 	struct mlx5dr_buddy_mem *buddy;
155 
156 	buddy = pool->db.buddy_manager->buddies[chunk->resource_idx];
157 	if (!buddy) {
158 		assert(false);
159 		DR_LOG(ERR, "No such buddy (%d)", chunk->resource_idx);
160 		return;
161 	}
162 
163 	mlx5dr_buddy_free_mem(buddy, chunk->offset, chunk->order);
164 }
165 
166 static struct mlx5dr_buddy_mem *
mlx5dr_pool_buddy_get_next_buddy(struct mlx5dr_pool * pool,int idx,uint32_t order,bool * is_new_buddy)167 mlx5dr_pool_buddy_get_next_buddy(struct mlx5dr_pool *pool, int idx,
168 				 uint32_t order, bool *is_new_buddy)
169 {
170 	static struct mlx5dr_buddy_mem *buddy;
171 	uint32_t new_buddy_size;
172 
173 	buddy = pool->db.buddy_manager->buddies[idx];
174 	if (buddy)
175 		return buddy;
176 
177 	new_buddy_size = RTE_MAX(pool->alloc_log_sz, order);
178 	*is_new_buddy = true;
179 	buddy = mlx5dr_buddy_create(new_buddy_size);
180 	if (!buddy) {
181 		DR_LOG(ERR, "Failed to create buddy order: %d index: %d",
182 		       new_buddy_size, idx);
183 		return NULL;
184 	}
185 
186 	if (mlx5dr_pool_resource_alloc(pool, new_buddy_size, idx) != 0) {
187 		DR_LOG(ERR, "Failed to create resource type: %d: size %d index: %d",
188 			pool->type, new_buddy_size, idx);
189 		mlx5dr_buddy_cleanup(buddy);
190 		return NULL;
191 	}
192 
193 	pool->db.buddy_manager->buddies[idx] = buddy;
194 
195 	return buddy;
196 }
197 
mlx5dr_pool_buddy_get_mem_chunk(struct mlx5dr_pool * pool,int order,uint32_t * buddy_idx,int * seg)198 static int mlx5dr_pool_buddy_get_mem_chunk(struct mlx5dr_pool *pool,
199 					   int order,
200 					   uint32_t *buddy_idx,
201 					   int *seg)
202 {
203 	struct mlx5dr_buddy_mem *buddy;
204 	bool new_mem = false;
205 	int err = 0;
206 	int i;
207 
208 	*seg = -1;
209 
210 	/* Find the next free place from the buddy array */
211 	while (*seg == -1) {
212 		for (i = 0; i < MLX5DR_POOL_RESOURCE_ARR_SZ; i++) {
213 			buddy = mlx5dr_pool_buddy_get_next_buddy(pool, i,
214 								 order,
215 								 &new_mem);
216 			if (!buddy) {
217 				err = rte_errno;
218 				goto out;
219 			}
220 
221 			*seg = mlx5dr_buddy_alloc_mem(buddy, order);
222 			if (*seg != -1)
223 				goto found;
224 
225 			if (pool->flags & MLX5DR_POOL_FLAGS_ONE_RESOURCE) {
226 				DR_LOG(ERR, "Fail to allocate seg for one resource pool");
227 				err = rte_errno;
228 				goto out;
229 			}
230 
231 			if (new_mem) {
232 				/* We have new memory pool, should be place for us */
233 				assert(false);
234 				DR_LOG(ERR, "No memory for order: %d with buddy no: %d",
235 					order, i);
236 				rte_errno = ENOMEM;
237 				err = ENOMEM;
238 				goto out;
239 			}
240 		}
241 	}
242 
243 found:
244 	*buddy_idx = i;
245 out:
246 	return err;
247 }
248 
mlx5dr_pool_buddy_db_get_chunk(struct mlx5dr_pool * pool,struct mlx5dr_pool_chunk * chunk)249 static int mlx5dr_pool_buddy_db_get_chunk(struct mlx5dr_pool *pool,
250 				     struct mlx5dr_pool_chunk *chunk)
251 {
252 	int ret = 0;
253 
254 	/* Go over the buddies and find next free slot */
255 	ret = mlx5dr_pool_buddy_get_mem_chunk(pool, chunk->order,
256 					      &chunk->resource_idx,
257 					      &chunk->offset);
258 	if (ret)
259 		DR_LOG(ERR, "Failed to get free slot for chunk with order: %d",
260 			chunk->order);
261 
262 	return ret;
263 }
264 
mlx5dr_pool_buddy_db_uninit(struct mlx5dr_pool * pool)265 static void mlx5dr_pool_buddy_db_uninit(struct mlx5dr_pool *pool)
266 {
267 	struct mlx5dr_buddy_mem *buddy;
268 	int i;
269 
270 	for (i = 0; i < MLX5DR_POOL_RESOURCE_ARR_SZ; i++) {
271 		buddy = pool->db.buddy_manager->buddies[i];
272 		if (buddy) {
273 			mlx5dr_buddy_cleanup(buddy);
274 			simple_free(buddy);
275 			pool->db.buddy_manager->buddies[i] = NULL;
276 		}
277 	}
278 
279 	simple_free(pool->db.buddy_manager);
280 }
281 
mlx5dr_pool_buddy_db_init(struct mlx5dr_pool * pool,uint32_t log_range)282 static int mlx5dr_pool_buddy_db_init(struct mlx5dr_pool *pool, uint32_t log_range)
283 {
284 	pool->db.buddy_manager = simple_calloc(1, sizeof(*pool->db.buddy_manager));
285 	if (!pool->db.buddy_manager) {
286 		DR_LOG(ERR, "No mem for buddy_manager with log_range: %d", log_range);
287 		rte_errno = ENOMEM;
288 		return rte_errno;
289 	}
290 
291 	if (pool->flags & MLX5DR_POOL_FLAGS_ALLOC_MEM_ON_CREATE) {
292 		bool new_buddy;
293 
294 		if (!mlx5dr_pool_buddy_get_next_buddy(pool, 0, log_range, &new_buddy)) {
295 			DR_LOG(ERR, "Failed allocating memory on create log_sz: %d", log_range);
296 			simple_free(pool->db.buddy_manager);
297 			return rte_errno;
298 		}
299 	}
300 
301 	pool->p_db_uninit = &mlx5dr_pool_buddy_db_uninit;
302 	pool->p_get_chunk = &mlx5dr_pool_buddy_db_get_chunk;
303 	pool->p_put_chunk = &mlx5dr_pool_buddy_db_put_chunk;
304 
305 	return 0;
306 }
307 
mlx5dr_pool_create_resource_on_index(struct mlx5dr_pool * pool,uint32_t alloc_size,int idx)308 static int mlx5dr_pool_create_resource_on_index(struct mlx5dr_pool *pool,
309 						uint32_t alloc_size, int idx)
310 {
311 	if (mlx5dr_pool_resource_alloc(pool, alloc_size, idx) != 0) {
312 		DR_LOG(ERR, "Failed to create resource type: %d: size %d index: %d",
313 			pool->type, alloc_size, idx);
314 		return rte_errno;
315 	}
316 
317 	return 0;
318 }
319 
320 static struct mlx5dr_pool_elements *
mlx5dr_pool_element_create_new_elem(struct mlx5dr_pool * pool,uint32_t order,int idx)321 mlx5dr_pool_element_create_new_elem(struct mlx5dr_pool *pool, uint32_t order, int idx)
322 {
323 	struct mlx5dr_pool_elements *elem;
324 	uint32_t alloc_size;
325 
326 	alloc_size = pool->alloc_log_sz;
327 
328 	elem = simple_calloc(1, sizeof(*elem));
329 	if (!elem) {
330 		DR_LOG(ERR, "Failed to create elem order: %d index: %d",
331 		       order, idx);
332 		rte_errno = ENOMEM;
333 		return NULL;
334 	}
335 	/*sharing the same resource, also means that all the elements are with size 1*/
336 	if ((pool->flags & MLX5DR_POOL_FLAGS_FIXED_SIZE_OBJECTS) &&
337 	    !(pool->flags & MLX5DR_POOL_FLAGS_RESOURCE_PER_CHUNK)) {
338 		 /* Currently all chunks in size 1 */
339 		elem->bitmap =  mlx5dr_pool_create_and_init_bitmap(alloc_size - order);
340 		if (!elem->bitmap) {
341 			DR_LOG(ERR, "Failed to create bitmap type: %d: size %d index: %d",
342 			       pool->type, alloc_size, idx);
343 			goto free_elem;
344 		}
345 	}
346 
347 	if (mlx5dr_pool_create_resource_on_index(pool, alloc_size, idx)) {
348 		DR_LOG(ERR, "Failed to create resource type: %d: size %d index: %d",
349 			pool->type, alloc_size, idx);
350 		goto free_db;
351 	}
352 
353 	pool->db.element_manager->elements[idx] = elem;
354 
355 	return elem;
356 
357 free_db:
358 	rte_free(elem->bitmap);
359 free_elem:
360 	simple_free(elem);
361 	return NULL;
362 }
363 
mlx5dr_pool_element_find_seg(struct mlx5dr_pool_elements * elem,int * seg)364 static int mlx5dr_pool_element_find_seg(struct mlx5dr_pool_elements *elem, int *seg)
365 {
366 	if (mlx5dr_pool_bitmap_get_free_slot(elem->bitmap, (uint32_t *)seg)) {
367 		elem->is_full = true;
368 		return ENOMEM;
369 	}
370 	return 0;
371 }
372 
373 static int
mlx5dr_pool_onesize_element_get_mem_chunk(struct mlx5dr_pool * pool,uint32_t order,uint32_t * idx,int * seg)374 mlx5dr_pool_onesize_element_get_mem_chunk(struct mlx5dr_pool *pool, uint32_t order,
375 					  uint32_t *idx, int *seg)
376 {
377 	struct mlx5dr_pool_elements *elem;
378 
379 	elem = pool->db.element_manager->elements[0];
380 	if (!elem)
381 		elem = mlx5dr_pool_element_create_new_elem(pool, order, 0);
382 	if (!elem)
383 		goto err_no_elem;
384 
385 	*idx = 0;
386 
387 	if (mlx5dr_pool_element_find_seg(elem, seg) != 0) {
388 		DR_LOG(ERR, "No more resources (last request order: %d)", order);
389 		rte_errno = ENOMEM;
390 		return ENOMEM;
391 	}
392 
393 	elem->num_of_elements++;
394 	return 0;
395 
396 err_no_elem:
397 	DR_LOG(ERR, "Failed to allocate element for order: %d", order);
398 	return ENOMEM;
399 }
400 
401 static int
mlx5dr_pool_general_element_get_mem_chunk(struct mlx5dr_pool * pool,uint32_t order,uint32_t * idx,int * seg)402 mlx5dr_pool_general_element_get_mem_chunk(struct mlx5dr_pool *pool, uint32_t order,
403 					  uint32_t *idx, int *seg)
404 {
405 	int ret;
406 	int i;
407 
408 	for (i = 0; i < MLX5DR_POOL_RESOURCE_ARR_SZ; i++) {
409 		if (!pool->resource[i]) {
410 			ret = mlx5dr_pool_create_resource_on_index(pool, order, i);
411 			if (ret)
412 				goto err_no_res;
413 			*idx = i;
414 			*seg = 0; /* One memory slot in that element */
415 			return 0;
416 		}
417 	}
418 
419 	rte_errno = ENOMEM;
420 	DR_LOG(ERR, "No more resources (last request order: %d)", order);
421 	return ENOMEM;
422 
423 err_no_res:
424 	DR_LOG(ERR, "Failed to allocate element for order: %d", order);
425 	return ENOMEM;
426 }
427 
mlx5dr_pool_general_element_db_get_chunk(struct mlx5dr_pool * pool,struct mlx5dr_pool_chunk * chunk)428 static int mlx5dr_pool_general_element_db_get_chunk(struct mlx5dr_pool *pool,
429 						    struct mlx5dr_pool_chunk *chunk)
430 {
431 	int ret;
432 
433 	/* Go over all memory elements and find/allocate free slot */
434 	ret = mlx5dr_pool_general_element_get_mem_chunk(pool, chunk->order,
435 							&chunk->resource_idx,
436 							&chunk->offset);
437 	if (ret)
438 		DR_LOG(ERR, "Failed to get free slot for chunk with order: %d",
439 			chunk->order);
440 
441 	return ret;
442 }
443 
mlx5dr_pool_general_element_db_put_chunk(struct mlx5dr_pool * pool,struct mlx5dr_pool_chunk * chunk)444 static void mlx5dr_pool_general_element_db_put_chunk(struct mlx5dr_pool *pool,
445 						     struct mlx5dr_pool_chunk *chunk)
446 {
447 	assert(pool->resource[chunk->resource_idx]);
448 
449 	if (pool->flags & MLX5DR_POOL_FLAGS_RELEASE_FREE_RESOURCE)
450 		mlx5dr_pool_resource_free(pool, chunk->resource_idx);
451 }
452 
mlx5dr_pool_general_element_db_uninit(struct mlx5dr_pool * pool)453 static void mlx5dr_pool_general_element_db_uninit(struct mlx5dr_pool *pool)
454 {
455 	(void)pool;
456 }
457 
458 /* This memory management works as the following:
459  * - At start doesn't allocate no mem at all.
460  * - When new request for chunk arrived:
461  *	allocate resource and give it.
462  * - When free that chunk:
463  *	the resource is freed.
464  */
mlx5dr_pool_general_element_db_init(struct mlx5dr_pool * pool)465 static int mlx5dr_pool_general_element_db_init(struct mlx5dr_pool *pool)
466 {
467 	pool->p_db_uninit = &mlx5dr_pool_general_element_db_uninit;
468 	pool->p_get_chunk = &mlx5dr_pool_general_element_db_get_chunk;
469 	pool->p_put_chunk = &mlx5dr_pool_general_element_db_put_chunk;
470 
471 	return 0;
472 }
473 
mlx5dr_onesize_element_db_destroy_element(struct mlx5dr_pool * pool,struct mlx5dr_pool_elements * elem,struct mlx5dr_pool_chunk * chunk)474 static void mlx5dr_onesize_element_db_destroy_element(struct mlx5dr_pool *pool,
475 						      struct mlx5dr_pool_elements *elem,
476 						      struct mlx5dr_pool_chunk *chunk)
477 {
478 	assert(pool->resource[chunk->resource_idx]);
479 
480 	mlx5dr_pool_resource_free(pool, chunk->resource_idx);
481 
482 	simple_free(elem);
483 	pool->db.element_manager->elements[chunk->resource_idx] = NULL;
484 }
485 
mlx5dr_onesize_element_db_put_chunk(struct mlx5dr_pool * pool,struct mlx5dr_pool_chunk * chunk)486 static void mlx5dr_onesize_element_db_put_chunk(struct mlx5dr_pool *pool,
487 						struct mlx5dr_pool_chunk *chunk)
488 {
489 	struct mlx5dr_pool_elements *elem;
490 
491 	assert(chunk->resource_idx == 0);
492 
493 	elem = pool->db.element_manager->elements[chunk->resource_idx];
494 	if (!elem) {
495 		assert(false);
496 		DR_LOG(ERR, "No such element (%d)", chunk->resource_idx);
497 		return;
498 	}
499 
500 	rte_bitmap_set(elem->bitmap, chunk->offset);
501 	elem->is_full = false;
502 	elem->num_of_elements--;
503 
504 	if (pool->flags & MLX5DR_POOL_FLAGS_RELEASE_FREE_RESOURCE &&
505 	   !elem->num_of_elements)
506 		mlx5dr_onesize_element_db_destroy_element(pool, elem, chunk);
507 }
508 
mlx5dr_onesize_element_db_get_chunk(struct mlx5dr_pool * pool,struct mlx5dr_pool_chunk * chunk)509 static int mlx5dr_onesize_element_db_get_chunk(struct mlx5dr_pool *pool,
510 					       struct mlx5dr_pool_chunk *chunk)
511 {
512 	int ret = 0;
513 
514 	/* Go over all memory elements and find/allocate free slot */
515 	ret = mlx5dr_pool_onesize_element_get_mem_chunk(pool, chunk->order,
516 							&chunk->resource_idx,
517 							&chunk->offset);
518 	if (ret)
519 		DR_LOG(ERR, "Failed to get free slot for chunk with order: %d",
520 			chunk->order);
521 
522 	return ret;
523 }
524 
mlx5dr_onesize_element_db_uninit(struct mlx5dr_pool * pool)525 static void mlx5dr_onesize_element_db_uninit(struct mlx5dr_pool *pool)
526 {
527 	struct mlx5dr_pool_elements *elem;
528 	int i;
529 
530 	for (i = 0; i < MLX5DR_POOL_RESOURCE_ARR_SZ; i++) {
531 		elem = pool->db.element_manager->elements[i];
532 		if (elem) {
533 			rte_free(elem->bitmap);
534 			simple_free(elem);
535 			pool->db.element_manager->elements[i] = NULL;
536 		}
537 	}
538 	simple_free(pool->db.element_manager);
539 }
540 
541 /* This memory management works as the following:
542  * - At start doesn't allocate no mem at all.
543  * - When new request for chunk arrived:
544  *  aloocate the first and only slot of memory/resource
545  *  when it ended return error.
546  */
mlx5dr_pool_onesize_element_db_init(struct mlx5dr_pool * pool)547 static int mlx5dr_pool_onesize_element_db_init(struct mlx5dr_pool *pool)
548 {
549 	pool->db.element_manager = simple_calloc(1, sizeof(*pool->db.element_manager));
550 	if (!pool->db.element_manager) {
551 		DR_LOG(ERR, "No mem for general elemnt_manager");
552 		rte_errno = ENOMEM;
553 		return rte_errno;
554 	}
555 
556 	pool->p_db_uninit = &mlx5dr_onesize_element_db_uninit;
557 	pool->p_get_chunk = &mlx5dr_onesize_element_db_get_chunk;
558 	pool->p_put_chunk = &mlx5dr_onesize_element_db_put_chunk;
559 
560 	return 0;
561 }
562 
mlx5dr_pool_db_init(struct mlx5dr_pool * pool,enum mlx5dr_db_type db_type)563 static int mlx5dr_pool_db_init(struct mlx5dr_pool *pool,
564 			       enum mlx5dr_db_type db_type)
565 {
566 	int ret;
567 
568 	if (db_type == MLX5DR_POOL_DB_TYPE_GENERAL_SIZE)
569 		ret = mlx5dr_pool_general_element_db_init(pool);
570 	else if (db_type == MLX5DR_POOL_DB_TYPE_ONE_SIZE_RESOURCE)
571 		ret = mlx5dr_pool_onesize_element_db_init(pool);
572 	else
573 		ret = mlx5dr_pool_buddy_db_init(pool, pool->alloc_log_sz);
574 
575 	if (ret) {
576 		DR_LOG(ERR, "Failed to init general db : %d (ret: %d)", db_type, ret);
577 		return ret;
578 	}
579 
580 	return 0;
581 }
582 
mlx5dr_pool_db_unint(struct mlx5dr_pool * pool)583 static void mlx5dr_pool_db_unint(struct mlx5dr_pool *pool)
584 {
585 	pool->p_db_uninit(pool);
586 }
587 
588 int
mlx5dr_pool_chunk_alloc(struct mlx5dr_pool * pool,struct mlx5dr_pool_chunk * chunk)589 mlx5dr_pool_chunk_alloc(struct mlx5dr_pool *pool,
590 			struct mlx5dr_pool_chunk *chunk)
591 {
592 	int ret;
593 
594 	pthread_spin_lock(&pool->lock);
595 	ret = pool->p_get_chunk(pool, chunk);
596 	pthread_spin_unlock(&pool->lock);
597 
598 	return ret;
599 }
600 
mlx5dr_pool_chunk_free(struct mlx5dr_pool * pool,struct mlx5dr_pool_chunk * chunk)601 void mlx5dr_pool_chunk_free(struct mlx5dr_pool *pool,
602 			    struct mlx5dr_pool_chunk *chunk)
603 {
604 	pthread_spin_lock(&pool->lock);
605 	pool->p_put_chunk(pool, chunk);
606 	pthread_spin_unlock(&pool->lock);
607 }
608 
609 struct mlx5dr_pool *
mlx5dr_pool_create(struct mlx5dr_context * ctx,struct mlx5dr_pool_attr * pool_attr)610 mlx5dr_pool_create(struct mlx5dr_context *ctx, struct mlx5dr_pool_attr *pool_attr)
611 {
612 	enum mlx5dr_db_type res_db_type;
613 	struct mlx5dr_pool *pool;
614 
615 	pool = simple_calloc(1, sizeof(*pool));
616 	if (!pool)
617 		return NULL;
618 
619 	pool->ctx = ctx;
620 	pool->type = pool_attr->pool_type;
621 	pool->alloc_log_sz = pool_attr->alloc_log_sz;
622 	pool->flags = pool_attr->flags;
623 	pool->tbl_type = pool_attr->table_type;
624 	pool->opt_type = pool_attr->opt_type;
625 
626 	pthread_spin_init(&pool->lock, PTHREAD_PROCESS_PRIVATE);
627 
628 	/* Support general db */
629 	if (pool->flags == (MLX5DR_POOL_FLAGS_RELEASE_FREE_RESOURCE |
630 			    MLX5DR_POOL_FLAGS_RESOURCE_PER_CHUNK))
631 		res_db_type = MLX5DR_POOL_DB_TYPE_GENERAL_SIZE;
632 	else if (pool->flags == (MLX5DR_POOL_FLAGS_ONE_RESOURCE |
633 				 MLX5DR_POOL_FLAGS_FIXED_SIZE_OBJECTS))
634 		res_db_type = MLX5DR_POOL_DB_TYPE_ONE_SIZE_RESOURCE;
635 	else
636 		res_db_type = MLX5DR_POOL_DB_TYPE_BUDDY;
637 
638 	pool->alloc_log_sz = pool_attr->alloc_log_sz;
639 
640 	if (mlx5dr_pool_db_init(pool, res_db_type))
641 		goto free_pool;
642 
643 	return pool;
644 
645 free_pool:
646 	pthread_spin_destroy(&pool->lock);
647 	simple_free(pool);
648 	return NULL;
649 }
650 
mlx5dr_pool_destroy(struct mlx5dr_pool * pool)651 int mlx5dr_pool_destroy(struct mlx5dr_pool *pool)
652 {
653 	int i;
654 
655 	for (i = 0; i < MLX5DR_POOL_RESOURCE_ARR_SZ; i++)
656 		if (pool->resource[i])
657 			mlx5dr_pool_resource_free(pool, i);
658 
659 	mlx5dr_pool_db_unint(pool);
660 
661 	pthread_spin_destroy(&pool->lock);
662 	simple_free(pool);
663 	return 0;
664 }
665