Home | History | Annotate | Download | only in ion
      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 
     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 
     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 
    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 
    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 
    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  */
    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 
    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 
    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