diff options
author | Alex Waterman <alexw@nvidia.com> | 2018-06-27 17:45:21 -0400 |
---|---|---|
committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2018-08-10 02:11:17 -0400 |
commit | 542e6a0ab4fe3839633a3a86c80b394fd046ac79 (patch) | |
tree | 4e754e0a4e74d20b624670741347eb3aaeda9980 /userspace/units/posix-bitops/posix-bitops.c | |
parent | 98d092e73679be792f99bb6debb9ecffbf403987 (diff) |
gpu: nvgpu: unit: Add a posix-bitmap impl unit test
Add a unit test to test the nvgpu-posix bitmap implementation. This
unit test aims to both verify the functionality of this low level
set of APIs and provide a reference for how to use the basic unit
test functionality.
JIRA NVGPU-525
Change-Id: Ide5263e5ce49f18f5f2a3d4a6f9e494395299386
Signed-off-by: Alex Waterman <alexw@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1695007
GVS: Gerrit_Virtual_Submit
Reviewed-by: Konsta Holtta <kholtta@nvidia.com>
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Diffstat (limited to 'userspace/units/posix-bitops/posix-bitops.c')
-rw-r--r-- | userspace/units/posix-bitops/posix-bitops.c | 672 |
1 files changed, 672 insertions, 0 deletions
diff --git a/userspace/units/posix-bitops/posix-bitops.c b/userspace/units/posix-bitops/posix-bitops.c new file mode 100644 index 00000000..4ebef7b5 --- /dev/null +++ b/userspace/units/posix-bitops/posix-bitops.c | |||
@@ -0,0 +1,672 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice shall be included in | ||
12 | * all copies or substantial portions of the Software. | ||
13 | * | ||
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
20 | * DEALINGS IN THE SOFTWARE. | ||
21 | */ | ||
22 | |||
23 | #include <stdlib.h> | ||
24 | |||
25 | #include <unit/io.h> | ||
26 | #include <unit/unit.h> | ||
27 | |||
28 | #include <nvgpu/posix/bitops.h> | ||
29 | |||
30 | #define NUM_WORDS 4 | ||
31 | |||
32 | static unsigned long single_ulong_maps[] = { | ||
33 | 0UL, | ||
34 | ~0UL, | ||
35 | 0xff00ff00UL, | ||
36 | 0x00ff00ffUL, | ||
37 | 0xa5a5a5a5UL, | ||
38 | 0x0000ffffUL, | ||
39 | 0xffff0000UL, | ||
40 | 0x1UL, | ||
41 | 0x80000000UL, | ||
42 | BIT(16), | ||
43 | }; | ||
44 | |||
45 | /* | ||
46 | * Can't fail - just some info prints. | ||
47 | */ | ||
48 | static int test_bitmap_info(struct unit_module *m, struct gk20a *g, void *args) | ||
49 | { | ||
50 | unit_info(m, "sizeof(unsigned long) = %zu\n", sizeof(unsigned long)); | ||
51 | unit_info(m, "BITS_PER_LONG = %lu\n", BITS_PER_LONG); | ||
52 | |||
53 | return UNIT_SUCCESS; | ||
54 | } | ||
55 | |||
56 | static int test_ffs(struct unit_module *m, struct gk20a *g, void *args) | ||
57 | { | ||
58 | #define CHECK_FFS_WORD(w, answer) \ | ||
59 | do { \ | ||
60 | unsigned long ret = ffs(w); \ | ||
61 | \ | ||
62 | if (ret != (answer)) \ | ||
63 | unit_return_fail(m, \ | ||
64 | "ffs(0x%016lx) = %lu " \ | ||
65 | "[expected %lu]\n", \ | ||
66 | w, ret, answer); \ | ||
67 | } while (0) | ||
68 | |||
69 | unsigned long i; | ||
70 | |||
71 | CHECK_FFS_WORD(single_ulong_maps[0], BITS_PER_LONG - 1UL); | ||
72 | CHECK_FFS_WORD(single_ulong_maps[1], 0UL); | ||
73 | CHECK_FFS_WORD(single_ulong_maps[2], 8UL); | ||
74 | CHECK_FFS_WORD(single_ulong_maps[3], 0UL); | ||
75 | CHECK_FFS_WORD(single_ulong_maps[4], 0UL); | ||
76 | CHECK_FFS_WORD(single_ulong_maps[5], 0UL); | ||
77 | CHECK_FFS_WORD(single_ulong_maps[6], 16UL); | ||
78 | CHECK_FFS_WORD(single_ulong_maps[7], 0UL); | ||
79 | CHECK_FFS_WORD(single_ulong_maps[8], 31UL); | ||
80 | CHECK_FFS_WORD(single_ulong_maps[9], 16UL); | ||
81 | |||
82 | #undef CHECK_FFS_WORD | ||
83 | |||
84 | /* | ||
85 | * Also just test every bit to make sure we definitely cover all | ||
86 | * possible return values of the function. | ||
87 | */ | ||
88 | for (i = 0; i < BITS_PER_LONG; i++) { | ||
89 | if (ffs(BIT(i)) != i) | ||
90 | unit_return_fail(m, "ffs(1 << %lu) != %lu [%lu]!\n", | ||
91 | i, i, ffs(BIT(i))); | ||
92 | } | ||
93 | |||
94 | return UNIT_SUCCESS; | ||
95 | } | ||
96 | |||
97 | static int test_fls(struct unit_module *m, struct gk20a *g, void *args) | ||
98 | { | ||
99 | #define CHECK_FLS_WORD(w, answer) \ | ||
100 | do { \ | ||
101 | unsigned long ret = fls(w); \ | ||
102 | \ | ||
103 | if (ret != (answer)) \ | ||
104 | unit_return_fail(m, \ | ||
105 | "fls(0x%016lx) = %lu " \ | ||
106 | "[expected = %lu]\n", \ | ||
107 | w, ret, answer); \ | ||
108 | } while (0) | ||
109 | |||
110 | unsigned long i; | ||
111 | |||
112 | CHECK_FLS_WORD(single_ulong_maps[0], 0UL); | ||
113 | CHECK_FLS_WORD(single_ulong_maps[1], BITS_PER_LONG - 1UL); | ||
114 | CHECK_FLS_WORD(single_ulong_maps[2], 31UL); | ||
115 | CHECK_FLS_WORD(single_ulong_maps[3], 23UL); | ||
116 | CHECK_FLS_WORD(single_ulong_maps[4], 31UL); | ||
117 | CHECK_FLS_WORD(single_ulong_maps[5], 15UL); | ||
118 | CHECK_FLS_WORD(single_ulong_maps[6], 31UL); | ||
119 | CHECK_FLS_WORD(single_ulong_maps[7], 0UL); | ||
120 | CHECK_FLS_WORD(single_ulong_maps[8], 31UL); | ||
121 | CHECK_FLS_WORD(single_ulong_maps[9], 16UL); | ||
122 | |||
123 | #undef CHECK_FLS_WORD | ||
124 | |||
125 | for (i = 0; i < BITS_PER_LONG; i++) { | ||
126 | if (fls(BIT(i)) != i) | ||
127 | unit_return_fail(m, "fls(1 << %lu) != %lu! [%lu]\n", | ||
128 | i, i, fls(BIT(i))); | ||
129 | } | ||
130 | |||
131 | return UNIT_SUCCESS; | ||
132 | } | ||
133 | |||
134 | static int test_ffz(struct unit_module *m, struct gk20a *g, void *args) | ||
135 | { | ||
136 | unsigned long i; | ||
137 | |||
138 | /* | ||
139 | * Since ffz(w) is implemented as ffs(~w) this does less extensive | ||
140 | * testing; but it should still cover every line of ffs(). | ||
141 | */ | ||
142 | |||
143 | for (i = 0; i < BITS_PER_LONG; i++) { | ||
144 | if (ffz(~BIT(i)) != i) | ||
145 | unit_return_fail(m, "ffz(~(1 << %lu)) != %lu! [%lu]\n", | ||
146 | i, i, ffz(BIT(i))); | ||
147 | } | ||
148 | |||
149 | return UNIT_SUCCESS; | ||
150 | } | ||
151 | |||
152 | struct test_find_bit_args { | ||
153 | bool find_zeros; | ||
154 | }; | ||
155 | |||
156 | static struct test_find_bit_args first_bit_args = { | ||
157 | .find_zeros = false | ||
158 | }; | ||
159 | |||
160 | static struct test_find_bit_args first_zero_args = { | ||
161 | .find_zeros = true | ||
162 | }; | ||
163 | |||
164 | static int test_find_first_bit(struct unit_module *m, | ||
165 | struct gk20a *g, void *__args) | ||
166 | { | ||
167 | struct test_find_bit_args *args = __args; | ||
168 | unsigned long words[NUM_WORDS]; | ||
169 | unsigned long word_idx, bit_idx; | ||
170 | unsigned long (*finder_function)(const unsigned long *, unsigned long); | ||
171 | unsigned long result; | ||
172 | |||
173 | if (args->find_zeros) | ||
174 | finder_function = find_first_zero_bit; | ||
175 | else | ||
176 | finder_function = find_first_bit; | ||
177 | |||
178 | /* | ||
179 | * First test: verify that the size parameter works. We only need the | ||
180 | * first word for this. | ||
181 | */ | ||
182 | words[0] = ~0xffffUL; | ||
183 | if (args->find_zeros) | ||
184 | words[0] = 0xffff; | ||
185 | |||
186 | if (finder_function(words, 8UL) != 8UL) | ||
187 | unit_return_fail(m, | ||
188 | "find_first_%s(0x%lx, 8) -> %lu [WRONG]\n", | ||
189 | args->find_zeros ? "zero_bit" : "bit", | ||
190 | words[0], finder_function(words, 8UL)); | ||
191 | |||
192 | if (finder_function(words, 20UL) != 16UL) | ||
193 | unit_return_fail(m, | ||
194 | "find_first_%s(0x%lx, 16) -> %lu [WRONG]\n", | ||
195 | args->find_zeros ? "zero_bit" : "bit", | ||
196 | words[0], finder_function(words, 20UL)); | ||
197 | |||
198 | /* | ||
199 | * Now make sure that for full/empty bitmap find_next_*() returns | ||
200 | * the size parameter. | ||
201 | */ | ||
202 | memset(words, args->find_zeros ? 0xff : 0x00, sizeof(words)); | ||
203 | result = finder_function(words, NUM_WORDS * BITS_PER_LONG); | ||
204 | if (result != NUM_WORDS * BITS_PER_LONG) | ||
205 | unit_return_fail(m, "find_first_%s() failed with empty map\n", | ||
206 | args->find_zeros ? "zero_bit" : "bit"); | ||
207 | |||
208 | /* | ||
209 | * Third test: set (or zero) the entire bitmap and incrementally clear | ||
210 | * bits. Check that we are correct even with multiple words. | ||
211 | */ | ||
212 | |||
213 | memset(words, args->find_zeros ? 0x00 : 0xff, sizeof(words)); | ||
214 | for (word_idx = 0; word_idx < NUM_WORDS; word_idx++) { | ||
215 | for (bit_idx = 0; bit_idx < BITS_PER_LONG; bit_idx++) { | ||
216 | unsigned long check = | ||
217 | (word_idx * BITS_PER_LONG) + bit_idx; | ||
218 | unsigned long answer = | ||
219 | finder_function(words, | ||
220 | NUM_WORDS * BITS_PER_LONG); | ||
221 | |||
222 | if (answer != check) | ||
223 | unit_return_fail(m, | ||
224 | "find_first_%s loop: " | ||
225 | "word_idx = %lu bit_idx = %lu " | ||
226 | "-> %lu [WRONG]\n", | ||
227 | args->find_zeros ? "zero_bit" : "bit", | ||
228 | word_idx, bit_idx, answer); | ||
229 | |||
230 | /* | ||
231 | * Now set/clear this bit in preparation for the next | ||
232 | * test. | ||
233 | */ | ||
234 | if (args->find_zeros) | ||
235 | words[word_idx] |= BIT(bit_idx); | ||
236 | else | ||
237 | words[word_idx] &= ~BIT(bit_idx); | ||
238 | } | ||
239 | } | ||
240 | |||
241 | return UNIT_SUCCESS; | ||
242 | } | ||
243 | |||
244 | /* | ||
245 | * Note: the find_first_bit() test also effectively tests the underlying | ||
246 | * find_next_bit() code since find_first_bit() is just find_next_bit() | ||
247 | * with a 0 start. | ||
248 | */ | ||
249 | |||
250 | static int test_find_next_bit(struct unit_module *m, | ||
251 | struct gk20a *g, void *__args) | ||
252 | { | ||
253 | unsigned long words[NUM_WORDS]; | ||
254 | unsigned long i, result; | ||
255 | |||
256 | /* | ||
257 | * Fully unset list. Should always return size. | ||
258 | */ | ||
259 | memset(words, 0x00, sizeof(words)); | ||
260 | for (i = 0; i < NUM_WORDS * BITS_PER_LONG; i++) { | ||
261 | result = find_next_bit(words, NUM_WORDS * BITS_PER_LONG, i); | ||
262 | |||
263 | if (result != NUM_WORDS * BITS_PER_LONG) | ||
264 | unit_return_fail(m, "Fail: empty map (%lu)\n", i); | ||
265 | } | ||
266 | |||
267 | /* | ||
268 | * Use a fully set list but increment the offset. | ||
269 | */ | ||
270 | memset(words, 0xff, sizeof(words)); | ||
271 | for (i = 0; i < NUM_WORDS * BITS_PER_LONG; i++) { | ||
272 | unsigned long first = | ||
273 | find_next_bit(words, NUM_WORDS * BITS_PER_LONG, i); | ||
274 | |||
275 | if (first != i) | ||
276 | unit_return_fail(m, | ||
277 | "Fail: first = %lu; should be %lu\n", | ||
278 | first, i); | ||
279 | } | ||
280 | |||
281 | /* | ||
282 | * Start > n should return n. | ||
283 | */ | ||
284 | #define TEST_START_GREATER_THAN_N(m, map, n, start) \ | ||
285 | do { \ | ||
286 | if (find_next_bit(map, n, start) != n) \ | ||
287 | unit_return_fail(m, \ | ||
288 | "Start not greater than N ?? " \ | ||
289 | "start=%lu, N=%lu\n", \ | ||
290 | start, n); \ | ||
291 | } while (0) | ||
292 | |||
293 | TEST_START_GREATER_THAN_N(m, words, BITS_PER_LONG, BITS_PER_LONG + 1); | ||
294 | TEST_START_GREATER_THAN_N(m, words, 32UL, 64UL); | ||
295 | TEST_START_GREATER_THAN_N(m, words, | ||
296 | BITS_PER_LONG * 2, (BITS_PER_LONG * 2) + 1); | ||
297 | TEST_START_GREATER_THAN_N(m, words, 0UL, 1UL); | ||
298 | TEST_START_GREATER_THAN_N(m, words, 0UL, BITS_PER_LONG * 2); | ||
299 | TEST_START_GREATER_THAN_N(m, words, 0UL, BITS_PER_LONG * NUM_WORDS + 1); | ||
300 | |||
301 | #undef TEST_START_GREATER_THAN_N | ||
302 | |||
303 | return UNIT_SUCCESS; | ||
304 | } | ||
305 | |||
306 | #define TEST_BITMAP_SIZE (BITS_PER_LONG * 4) | ||
307 | /* | ||
308 | * 32/64 bit invarient. | ||
309 | */ | ||
310 | static DECLARE_BITMAP(bmap_all_zeros, TEST_BITMAP_SIZE) = | ||
311 | { | ||
312 | 0x0UL, 0x0UL, 0x0UL, 0x0UL | ||
313 | }; | ||
314 | static DECLARE_BITMAP(bmap_all_ones, TEST_BITMAP_SIZE) = | ||
315 | { | ||
316 | ~0x0UL, ~0x0UL, ~0x0UL, ~0x0UL | ||
317 | }; | ||
318 | |||
319 | static int test_find_zero_area(struct unit_module *m, | ||
320 | struct gk20a *g, void *unused) | ||
321 | { | ||
322 | #define FAIL_MSG "Fail: bmap-test='%s' (i=%lu)\n" | ||
323 | #define FAIL_MSG_EX "Fail: bmap-test='%s' (i=%lu, j=%lu)\n" | ||
324 | unsigned long i, j, result; | ||
325 | unsigned long words[NUM_WORDS]; | ||
326 | |||
327 | for (i = 0; i < TEST_BITMAP_SIZE; i++) { | ||
328 | result = bitmap_find_next_zero_area_off(bmap_all_zeros, | ||
329 | TEST_BITMAP_SIZE, | ||
330 | i, | ||
331 | TEST_BITMAP_SIZE - i, | ||
332 | 0, 0); | ||
333 | if (result != i) | ||
334 | unit_return_fail(m, FAIL_MSG, | ||
335 | "all_zeros: alloc-to-end", i); | ||
336 | |||
337 | result = bitmap_find_next_zero_area_off(bmap_all_zeros, | ||
338 | TEST_BITMAP_SIZE, | ||
339 | i, | ||
340 | 1, | ||
341 | 0, 0); | ||
342 | if (result != i) | ||
343 | unit_return_fail(m, FAIL_MSG, | ||
344 | "all_zeros: alloc-one-bit", i); | ||
345 | |||
346 | result = bitmap_find_next_zero_area_off(bmap_all_zeros, | ||
347 | TEST_BITMAP_SIZE, | ||
348 | 0, | ||
349 | TEST_BITMAP_SIZE - i, | ||
350 | 0, 0); | ||
351 | if (result != 0) | ||
352 | unit_return_fail(m, FAIL_MSG, | ||
353 | "all_zeros: alloc-i-bits-at-0", i); | ||
354 | } | ||
355 | |||
356 | /* | ||
357 | * For the all ones bit map not a single alloc should succeed. We can | ||
358 | * just iterate through them all and make sure they all fail. | ||
359 | */ | ||
360 | for (i = 0; i < TEST_BITMAP_SIZE; i++) { | ||
361 | for (j = 0; j < (TEST_BITMAP_SIZE - i); j++) { | ||
362 | result = bitmap_find_next_zero_area_off(bmap_all_ones, | ||
363 | TEST_BITMAP_SIZE, | ||
364 | i, | ||
365 | j, | ||
366 | 0, 0); | ||
367 | if (result != TEST_BITMAP_SIZE) | ||
368 | unit_return_fail(m, FAIL_MSG_EX, | ||
369 | "all_ones: failed", i, j); | ||
370 | } | ||
371 | } | ||
372 | |||
373 | /* | ||
374 | * Alternating nibbles (4 bits). Make sure we don't start searching from | ||
375 | * too high in the bitmap since that will cause failures that are | ||
376 | * actually valid. This keeps the logic in the below loop a little more | ||
377 | * simple. | ||
378 | */ | ||
379 | memset(words, 0x0f, sizeof(words)); | ||
380 | for (i = 0; i < ((NUM_WORDS * BITS_PER_LONG) - 8); i++) { | ||
381 | for (j = 0; j < ((NUM_WORDS * BITS_PER_LONG) - i - 8); j++) { | ||
382 | result = bitmap_find_next_zero_area_off(words, | ||
383 | NUM_WORDS * BITS_PER_LONG, | ||
384 | i, | ||
385 | j, | ||
386 | 0, 0); | ||
387 | |||
388 | /* | ||
389 | * Should only return a valid result when j < 4 (since | ||
390 | * the map consists of 4 ones, then 4 zeros, | ||
391 | * alternating. | ||
392 | */ | ||
393 | if (j <= 4 && result >= (NUM_WORDS * BITS_PER_LONG)) | ||
394 | unit_return_fail(m, FAIL_MSG_EX, | ||
395 | "alternating-nibbles: failed", | ||
396 | i, j); | ||
397 | if (j > 4 && result != (NUM_WORDS * BITS_PER_LONG)) | ||
398 | unit_return_fail(m, FAIL_MSG_EX, | ||
399 | "alternating-nibbles: failed", | ||
400 | i, j); | ||
401 | |||
402 | result = bitmap_find_next_zero_area_off(words, | ||
403 | NUM_WORDS * BITS_PER_LONG, | ||
404 | i, | ||
405 | (j % 4) + 1, | ||
406 | 0x3, 0); | ||
407 | if (result % 8 != 4) | ||
408 | unit_return_fail(m, FAIL_MSG_EX, | ||
409 | "basic-align_mask: failed", | ||
410 | i, j); | ||
411 | |||
412 | |||
413 | result = bitmap_find_next_zero_area_off(words, | ||
414 | NUM_WORDS * BITS_PER_LONG, | ||
415 | i, | ||
416 | (j % 2) + 1, | ||
417 | 0x7, 2); | ||
418 | |||
419 | if (result % 8 != 6) | ||
420 | unit_return_fail(m, FAIL_MSG_EX, | ||
421 | "basic-align_offset: failed", | ||
422 | i, j); | ||
423 | } | ||
424 | } | ||
425 | |||
426 | #undef FAIL_MSG | ||
427 | #undef FAIL_MSG_EX | ||
428 | return UNIT_SUCCESS; | ||
429 | } | ||
430 | |||
431 | struct test_setclear_args { | ||
432 | bool clear; | ||
433 | }; | ||
434 | |||
435 | static struct test_setclear_args set_args = { | ||
436 | .clear = false, | ||
437 | }; | ||
438 | |||
439 | static struct test_setclear_args clear_args = { | ||
440 | .clear = true, | ||
441 | }; | ||
442 | |||
443 | static void __print_bitmap(unsigned long *map, unsigned long length) | ||
444 | { | ||
445 | unsigned int idx, bidx; | ||
446 | |||
447 | for (idx = 0; idx < (length / BITS_PER_LONG); idx++) { | ||
448 | printf(" "); | ||
449 | for (bidx = 0; bidx < BITS_PER_LONG; bidx++) { | ||
450 | printf("%c", (map[idx] & BIT(bidx)) ? '1' : '0'); | ||
451 | if (bidx % 4 == 3) | ||
452 | printf(" "); | ||
453 | } | ||
454 | printf("\n"); | ||
455 | } | ||
456 | |||
457 | printf("\n"); | ||
458 | } | ||
459 | |||
460 | /* | ||
461 | * Verify the bits from i to i + len are set and no others are set. 'size' is in | ||
462 | * bits (not words). | ||
463 | */ | ||
464 | static bool verify_set_buf(unsigned long *words, unsigned long size, | ||
465 | unsigned long i, unsigned long len, | ||
466 | bool invert) | ||
467 | { | ||
468 | unsigned int idx, bidx; | ||
469 | unsigned int bit, bit_value; | ||
470 | unsigned int set_start, set_end; | ||
471 | unsigned int set_value = invert ? 0 : 1; | ||
472 | unsigned int clear_value = invert ? 1 : 0; | ||
473 | |||
474 | set_start = i; | ||
475 | set_end = i + len; | ||
476 | |||
477 | for (idx = 0; idx < (size / BITS_PER_LONG); idx++) { | ||
478 | for (bidx = 0; bidx < BITS_PER_LONG; bidx++) { | ||
479 | bit = idx * BITS_PER_LONG + bidx; | ||
480 | bit_value = !!(words[idx] & BIT(bidx)); | ||
481 | |||
482 | /* | ||
483 | * Bit inside set zone. | ||
484 | */ | ||
485 | if ((bit >= set_start && bit < set_end) && | ||
486 | bit_value != set_value) | ||
487 | return false; | ||
488 | |||
489 | /* | ||
490 | * Bit outside set zone. | ||
491 | */ | ||
492 | if ((bit < set_start || bit >= set_end) && | ||
493 | bit_value != clear_value) | ||
494 | return false; | ||
495 | } | ||
496 | } | ||
497 | |||
498 | return true; | ||
499 | } | ||
500 | |||
501 | static int test_single_bitops(struct unit_module *m, | ||
502 | struct gk20a *g, void *__args) | ||
503 | { | ||
504 | unsigned long words[NUM_WORDS]; | ||
505 | unsigned int i; | ||
506 | |||
507 | /* | ||
508 | * First set all the bits and make sure the words are set. | ||
509 | */ | ||
510 | for (i = 0; i < NUM_WORDS * BITS_PER_LONG; i++) | ||
511 | set_bit(i, words); | ||
512 | |||
513 | if (!verify_set_buf(words, NUM_WORDS * BITS_PER_LONG, | ||
514 | 0, NUM_WORDS * BITS_PER_LONG, false)) { | ||
515 | __print_bitmap(words, NUM_WORDS * BITS_PER_LONG); | ||
516 | unit_return_fail(m, "set_bit: Failed to set a bit!\n"); | ||
517 | } | ||
518 | |||
519 | /* | ||
520 | * Now make sure the test_bit works for set bits. | ||
521 | */ | ||
522 | for (i = 0; i < NUM_WORDS * BITS_PER_LONG; i++) | ||
523 | if (!test_bit(i, words)) | ||
524 | unit_return_fail(m, "test_bit: bit %d failed!\n", i); | ||
525 | |||
526 | for (i = 0; i < NUM_WORDS * BITS_PER_LONG; i++) | ||
527 | clear_bit(i, words); | ||
528 | |||
529 | if (!verify_set_buf(words, NUM_WORDS * BITS_PER_LONG, | ||
530 | 0, NUM_WORDS * BITS_PER_LONG, true)) { | ||
531 | __print_bitmap(words, NUM_WORDS * BITS_PER_LONG); | ||
532 | unit_return_fail(m, "clear_bit: Failed to set a bit!\n"); | ||
533 | } | ||
534 | |||
535 | for (i = 0; i < NUM_WORDS * BITS_PER_LONG; i++) | ||
536 | if (test_bit(i, words)) | ||
537 | unit_return_fail(m, "test_bit: bit %d failed!\n", i); | ||
538 | |||
539 | return UNIT_SUCCESS; | ||
540 | } | ||
541 | |||
542 | static int test_bit_setclear(struct unit_module *m, | ||
543 | struct gk20a *g, void *__args) | ||
544 | { | ||
545 | struct test_setclear_args *args = __args; | ||
546 | void (*testfn)(int, volatile unsigned long *) = | ||
547 | args->clear ? clear_bit : set_bit; | ||
548 | unsigned long words[NUM_WORDS]; | ||
549 | unsigned int i; | ||
550 | |||
551 | memset(words, args->clear ? 0xff : 0x0, sizeof(words)); | ||
552 | |||
553 | for (i = 0; i < NUM_WORDS * BITS_PER_LONG; i++) | ||
554 | testfn(i, words); | ||
555 | |||
556 | if (!verify_set_buf(words, NUM_WORDS * BITS_PER_LONG, | ||
557 | 0, NUM_WORDS * BITS_PER_LONG, args->clear)) { | ||
558 | __print_bitmap(words, NUM_WORDS * BITS_PER_LONG); | ||
559 | unit_return_fail(m, "%s_bit: Failed to %s a bit!\n", | ||
560 | args->clear ? "clear" : "set", | ||
561 | args->clear ? "clear" : "set"); | ||
562 | } | ||
563 | |||
564 | return UNIT_SUCCESS; | ||
565 | } | ||
566 | |||
567 | static int test_test_and_setclear_bit(struct unit_module *m, | ||
568 | struct gk20a *g, void *__args) | ||
569 | { | ||
570 | struct test_setclear_args *args = __args; | ||
571 | bool (*testfn)(int, volatile unsigned long *) = | ||
572 | args->clear ? test_and_clear_bit : test_and_set_bit; | ||
573 | bool (*testfn_reset)(int, volatile unsigned long *) = | ||
574 | args->clear ? test_and_set_bit : test_and_clear_bit; | ||
575 | unsigned long words[NUM_WORDS]; | ||
576 | unsigned int i; | ||
577 | |||
578 | memset(words, args->clear ? 0xff : 0x0, sizeof(words)); | ||
579 | |||
580 | /* | ||
581 | * First we will set/clear the bits. Then we will clear/set the bits | ||
582 | * (i.e do the opposite of this loop). | ||
583 | */ | ||
584 | for (i = 0; i < NUM_WORDS * BITS_PER_LONG; i++) { | ||
585 | bool status = testfn(i, words); | ||
586 | |||
587 | if (status != args->clear) { | ||
588 | __print_bitmap(words, NUM_WORDS * BITS_PER_LONG); | ||
589 | unit_return_fail(m, "test_and_%s_bit: Failed at %d\n", | ||
590 | args->clear ? "clear" : "set", i); | ||
591 | } | ||
592 | } | ||
593 | |||
594 | for (i = 0; i < NUM_WORDS * BITS_PER_LONG; i++) { | ||
595 | bool status = testfn_reset(i, words); | ||
596 | |||
597 | if (status == args->clear) { | ||
598 | __print_bitmap(words, NUM_WORDS * BITS_PER_LONG); | ||
599 | unit_return_fail(m, "test_and_%s_bit: Failed at %d\n", | ||
600 | args->clear ? "set" : "clear", i); | ||
601 | } | ||
602 | } | ||
603 | |||
604 | /* The bitmap should be the same as we started with. */ | ||
605 | if (!verify_set_buf(words, NUM_WORDS * BITS_PER_LONG, | ||
606 | 0, NUM_WORDS * BITS_PER_LONG, !args->clear)) { | ||
607 | __print_bitmap(words, NUM_WORDS * BITS_PER_LONG); | ||
608 | unit_return_fail(m, | ||
609 | "test_and_%s_bit: Final bitmap is wrong!\n", | ||
610 | args->clear ? "set" : "clear"); | ||
611 | } | ||
612 | |||
613 | return UNIT_SUCCESS; | ||
614 | } | ||
615 | |||
616 | static int test_bitmap_setclear(struct unit_module *m, | ||
617 | struct gk20a *g, void *__args) | ||
618 | { | ||
619 | struct test_setclear_args *args = __args; | ||
620 | void (*testfn)(unsigned long *, unsigned int, int) = | ||
621 | args->clear ? bitmap_clear : bitmap_set; | ||
622 | unsigned long words[NUM_WORDS]; | ||
623 | unsigned long i, j; | ||
624 | int set_char = args->clear ? 0xff : 0x0; | ||
625 | |||
626 | /* | ||
627 | * Run through all combos of set/clear for a 4 word bitmap. | ||
628 | */ | ||
629 | for (i = 0; i < NUM_WORDS * BITS_PER_LONG; i++) { | ||
630 | for (j = 0; j < (NUM_WORDS * BITS_PER_LONG) - i; j++) { | ||
631 | /* | ||
632 | * Just make sure we start in a known state. | ||
633 | */ | ||
634 | memset(words, set_char, sizeof(words)); | ||
635 | |||
636 | testfn(words, i, j); | ||
637 | |||
638 | if (!verify_set_buf(words, NUM_WORDS * BITS_PER_LONG, | ||
639 | i, j, args->clear)) { | ||
640 | __print_bitmap(words, NUM_WORDS * BITS_PER_LONG); | ||
641 | unit_return_fail(m, | ||
642 | "%s: fail at i,j = %lu,%lu\n", | ||
643 | args->clear ? "clear" : "set", | ||
644 | i, j); | ||
645 | } | ||
646 | } | ||
647 | } | ||
648 | |||
649 | return UNIT_SUCCESS; | ||
650 | } | ||
651 | |||
652 | |||
653 | |||
654 | struct unit_module_test posix_bitops_tests[] = { | ||
655 | UNIT_TEST(info, test_bitmap_info, NULL), | ||
656 | UNIT_TEST(ffs, test_ffs, NULL), | ||
657 | UNIT_TEST(fls, test_fls, NULL), | ||
658 | UNIT_TEST(ffz, test_ffz, NULL), | ||
659 | UNIT_TEST(find_first_bit, test_find_first_bit, &first_bit_args), | ||
660 | UNIT_TEST(find_first_zero_bit, test_find_first_bit, &first_zero_args), | ||
661 | UNIT_TEST(find_next_bit, test_find_next_bit, NULL), | ||
662 | UNIT_TEST(find_zero_area, test_find_zero_area, NULL), | ||
663 | UNIT_TEST(single_bitops, test_single_bitops, NULL), | ||
664 | UNIT_TEST(bit_set, test_bit_setclear, &set_args), | ||
665 | UNIT_TEST(bit_clear, test_bit_setclear, &clear_args), | ||
666 | UNIT_TEST(test_and_set_bit, test_test_and_setclear_bit, &set_args), | ||
667 | UNIT_TEST(test_and_clear_bit, test_test_and_setclear_bit, &clear_args), | ||
668 | UNIT_TEST(bitmap_set, test_bitmap_setclear, &set_args), | ||
669 | UNIT_TEST(bitmap_clear, test_bitmap_setclear, &clear_args), | ||
670 | }; | ||
671 | |||
672 | UNIT_MODULE(posix_bitops, posix_bitops_tests, UNIT_PRIO_POSIX_TEST); | ||