1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 /* Copyright (c) 2024 NVIDIA Corporation & Affiliates */
3 
4 #include "mlx5hws_internal.h"
5 #include "mlx5hws_buddy.h"
6 
hws_pool_free_one_resource(struct mlx5hws_pool_resource * resource)7 static void hws_pool_free_one_resource(struct mlx5hws_pool_resource *resource)
8 {
9 	switch (resource->pool->type) {
10 	case MLX5HWS_POOL_TYPE_STE:
11 		mlx5hws_cmd_ste_destroy(resource->pool->ctx->mdev, resource->base_id);
12 		break;
13 	case MLX5HWS_POOL_TYPE_STC:
14 		mlx5hws_cmd_stc_destroy(resource->pool->ctx->mdev, resource->base_id);
15 		break;
16 	default:
17 		break;
18 	}
19 
20 	kfree(resource);
21 }
22 
hws_pool_resource_free(struct mlx5hws_pool * pool,int resource_idx)23 static void hws_pool_resource_free(struct mlx5hws_pool *pool,
24 				   int resource_idx)
25 {
26 	hws_pool_free_one_resource(pool->resource[resource_idx]);
27 	pool->resource[resource_idx] = NULL;
28 
29 	if (pool->tbl_type == MLX5HWS_TABLE_TYPE_FDB) {
30 		hws_pool_free_one_resource(pool->mirror_resource[resource_idx]);
31 		pool->mirror_resource[resource_idx] = NULL;
32 	}
33 }
34 
35 static struct mlx5hws_pool_resource *
hws_pool_create_one_resource(struct mlx5hws_pool * pool,u32 log_range,u32 fw_ft_type)36 hws_pool_create_one_resource(struct mlx5hws_pool *pool, u32 log_range,
37 			     u32 fw_ft_type)
38 {
39 	struct mlx5hws_cmd_ste_create_attr ste_attr;
40 	struct mlx5hws_cmd_stc_create_attr stc_attr;
41 	struct mlx5hws_pool_resource *resource;
42 	u32 obj_id = 0;
43 	int ret;
44 
45 	resource = kzalloc(sizeof(*resource), GFP_KERNEL);
46 	if (!resource)
47 		return NULL;
48 
49 	switch (pool->type) {
50 	case MLX5HWS_POOL_TYPE_STE:
51 		ste_attr.log_obj_range = log_range;
52 		ste_attr.table_type = fw_ft_type;
53 		ret = mlx5hws_cmd_ste_create(pool->ctx->mdev, &ste_attr, &obj_id);
54 		break;
55 	case MLX5HWS_POOL_TYPE_STC:
56 		stc_attr.log_obj_range = log_range;
57 		stc_attr.table_type = fw_ft_type;
58 		ret = mlx5hws_cmd_stc_create(pool->ctx->mdev, &stc_attr, &obj_id);
59 		break;
60 	default:
61 		ret = -EINVAL;
62 	}
63 
64 	if (ret) {
65 		mlx5hws_err(pool->ctx, "Failed to allocate resource objects\n");
66 		goto free_resource;
67 	}
68 
69 	resource->pool = pool;
70 	resource->range = 1 << log_range;
71 	resource->base_id = obj_id;
72 
73 	return resource;
74 
75 free_resource:
76 	kfree(resource);
77 	return NULL;
78 }
79 
80 static int
hws_pool_resource_alloc(struct mlx5hws_pool * pool,u32 log_range,int idx)81 hws_pool_resource_alloc(struct mlx5hws_pool *pool, u32 log_range, int idx)
82 {
83 	struct mlx5hws_pool_resource *resource;
84 	u32 fw_ft_type, opt_log_range;
85 
86 	fw_ft_type = mlx5hws_table_get_res_fw_ft_type(pool->tbl_type, false);
87 	opt_log_range = pool->opt_type == MLX5HWS_POOL_OPTIMIZE_ORIG ? 0 : log_range;
88 	resource = hws_pool_create_one_resource(pool, opt_log_range, fw_ft_type);
89 	if (!resource) {
90 		mlx5hws_err(pool->ctx, "Failed allocating resource\n");
91 		return -EINVAL;
92 	}
93 
94 	pool->resource[idx] = resource;
95 
96 	if (pool->tbl_type == MLX5HWS_TABLE_TYPE_FDB) {
97 		struct mlx5hws_pool_resource *mirror_resource;
98 
99 		fw_ft_type = mlx5hws_table_get_res_fw_ft_type(pool->tbl_type, true);
100 		opt_log_range = pool->opt_type == MLX5HWS_POOL_OPTIMIZE_MIRROR ? 0 : log_range;
101 		mirror_resource = hws_pool_create_one_resource(pool, opt_log_range, fw_ft_type);
102 		if (!mirror_resource) {
103 			mlx5hws_err(pool->ctx, "Failed allocating mirrored resource\n");
104 			hws_pool_free_one_resource(resource);
105 			pool->resource[idx] = NULL;
106 			return -EINVAL;
107 		}
108 		pool->mirror_resource[idx] = mirror_resource;
109 	}
110 
111 	return 0;
112 }
113 
hws_pool_create_and_init_bitmap(u32 log_range)114 static unsigned long *hws_pool_create_and_init_bitmap(u32 log_range)
115 {
116 	unsigned long *cur_bmp;
117 
118 	cur_bmp = bitmap_zalloc(1 << log_range, GFP_KERNEL);
119 	if (!cur_bmp)
120 		return NULL;
121 
122 	bitmap_fill(cur_bmp, 1 << log_range);
123 
124 	return cur_bmp;
125 }
126 
hws_pool_buddy_db_put_chunk(struct mlx5hws_pool * pool,struct mlx5hws_pool_chunk * chunk)127 static void hws_pool_buddy_db_put_chunk(struct mlx5hws_pool *pool,
128 					struct mlx5hws_pool_chunk *chunk)
129 {
130 	struct mlx5hws_buddy_mem *buddy;
131 
132 	buddy = pool->db.buddy_manager->buddies[chunk->resource_idx];
133 	if (!buddy) {
134 		mlx5hws_err(pool->ctx, "No such buddy (%d)\n", chunk->resource_idx);
135 		return;
136 	}
137 
138 	mlx5hws_buddy_free_mem(buddy, chunk->offset, chunk->order);
139 }
140 
141 static struct mlx5hws_buddy_mem *
hws_pool_buddy_get_next_buddy(struct mlx5hws_pool * pool,int idx,u32 order,bool * is_new_buddy)142 hws_pool_buddy_get_next_buddy(struct mlx5hws_pool *pool, int idx,
143 			      u32 order, bool *is_new_buddy)
144 {
145 	static struct mlx5hws_buddy_mem *buddy;
146 	u32 new_buddy_size;
147 
148 	buddy = pool->db.buddy_manager->buddies[idx];
149 	if (buddy)
150 		return buddy;
151 
152 	new_buddy_size = max(pool->alloc_log_sz, order);
153 	*is_new_buddy = true;
154 	buddy = mlx5hws_buddy_create(new_buddy_size);
155 	if (!buddy) {
156 		mlx5hws_err(pool->ctx, "Failed to create buddy order: %d index: %d\n",
157 			    new_buddy_size, idx);
158 		return NULL;
159 	}
160 
161 	if (hws_pool_resource_alloc(pool, new_buddy_size, idx) != 0) {
162 		mlx5hws_err(pool->ctx, "Failed to create resource type: %d: size %d index: %d\n",
163 			    pool->type, new_buddy_size, idx);
164 		mlx5hws_buddy_cleanup(buddy);
165 		return NULL;
166 	}
167 
168 	pool->db.buddy_manager->buddies[idx] = buddy;
169 
170 	return buddy;
171 }
172 
hws_pool_buddy_get_mem_chunk(struct mlx5hws_pool * pool,int order,u32 * buddy_idx,int * seg)173 static int hws_pool_buddy_get_mem_chunk(struct mlx5hws_pool *pool,
174 					int order,
175 					u32 *buddy_idx,
176 					int *seg)
177 {
178 	struct mlx5hws_buddy_mem *buddy;
179 	bool new_mem = false;
180 	int ret = 0;
181 	int i;
182 
183 	*seg = -1;
184 
185 	/* Find the next free place from the buddy array */
186 	while (*seg == -1) {
187 		for (i = 0; i < MLX5HWS_POOL_RESOURCE_ARR_SZ; i++) {
188 			buddy = hws_pool_buddy_get_next_buddy(pool, i,
189 							      order,
190 							      &new_mem);
191 			if (!buddy) {
192 				ret = -ENOMEM;
193 				goto out;
194 			}
195 
196 			*seg = mlx5hws_buddy_alloc_mem(buddy, order);
197 			if (*seg != -1)
198 				goto found;
199 
200 			if (pool->flags & MLX5HWS_POOL_FLAGS_ONE_RESOURCE) {
201 				mlx5hws_err(pool->ctx,
202 					    "Fail to allocate seg for one resource pool\n");
203 				ret = -ENOMEM;
204 				goto out;
205 			}
206 
207 			if (new_mem) {
208 				/* We have new memory pool, should be place for us */
209 				mlx5hws_err(pool->ctx,
210 					    "No memory for order: %d with buddy no: %d\n",
211 					    order, i);
212 				ret = -ENOMEM;
213 				goto out;
214 			}
215 		}
216 	}
217 
218 found:
219 	*buddy_idx = i;
220 out:
221 	return ret;
222 }
223 
hws_pool_buddy_db_get_chunk(struct mlx5hws_pool * pool,struct mlx5hws_pool_chunk * chunk)224 static int hws_pool_buddy_db_get_chunk(struct mlx5hws_pool *pool,
225 				       struct mlx5hws_pool_chunk *chunk)
226 {
227 	int ret = 0;
228 
229 	/* Go over the buddies and find next free slot */
230 	ret = hws_pool_buddy_get_mem_chunk(pool, chunk->order,
231 					   &chunk->resource_idx,
232 					   &chunk->offset);
233 	if (ret)
234 		mlx5hws_err(pool->ctx, "Failed to get free slot for chunk with order: %d\n",
235 			    chunk->order);
236 
237 	return ret;
238 }
239 
hws_pool_buddy_db_uninit(struct mlx5hws_pool * pool)240 static void hws_pool_buddy_db_uninit(struct mlx5hws_pool *pool)
241 {
242 	struct mlx5hws_buddy_mem *buddy;
243 	int i;
244 
245 	for (i = 0; i < MLX5HWS_POOL_RESOURCE_ARR_SZ; i++) {
246 		buddy = pool->db.buddy_manager->buddies[i];
247 		if (buddy) {
248 			mlx5hws_buddy_cleanup(buddy);
249 			kfree(buddy);
250 			pool->db.buddy_manager->buddies[i] = NULL;
251 		}
252 	}
253 
254 	kfree(pool->db.buddy_manager);
255 }
256 
hws_pool_buddy_db_init(struct mlx5hws_pool * pool,u32 log_range)257 static int hws_pool_buddy_db_init(struct mlx5hws_pool *pool, u32 log_range)
258 {
259 	pool->db.buddy_manager = kzalloc(sizeof(*pool->db.buddy_manager), GFP_KERNEL);
260 	if (!pool->db.buddy_manager)
261 		return -ENOMEM;
262 
263 	if (pool->flags & MLX5HWS_POOL_FLAGS_ALLOC_MEM_ON_CREATE) {
264 		bool new_buddy;
265 
266 		if (!hws_pool_buddy_get_next_buddy(pool, 0, log_range, &new_buddy)) {
267 			mlx5hws_err(pool->ctx,
268 				    "Failed allocating memory on create log_sz: %d\n", log_range);
269 			kfree(pool->db.buddy_manager);
270 			return -ENOMEM;
271 		}
272 	}
273 
274 	pool->p_db_uninit = &hws_pool_buddy_db_uninit;
275 	pool->p_get_chunk = &hws_pool_buddy_db_get_chunk;
276 	pool->p_put_chunk = &hws_pool_buddy_db_put_chunk;
277 
278 	return 0;
279 }
280 
hws_pool_create_resource_on_index(struct mlx5hws_pool * pool,u32 alloc_size,int idx)281 static int hws_pool_create_resource_on_index(struct mlx5hws_pool *pool,
282 					     u32 alloc_size, int idx)
283 {
284 	int ret = hws_pool_resource_alloc(pool, alloc_size, idx);
285 
286 	if (ret) {
287 		mlx5hws_err(pool->ctx, "Failed to create resource type: %d: size %d index: %d\n",
288 			    pool->type, alloc_size, idx);
289 		return ret;
290 	}
291 
292 	return 0;
293 }
294 
295 static struct mlx5hws_pool_elements *
hws_pool_element_create_new_elem(struct mlx5hws_pool * pool,u32 order,int idx)296 hws_pool_element_create_new_elem(struct mlx5hws_pool *pool, u32 order, int idx)
297 {
298 	struct mlx5hws_pool_elements *elem;
299 	u32 alloc_size;
300 
301 	alloc_size = pool->alloc_log_sz;
302 
303 	elem = kzalloc(sizeof(*elem), GFP_KERNEL);
304 	if (!elem)
305 		return NULL;
306 
307 	/* Sharing the same resource, also means that all the elements are with size 1 */
308 	if ((pool->flags & MLX5HWS_POOL_FLAGS_FIXED_SIZE_OBJECTS) &&
309 	    !(pool->flags & MLX5HWS_POOL_FLAGS_RESOURCE_PER_CHUNK)) {
310 		 /* Currently all chunks in size 1 */
311 		elem->bitmap = hws_pool_create_and_init_bitmap(alloc_size - order);
312 		if (!elem->bitmap) {
313 			mlx5hws_err(pool->ctx,
314 				    "Failed to create bitmap type: %d: size %d index: %d\n",
315 				    pool->type, alloc_size, idx);
316 			goto free_elem;
317 		}
318 
319 		elem->log_size = alloc_size - order;
320 	}
321 
322 	if (hws_pool_create_resource_on_index(pool, alloc_size, idx)) {
323 		mlx5hws_err(pool->ctx, "Failed to create resource type: %d: size %d index: %d\n",
324 			    pool->type, alloc_size, idx);
325 		goto free_db;
326 	}
327 
328 	pool->db.element_manager->elements[idx] = elem;
329 
330 	return elem;
331 
332 free_db:
333 	bitmap_free(elem->bitmap);
334 free_elem:
335 	kfree(elem);
336 	return NULL;
337 }
338 
hws_pool_element_find_seg(struct mlx5hws_pool_elements * elem,int * seg)339 static int hws_pool_element_find_seg(struct mlx5hws_pool_elements *elem, int *seg)
340 {
341 	unsigned int segment, size;
342 
343 	size = 1 << elem->log_size;
344 
345 	segment = find_first_bit(elem->bitmap, size);
346 	if (segment >= size) {
347 		elem->is_full = true;
348 		return -ENOMEM;
349 	}
350 
351 	bitmap_clear(elem->bitmap, segment, 1);
352 	*seg = segment;
353 	return 0;
354 }
355 
356 static int
hws_pool_onesize_element_get_mem_chunk(struct mlx5hws_pool * pool,u32 order,u32 * idx,int * seg)357 hws_pool_onesize_element_get_mem_chunk(struct mlx5hws_pool *pool, u32 order,
358 				       u32 *idx, int *seg)
359 {
360 	struct mlx5hws_pool_elements *elem;
361 
362 	elem = pool->db.element_manager->elements[0];
363 	if (!elem)
364 		elem = hws_pool_element_create_new_elem(pool, order, 0);
365 	if (!elem)
366 		goto err_no_elem;
367 
368 	if (hws_pool_element_find_seg(elem, seg) != 0) {
369 		mlx5hws_err(pool->ctx, "No more resources (last request order: %d)\n", order);
370 		return -ENOMEM;
371 	}
372 
373 	*idx = 0;
374 	elem->num_of_elements++;
375 	return 0;
376 
377 err_no_elem:
378 	mlx5hws_err(pool->ctx, "Failed to allocate element for order: %d\n", order);
379 	return -ENOMEM;
380 }
381 
382 static int
hws_pool_general_element_get_mem_chunk(struct mlx5hws_pool * pool,u32 order,u32 * idx,int * seg)383 hws_pool_general_element_get_mem_chunk(struct mlx5hws_pool *pool, u32 order,
384 				       u32 *idx, int *seg)
385 {
386 	int ret, i;
387 
388 	for (i = 0; i < MLX5HWS_POOL_RESOURCE_ARR_SZ; i++) {
389 		if (!pool->resource[i]) {
390 			ret = hws_pool_create_resource_on_index(pool, order, i);
391 			if (ret)
392 				goto err_no_res;
393 			*idx = i;
394 			*seg = 0; /* One memory slot in that element */
395 			return 0;
396 		}
397 	}
398 
399 	mlx5hws_err(pool->ctx, "No more resources (last request order: %d)\n", order);
400 	return -ENOMEM;
401 
402 err_no_res:
403 	mlx5hws_err(pool->ctx, "Failed to allocate element for order: %d\n", order);
404 	return -ENOMEM;
405 }
406 
hws_pool_general_element_db_get_chunk(struct mlx5hws_pool * pool,struct mlx5hws_pool_chunk * chunk)407 static int hws_pool_general_element_db_get_chunk(struct mlx5hws_pool *pool,
408 						 struct mlx5hws_pool_chunk *chunk)
409 {
410 	int ret;
411 
412 	/* Go over all memory elements and find/allocate free slot */
413 	ret = hws_pool_general_element_get_mem_chunk(pool, chunk->order,
414 						     &chunk->resource_idx,
415 						     &chunk->offset);
416 	if (ret)
417 		mlx5hws_err(pool->ctx, "Failed to get free slot for chunk with order: %d\n",
418 			    chunk->order);
419 
420 	return ret;
421 }
422 
hws_pool_general_element_db_put_chunk(struct mlx5hws_pool * pool,struct mlx5hws_pool_chunk * chunk)423 static void hws_pool_general_element_db_put_chunk(struct mlx5hws_pool *pool,
424 						  struct mlx5hws_pool_chunk *chunk)
425 {
426 	if (unlikely(!pool->resource[chunk->resource_idx]))
427 		pr_warn("HWS: invalid resource with index %d\n", chunk->resource_idx);
428 
429 	if (pool->flags & MLX5HWS_POOL_FLAGS_RELEASE_FREE_RESOURCE)
430 		hws_pool_resource_free(pool, chunk->resource_idx);
431 }
432 
hws_pool_general_element_db_uninit(struct mlx5hws_pool * pool)433 static void hws_pool_general_element_db_uninit(struct mlx5hws_pool *pool)
434 {
435 	(void)pool;
436 }
437 
438 /* This memory management works as the following:
439  * - At start doesn't allocate no mem at all.
440  * - When new request for chunk arrived:
441  *	allocate resource and give it.
442  * - When free that chunk:
443  *	the resource is freed.
444  */
hws_pool_general_element_db_init(struct mlx5hws_pool * pool)445 static int hws_pool_general_element_db_init(struct mlx5hws_pool *pool)
446 {
447 	pool->p_db_uninit = &hws_pool_general_element_db_uninit;
448 	pool->p_get_chunk = &hws_pool_general_element_db_get_chunk;
449 	pool->p_put_chunk = &hws_pool_general_element_db_put_chunk;
450 
451 	return 0;
452 }
453 
hws_onesize_element_db_destroy_element(struct mlx5hws_pool * pool,struct mlx5hws_pool_elements * elem,struct mlx5hws_pool_chunk * chunk)454 static void hws_onesize_element_db_destroy_element(struct mlx5hws_pool *pool,
455 						   struct mlx5hws_pool_elements *elem,
456 						   struct mlx5hws_pool_chunk *chunk)
457 {
458 	if (unlikely(!pool->resource[chunk->resource_idx]))
459 		pr_warn("HWS: invalid resource with index %d\n", chunk->resource_idx);
460 
461 	hws_pool_resource_free(pool, chunk->resource_idx);
462 	kfree(elem);
463 	pool->db.element_manager->elements[chunk->resource_idx] = NULL;
464 }
465 
hws_onesize_element_db_put_chunk(struct mlx5hws_pool * pool,struct mlx5hws_pool_chunk * chunk)466 static void hws_onesize_element_db_put_chunk(struct mlx5hws_pool *pool,
467 					     struct mlx5hws_pool_chunk *chunk)
468 {
469 	struct mlx5hws_pool_elements *elem;
470 
471 	if (unlikely(chunk->resource_idx))
472 		pr_warn("HWS: invalid resource with index %d\n", chunk->resource_idx);
473 
474 	elem = pool->db.element_manager->elements[chunk->resource_idx];
475 	if (!elem) {
476 		mlx5hws_err(pool->ctx, "No such element (%d)\n", chunk->resource_idx);
477 		return;
478 	}
479 
480 	bitmap_set(elem->bitmap, chunk->offset, 1);
481 	elem->is_full = false;
482 	elem->num_of_elements--;
483 
484 	if (pool->flags & MLX5HWS_POOL_FLAGS_RELEASE_FREE_RESOURCE &&
485 	    !elem->num_of_elements)
486 		hws_onesize_element_db_destroy_element(pool, elem, chunk);
487 }
488 
hws_onesize_element_db_get_chunk(struct mlx5hws_pool * pool,struct mlx5hws_pool_chunk * chunk)489 static int hws_onesize_element_db_get_chunk(struct mlx5hws_pool *pool,
490 					    struct mlx5hws_pool_chunk *chunk)
491 {
492 	int ret = 0;
493 
494 	/* Go over all memory elements and find/allocate free slot */
495 	ret = hws_pool_onesize_element_get_mem_chunk(pool, chunk->order,
496 						     &chunk->resource_idx,
497 						     &chunk->offset);
498 	if (ret)
499 		mlx5hws_err(pool->ctx, "Failed to get free slot for chunk with order: %d\n",
500 			    chunk->order);
501 
502 	return ret;
503 }
504 
hws_onesize_element_db_uninit(struct mlx5hws_pool * pool)505 static void hws_onesize_element_db_uninit(struct mlx5hws_pool *pool)
506 {
507 	struct mlx5hws_pool_elements *elem;
508 	int i;
509 
510 	for (i = 0; i < MLX5HWS_POOL_RESOURCE_ARR_SZ; i++) {
511 		elem = pool->db.element_manager->elements[i];
512 		if (elem) {
513 			bitmap_free(elem->bitmap);
514 			kfree(elem);
515 			pool->db.element_manager->elements[i] = NULL;
516 		}
517 	}
518 	kfree(pool->db.element_manager);
519 }
520 
521 /* This memory management works as the following:
522  * - At start doesn't allocate no mem at all.
523  * - When new request for chunk arrived:
524  *  aloocate the first and only slot of memory/resource
525  *  when it ended return error.
526  */
hws_pool_onesize_element_db_init(struct mlx5hws_pool * pool)527 static int hws_pool_onesize_element_db_init(struct mlx5hws_pool *pool)
528 {
529 	pool->db.element_manager = kzalloc(sizeof(*pool->db.element_manager), GFP_KERNEL);
530 	if (!pool->db.element_manager)
531 		return -ENOMEM;
532 
533 	pool->p_db_uninit = &hws_onesize_element_db_uninit;
534 	pool->p_get_chunk = &hws_onesize_element_db_get_chunk;
535 	pool->p_put_chunk = &hws_onesize_element_db_put_chunk;
536 
537 	return 0;
538 }
539 
hws_pool_db_init(struct mlx5hws_pool * pool,enum mlx5hws_db_type db_type)540 static int hws_pool_db_init(struct mlx5hws_pool *pool,
541 			    enum mlx5hws_db_type db_type)
542 {
543 	int ret;
544 
545 	if (db_type == MLX5HWS_POOL_DB_TYPE_GENERAL_SIZE)
546 		ret = hws_pool_general_element_db_init(pool);
547 	else if (db_type == MLX5HWS_POOL_DB_TYPE_ONE_SIZE_RESOURCE)
548 		ret = hws_pool_onesize_element_db_init(pool);
549 	else
550 		ret = hws_pool_buddy_db_init(pool, pool->alloc_log_sz);
551 
552 	if (ret) {
553 		mlx5hws_err(pool->ctx, "Failed to init general db : %d (ret: %d)\n", db_type, ret);
554 		return ret;
555 	}
556 
557 	return 0;
558 }
559 
hws_pool_db_unint(struct mlx5hws_pool * pool)560 static void hws_pool_db_unint(struct mlx5hws_pool *pool)
561 {
562 	pool->p_db_uninit(pool);
563 }
564 
mlx5hws_pool_chunk_alloc(struct mlx5hws_pool * pool,struct mlx5hws_pool_chunk * chunk)565 int mlx5hws_pool_chunk_alloc(struct mlx5hws_pool *pool,
566 			     struct mlx5hws_pool_chunk *chunk)
567 {
568 	int ret;
569 
570 	mutex_lock(&pool->lock);
571 	ret = pool->p_get_chunk(pool, chunk);
572 	mutex_unlock(&pool->lock);
573 
574 	return ret;
575 }
576 
mlx5hws_pool_chunk_free(struct mlx5hws_pool * pool,struct mlx5hws_pool_chunk * chunk)577 void mlx5hws_pool_chunk_free(struct mlx5hws_pool *pool,
578 			     struct mlx5hws_pool_chunk *chunk)
579 {
580 	mutex_lock(&pool->lock);
581 	pool->p_put_chunk(pool, chunk);
582 	mutex_unlock(&pool->lock);
583 }
584 
585 struct mlx5hws_pool *
mlx5hws_pool_create(struct mlx5hws_context * ctx,struct mlx5hws_pool_attr * pool_attr)586 mlx5hws_pool_create(struct mlx5hws_context *ctx, struct mlx5hws_pool_attr *pool_attr)
587 {
588 	enum mlx5hws_db_type res_db_type;
589 	struct mlx5hws_pool *pool;
590 
591 	pool = kzalloc(sizeof(*pool), GFP_KERNEL);
592 	if (!pool)
593 		return NULL;
594 
595 	pool->ctx = ctx;
596 	pool->type = pool_attr->pool_type;
597 	pool->alloc_log_sz = pool_attr->alloc_log_sz;
598 	pool->flags = pool_attr->flags;
599 	pool->tbl_type = pool_attr->table_type;
600 	pool->opt_type = pool_attr->opt_type;
601 
602 	/* Support general db */
603 	if (pool->flags == (MLX5HWS_POOL_FLAGS_RELEASE_FREE_RESOURCE |
604 			    MLX5HWS_POOL_FLAGS_RESOURCE_PER_CHUNK))
605 		res_db_type = MLX5HWS_POOL_DB_TYPE_GENERAL_SIZE;
606 	else if (pool->flags == (MLX5HWS_POOL_FLAGS_ONE_RESOURCE |
607 				 MLX5HWS_POOL_FLAGS_FIXED_SIZE_OBJECTS))
608 		res_db_type = MLX5HWS_POOL_DB_TYPE_ONE_SIZE_RESOURCE;
609 	else
610 		res_db_type = MLX5HWS_POOL_DB_TYPE_BUDDY;
611 
612 	pool->alloc_log_sz = pool_attr->alloc_log_sz;
613 
614 	if (hws_pool_db_init(pool, res_db_type))
615 		goto free_pool;
616 
617 	mutex_init(&pool->lock);
618 
619 	return pool;
620 
621 free_pool:
622 	kfree(pool);
623 	return NULL;
624 }
625 
mlx5hws_pool_destroy(struct mlx5hws_pool * pool)626 int mlx5hws_pool_destroy(struct mlx5hws_pool *pool)
627 {
628 	int i;
629 
630 	mutex_destroy(&pool->lock);
631 
632 	for (i = 0; i < MLX5HWS_POOL_RESOURCE_ARR_SZ; i++)
633 		if (pool->resource[i])
634 			hws_pool_resource_free(pool, i);
635 
636 	hws_pool_db_unint(pool);
637 
638 	kfree(pool);
639 	return 0;
640 }
641