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