1 /* 2 * Copyright 2014 Advanced Micro Devices, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22 */ 23 24 #ifdef HAVE_CONFIG_H 25 #include "config.h" 26 #endif 27 28 #include <string.h> 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <unistd.h> 32 #include <string.h> 33 #include <ctype.h> 34 #include <fcntl.h> 35 #include <errno.h> 36 #include <signal.h> 37 #include <time.h> 38 #include <sys/types.h> 39 #include <sys/stat.h> 40 #include <sys/ioctl.h> 41 #include <sys/time.h> 42 #include <stdarg.h> 43 #include <stdint.h> 44 45 #include "drm.h" 46 #include "xf86drmMode.h" 47 #include "xf86drm.h" 48 49 #include "CUnit/Basic.h" 50 51 #include "amdgpu_test.h" 52 53 /** 54 * Open handles for amdgpu devices 55 * 56 */ 57 int drm_amdgpu[MAX_CARDS_SUPPORTED]; 58 59 /** Open render node to test */ 60 int open_render_node = 0; /* By default run most tests on primary node */ 61 62 /** The table of all known test suites to run */ 63 static CU_SuiteInfo suites[] = { 64 { 65 .pName = "Basic Tests", 66 .pInitFunc = suite_basic_tests_init, 67 .pCleanupFunc = suite_basic_tests_clean, 68 .pTests = basic_tests, 69 }, 70 { 71 .pName = "BO Tests", 72 .pInitFunc = suite_bo_tests_init, 73 .pCleanupFunc = suite_bo_tests_clean, 74 .pTests = bo_tests, 75 }, 76 { 77 .pName = "CS Tests", 78 .pInitFunc = suite_cs_tests_init, 79 .pCleanupFunc = suite_cs_tests_clean, 80 .pTests = cs_tests, 81 }, 82 { 83 .pName = "VCE Tests", 84 .pInitFunc = suite_vce_tests_init, 85 .pCleanupFunc = suite_vce_tests_clean, 86 .pTests = vce_tests, 87 }, 88 CU_SUITE_INFO_NULL, 89 }; 90 91 92 /** Display information about all suites and their tests */ 93 static void display_test_suites(void) 94 { 95 int iSuite; 96 int iTest; 97 98 printf("Suites\n"); 99 100 for (iSuite = 0; suites[iSuite].pName != NULL; iSuite++) { 101 printf("Suite id = %d: Name '%s'\n", 102 iSuite + 1, suites[iSuite].pName); 103 104 for (iTest = 0; suites[iSuite].pTests[iTest].pName != NULL; 105 iTest++) { 106 printf(" Test id %d: Name: '%s'\n", iTest + 1, 107 suites[iSuite].pTests[iTest].pName); 108 } 109 } 110 } 111 112 113 /** Help string for command line parameters */ 114 static const char usage[] = 115 "Usage: %s [-hlpr] [<-s <suite id>> [-t <test id>]] " 116 "[-b <pci_bus_id> [-d <pci_device_id>]]\n" 117 "where:\n" 118 " l - Display all suites and their tests\n" 119 " r - Run the tests on render node\n" 120 " b - Specify device's PCI bus id to run tests\n" 121 " d - Specify device's PCI device id to run tests (optional)\n" 122 " p - Display information of AMDGPU devices in system\n" 123 " h - Display this help\n"; 124 /** Specified options strings for getopt */ 125 static const char options[] = "hlrps:t:b:d:"; 126 127 /* Open AMD devices. 128 * Return the number of AMD device openned. 129 */ 130 static int amdgpu_open_devices(int open_render_node) 131 { 132 drmDevicePtr devices[MAX_CARDS_SUPPORTED]; 133 int ret; 134 int i; 135 int drm_node; 136 int amd_index = 0; 137 int drm_count; 138 int fd; 139 drmVersionPtr version; 140 141 drm_count = drmGetDevices2(0, devices, MAX_CARDS_SUPPORTED); 142 143 if (drm_count < 0) { 144 fprintf(stderr, 145 "drmGetDevices2() returned an error %d\n", 146 drm_count); 147 return 0; 148 } 149 150 for (i = 0; i < drm_count; i++) { 151 /* If this is not PCI device, skip*/ 152 if (devices[i]->bustype != DRM_BUS_PCI) 153 continue; 154 155 /* If this is not AMD GPU vender ID, skip*/ 156 if (devices[i]->deviceinfo.pci->vendor_id != 0x1002) 157 continue; 158 159 if (open_render_node) 160 drm_node = DRM_NODE_RENDER; 161 else 162 drm_node = DRM_NODE_PRIMARY; 163 164 fd = -1; 165 if (devices[i]->available_nodes & 1 << drm_node) 166 fd = open( 167 devices[i]->nodes[drm_node], 168 O_RDWR | O_CLOEXEC); 169 170 /* This node is not available. */ 171 if (fd < 0) continue; 172 173 version = drmGetVersion(fd); 174 if (!version) { 175 fprintf(stderr, 176 "Warning: Cannot get version for %s." 177 "Error is %s\n", 178 devices[i]->nodes[drm_node], 179 strerror(errno)); 180 close(fd); 181 continue; 182 } 183 184 if (strcmp(version->name, "amdgpu")) { 185 /* This is not AMDGPU driver, skip.*/ 186 drmFreeVersion(version); 187 close(fd); 188 continue; 189 } 190 191 drmFreeVersion(version); 192 193 drm_amdgpu[amd_index] = fd; 194 amd_index++; 195 } 196 197 drmFreeDevices(devices, drm_count); 198 return amd_index; 199 } 200 201 /* Close AMD devices. 202 */ 203 static void amdgpu_close_devices() 204 { 205 int i; 206 for (i = 0; i < MAX_CARDS_SUPPORTED; i++) 207 if (drm_amdgpu[i] >=0) 208 close(drm_amdgpu[i]); 209 } 210 211 /* Print AMD devices information */ 212 static void amdgpu_print_devices() 213 { 214 int i; 215 drmDevicePtr device; 216 217 /* Open the first AMD devcie to print driver information. */ 218 if (drm_amdgpu[0] >=0) { 219 /* Display AMD driver version information.*/ 220 drmVersionPtr retval = drmGetVersion(drm_amdgpu[0]); 221 222 if (retval == NULL) { 223 perror("Cannot get version for AMDGPU device"); 224 return; 225 } 226 227 printf("Driver name: %s, Date: %s, Description: %s.\n", 228 retval->name, retval->date, retval->desc); 229 drmFreeVersion(retval); 230 } 231 232 /* Display information of AMD devices */ 233 printf("Devices:\n"); 234 for (i = 0; i < MAX_CARDS_SUPPORTED && drm_amdgpu[i] >=0; i++) 235 if (drmGetDevice2(drm_amdgpu[i], 236 DRM_DEVICE_GET_PCI_REVISION, 237 &device) == 0) { 238 if (device->bustype == DRM_BUS_PCI) { 239 printf("PCI "); 240 printf(" domain:%04x", 241 device->businfo.pci->domain); 242 printf(" bus:%02x", 243 device->businfo.pci->bus); 244 printf(" device:%02x", 245 device->businfo.pci->dev); 246 printf(" function:%01x", 247 device->businfo.pci->func); 248 printf(" vendor_id:%04x", 249 device->deviceinfo.pci->vendor_id); 250 printf(" device_id:%04x", 251 device->deviceinfo.pci->device_id); 252 printf(" subvendor_id:%04x", 253 device->deviceinfo.pci->subvendor_id); 254 printf(" subdevice_id:%04x", 255 device->deviceinfo.pci->subdevice_id); 256 printf(" revision_id:%02x", 257 device->deviceinfo.pci->revision_id); 258 printf("\n"); 259 } 260 drmFreeDevice(&device); 261 } 262 } 263 264 /* Find a match AMD device in PCI bus 265 * Return the index of the device or -1 if not found 266 */ 267 static int amdgpu_find_device(uint8_t bus, uint8_t dev) 268 { 269 int i; 270 drmDevicePtr device; 271 272 for (i = 0; i < MAX_CARDS_SUPPORTED && drm_amdgpu[i] >=0; i++) 273 if (drmGetDevice2(drm_amdgpu[i], 274 DRM_DEVICE_GET_PCI_REVISION, 275 &device) == 0) { 276 if (device->bustype == DRM_BUS_PCI) 277 if (device->businfo.pci->bus == bus && 278 device->businfo.pci->dev == dev) { 279 280 drmFreeDevice(&device); 281 return i; 282 } 283 284 drmFreeDevice(&device); 285 } 286 287 return -1; 288 } 289 290 /* The main() function for setting up and running the tests. 291 * Returns a CUE_SUCCESS on successful running, another 292 * CUnit error code on failure. 293 */ 294 int main(int argc, char **argv) 295 { 296 int c; /* Character received from getopt */ 297 int i = 0; 298 int suite_id = -1; /* By default run everything */ 299 int test_id = -1; /* By default run all tests in the suite */ 300 int pci_bus_id = -1; /* By default PC bus ID is not specified */ 301 int pci_device_id = 0; /* By default PC device ID is zero */ 302 int display_devices = 0;/* By default not to display devices' info */ 303 CU_pSuite pSuite = NULL; 304 CU_pTest pTest = NULL; 305 int test_device_index; 306 307 for (i = 0; i < MAX_CARDS_SUPPORTED; i++) 308 drm_amdgpu[i] = -1; 309 310 311 /* Parse command line string */ 312 opterr = 0; /* Do not print error messages from getopt */ 313 while ((c = getopt(argc, argv, options)) != -1) { 314 switch (c) { 315 case 'l': 316 display_test_suites(); 317 exit(EXIT_SUCCESS); 318 case 's': 319 suite_id = atoi(optarg); 320 break; 321 case 't': 322 test_id = atoi(optarg); 323 break; 324 case 'b': 325 pci_bus_id = atoi(optarg); 326 break; 327 case 'd': 328 pci_device_id = atoi(optarg); 329 break; 330 case 'p': 331 display_devices = 1; 332 break; 333 case 'r': 334 open_render_node = 1; 335 break; 336 case '?': 337 case 'h': 338 fprintf(stderr, usage, argv[0]); 339 exit(EXIT_SUCCESS); 340 default: 341 fprintf(stderr, usage, argv[0]); 342 exit(EXIT_FAILURE); 343 } 344 } 345 346 if (amdgpu_open_devices(open_render_node) <= 0) { 347 perror("Cannot open AMDGPU device"); 348 exit(EXIT_FAILURE); 349 } 350 351 if (drm_amdgpu[0] < 0) { 352 perror("Cannot open AMDGPU device"); 353 exit(EXIT_FAILURE); 354 } 355 356 if (display_devices) { 357 amdgpu_print_devices(); 358 amdgpu_close_devices(); 359 exit(EXIT_SUCCESS); 360 } 361 362 if (pci_bus_id > 0) { 363 /* A device was specified to run the test */ 364 test_device_index = amdgpu_find_device((uint8_t)pci_bus_id, 365 (uint8_t)pci_device_id); 366 367 if (test_device_index >= 0) { 368 /* Most tests run on device of drm_amdgpu[0]. 369 * Swap the chosen device to drm_amdgpu[0]. 370 */ 371 i = drm_amdgpu[0]; 372 drm_amdgpu[0] = drm_amdgpu[test_device_index]; 373 drm_amdgpu[test_device_index] = i; 374 } else { 375 fprintf(stderr, 376 "The specified GPU device does not exist.\n"); 377 exit(EXIT_FAILURE); 378 } 379 } 380 381 /* Initialize test suites to run */ 382 383 /* initialize the CUnit test registry */ 384 if (CUE_SUCCESS != CU_initialize_registry()) { 385 amdgpu_close_devices(); 386 return CU_get_error(); 387 } 388 389 /* Register suites. */ 390 if (CU_register_suites(suites) != CUE_SUCCESS) { 391 fprintf(stderr, "suite registration failed - %s\n", 392 CU_get_error_msg()); 393 CU_cleanup_registry(); 394 amdgpu_close_devices(); 395 exit(EXIT_FAILURE); 396 } 397 398 /* Run tests using the CUnit Basic interface */ 399 CU_basic_set_mode(CU_BRM_VERBOSE); 400 401 if (suite_id != -1) { /* If user specify particular suite? */ 402 pSuite = CU_get_suite_by_index((unsigned int) suite_id, 403 CU_get_registry()); 404 405 if (pSuite) { 406 if (test_id != -1) { /* If user specify test id */ 407 pTest = CU_get_test_by_index( 408 (unsigned int) test_id, 409 pSuite); 410 if (pTest) 411 CU_basic_run_test(pSuite, pTest); 412 else { 413 fprintf(stderr, "Invalid test id: %d\n", 414 test_id); 415 CU_cleanup_registry(); 416 amdgpu_close_devices(); 417 exit(EXIT_FAILURE); 418 } 419 } else 420 CU_basic_run_suite(pSuite); 421 } else { 422 fprintf(stderr, "Invalid suite id : %d\n", 423 suite_id); 424 CU_cleanup_registry(); 425 amdgpu_close_devices(); 426 exit(EXIT_FAILURE); 427 } 428 } else 429 CU_basic_run_tests(); 430 431 CU_cleanup_registry(); 432 amdgpu_close_devices(); 433 return CU_get_error(); 434 } 435