Skip to content

Commit c61afff

Browse files
kliteynSaeed Mahameed
authored andcommitted
net/mlx5: HWS, added memory management handling
Added object pools and buddy allocator functionality. Reviewed-by: Itamar Gozlan <[email protected]> Signed-off-by: Yevgeny Kliteynik <[email protected]> Signed-off-by: Saeed Mahameed <[email protected]>
1 parent 6c5e682 commit c61afff

File tree

4 files changed

+961
-0
lines changed

4 files changed

+961
-0
lines changed
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
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+
7+
static int hws_buddy_init(struct mlx5hws_buddy_mem *buddy, u32 max_order)
8+
{
9+
int i, s, ret = 0;
10+
11+
buddy->max_order = max_order;
12+
13+
buddy->bitmap = kcalloc(buddy->max_order + 1,
14+
sizeof(*buddy->bitmap),
15+
GFP_KERNEL);
16+
if (!buddy->bitmap)
17+
return -ENOMEM;
18+
19+
buddy->num_free = kcalloc(buddy->max_order + 1,
20+
sizeof(*buddy->num_free),
21+
GFP_KERNEL);
22+
if (!buddy->num_free) {
23+
ret = -ENOMEM;
24+
goto err_out_free_bits;
25+
}
26+
27+
for (i = 0; i <= (int)buddy->max_order; ++i) {
28+
s = 1 << (buddy->max_order - i);
29+
30+
buddy->bitmap[i] = bitmap_zalloc(s, GFP_KERNEL);
31+
if (!buddy->bitmap[i]) {
32+
ret = -ENOMEM;
33+
goto err_out_free_num_free;
34+
}
35+
}
36+
37+
bitmap_set(buddy->bitmap[buddy->max_order], 0, 1);
38+
buddy->num_free[buddy->max_order] = 1;
39+
40+
return 0;
41+
42+
err_out_free_num_free:
43+
for (i = 0; i <= (int)buddy->max_order; ++i)
44+
bitmap_free(buddy->bitmap[i]);
45+
46+
kfree(buddy->num_free);
47+
48+
err_out_free_bits:
49+
kfree(buddy->bitmap);
50+
return ret;
51+
}
52+
53+
struct mlx5hws_buddy_mem *mlx5hws_buddy_create(u32 max_order)
54+
{
55+
struct mlx5hws_buddy_mem *buddy;
56+
57+
buddy = kzalloc(sizeof(*buddy), GFP_KERNEL);
58+
if (!buddy)
59+
return NULL;
60+
61+
if (hws_buddy_init(buddy, max_order))
62+
goto free_buddy;
63+
64+
return buddy;
65+
66+
free_buddy:
67+
kfree(buddy);
68+
return NULL;
69+
}
70+
71+
void mlx5hws_buddy_cleanup(struct mlx5hws_buddy_mem *buddy)
72+
{
73+
int i;
74+
75+
for (i = 0; i <= (int)buddy->max_order; ++i)
76+
bitmap_free(buddy->bitmap[i]);
77+
78+
kfree(buddy->num_free);
79+
kfree(buddy->bitmap);
80+
}
81+
82+
static int hws_buddy_find_free_seg(struct mlx5hws_buddy_mem *buddy,
83+
u32 start_order,
84+
u32 *segment,
85+
u32 *order)
86+
{
87+
unsigned int seg, order_iter, m;
88+
89+
for (order_iter = start_order;
90+
order_iter <= buddy->max_order; ++order_iter) {
91+
if (!buddy->num_free[order_iter])
92+
continue;
93+
94+
m = 1 << (buddy->max_order - order_iter);
95+
seg = find_first_bit(buddy->bitmap[order_iter], m);
96+
97+
if (WARN(seg >= m,
98+
"ICM Buddy: failed finding free mem for order %d\n",
99+
order_iter))
100+
return -ENOMEM;
101+
102+
break;
103+
}
104+
105+
if (order_iter > buddy->max_order)
106+
return -ENOMEM;
107+
108+
*segment = seg;
109+
*order = order_iter;
110+
return 0;
111+
}
112+
113+
int mlx5hws_buddy_alloc_mem(struct mlx5hws_buddy_mem *buddy, u32 order)
114+
{
115+
u32 seg, order_iter, err;
116+
117+
err = hws_buddy_find_free_seg(buddy, order, &seg, &order_iter);
118+
if (err)
119+
return err;
120+
121+
bitmap_clear(buddy->bitmap[order_iter], seg, 1);
122+
--buddy->num_free[order_iter];
123+
124+
while (order_iter > order) {
125+
--order_iter;
126+
seg <<= 1;
127+
bitmap_set(buddy->bitmap[order_iter], seg ^ 1, 1);
128+
++buddy->num_free[order_iter];
129+
}
130+
131+
seg <<= order;
132+
133+
return seg;
134+
}
135+
136+
void mlx5hws_buddy_free_mem(struct mlx5hws_buddy_mem *buddy, u32 seg, u32 order)
137+
{
138+
seg >>= order;
139+
140+
while (test_bit(seg ^ 1, buddy->bitmap[order])) {
141+
bitmap_clear(buddy->bitmap[order], seg ^ 1, 1);
142+
--buddy->num_free[order];
143+
seg >>= 1;
144+
++order;
145+
}
146+
147+
bitmap_set(buddy->bitmap[order], seg, 1);
148+
++buddy->num_free[order];
149+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
2+
/* Copyright (c) 2024 NVIDIA Corporation & Affiliates */
3+
4+
#ifndef MLX5HWS_BUDDY_H_
5+
#define MLX5HWS_BUDDY_H_
6+
7+
struct mlx5hws_buddy_mem {
8+
unsigned long **bitmap;
9+
unsigned int *num_free;
10+
u32 max_order;
11+
};
12+
13+
struct mlx5hws_buddy_mem *mlx5hws_buddy_create(u32 max_order);
14+
15+
void mlx5hws_buddy_cleanup(struct mlx5hws_buddy_mem *buddy);
16+
17+
int mlx5hws_buddy_alloc_mem(struct mlx5hws_buddy_mem *buddy, u32 order);
18+
19+
void mlx5hws_buddy_free_mem(struct mlx5hws_buddy_mem *buddy, u32 seg, u32 order);
20+
21+
#endif /* MLX5HWS_BUDDY_H_ */

0 commit comments

Comments
 (0)