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_internal.h"
8 : : #include "mlx5dr_buddy.h"
9 : :
10 : 0 : static struct rte_bitmap *bitmap_alloc0(int s)
11 : : {
12 : : struct rte_bitmap *bitmap;
13 : : uint32_t bmp_size;
14 : : void *mem;
15 : :
16 : 0 : bmp_size = rte_bitmap_get_memory_footprint(s);
17 : 0 : mem = rte_zmalloc("create_bmap", bmp_size, RTE_CACHE_LINE_SIZE);
18 [ # # ]: 0 : if (!mem) {
19 : 0 : DR_LOG(ERR, "No mem for bitmap");
20 : 0 : rte_errno = ENOMEM;
21 : 0 : return NULL;
22 : : }
23 : :
24 : 0 : bitmap = rte_bitmap_init(s, mem, bmp_size);
25 [ # # ]: 0 : if (!bitmap) {
26 : 0 : DR_LOG(ERR, "%s Failed to initialize bitmap", __func__);
27 : 0 : rte_errno = EINVAL;
28 : 0 : goto err_mem_alloc;
29 : : }
30 : :
31 : : return bitmap;
32 : :
33 : : err_mem_alloc:
34 : 0 : rte_free(mem);
35 : 0 : return NULL;
36 : : }
37 : :
38 : : static void bitmap_set_bit(struct rte_bitmap *bmp, uint32_t pos)
39 : : {
40 : 0 : rte_bitmap_set(bmp, pos);
41 : : }
42 : :
43 : : static void bitmap_clear_bit(struct rte_bitmap *bmp, uint32_t pos)
44 : : {
45 : 0 : rte_bitmap_clear(bmp, pos);
46 : : }
47 : :
48 : : static bool bitmap_test_bit(struct rte_bitmap *bmp, unsigned long n)
49 : : {
50 : : return !!rte_bitmap_get(bmp, n);
51 : : }
52 : :
53 : 0 : static unsigned long bitmap_ffs(struct rte_bitmap *bmap,
54 : : uint64_t n, unsigned long m)
55 : : {
56 : 0 : uint64_t out_slab = 0;
57 : 0 : uint32_t pos = 0; /* Compilation warn */
58 : :
59 : : __rte_bitmap_scan_init(bmap);
60 [ # # ]: 0 : if (!rte_bitmap_scan(bmap, &pos, &out_slab)) {
61 : 0 : DR_LOG(ERR, "Failed to get slab from bitmap.");
62 : 0 : return m;
63 : : }
64 [ # # ]: 0 : pos = pos + rte_ctz64(out_slab);
65 : :
66 [ # # ]: 0 : if (pos < n) {
67 : 0 : DR_LOG(ERR, "Unexpected bit (%d < %"PRIx64") from bitmap", pos, n);
68 : 0 : return m;
69 : : }
70 : : return pos;
71 : : }
72 : :
73 : : static unsigned long mlx5dr_buddy_find_first_bit(struct rte_bitmap *addr,
74 : : uint32_t size)
75 : : {
76 : 0 : return bitmap_ffs(addr, 0, size);
77 : : }
78 : :
79 : 0 : static int mlx5dr_buddy_init(struct mlx5dr_buddy_mem *buddy, uint32_t max_order)
80 : : {
81 : : int i, s;
82 : :
83 : 0 : buddy->max_order = max_order;
84 : :
85 : 0 : buddy->bits = simple_calloc(buddy->max_order + 1, sizeof(long *));
86 [ # # ]: 0 : if (!buddy->bits) {
87 : 0 : rte_errno = ENOMEM;
88 : 0 : return -1;
89 : : }
90 : :
91 : 0 : buddy->num_free = simple_calloc(buddy->max_order + 1, sizeof(*buddy->num_free));
92 [ # # ]: 0 : if (!buddy->num_free) {
93 : 0 : rte_errno = ENOMEM;
94 : 0 : goto err_out_free_bits;
95 : : }
96 : :
97 [ # # ]: 0 : for (i = 0; i <= (int)buddy->max_order; ++i) {
98 : 0 : s = 1 << (buddy->max_order - i);
99 : 0 : buddy->bits[i] = bitmap_alloc0(s);
100 [ # # ]: 0 : if (!buddy->bits[i])
101 : 0 : goto err_out_free_num_free;
102 : : }
103 : :
104 : 0 : bitmap_set_bit(buddy->bits[buddy->max_order], 0);
105 : :
106 : 0 : buddy->num_free[buddy->max_order] = 1;
107 : :
108 : 0 : return 0;
109 : :
110 : : err_out_free_num_free:
111 [ # # ]: 0 : for (i = 0; i <= (int)buddy->max_order; ++i)
112 : 0 : rte_free(buddy->bits[i]);
113 : :
114 : 0 : simple_free(buddy->num_free);
115 : :
116 : 0 : err_out_free_bits:
117 : 0 : simple_free(buddy->bits);
118 : 0 : return -1;
119 : : }
120 : :
121 : 0 : struct mlx5dr_buddy_mem *mlx5dr_buddy_create(uint32_t max_order)
122 : : {
123 : : struct mlx5dr_buddy_mem *buddy;
124 : :
125 : : buddy = simple_calloc(1, sizeof(*buddy));
126 [ # # ]: 0 : if (!buddy) {
127 : 0 : rte_errno = ENOMEM;
128 : 0 : return NULL;
129 : : }
130 : :
131 [ # # ]: 0 : if (mlx5dr_buddy_init(buddy, max_order))
132 : 0 : goto free_buddy;
133 : :
134 : : return buddy;
135 : :
136 : : free_buddy:
137 : : simple_free(buddy);
138 : 0 : return NULL;
139 : : }
140 : :
141 : 0 : void mlx5dr_buddy_cleanup(struct mlx5dr_buddy_mem *buddy)
142 : : {
143 : : int i;
144 : :
145 [ # # ]: 0 : for (i = 0; i <= (int)buddy->max_order; ++i)
146 : 0 : rte_free(buddy->bits[i]);
147 : :
148 : 0 : simple_free(buddy->num_free);
149 : 0 : simple_free(buddy->bits);
150 : 0 : }
151 : :
152 : 0 : int mlx5dr_buddy_alloc_mem(struct mlx5dr_buddy_mem *buddy, int order)
153 : : {
154 : : int seg;
155 : : int o, m;
156 : :
157 [ # # ]: 0 : for (o = order; o <= (int)buddy->max_order; ++o)
158 [ # # ]: 0 : if (buddy->num_free[o]) {
159 : 0 : m = 1 << (buddy->max_order - o);
160 : 0 : seg = mlx5dr_buddy_find_first_bit(buddy->bits[o], m);
161 [ # # ]: 0 : if (m <= seg)
162 : : return -1;
163 : :
164 : 0 : goto found;
165 : : }
166 : :
167 : : return -1;
168 : :
169 : : found:
170 : 0 : bitmap_clear_bit(buddy->bits[o], seg);
171 : 0 : --buddy->num_free[o];
172 : :
173 [ # # ]: 0 : while (o > order) {
174 : 0 : --o;
175 : 0 : seg <<= 1;
176 : 0 : bitmap_set_bit(buddy->bits[o], seg ^ 1);
177 : 0 : ++buddy->num_free[o];
178 : : }
179 : :
180 : 0 : seg <<= order;
181 : :
182 : 0 : return seg;
183 : : }
184 : :
185 : 0 : void mlx5dr_buddy_free_mem(struct mlx5dr_buddy_mem *buddy, uint32_t seg, int order)
186 : : {
187 : 0 : seg >>= order;
188 : :
189 [ # # ]: 0 : while (bitmap_test_bit(buddy->bits[order], seg ^ 1)) {
190 : : bitmap_clear_bit(buddy->bits[order], seg ^ 1);
191 : 0 : --buddy->num_free[order];
192 : 0 : seg >>= 1;
193 : 0 : ++order;
194 : : }
195 : :
196 : : bitmap_set_bit(buddy->bits[order], seg);
197 : :
198 : 0 : ++buddy->num_free[order];
199 : 0 : }
200 : :
|