1
2
3
4
5
6
7
8#include <linux/bitmap.h>
9
10#include "ai-engine-internal.h"
11
12
13
14
15
16
17
18
19
20
21int aie_resource_initialize(struct aie_resource *res, int count)
22{
23 if (!res || !count)
24 return -EINVAL;
25 res->bitmap = bitmap_zalloc(count, GFP_KERNEL);
26 if (!res->bitmap)
27 return -ENOMEM;
28 res->total = count;
29
30 return 0;
31}
32
33
34
35
36
37
38
39void aie_resource_uninitialize(struct aie_resource *res)
40{
41 res->total = 0;
42 if (res->bitmap)
43 bitmap_free(res->bitmap);
44}
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59int aie_resource_check_region(struct aie_resource *res,
60 u32 start, u32 count)
61{
62 unsigned long id;
63
64 if (!res || !res->bitmap || !count)
65 return -EINVAL;
66 id = bitmap_find_next_zero_area(res->bitmap, res->total, start,
67 count, 0);
68 if (id >= res->total)
69 return -ERANGE;
70
71 return (int)id;
72}
73
74
75
76
77
78
79
80
81
82
83
84int aie_resource_get_region(struct aie_resource *res, u32 start, u32 count)
85{
86 unsigned long off;
87
88 if (!res || !res->bitmap || !count)
89 return -EINVAL;
90 off = bitmap_find_next_zero_area(res->bitmap, res->total, start,
91 count, 0);
92 if (off >= res->total) {
93 pr_err("Failed to get available AI engine resource.\n");
94 return -ERANGE;
95 }
96 bitmap_set(res->bitmap, off, count);
97
98 return (int)off;
99}
100
101
102
103
104
105
106
107
108
109void aie_resource_put_region(struct aie_resource *res, int start, u32 count)
110{
111 if (!res || !count)
112 return;
113 bitmap_clear(res->bitmap, start, count);
114}
115
116
117
118
119
120
121
122
123
124
125int aie_resource_set(struct aie_resource *res, u32 start, u32 count)
126{
127 if (!res || !res->bitmap || !count || start + count > res->total)
128 return -EINVAL;
129
130 bitmap_set(res->bitmap, start, count);
131 return 0;
132}
133
134
135
136
137
138
139
140
141
142int aie_resource_cpy_from_arr32(struct aie_resource *res, u32 start,
143 const u32 *src, u32 nbits)
144{
145 if (!res || !res->bitmap || !nbits || start + nbits > res->total ||
146 !src)
147 return -EINVAL;
148
149 bitmap_from_arr32(res->bitmap + BIT_WORD(start), src, nbits);
150 return 0;
151}
152
153
154
155
156
157
158
159
160
161int aie_resource_cpy_to_arr32(struct aie_resource *res, u32 start, u32 *dst,
162 u32 nbits)
163{
164 if (!res || !res->bitmap || !nbits || start + nbits > res->total ||
165 !dst)
166 return -EINVAL;
167
168 bitmap_to_arr32(dst, res->bitmap + BIT_WORD(start), nbits);
169 return 0;
170}
171
172
173
174
175
176
177
178
179
180
181int aie_resource_clear(struct aie_resource *res, u32 start, u32 count)
182{
183 if (!res || !res->bitmap || !count || start + count > res->total)
184 return -EINVAL;
185
186 bitmap_clear(res->bitmap, start, count);
187 return 0;
188}
189
190
191
192
193
194
195
196
197int aie_resource_clear_all(struct aie_resource *res)
198{
199 if (!res || !res->bitmap)
200 return -EINVAL;
201
202 bitmap_clear(res->bitmap, 0, res->total);
203 return 0;
204}
205
206
207
208
209
210
211
212bool aie_resource_testbit(struct aie_resource *res, u32 bit)
213{
214 if (!res || !res->bitmap || bit >= res->total)
215 return false;
216
217
218 return test_bit(bit, res->bitmap);
219}
220
221
222
223
224
225
226
227
228
229
230int aie_resource_check_common_avail(struct aie_resource *res0,
231 struct aie_resource *res1,
232 u32 sbit, u32 nbits)
233{
234 u32 ebit, avails;
235
236 if (!nbits || !res0 || !res1 || !res0->bitmap || !res1->bitmap ||
237 (sbit + nbits) > res0->total || (sbit + nbits) > res1->total)
238 return -EINVAL;
239
240 ebit = sbit + nbits - 1;
241 avails = 0;
242 while (sbit <= ebit) {
243 unsigned long *bitmap0, *bitmap1, tbits;
244 u32 tlbit, lbit = sbit % BITS_PER_LONG;
245 u32 lnbits = ebit - sbit + 1;
246
247 if (lnbits + lbit > BITS_PER_LONG)
248 lnbits = BITS_PER_LONG - lbit;
249
250 bitmap0 = &res0->bitmap[sbit / BITS_PER_LONG];
251 bitmap1 = &res1->bitmap[sbit / BITS_PER_LONG];
252 bitmap_or(&tbits, bitmap0, bitmap1, BITS_PER_LONG);
253 tlbit = lbit;
254 while (tlbit < lbit + lnbits) {
255 u32 b = bitmap_find_next_zero_area(&tbits,
256 BITS_PER_LONG, tlbit,
257 1, 0);
258 if (b >= lbit + lnbits)
259 break;
260 avails++;
261 tlbit = b + 1;
262 }
263 sbit += lnbits;
264 };
265
266 return avails;
267}
268
269
270
271
272
273
274
275
276
277
278
279
280int aie_resource_get_common_avail(struct aie_resource *res0,
281 struct aie_resource *res1,
282 u32 sbit, u32 nbits, u32 total,
283 struct aie_rsc *rscs)
284{
285 u32 ebit, tsbit, tnbits;
286
287 if (!nbits || !res0 || !res1 || !res0->bitmap || !res1->bitmap ||
288 nbits > total || (sbit + total) > res0->total ||
289 (sbit + total) > res1->total)
290 return -EINVAL;
291
292 ebit = sbit + total - 1;
293 tsbit = sbit;
294 tnbits = 0;
295 while (tsbit <= ebit && tnbits != nbits) {
296 unsigned long *bitmap0, *bitmap1, tbits;
297 u32 tlbit, lbit = tsbit % BITS_PER_LONG;
298 u32 lnbits = ebit - tsbit + 1;
299
300 if (lnbits + lbit > BITS_PER_LONG)
301 lnbits = BITS_PER_LONG - lbit;
302
303 bitmap0 = &res0->bitmap[sbit / BITS_PER_LONG];
304 bitmap1 = &res1->bitmap[sbit / BITS_PER_LONG];
305 bitmap_or(&tbits, bitmap0, bitmap1, BITS_PER_LONG);
306 tlbit = lbit;
307 while (tlbit < lbit + lnbits && tnbits != nbits) {
308 u32 b = bitmap_find_next_zero_area(&tbits,
309 BITS_PER_LONG, tlbit,
310 1, 0);
311 if (b >= lbit + lnbits)
312 break;
313 rscs[tnbits].id = tsbit - sbit + b - lbit;
314 tnbits++;
315 tlbit = b + 1;
316 }
317 tsbit += lnbits;
318 };
319
320 if (tnbits != nbits)
321 return -EINVAL;
322
323 while (tnbits--) {
324 aie_resource_set(res0, sbit + rscs[tnbits].id, 1);
325 aie_resource_set(res1, sbit + rscs[tnbits].id, 1);
326 }
327
328 return nbits;
329}
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349int aie_resource_check_pattern_region(struct aie_resource *res,
350 u32 start, u32 end, u32 count)
351{
352 unsigned long id;
353 u32 lstart;
354
355 if (!res || !res->bitmap || !count)
356 return -EINVAL;
357 lstart = start;
358 while (lstart < end) {
359 id = bitmap_find_next_zero_area(res->bitmap, res->total, lstart,
360 count, 0);
361 if (id + count > end + 1)
362 return -ERANGE;
363 else if (!((id - lstart) % count))
364 return (int)id;
365
366 lstart += count;
367 }
368
369 return -ERANGE;
370}
371
372
373
374
375
376
377
378
379
380
381
382
383int aie_resource_check_common_pattern_region(struct aie_resource *res0,
384 struct aie_resource *res1,
385 u32 sbit, u32 nbits, u32 total)
386{
387 int sbit0, sbit1;
388
389 if (!nbits || !res0 || !res1 || !res0->bitmap || !res1->bitmap ||
390 nbits > total || (sbit + total) > res0->total ||
391 (sbit + total) > res1->total)
392 return -EINVAL;
393
394 sbit0 = aie_resource_check_pattern_region(res0, sbit,
395 sbit + total - 1, nbits);
396 if (sbit0 < 0)
397 return sbit0;
398
399 if ((u32)sbit0 + nbits > sbit + total)
400 return -EINVAL;
401
402 sbit1 = aie_resource_check_pattern_region(res1, sbit0,
403 sbit0 + nbits - 1, nbits);
404 if (sbit1 != sbit0)
405 return -EINVAL;
406
407 return sbit1;
408}
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427int aie_resource_get_common_pattern_region(struct aie_resource *res0,
428 struct aie_resource *res1,
429 u32 sbit, u32 nbits, u32 total,
430 struct aie_rsc *rscs)
431{
432 int rsbit, ret;
433
434 rsbit = aie_resource_check_common_pattern_region(res0, res1, sbit,
435 nbits, total);
436 if (rsbit < 0)
437 return rsbit;
438
439 ret = aie_resource_get_region(res0, rsbit, nbits);
440 if (ret < 0)
441 return ret;
442
443 if (ret != rsbit) {
444 aie_resource_put_region(res0, ret, nbits);
445 return -EINVAL;
446 }
447
448 ret = aie_resource_get_region(res1, rsbit, nbits);
449 if (ret < 0)
450 return ret;
451
452 if (ret != rsbit) {
453 aie_resource_put_region(res0, rsbit, nbits);
454 aie_resource_put_region(res1, ret, nbits);
455 return -EINVAL;
456 }
457
458 if (rscs) {
459 u32 i;
460
461 for (i = 0; i < nbits; i++, rscs++)
462 rscs->id = rsbit - sbit + i;
463 }
464
465 return rsbit;
466}
467