blob: 5c19102f131624f27fd66cb97d3a72776c3f27aa [file] [log] [blame]
codeworkx222b7942013-02-11 17:29:55 +00001/*
2 * Copyright (C) Texas Instruments - http://www.ti.com/
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/*
18 * Test case to test ION Memory Allocator module
19 */
20
21#include <errno.h>
22#include <fcntl.h>
23#include <getopt.h>
24#include <string.h>
25#include <stdlib.h>
26#include <stdio.h>
27#include <sys/mman.h>
28#include <sys/ioctl.h>
29#include <sys/socket.h>
30#include <sys/stat.h>
31#include <sys/types.h>
32#include <unistd.h>
33
34#include "ion.h"
35
36size_t len = 1024*1024, align = 0;
37int prot = PROT_READ | PROT_WRITE;
38int map_flags = MAP_SHARED;
39int alloc_flags = 0;
40int test = -1;
41size_t width = 1024*1024, height = 1024*1024;
42int fmt = TILER_PIXEL_FMT_32BIT;
43int tiler_test = 0;
44size_t stride;
45
46int _ion_alloc_test(int fd, struct ion_handle **handle)
47{
48 int ret;
49
50 if (tiler_test)
51 ret = ion_alloc_tiler(fd, width, height, fmt, alloc_flags,
52 handle, &stride);
53 else
54 ret = ion_alloc(fd, len, align, alloc_flags, handle);
55
56 if (ret)
57 printf("%s() failed: %s\n", __func__, strerror(ret));
58 return ret;
59}
60
61int ion_alloc_test(int count)
62{
63 int fd, ret = 0, i, count_alloc;
64 struct ion_handle **handle;
65
66 fd = ion_open();
67 if (fd < 0) {
68 printf("%s(): FAILED to open ion device\n", __func__);
69 return -1;
70 }
71
72 handle = (struct ion_handle **)malloc(count * sizeof(struct ion_handle *));
73 if(handle == NULL) {
74 printf("%s() : FAILED to allocate memory for ion_handles\n", __func__);
75 return -ENOMEM;
76 }
77
78 /* Allocate ion_handles */
79 count_alloc = count;
80 for(i = 0; i < count; i++) {
81 ret = _ion_alloc_test(fd, &(handle[i]));
82 printf("%s(): Alloc handle[%d]=%p\n", __func__, i, handle[i]);
83 if(ret || ((int)handle[i] == -ENOMEM)) {
84 printf("%s(): Alloc handle[%d]=%p FAILED, err:%s\n",
85 __func__, i, handle[i], strerror(ret));
86 count_alloc = i;
87 goto err_alloc;
88 }
89 }
90
91 err_alloc:
92 /* Free ion_handles */
93 for (i = 0; i < count_alloc; i++) {
94 printf("%s(): Free handle[%d]=%p\n", __func__, i, handle[i]);
95 ret = ion_free(fd, handle[i]);
96 if (ret) {
97 printf("%s(): Free handle[%d]=%p FAILED, err:%s\n",
98 __func__, i, handle[i], strerror(ret));
99 }
100 }
101
102 ion_close(fd);
103 free(handle);
104 handle = NULL;
105
106 if(ret || (count_alloc != count)) {
107 printf("\nion alloc test: FAILED\n\n");
108 if(count_alloc != count)
109 ret = -ENOMEM;
110 }
111 else
112 printf("\nion alloc test: PASSED\n\n");
113
114 return ret;
115}
116
117void _ion_tiler_map_test(unsigned char *ptr)
118{
119 size_t row, col;
120
121 for (row = 0; row < height; row++)
122 for (col = 0; col < width; col++) {
123 int i = (row * stride) + col;
124 ptr[i] = (unsigned char)i;
125 }
126 for (row = 0; row < height; row++)
127 for (col = 0; col < width; col++) {
128 int i = (row * stride) + col;
129 if (ptr[i] != (unsigned char)i)
130 printf("%s(): FAILED, wrote %d read %d from mapped "
131 "memory\n", __func__, i, ptr[i]);
132 }
133}
134
135void _ion_map_test(unsigned char *ptr)
136{
137 size_t i;
138
139 for (i = 0; i < len; i++) {
140 ptr[i] = (unsigned char)i;
141 }
142 for (i = 0; i < len; i++) {
143 if (ptr[i] != (unsigned char)i)
144 printf("%s(): failed wrote %d read %d from mapped "
145 "memory\n", __func__, i, ptr[i]);
146 }
147}
148
149int ion_map_test(int count)
150{
151 int fd, ret = 0, i, count_alloc, count_map;
152 struct ion_handle **handle;
153 unsigned char **ptr;
154 int *map_fd;
155
156 fd = ion_open();
157 if (fd < 0) {
158 printf("%s(): FAILED to open ion device\n", __func__);
159 return -1;
160 }
161
162 handle = (struct ion_handle **)malloc(count * sizeof(struct ion_handle *));
163 if(handle == NULL) {
164 printf("%s(): FAILED to allocate memory for ion_handles\n", __func__);
165 return -ENOMEM;
166 }
167
168 count_alloc = count;
169 count_map = count;
170
171 /* Allocate ion_handles */
172 for(i = 0; i < count; i++) {
173 ret = _ion_alloc_test(fd, &(handle[i]));
174 printf("%s(): Alloc handle[%d]=%p\n", __func__, i, handle[i]);
175 if(ret || ((int)handle[i] == -ENOMEM)) {
176 printf("%s(): Alloc handle[%d]=%p FAILED, err:%s\n",
177 __func__, i, handle[i], strerror(ret));
178 count_alloc = i;
179 goto err_alloc;
180 }
181 }
182
183 /* Map ion_handles and validate */
184 if (tiler_test)
185 len = height * stride;
186
187 ptr = (unsigned char **)malloc(count * sizeof(unsigned char **));
188 map_fd = (int *)malloc(count * sizeof(int *));
189
190 for(i = 0; i < count; i++) {
191 /* Map ion_handle on userside */
192 ret = ion_map(fd, handle[i], len, prot, map_flags, 0, &(ptr[i]), &(map_fd[i]));
193 printf("%s(): Map handle[%d]=%p, map_fd=%d, ptr=%p\n",
194 __func__, i, handle[i], map_fd[i], ptr[i]);
195 if(ret) {
196 printf("%s Map handle[%d]=%p FAILED, err:%s\n",
197 __func__, i, handle[i], strerror(ret));
198 count_map = i;
199 goto err_map;
200 }
201
202 /* Validate mapping by writing the data and reading it back */
203 if (tiler_test)
204 _ion_tiler_map_test(ptr[i]);
205 else
206 _ion_map_test(ptr[i]);
207 }
208
209 /* clean up properly */
210 err_map:
211 for(i = 0; i < count_map; i++) {
212 /* Unmap ion_handles */
213 ret = munmap(ptr[i], len);
214 printf("%s(): Unmap handle[%d]=%p, map_fd=%d, ptr=%p\n",
215 __func__, i, handle[i], map_fd[i], ptr[i]);
216 if(ret) {
217 printf("%s(): Unmap handle[%d]=%p FAILED, err:%s\n",
218 __func__, i, handle[i], strerror(ret));
219 goto err_map;
220 }
221 /* Close fds */
222 close(map_fd[i]);
223 }
224 free(map_fd);
225 free(ptr);
226
227 err_alloc:
228 /* Free ion_handles */
229 for (i = 0; i < count_alloc; i++) {
230 printf("%s(): Free handle[%d]=%p\n", __func__, i, handle[i]);
231 ret = ion_free(fd, handle[i]);
232 if (ret) {
233 printf("%s(): Free handle[%d]=%p FAILED, err:%s\n",
234 __func__, i, handle[i], strerror(ret));
235 }
236 }
237
238 ion_close(fd);
239 free(handle);
240 handle = NULL;
241
242 if(ret || (count_alloc != count) || (count_map != count))
243 {
244 printf("\nion map test: FAILED\n\n");
245 if((count_alloc != count) || (count_map != count))
246 ret = -ENOMEM;
247 } else
248 printf("\nion map test: PASSED\n");
249
250 return ret;
251}
252
253/**
254 * Go on allocating buffers of specified size & type, untill the allocation fails.
255 * Then free 10 buffers and allocate 10 buffers again.
256 */
257int ion_alloc_fail_alloc_test()
258{
259 int fd, ret = 0, i;
260 struct ion_handle **handle;
261 const int COUNT_ALLOC_MAX = 200;
262 const int COUNT_REALLOC_MAX = 10;
263 int count_alloc = COUNT_ALLOC_MAX, count_realloc = COUNT_ALLOC_MAX;
264
265 fd = ion_open();
266 if (fd < 0) {
267 printf("%s(): FAILED to open ion device\n", __func__);
268 return -1;
269 }
270
271 handle = (struct ion_handle **)malloc(COUNT_ALLOC_MAX * sizeof(struct ion_handle *));
272 if(handle == NULL) {
273 printf("%s(): FAILED to allocate memory for ion_handles\n", __func__);
274 return -ENOMEM;
275 }
276
277 /* Allocate ion_handles as much as possible */
278 for(i = 0; i < COUNT_ALLOC_MAX; i++) {
279 ret = _ion_alloc_test(fd, &(handle[i]));
280 printf("%s(): Alloc handle[%d]=%p\n", __func__, i, handle[i]);
281 if(ret || ((int)handle[i] == -ENOMEM)) {
282 printf("%s(): Alloc handle[%d]=%p FAILED, err:%s\n\n",
283 __func__, i, handle[i], strerror(ret));
284 count_alloc = i;
285 break;
286 }
287 }
288
289 /* Free COUNT_REALLOC_MAX ion_handles */
290 for (i = count_alloc-1; i > (count_alloc-1 - COUNT_REALLOC_MAX); i--) {
291 printf("%s(): Free handle[%d]=%p\n", __func__, i, handle[i]);
292 ret = ion_free(fd, handle[i]);
293 if (ret) {
294 printf("%s(): Free handle[%d]=%p FAILED, err:%s\n\n",
295 __func__, i, handle[i], strerror(ret));
296 }
297 }
298
299 /* Again allocate COUNT_REALLOC_MAX ion_handles to test
300 that we are still able to allocate */
301 for(i = (count_alloc - COUNT_REALLOC_MAX); i < count_alloc; i++) {
302 ret = _ion_alloc_test(fd, &(handle[i]));
303 printf("%s(): Alloc handle[%d]=%p\n", __func__, i, handle[i]);
304 if(ret || ((int)handle[i] == -ENOMEM)) {
305 printf("%s(): Alloc handle[%d]=%p FAILED, err:%s\n\n",
306 __func__, i, handle[i], strerror(ret));
307 count_realloc = i;
308 goto err_alloc;
309 }
310 }
311 count_realloc = i;
312
313 err_alloc:
314 /* Free all ion_handles */
315 for (i = 0; i < count_alloc; i++) {
316 printf("%s(): Free handle[%d]=%p\n", __func__, i, handle[i]);
317 ret = ion_free(fd, handle[i]);
318 if (ret) {
319 printf("%s(): Free handle[%d]=%p FAILED, err:%s\n",
320 __func__, i, handle[i], strerror(ret));
321 }
322 }
323
324 ion_close(fd);
325 free(handle);
326 handle = NULL;
327
328 printf("\ncount_alloc=%d, count_realloc=%d\n",count_alloc, count_realloc);
329
330 if(ret || (count_alloc != count_realloc)) {
331 printf("\nion alloc->fail->alloc test: FAILED\n\n");
332 if(count_alloc != COUNT_ALLOC_MAX)
333 ret = -ENOMEM;
334 }
335 else
336 printf("\nion alloc->fail->alloc test: PASSED\n\n");
337
338 return ret;
339}
340
341int custom_test(int test_number)
342{
343 switch(test_number) {
344 case 1 :
345 return ion_alloc_fail_alloc_test();
346 default :
347 printf("%s(): Invalid custom_test_number=%d\n", __func__, test_number);
348 return -EINVAL;
349 }
350}
351
352int main(int argc, char* argv[]) {
353 int c, ret;
354 unsigned int count = 1, iteration = 1, j, custom_test_num = 1;
355 enum tests {
356 ALLOC_TEST = 0, MAP_TEST, CUSTOM_TEST,
357 };
358
359 while (1) {
360 static struct option opts[] = {
361 {"alloc", no_argument, 0, 'a'},
362 {"alloc_flags", required_argument, 0, 'f'},
363 {"map", no_argument, 0, 'm'},
364 {"custom", required_argument, 0, 'c'},
365 {"len", required_argument, 0, 'l'},
366 {"align", required_argument, 0, 'g'},
367 {"map_flags", required_argument, 0, 'z'},
368 {"prot", required_argument, 0, 'p'},
369 {"alloc_tiler", no_argument, 0, 't'},
370 {"width", required_argument, 0, 'w'},
371 {"height", required_argument, 0, 'h'},
372 {"fmt", required_argument, 0, 'r'},
373 {"count", required_argument, 0, 'n'},
374 {"iteration", required_argument, 0, 'i'},
375 };
376 int i = 0;
377 c = getopt_long(argc, argv, "af:h:l:mr:stw:c:n:i:", opts, &i);
378 if (c == -1)
379 break;
380
381 switch (c) {
382 case 'l':
383 len = atol(optarg);
384 break;
385 case 'g':
386 align = atol(optarg);
387 break;
388 case 'z':
389 map_flags = 0;
390 map_flags |= strstr(optarg, "PROT_EXEC") ?
391 PROT_EXEC : 0;
392 map_flags |= strstr(optarg, "PROT_READ") ?
393 PROT_READ: 0;
394 map_flags |= strstr(optarg, "PROT_WRITE") ?
395 PROT_WRITE: 0;
396 map_flags |= strstr(optarg, "PROT_NONE") ?
397 PROT_NONE: 0;
398 break;
399 case 'p':
400 prot = 0;
401 prot |= strstr(optarg, "MAP_PRIVATE") ?
402 MAP_PRIVATE : 0;
403 prot |= strstr(optarg, "MAP_SHARED") ?
404 MAP_PRIVATE : 0;
405 break;
406 case 'f':
407 alloc_flags = atol(optarg);
408 break;
409 case 'a':
410 test = ALLOC_TEST;
411 break;
412 case 'm':
413 test = MAP_TEST;
414 break;
415 case 'c':
416 test = CUSTOM_TEST;
417 printf("KALP : Case 'c'\n");
418 custom_test_num = atol(optarg);
419 break;
420 case 'r':
421 fmt = atol(optarg);
422 break;
423 case 'w':
424 width = atol(optarg);
425 break;
426 case 'h':
427 height = atol(optarg);
428 break;
429 case 't':
430 tiler_test = 1;
431 break;
432 case 'n':
433 printf("KALP : Case 'n'\n");
434 count = atol(optarg);
435 break;
436 case 'i':
437 printf("KALP : Case 'i'\n");
438 iteration = atol(optarg);
439 break;
440 }
441 }
442 printf("test %d, len %u, width %u, height %u, fmt %u, align %u, count %d, "
443 "iteration %d, map_flags %d, prot %d, alloc_flags %d\n", test, len, width,
444 height, fmt, align, count, iteration, map_flags, prot, alloc_flags);
445
446 switch (test) {
447 case ALLOC_TEST:
448 for(j = 0; j < iteration; j++) {
449 ret = ion_alloc_test(count);
450 if(ret) {
451 printf("\nion alloc test: FAILED at iteration-%d\n", j+1);
452 break;
453 }
454 }
455 break;
456
457 case MAP_TEST:
458 for(j = 0; j < iteration; j++) {
459 ret = ion_map_test(count);
460 if(ret) {
461 printf("\nion map test: FAILED at iteration-%d\n", j+1);
462 break;
463 }
464 }
465 break;
466
467 case CUSTOM_TEST:
468 ret = custom_test(custom_test_num);
469 if(ret) {
470 printf("\nion custom test #%d: FAILED\n", custom_test_num);
471 }
472 break;
473
474 default:
475 printf("must specify a test (alloc, map, custom)\n");
476 }
477
478 return 0;
479}