1 #include <errno.h> 2 #include <fcntl.h> 3 #include <getopt.h> 4 #include <string.h> 5 #include <stdlib.h> 6 #include <stdio.h> 7 #include <sys/mman.h> 8 #include <sys/ioctl.h> 9 #include <sys/socket.h> 10 #include <sys/stat.h> 11 #include <sys/types.h> 12 #include <unistd.h> 13 14 #include <ion/ion.h> 15 #include <linux/ion.h> 16 #include <linux/omap_ion.h> 17 18 size_t len = 1024*1024, align = 0; 19 int prot = PROT_READ | PROT_WRITE; 20 int map_flags = MAP_SHARED; 21 int alloc_flags = 0; 22 int heap_mask = 1; 23 int test = -1; 24 size_t width = 1024*1024, height = 1024*1024; 25 int fmt = TILER_PIXEL_FMT_32BIT; 26 int tiler_test = 0; 27 size_t stride; 28 29 int _ion_alloc_test(int *fd, struct ion_handle **handle) 30 { 31 int ret; 32 33 *fd = ion_open(); 34 if (*fd < 0) 35 return *fd; 36 37 if (tiler_test) 38 ret = ion_alloc_tiler(*fd, width, height, fmt, alloc_flags, 39 handle, &stride); 40 else 41 ret = ion_alloc(*fd, len, align, alloc_flags, handle); 42 43 if (ret) 44 printf("%s failed: %s\n", __func__, strerror(ret)); 45 return ret; 46 } 47 48 void ion_alloc_test() 49 { 50 int fd, ret; 51 struct ion_handle *handle; 52 53 if(_ion_alloc_test(&fd, &handle)) 54 return; 55 56 ret = ion_free(fd, handle); 57 if (ret) { 58 printf("%s failed: %s %p\n", __func__, strerror(ret), handle); 59 return; 60 } 61 ion_close(fd); 62 printf("ion alloc test: passed\n"); 63 } 64 65 void _ion_tiler_map_test(unsigned char *ptr) 66 { 67 size_t row, col; 68 69 for (row = 0; row < height; row++) 70 for (col = 0; col < width; col++) { 71 int i = (row * stride) + col; 72 ptr[i] = (unsigned char)i; 73 } 74 for (row = 0; row < height; row++) 75 for (col = 0; col < width; col++) { 76 int i = (row * stride) + col; 77 if (ptr[i] != (unsigned char)i) 78 printf("%s failed wrote %d read %d from mapped " 79 "memory\n", __func__, i, ptr[i]); 80 } 81 } 82 83 84 void ion_map_test() 85 { 86 int fd, map_fd, ret; 87 size_t i; 88 struct ion_handle *handle; 89 unsigned char *ptr; 90 91 if(_ion_alloc_test(&fd, &handle)) 92 return; 93 94 if (tiler_test) 95 len = height * stride; 96 ret = ion_map(fd, handle, len, prot, map_flags, 0, &ptr, &map_fd); 97 if (ret) 98 return; 99 100 if (tiler_test) 101 _ion_tiler_map_test(ptr); 102 else { 103 for (i = 0; i < len; i++) { 104 ptr[i] = (unsigned char)i; 105 } 106 for (i = 0; i < len; i++) 107 if (ptr[i] != (unsigned char)i) 108 printf("%s failed wrote %d read %d from mapped " 109 "memory\n", __func__, i, ptr[i]); 110 } 111 /* clean up properly */ 112 ret = ion_free(fd, handle); 113 ion_close(fd); 114 munmap(ptr, len); 115 close(map_fd); 116 117 _ion_alloc_test(&fd, &handle); 118 close(fd); 119 120 #if 0 121 munmap(ptr, len); 122 close(map_fd); 123 ion_close(fd); 124 125 _ion_alloc_test(len, align, flags, &fd, &handle); 126 close(map_fd); 127 ret = ion_map(fd, handle, len, prot, flags, 0, &ptr, &map_fd); 128 /* don't clean up */ 129 #endif 130 } 131 132 void ion_share_test() 133 134 { 135 struct ion_handle *handle; 136 int sd[2]; 137 int num_fd = 1; 138 struct iovec count_vec = { 139 .iov_base = &num_fd, 140 .iov_len = sizeof num_fd, 141 }; 142 char buf[CMSG_SPACE(sizeof(int))]; 143 socketpair(AF_UNIX, SOCK_STREAM, 0, sd); 144 if (fork()) { 145 struct msghdr msg = { 146 .msg_control = buf, 147 .msg_controllen = sizeof buf, 148 .msg_iov = &count_vec, 149 .msg_iovlen = 1, 150 }; 151 152 struct cmsghdr *cmsg; 153 int fd, share_fd, ret; 154 char *ptr; 155 /* parent */ 156 if(_ion_alloc_test(&fd, &handle)) 157 return; 158 ret = ion_share(fd, handle, &share_fd); 159 if (ret) 160 printf("share failed %s\n", strerror(errno)); 161 ptr = mmap(NULL, len, prot, map_flags, share_fd, 0); 162 if (ptr == MAP_FAILED) { 163 return; 164 } 165 strcpy(ptr, "master"); 166 cmsg = CMSG_FIRSTHDR(&msg); 167 cmsg->cmsg_level = SOL_SOCKET; 168 cmsg->cmsg_type = SCM_RIGHTS; 169 cmsg->cmsg_len = CMSG_LEN(sizeof(int)); 170 *(int *)CMSG_DATA(cmsg) = share_fd; 171 /* send the fd */ 172 printf("master? [%10s] should be [master]\n", ptr); 173 printf("master sending msg 1\n"); 174 sendmsg(sd[0], &msg, 0); 175 if (recvmsg(sd[0], &msg, 0) < 0) 176 perror("master recv msg 2"); 177 printf("master? [%10s] should be [child]\n", ptr); 178 179 /* send ping */ 180 sendmsg(sd[0], &msg, 0); 181 printf("master->master? [%10s]\n", ptr); 182 if (recvmsg(sd[0], &msg, 0) < 0) 183 perror("master recv 1"); 184 } else { 185 struct msghdr msg; 186 struct cmsghdr *cmsg; 187 char* ptr; 188 int fd, recv_fd; 189 char* child_buf[100]; 190 /* child */ 191 struct iovec count_vec = { 192 .iov_base = child_buf, 193 .iov_len = sizeof child_buf, 194 }; 195 196 struct msghdr child_msg = { 197 .msg_control = buf, 198 .msg_controllen = sizeof buf, 199 .msg_iov = &count_vec, 200 .msg_iovlen = 1, 201 }; 202 203 if (recvmsg(sd[1], &child_msg, 0) < 0) 204 perror("child recv msg 1"); 205 cmsg = CMSG_FIRSTHDR(&child_msg); 206 if (cmsg == NULL) { 207 printf("no cmsg rcvd in child"); 208 return; 209 } 210 recv_fd = *(int*)CMSG_DATA(cmsg); 211 if (recv_fd < 0) { 212 printf("could not get recv_fd from socket"); 213 return; 214 } 215 printf("child %d\n", recv_fd); 216 fd = ion_open(); 217 ptr = mmap(NULL, len, prot, map_flags, recv_fd, 0); 218 if (ptr == MAP_FAILED) { 219 return; 220 } 221 printf("child? [%10s] should be [master]\n", ptr); 222 strcpy(ptr, "child"); 223 printf("child sending msg 2\n"); 224 sendmsg(sd[1], &child_msg, 0); 225 } 226 } 227 228 int main(int argc, char* argv[]) { 229 int c; 230 enum tests { 231 ALLOC_TEST = 0, MAP_TEST, SHARE_TEST, 232 }; 233 234 while (1) { 235 static struct option opts[] = { 236 {"alloc", no_argument, 0, 'a'}, 237 {"alloc_flags", required_argument, 0, 'f'}, 238 {"heap_mask", required_argument, 0, 'h'}, 239 {"map", no_argument, 0, 'm'}, 240 {"share", no_argument, 0, 's'}, 241 {"len", required_argument, 0, 'l'}, 242 {"align", required_argument, 0, 'g'}, 243 {"map_flags", required_argument, 0, 'z'}, 244 {"prot", required_argument, 0, 'p'}, 245 {"alloc_tiler", no_argument, 0, 't'}, 246 {"width", required_argument, 0, 'w'}, 247 {"height", required_argument, 0, 'h'}, 248 {"fmt", required_argument, 0, 'r'}, 249 }; 250 int i = 0; 251 c = getopt_long(argc, argv, "af:h:l:mr:st", opts, &i); 252 if (c == -1) 253 break; 254 255 switch (c) { 256 case 'l': 257 len = atol(optarg); 258 break; 259 case 'g': 260 align = atol(optarg); 261 break; 262 case 'z': 263 map_flags = 0; 264 map_flags |= strstr(optarg, "PROT_EXEC") ? 265 PROT_EXEC : 0; 266 map_flags |= strstr(optarg, "PROT_READ") ? 267 PROT_READ: 0; 268 map_flags |= strstr(optarg, "PROT_WRITE") ? 269 PROT_WRITE: 0; 270 map_flags |= strstr(optarg, "PROT_NONE") ? 271 PROT_NONE: 0; 272 break; 273 case 'p': 274 prot = 0; 275 prot |= strstr(optarg, "MAP_PRIVATE") ? 276 MAP_PRIVATE : 0; 277 prot |= strstr(optarg, "MAP_SHARED") ? 278 MAP_PRIVATE : 0; 279 break; 280 case 'f': 281 alloc_flags = atol(optarg); 282 break; 283 case 'a': 284 test = ALLOC_TEST; 285 break; 286 case 'm': 287 test = MAP_TEST; 288 break; 289 case 'r': 290 fmt = atol(optarg); 291 break; 292 case 's': 293 test = SHARE_TEST; 294 break; 295 case 'w': 296 width = atol(optarg); 297 break; 298 case 'h': 299 height = atol(optarg); 300 break; 301 case 't': 302 tiler_test = 1; 303 break; 304 } 305 } 306 printf("test %d, len %u, width %u, height %u fmt %u align %u, " 307 "map_flags %d, prot %d, alloc_flags %d\n", test, len, width, 308 height, fmt, align, map_flags, prot, alloc_flags); 309 switch (test) { 310 case ALLOC_TEST: 311 ion_alloc_test(); 312 break; 313 case MAP_TEST: 314 ion_map_test(); 315 break; 316 case SHARE_TEST: 317 ion_share_test(); 318 break; 319 default: 320 printf("must specify a test (alloc, map, share)\n"); 321 } 322 return 0; 323 } 324