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