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 : : simple_free(buddy);
151 : 0 : }
152 : :
153 : 0 : int mlx5dr_buddy_alloc_mem(struct mlx5dr_buddy_mem *buddy, int order)
154 : : {
155 : : int seg;
156 : : int o, m;
157 : :
158 [ # # ]: 0 : for (o = order; o <= (int)buddy->max_order; ++o)
159 [ # # ]: 0 : if (buddy->num_free[o]) {
160 : 0 : m = 1 << (buddy->max_order - o);
161 : 0 : seg = mlx5dr_buddy_find_first_bit(buddy->bits[o], m);
162 [ # # ]: 0 : if (m <= seg)
163 : : return -1;
164 : :
165 : 0 : goto found;
166 : : }
167 : :
168 : : return -1;
169 : :
170 : : found:
171 : 0 : bitmap_clear_bit(buddy->bits[o], seg);
172 : 0 : --buddy->num_free[o];
173 : :
174 [ # # ]: 0 : while (o > order) {
175 : 0 : --o;
176 : 0 : seg <<= 1;
177 : 0 : bitmap_set_bit(buddy->bits[o], seg ^ 1);
178 : 0 : ++buddy->num_free[o];
179 : : }
180 : :
181 : 0 : seg <<= order;
182 : :
183 : 0 : return seg;
184 : : }
185 : :
186 : 0 : void mlx5dr_buddy_free_mem(struct mlx5dr_buddy_mem *buddy, uint32_t seg, int order)
187 : : {
188 : 0 : seg >>= order;
189 : :
190 [ # # ]: 0 : while (bitmap_test_bit(buddy->bits[order], seg ^ 1)) {
191 : : bitmap_clear_bit(buddy->bits[order], seg ^ 1);
192 : 0 : --buddy->num_free[order];
193 : 0 : seg >>= 1;
194 : 0 : ++order;
195 : : }
196 : :
197 : : bitmap_set_bit(buddy->bits[order], seg);
198 : :
199 : 0 : ++buddy->num_free[order];
200 : 0 : }
201 : :
|