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