13f012e29Smrg/*
23f012e29Smrg * Copyright 2014 Advanced Micro Devices, Inc.
33f012e29Smrg *
43f012e29Smrg * Permission is hereby granted, free of charge, to any person obtaining a
53f012e29Smrg * copy of this software and associated documentation files (the "Software"),
63f012e29Smrg * to deal in the Software without restriction, including without limitation
73f012e29Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
83f012e29Smrg * and/or sell copies of the Software, and to permit persons to whom the
93f012e29Smrg * Software is furnished to do so, subject to the following conditions:
103f012e29Smrg *
113f012e29Smrg * The above copyright notice and this permission notice shall be included in
123f012e29Smrg * all copies or substantial portions of the Software.
133f012e29Smrg *
143f012e29Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
153f012e29Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
163f012e29Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
173f012e29Smrg * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
183f012e29Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
193f012e29Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
203f012e29Smrg * OTHER DEALINGS IN THE SOFTWARE.
213f012e29Smrg *
223f012e29Smrg*/
233f012e29Smrg
243f012e29Smrg#include <string.h>
253f012e29Smrg#include <stdio.h>
263f012e29Smrg#include <stdlib.h>
273f012e29Smrg#include <unistd.h>
283f012e29Smrg#include <string.h>
293f012e29Smrg#include <ctype.h>
303f012e29Smrg#include <fcntl.h>
313f012e29Smrg#include <errno.h>
323f012e29Smrg#include <signal.h>
333f012e29Smrg#include <time.h>
343f012e29Smrg#include <sys/types.h>
353f012e29Smrg#include <sys/stat.h>
363f012e29Smrg#include <sys/ioctl.h>
373f012e29Smrg#include <sys/time.h>
383f012e29Smrg#include <stdarg.h>
393f012e29Smrg#include <stdint.h>
404babd585Smrg#ifdef __linux__
414babd585Smrg#include <linux/limits.h>
424babd585Smrg#elif __FreeBSD__
434babd585Smrg/* SPECNAMELEN in FreeBSD is defined here: */
444babd585Smrg#include <sys/param.h>
454babd585Smrg#endif
464babd585Smrg#ifdef MAJOR_IN_MKDEV
474babd585Smrg#include <sys/mkdev.h>
484babd585Smrg#endif
494babd585Smrg#ifdef MAJOR_IN_SYSMACROS
504babd585Smrg#include <sys/sysmacros.h>
514babd585Smrg#endif
523f012e29Smrg
533f012e29Smrg#include "drm.h"
543f012e29Smrg#include "xf86drmMode.h"
553f012e29Smrg#include "xf86drm.h"
563f012e29Smrg
573f012e29Smrg#include "CUnit/Basic.h"
583f012e29Smrg
593f012e29Smrg#include "amdgpu_test.h"
6000a23bdaSmrg#include "amdgpu_internal.h"
6100a23bdaSmrg
6200a23bdaSmrg/* Test suite names */
6300a23bdaSmrg#define BASIC_TESTS_STR "Basic Tests"
6400a23bdaSmrg#define BO_TESTS_STR "BO Tests"
6500a23bdaSmrg#define CS_TESTS_STR "CS Tests"
6600a23bdaSmrg#define VCE_TESTS_STR "VCE Tests"
6700a23bdaSmrg#define VCN_TESTS_STR "VCN Tests"
680ed5401bSmrg#define JPEG_TESTS_STR "JPEG Tests"
6900a23bdaSmrg#define UVD_ENC_TESTS_STR "UVD ENC Tests"
7000a23bdaSmrg#define DEADLOCK_TESTS_STR "Deadlock Tests"
7100a23bdaSmrg#define VM_TESTS_STR "VM Tests"
725324fb0dSmrg#define RAS_TESTS_STR "RAS Tests"
735324fb0dSmrg#define SYNCOBJ_TIMELINE_TESTS_STR "SYNCOBJ TIMELINE Tests"
7441687f09Smrg#define SECURITY_TESTS_STR "Security Tests"
754babd585Smrg#define HOTUNPLUG_TESTS_STR "Hotunplug Tests"
760ed5401bSmrg#define CP_DMA_TESTS_STR "CP DMA Tests"
773f012e29Smrg
783f012e29Smrg/**
793f012e29Smrg *  Open handles for amdgpu devices
803f012e29Smrg *
813f012e29Smrg */
823f012e29Smrgint drm_amdgpu[MAX_CARDS_SUPPORTED];
833f012e29Smrg
84037b3c26Smrg/** Open render node to test */
85037b3c26Smrgint open_render_node = 0;	/* By default run most tests on primary node */
86037b3c26Smrg
873f012e29Smrg/** The table of all known test suites to run */
883f012e29Smrgstatic CU_SuiteInfo suites[] = {
893f012e29Smrg	{
9000a23bdaSmrg		.pName = BASIC_TESTS_STR,
913f012e29Smrg		.pInitFunc = suite_basic_tests_init,
923f012e29Smrg		.pCleanupFunc = suite_basic_tests_clean,
933f012e29Smrg		.pTests = basic_tests,
943f012e29Smrg	},
953f012e29Smrg	{
9600a23bdaSmrg		.pName = BO_TESTS_STR,
973f012e29Smrg		.pInitFunc = suite_bo_tests_init,
983f012e29Smrg		.pCleanupFunc = suite_bo_tests_clean,
993f012e29Smrg		.pTests = bo_tests,
1003f012e29Smrg	},
1013f012e29Smrg	{
10200a23bdaSmrg		.pName = CS_TESTS_STR,
1033f012e29Smrg		.pInitFunc = suite_cs_tests_init,
1043f012e29Smrg		.pCleanupFunc = suite_cs_tests_clean,
1053f012e29Smrg		.pTests = cs_tests,
1063f012e29Smrg	},
1073f012e29Smrg	{
10800a23bdaSmrg		.pName = VCE_TESTS_STR,
1093f012e29Smrg		.pInitFunc = suite_vce_tests_init,
1103f012e29Smrg		.pCleanupFunc = suite_vce_tests_clean,
1113f012e29Smrg		.pTests = vce_tests,
1123f012e29Smrg	},
113d8807b2fSmrg	{
11400a23bdaSmrg		.pName = VCN_TESTS_STR,
115d8807b2fSmrg		.pInitFunc = suite_vcn_tests_init,
116d8807b2fSmrg		.pCleanupFunc = suite_vcn_tests_clean,
117d8807b2fSmrg		.pTests = vcn_tests,
118d8807b2fSmrg	},
1190ed5401bSmrg	{
1200ed5401bSmrg		.pName = JPEG_TESTS_STR,
1210ed5401bSmrg		.pInitFunc = suite_jpeg_tests_init,
1220ed5401bSmrg		.pCleanupFunc = suite_jpeg_tests_clean,
1230ed5401bSmrg		.pTests = jpeg_tests,
1240ed5401bSmrg	},
125d8807b2fSmrg	{
12600a23bdaSmrg		.pName = UVD_ENC_TESTS_STR,
127d8807b2fSmrg		.pInitFunc = suite_uvd_enc_tests_init,
128d8807b2fSmrg		.pCleanupFunc = suite_uvd_enc_tests_clean,
129d8807b2fSmrg		.pTests = uvd_enc_tests,
130d8807b2fSmrg	},
13100a23bdaSmrg	{
13200a23bdaSmrg		.pName = DEADLOCK_TESTS_STR,
13300a23bdaSmrg		.pInitFunc = suite_deadlock_tests_init,
13400a23bdaSmrg		.pCleanupFunc = suite_deadlock_tests_clean,
13500a23bdaSmrg		.pTests = deadlock_tests,
13600a23bdaSmrg	},
13700a23bdaSmrg	{
13800a23bdaSmrg		.pName = VM_TESTS_STR,
13900a23bdaSmrg		.pInitFunc = suite_vm_tests_init,
14000a23bdaSmrg		.pCleanupFunc = suite_vm_tests_clean,
14100a23bdaSmrg		.pTests = vm_tests,
14200a23bdaSmrg	},
1435324fb0dSmrg	{
1445324fb0dSmrg		.pName = RAS_TESTS_STR,
1455324fb0dSmrg		.pInitFunc = suite_ras_tests_init,
1465324fb0dSmrg		.pCleanupFunc = suite_ras_tests_clean,
1475324fb0dSmrg		.pTests = ras_tests,
1485324fb0dSmrg	},
1495324fb0dSmrg	{
1505324fb0dSmrg		.pName = SYNCOBJ_TIMELINE_TESTS_STR,
1515324fb0dSmrg		.pInitFunc = suite_syncobj_timeline_tests_init,
1525324fb0dSmrg		.pCleanupFunc = suite_syncobj_timeline_tests_clean,
1535324fb0dSmrg		.pTests = syncobj_timeline_tests,
1545324fb0dSmrg	},
15541687f09Smrg	{
15641687f09Smrg		.pName = SECURITY_TESTS_STR,
15741687f09Smrg		.pInitFunc = suite_security_tests_init,
15841687f09Smrg		.pCleanupFunc = suite_security_tests_clean,
15941687f09Smrg		.pTests = security_tests,
16041687f09Smrg	},
1614babd585Smrg	{
1624babd585Smrg		.pName = HOTUNPLUG_TESTS_STR,
1634babd585Smrg		.pInitFunc = suite_hotunplug_tests_init,
1644babd585Smrg		.pCleanupFunc = suite_hotunplug_tests_clean,
1654babd585Smrg		.pTests = hotunplug_tests,
1664babd585Smrg	},
1670ed5401bSmrg	{
1680ed5401bSmrg		.pName = CP_DMA_TESTS_STR,
1690ed5401bSmrg		.pInitFunc = suite_cp_dma_tests_init,
1700ed5401bSmrg		.pCleanupFunc = suite_cp_dma_tests_clean,
1710ed5401bSmrg		.pTests = cp_dma_tests,
1720ed5401bSmrg	},
17300a23bdaSmrg
1743f012e29Smrg	CU_SUITE_INFO_NULL,
1753f012e29Smrg};
1763f012e29Smrg
17700a23bdaSmrgtypedef CU_BOOL (*active__stat_func)(void);
17800a23bdaSmrg
17900a23bdaSmrgtypedef struct Suites_Active_Status {
18000a23bdaSmrg	char*             pName;
18100a23bdaSmrg	active__stat_func pActive;
18200a23bdaSmrg}Suites_Active_Status;
1833f012e29Smrg
18400a23bdaSmrgstatic CU_BOOL always_active()
18500a23bdaSmrg{
18600a23bdaSmrg	return CU_TRUE;
18700a23bdaSmrg}
18800a23bdaSmrg
18900a23bdaSmrgstatic Suites_Active_Status suites_active_stat[] = {
19000a23bdaSmrg		{
19100a23bdaSmrg			.pName = BASIC_TESTS_STR,
19241687f09Smrg			.pActive = suite_basic_tests_enable,
19300a23bdaSmrg		},
19400a23bdaSmrg		{
19500a23bdaSmrg			.pName = BO_TESTS_STR,
19600a23bdaSmrg			.pActive = always_active,
19700a23bdaSmrg		},
19800a23bdaSmrg		{
19900a23bdaSmrg			.pName = CS_TESTS_STR,
20000a23bdaSmrg			.pActive = suite_cs_tests_enable,
20100a23bdaSmrg		},
20200a23bdaSmrg		{
20300a23bdaSmrg			.pName = VCE_TESTS_STR,
20400a23bdaSmrg			.pActive = suite_vce_tests_enable,
20500a23bdaSmrg		},
20600a23bdaSmrg		{
20700a23bdaSmrg			.pName = VCN_TESTS_STR,
20800a23bdaSmrg			.pActive = suite_vcn_tests_enable,
20900a23bdaSmrg		},
2100ed5401bSmrg		{
2110ed5401bSmrg			.pName = JPEG_TESTS_STR,
2120ed5401bSmrg			.pActive = suite_jpeg_tests_enable,
2130ed5401bSmrg		},
21400a23bdaSmrg		{
21500a23bdaSmrg			.pName = UVD_ENC_TESTS_STR,
21600a23bdaSmrg			.pActive = suite_uvd_enc_tests_enable,
21700a23bdaSmrg		},
21800a23bdaSmrg		{
21900a23bdaSmrg			.pName = DEADLOCK_TESTS_STR,
22000a23bdaSmrg			.pActive = suite_deadlock_tests_enable,
22100a23bdaSmrg		},
22200a23bdaSmrg		{
22300a23bdaSmrg			.pName = VM_TESTS_STR,
22400a23bdaSmrg			.pActive = suite_vm_tests_enable,
22500a23bdaSmrg		},
2265324fb0dSmrg		{
2275324fb0dSmrg			.pName = RAS_TESTS_STR,
2285324fb0dSmrg			.pActive = suite_ras_tests_enable,
2295324fb0dSmrg		},
2305324fb0dSmrg		{
2315324fb0dSmrg			.pName = SYNCOBJ_TIMELINE_TESTS_STR,
2325324fb0dSmrg			.pActive = suite_syncobj_timeline_tests_enable,
2335324fb0dSmrg		},
23441687f09Smrg		{
23541687f09Smrg			.pName = SECURITY_TESTS_STR,
23641687f09Smrg			.pActive = suite_security_tests_enable,
23741687f09Smrg		},
2384babd585Smrg		{
2394babd585Smrg			.pName = HOTUNPLUG_TESTS_STR,
2404babd585Smrg			.pActive = suite_hotunplug_tests_enable,
2414babd585Smrg		},
2420ed5401bSmrg		{
2430ed5401bSmrg			.pName = CP_DMA_TESTS_STR,
2440ed5401bSmrg			.pActive = suite_cp_dma_tests_enable,
2450ed5401bSmrg		},
24600a23bdaSmrg};
24700a23bdaSmrg
24800a23bdaSmrg
24900a23bdaSmrg/*
25000a23bdaSmrg * Display information about all  suites and their tests
25100a23bdaSmrg *
25200a23bdaSmrg * NOTE: Must be run after registry is initialized and suites registered.
25300a23bdaSmrg */
2543f012e29Smrgstatic void display_test_suites(void)
2553f012e29Smrg{
2563f012e29Smrg	int iSuite;
2573f012e29Smrg	int iTest;
25800a23bdaSmrg	CU_pSuite pSuite = NULL;
25900a23bdaSmrg	CU_pTest  pTest  = NULL;
2603f012e29Smrg
2619bd392adSmrg	printf("%5s: %2s: %8s: %s\n", "What", "ID", "Status", "Name");
2623f012e29Smrg
2633f012e29Smrg	for (iSuite = 0; suites[iSuite].pName != NULL; iSuite++) {
26400a23bdaSmrg
26500a23bdaSmrg		pSuite = CU_get_suite_by_index((unsigned int) iSuite + 1,
2669bd392adSmrg					       CU_get_registry());
26700a23bdaSmrg
26800a23bdaSmrg		if (!pSuite) {
26900a23bdaSmrg			fprintf(stderr, "Invalid suite id : %d\n", iSuite + 1);
27000a23bdaSmrg			continue;
27100a23bdaSmrg		}
27200a23bdaSmrg
2739bd392adSmrg		printf("Suite: %2d: %8s: %s\n",
2749bd392adSmrg		       iSuite + 1,
2759bd392adSmrg		       pSuite->fActive ? "ENABLED" : "DISABLED",
2769bd392adSmrg		       suites[iSuite].pName);
27700a23bdaSmrg
2789bd392adSmrg		if (!pSuite->fActive)
2799bd392adSmrg			continue;
2803f012e29Smrg
2813f012e29Smrg		for (iTest = 0; suites[iSuite].pTests[iTest].pName != NULL;
2829bd392adSmrg		     iTest++) {
28300a23bdaSmrg			pTest = CU_get_test_by_index((unsigned int) iTest + 1,
2849bd392adSmrg						     pSuite);
28500a23bdaSmrg			if (!pTest) {
28600a23bdaSmrg				fprintf(stderr, "Invalid test id : %d\n", iTest + 1);
28700a23bdaSmrg				continue;
28800a23bdaSmrg			}
2899bd392adSmrg			printf(" Test: %2d: %8s: %s\n",
2909bd392adSmrg			       iTest + 1,
2919bd392adSmrg			       pSuite->fActive && pTest->fActive ? "ENABLED" : "DISABLED",
2929bd392adSmrg			       suites[iSuite].pTests[iTest].pName);
2933f012e29Smrg		}
2943f012e29Smrg	}
2953f012e29Smrg}
2963f012e29Smrg
2973f012e29Smrg/** Help string for command line parameters */
298037b3c26Smrgstatic const char usage[] =
299bbff01ceSmrg	"Usage: %s [-hlpr] [-s <suite id>] [-e <s>[.<t>] [-e ...]] [-t <test id>] [-f] "
300bbff01ceSmrg	"[-b <pci_bus_id>] [-d <pci_device_id>]\n"
301bbff01ceSmrg	"Where,\n"
302bbff01ceSmrg	"  -b      Specify device's PCI bus id to run tests\n"
303bbff01ceSmrg	"  -d      Specify device's PCI device id to run tests (optional)\n"
304bbff01ceSmrg	"  -e <s>[.<t>]  Disable test <t> of suite <s>. If only <s> is given, then disable\n"
305bbff01ceSmrg	"          the whole suite. Can be specified more than once on the command line\n"
306bbff01ceSmrg	"          to disable multiple tests or suites.\n"
307bbff01ceSmrg	"  -f      Force executing inactive suite or test\n"
308bbff01ceSmrg	"  -h      Display this help\n"
309bbff01ceSmrg	"  -l      Display all test suites and their tests\n"
310bbff01ceSmrg	"  -p      Display information of AMDGPU devices in system\n"
311bbff01ceSmrg	"  -r      Run the tests on render node\n"
312bbff01ceSmrg	"  -s <s>  Enable only test suite <s>\n"
313bbff01ceSmrg	"  -t <t>  Enable only test <t> of test suite <s>\n";
3143f012e29Smrg/** Specified options strings for getopt */
315bbff01ceSmrgstatic const char options[]   = "hlrps:t:e:b:d:f";
316037b3c26Smrg
317037b3c26Smrg/* Open AMD devices.
3185324fb0dSmrg * Return the number of AMD device opened.
319037b3c26Smrg */
320037b3c26Smrgstatic int amdgpu_open_devices(int open_render_node)
321037b3c26Smrg{
322037b3c26Smrg	drmDevicePtr devices[MAX_CARDS_SUPPORTED];
323037b3c26Smrg	int i;
324037b3c26Smrg	int drm_node;
325037b3c26Smrg	int amd_index = 0;
326037b3c26Smrg	int drm_count;
327037b3c26Smrg	int fd;
328037b3c26Smrg	drmVersionPtr version;
329037b3c26Smrg
3300ed5401bSmrg	for (i = 0; i < MAX_CARDS_SUPPORTED; i++) {
3310ed5401bSmrg		drm_amdgpu[i] = -1;
3320ed5401bSmrg	}
3330ed5401bSmrg
334037b3c26Smrg	drm_count = drmGetDevices2(0, devices, MAX_CARDS_SUPPORTED);
335037b3c26Smrg
336037b3c26Smrg	if (drm_count < 0) {
337037b3c26Smrg		fprintf(stderr,
338037b3c26Smrg			"drmGetDevices2() returned an error %d\n",
339037b3c26Smrg			drm_count);
340037b3c26Smrg		return 0;
341037b3c26Smrg	}
342037b3c26Smrg
343037b3c26Smrg	for (i = 0; i < drm_count; i++) {
344037b3c26Smrg		/* If this is not PCI device, skip*/
345037b3c26Smrg		if (devices[i]->bustype != DRM_BUS_PCI)
346037b3c26Smrg			continue;
347037b3c26Smrg
348037b3c26Smrg		/* If this is not AMD GPU vender ID, skip*/
349037b3c26Smrg		if (devices[i]->deviceinfo.pci->vendor_id != 0x1002)
350037b3c26Smrg			continue;
351037b3c26Smrg
352037b3c26Smrg		if (open_render_node)
353037b3c26Smrg			drm_node = DRM_NODE_RENDER;
354037b3c26Smrg		else
355037b3c26Smrg			drm_node = DRM_NODE_PRIMARY;
356037b3c26Smrg
357037b3c26Smrg		fd = -1;
358037b3c26Smrg		if (devices[i]->available_nodes & 1 << drm_node)
359037b3c26Smrg			fd = open(
360037b3c26Smrg				devices[i]->nodes[drm_node],
361037b3c26Smrg				O_RDWR | O_CLOEXEC);
362037b3c26Smrg
363037b3c26Smrg		/* This node is not available. */
364037b3c26Smrg		if (fd < 0) continue;
365037b3c26Smrg
366037b3c26Smrg		version = drmGetVersion(fd);
367037b3c26Smrg		if (!version) {
368037b3c26Smrg			fprintf(stderr,
369037b3c26Smrg				"Warning: Cannot get version for %s."
370037b3c26Smrg				"Error is %s\n",
371037b3c26Smrg				devices[i]->nodes[drm_node],
372037b3c26Smrg				strerror(errno));
373037b3c26Smrg			close(fd);
374037b3c26Smrg			continue;
375037b3c26Smrg		}
376037b3c26Smrg
377037b3c26Smrg		if (strcmp(version->name, "amdgpu")) {
378037b3c26Smrg			/* This is not AMDGPU driver, skip.*/
379037b3c26Smrg			drmFreeVersion(version);
380037b3c26Smrg			close(fd);
381037b3c26Smrg			continue;
382037b3c26Smrg		}
383037b3c26Smrg
384037b3c26Smrg		drmFreeVersion(version);
385037b3c26Smrg
386037b3c26Smrg		drm_amdgpu[amd_index] = fd;
387037b3c26Smrg		amd_index++;
388037b3c26Smrg	}
389037b3c26Smrg
390037b3c26Smrg	drmFreeDevices(devices, drm_count);
391037b3c26Smrg	return amd_index;
392037b3c26Smrg}
393037b3c26Smrg
394037b3c26Smrg/* Close AMD devices.
395037b3c26Smrg */
3964babd585Smrgvoid amdgpu_close_devices()
397037b3c26Smrg{
398037b3c26Smrg	int i;
399037b3c26Smrg	for (i = 0; i < MAX_CARDS_SUPPORTED; i++)
4004babd585Smrg		if (drm_amdgpu[i] >=0) {
401037b3c26Smrg			close(drm_amdgpu[i]);
4024babd585Smrg		}
403037b3c26Smrg}
404037b3c26Smrg
405037b3c26Smrg/* Print AMD devices information */
406037b3c26Smrgstatic void amdgpu_print_devices()
407037b3c26Smrg{
408037b3c26Smrg	int i;
409037b3c26Smrg	drmDevicePtr device;
410037b3c26Smrg
4115324fb0dSmrg	/* Open the first AMD device to print driver information. */
412037b3c26Smrg	if (drm_amdgpu[0] >=0) {
413037b3c26Smrg		/* Display AMD driver version information.*/
414037b3c26Smrg		drmVersionPtr retval = drmGetVersion(drm_amdgpu[0]);
415037b3c26Smrg
416037b3c26Smrg		if (retval == NULL) {
417037b3c26Smrg			perror("Cannot get version for AMDGPU device");
418037b3c26Smrg			return;
419037b3c26Smrg		}
420037b3c26Smrg
421037b3c26Smrg		printf("Driver name: %s, Date: %s, Description: %s.\n",
422037b3c26Smrg			retval->name, retval->date, retval->desc);
423037b3c26Smrg		drmFreeVersion(retval);
424037b3c26Smrg	}
425037b3c26Smrg
426037b3c26Smrg	/* Display information of AMD devices */
427037b3c26Smrg	printf("Devices:\n");
428037b3c26Smrg	for (i = 0; i < MAX_CARDS_SUPPORTED && drm_amdgpu[i] >=0; i++)
429037b3c26Smrg		if (drmGetDevice2(drm_amdgpu[i],
430037b3c26Smrg			DRM_DEVICE_GET_PCI_REVISION,
431037b3c26Smrg			&device) == 0) {
432037b3c26Smrg			if (device->bustype == DRM_BUS_PCI) {
433037b3c26Smrg				printf("PCI ");
434037b3c26Smrg				printf(" domain:%04x",
435037b3c26Smrg					device->businfo.pci->domain);
436037b3c26Smrg				printf(" bus:%02x",
437037b3c26Smrg					device->businfo.pci->bus);
438037b3c26Smrg				printf(" device:%02x",
439037b3c26Smrg					device->businfo.pci->dev);
440037b3c26Smrg				printf(" function:%01x",
441037b3c26Smrg					device->businfo.pci->func);
442037b3c26Smrg				printf(" vendor_id:%04x",
443037b3c26Smrg					device->deviceinfo.pci->vendor_id);
444037b3c26Smrg				printf(" device_id:%04x",
445037b3c26Smrg					device->deviceinfo.pci->device_id);
446037b3c26Smrg				printf(" subvendor_id:%04x",
447037b3c26Smrg					device->deviceinfo.pci->subvendor_id);
448037b3c26Smrg				printf(" subdevice_id:%04x",
449037b3c26Smrg					device->deviceinfo.pci->subdevice_id);
450037b3c26Smrg				printf(" revision_id:%02x",
451037b3c26Smrg					device->deviceinfo.pci->revision_id);
452037b3c26Smrg				printf("\n");
453037b3c26Smrg			}
454037b3c26Smrg			drmFreeDevice(&device);
455037b3c26Smrg		}
456037b3c26Smrg}
457037b3c26Smrg
458037b3c26Smrg/* Find a match AMD device in PCI bus
459037b3c26Smrg * Return the index of the device or -1 if not found
460037b3c26Smrg */
461d8807b2fSmrgstatic int amdgpu_find_device(uint8_t bus, uint16_t dev)
462037b3c26Smrg{
463037b3c26Smrg	int i;
464037b3c26Smrg	drmDevicePtr device;
465037b3c26Smrg
466d8807b2fSmrg	for (i = 0; i < MAX_CARDS_SUPPORTED && drm_amdgpu[i] >= 0; i++) {
467037b3c26Smrg		if (drmGetDevice2(drm_amdgpu[i],
468037b3c26Smrg			DRM_DEVICE_GET_PCI_REVISION,
469037b3c26Smrg			&device) == 0) {
470037b3c26Smrg			if (device->bustype == DRM_BUS_PCI)
471d8807b2fSmrg				if ((bus == 0xFF || device->businfo.pci->bus == bus) &&
472d8807b2fSmrg					device->deviceinfo.pci->device_id == dev) {
473037b3c26Smrg					drmFreeDevice(&device);
474037b3c26Smrg					return i;
475037b3c26Smrg				}
476037b3c26Smrg
477037b3c26Smrg			drmFreeDevice(&device);
478037b3c26Smrg		}
479d8807b2fSmrg	}
480037b3c26Smrg
481037b3c26Smrg	return -1;
482037b3c26Smrg}
4833f012e29Smrg
48400a23bdaSmrgstatic void amdgpu_disable_suites()
48500a23bdaSmrg{
48600a23bdaSmrg	amdgpu_device_handle device_handle;
48700a23bdaSmrg	uint32_t major_version, minor_version, family_id;
4884babd585Smrg	drmDevicePtr devices[MAX_CARDS_SUPPORTED];
4894babd585Smrg	int i, drm_count;
49000a23bdaSmrg	int size = sizeof(suites_active_stat) / sizeof(suites_active_stat[0]);
49100a23bdaSmrg
49200a23bdaSmrg	if (amdgpu_device_initialize(drm_amdgpu[0], &major_version,
49300a23bdaSmrg				   &minor_version, &device_handle))
49400a23bdaSmrg		return;
49500a23bdaSmrg
49600a23bdaSmrg	family_id = device_handle->info.family_id;
49700a23bdaSmrg
49800a23bdaSmrg	if (amdgpu_device_deinitialize(device_handle))
49900a23bdaSmrg		return;
50000a23bdaSmrg
5014babd585Smrg	drm_count = drmGetDevices2(0, devices, MAX_CARDS_SUPPORTED);
5024babd585Smrg
50300a23bdaSmrg	/* Set active status for suites based on their policies */
50400a23bdaSmrg	for (i = 0; i < size; ++i)
50500a23bdaSmrg		if (amdgpu_set_suite_active(suites_active_stat[i].pName,
50600a23bdaSmrg				suites_active_stat[i].pActive()))
50700a23bdaSmrg			fprintf(stderr, "suite deactivation failed - %s\n", CU_get_error_msg());
50800a23bdaSmrg
50900a23bdaSmrg	/* Explicitly disable specific tests due to known bugs or preferences */
51000a23bdaSmrg	/*
51100a23bdaSmrg	* BUG: Compute ring stalls and never recovers when the address is
51200a23bdaSmrg	* written after the command already submitted
51300a23bdaSmrg	*/
5146532f28eSmrg	if (amdgpu_set_test_active(DEADLOCK_TESTS_STR,
5156532f28eSmrg			"compute ring block test (set amdgpu.lockup_timeout=50)", CU_FALSE))
51600a23bdaSmrg		fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg());
51700a23bdaSmrg
5185324fb0dSmrg	if (amdgpu_set_test_active(DEADLOCK_TESTS_STR,
5195324fb0dSmrg				"sdma ring block test (set amdgpu.lockup_timeout=50)", CU_FALSE))
5205324fb0dSmrg		fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg());
5215324fb0dSmrg
5229bd392adSmrg	/* This test was ran on GFX9 only */
5239bd392adSmrg	//if (family_id < AMDGPU_FAMILY_AI || family_id > AMDGPU_FAMILY_RV)
5249bd392adSmrg		if (amdgpu_set_test_active(DEADLOCK_TESTS_STR,
5259bd392adSmrg				"gfx ring bad dispatch test (set amdgpu.lockup_timeout=50)", CU_FALSE))
5269bd392adSmrg			fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg());
5279bd392adSmrg
5289bd392adSmrg	/* This test was ran on GFX9 only */
5299bd392adSmrg	//if (family_id < AMDGPU_FAMILY_AI || family_id > AMDGPU_FAMILY_RV)
5309bd392adSmrg		if (amdgpu_set_test_active(DEADLOCK_TESTS_STR,
5319bd392adSmrg				"compute ring bad dispatch test (set amdgpu.lockup_timeout=50,50)", CU_FALSE))
5329bd392adSmrg			fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg());
5339bd392adSmrg
5349bd392adSmrg	/* This test was ran on GFX9 only */
5359bd392adSmrg	//if (family_id < AMDGPU_FAMILY_AI || family_id > AMDGPU_FAMILY_RV)
5369bd392adSmrg		if (amdgpu_set_test_active(DEADLOCK_TESTS_STR,
5379bd392adSmrg				"gfx ring bad slow dispatch test (set amdgpu.lockup_timeout=50)", CU_FALSE))
5389bd392adSmrg			fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg());
5399bd392adSmrg
5409bd392adSmrg	/* This test was ran on GFX9 only */
5419bd392adSmrg	//if (family_id < AMDGPU_FAMILY_AI || family_id > AMDGPU_FAMILY_RV)
5429bd392adSmrg		if (amdgpu_set_test_active(DEADLOCK_TESTS_STR,
5439bd392adSmrg				"compute ring bad slow dispatch test (set amdgpu.lockup_timeout=50,50)", CU_FALSE))
5449bd392adSmrg			fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg());
5459bd392adSmrg
5469bd392adSmrg	//if (family_id < AMDGPU_FAMILY_AI || family_id > AMDGPU_FAMILY_RV)
5479bd392adSmrg		if (amdgpu_set_test_active(DEADLOCK_TESTS_STR,
5489bd392adSmrg				"gfx ring bad draw test (set amdgpu.lockup_timeout=50)", CU_FALSE))
5499bd392adSmrg			fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg());
5509bd392adSmrg
5519bd392adSmrg	/* This test was ran on GFX9 only */
5529bd392adSmrg	//if (family_id < AMDGPU_FAMILY_AI || family_id > AMDGPU_FAMILY_RV)
5539bd392adSmrg		if (amdgpu_set_test_active(DEADLOCK_TESTS_STR,
5549bd392adSmrg				"gfx ring slow bad draw test (set amdgpu.lockup_timeout=50)", CU_FALSE))
5559bd392adSmrg			fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg());
556b0ab5608Smrg
557b0ab5608Smrg	if (amdgpu_set_test_active(DEADLOCK_TESTS_STR,
558b0ab5608Smrg			"sdma ring corrupted header test (set amdgpu.lockup_timeout=50)", CU_FALSE))
559b0ab5608Smrg		fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg());
560b0ab5608Smrg
561b0ab5608Smrg	if (amdgpu_set_test_active(DEADLOCK_TESTS_STR,
562b0ab5608Smrg			"sdma ring slow linear copy test (set amdgpu.lockup_timeout=50)", CU_FALSE))
563b0ab5608Smrg		fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg());
5649bd392adSmrg
5654babd585Smrg	if (amdgpu_set_test_active(BASIC_TESTS_STR, "bo eviction Test", CU_FALSE))
5664babd585Smrg		fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg());
5674babd585Smrg
56800a23bdaSmrg	/* This test was ran on GFX8 and GFX9 only */
56900a23bdaSmrg	if (family_id < AMDGPU_FAMILY_VI || family_id > AMDGPU_FAMILY_RV)
57000a23bdaSmrg		if (amdgpu_set_test_active(BASIC_TESTS_STR, "Sync dependency Test", CU_FALSE))
57100a23bdaSmrg			fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg());
5725324fb0dSmrg
5735324fb0dSmrg	/* This test was ran on GFX9 only */
57488f8a8d2Smrg	if (family_id < AMDGPU_FAMILY_AI || family_id > AMDGPU_FAMILY_RV) {
57588f8a8d2Smrg		if (amdgpu_set_test_active(BASIC_TESTS_STR, "Dispatch Test (GFX)", CU_FALSE))
57688f8a8d2Smrg			fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg());
57788f8a8d2Smrg		if (amdgpu_set_test_active(BASIC_TESTS_STR, "Dispatch Test (Compute)", CU_FALSE))
5785324fb0dSmrg			fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg());
57988f8a8d2Smrg	}
5805324fb0dSmrg
5815324fb0dSmrg	/* This test was ran on GFX9 only */
5825324fb0dSmrg	if (family_id < AMDGPU_FAMILY_AI || family_id > AMDGPU_FAMILY_RV)
5835324fb0dSmrg		if (amdgpu_set_test_active(BASIC_TESTS_STR, "Draw Test", CU_FALSE))
5845324fb0dSmrg			fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg());
58588f8a8d2Smrg
58688f8a8d2Smrg	/* This test was ran on GFX9 only */
58788f8a8d2Smrg	//if (family_id < AMDGPU_FAMILY_AI || family_id > AMDGPU_FAMILY_RV)
58888f8a8d2Smrg		if (amdgpu_set_test_active(BASIC_TESTS_STR, "GPU reset Test", CU_FALSE))
58988f8a8d2Smrg			fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg());
5904babd585Smrg
5914babd585Smrg	/* You need at least 2 devices for this	*/
5924babd585Smrg	if (drm_count < 2)
5934babd585Smrg		if (amdgpu_set_test_active(HOTUNPLUG_TESTS_STR, "Unplug with exported fence", CU_FALSE))
5944babd585Smrg			fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg());
5954babd585Smrg}
5964babd585Smrg
5974babd585Smrgint test_device_index;
5984babd585Smrg
5994babd585Smrgint amdgpu_open_device_on_test_index(int render_node)
6004babd585Smrg{
6014babd585Smrg	int i;
6024babd585Smrg
6034babd585Smrg	if (amdgpu_open_devices(open_render_node) <= 0) {
6044babd585Smrg		perror("Cannot open AMDGPU device");
6054babd585Smrg		return -1;
6064babd585Smrg	}
6074babd585Smrg
6084babd585Smrg	if (test_device_index >= 0) {
6094babd585Smrg		/* Most tests run on device of drm_amdgpu[0].
6104babd585Smrg		 * Swap the chosen device to drm_amdgpu[0].
6114babd585Smrg		 */
6124babd585Smrg		i = drm_amdgpu[0];
6134babd585Smrg		drm_amdgpu[0] = drm_amdgpu[test_device_index];
6144babd585Smrg		drm_amdgpu[test_device_index] = i;
6154babd585Smrg	}
6164babd585Smrg
6174babd585Smrg	return 0;
6184babd585Smrg
6194babd585Smrg
6204babd585Smrg}
6214babd585Smrg
6224babd585Smrg
6234babd585Smrgstatic bool amdgpu_node_is_drm(int maj, int min)
6244babd585Smrg{
6254babd585Smrg#ifdef __linux__
6264babd585Smrg    char path[64];
6274babd585Smrg    struct stat sbuf;
6284babd585Smrg
6294babd585Smrg    snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device/drm",
6304babd585Smrg             maj, min);
6314babd585Smrg    return stat(path, &sbuf) == 0;
6324babd585Smrg#elif defined(__FreeBSD__)
6334babd585Smrg    char name[SPECNAMELEN];
6344babd585Smrg
6354babd585Smrg    if (!devname_r(makedev(maj, min), S_IFCHR, name, sizeof(name)))
6364babd585Smrg      return 0;
6374babd585Smrg    /* Handle drm/ and dri/ as both are present in different FreeBSD version
6384babd585Smrg     * FreeBSD on amd64/i386/powerpc external kernel modules create node in
6394babd585Smrg     * in /dev/drm/ and links in /dev/dri while a WIP in kernel driver creates
6404babd585Smrg     * only device nodes in /dev/dri/ */
6414babd585Smrg    return (!strncmp(name, "drm/", 4) || !strncmp(name, "dri/", 4));
6424babd585Smrg#else
6434babd585Smrg    return maj == DRM_MAJOR;
6444babd585Smrg#endif
6454babd585Smrg}
6464babd585Smrg
6474babd585Smrgchar *amdgpu_get_device_from_fd(int fd)
6484babd585Smrg{
6494babd585Smrg#ifdef __linux__
6504babd585Smrg    struct stat sbuf;
6514babd585Smrg    char path[PATH_MAX + 1];
6524babd585Smrg    unsigned int maj, min;
6534babd585Smrg
6544babd585Smrg    if (fstat(fd, &sbuf))
6554babd585Smrg        return NULL;
6564babd585Smrg
6574babd585Smrg    maj = major(sbuf.st_rdev);
6584babd585Smrg    min = minor(sbuf.st_rdev);
6594babd585Smrg
6604babd585Smrg    if (!amdgpu_node_is_drm(maj, min) || !S_ISCHR(sbuf.st_mode))
6614babd585Smrg        return NULL;
6624babd585Smrg
6634babd585Smrg    snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min);
6644babd585Smrg    return strdup(path);
6654babd585Smrg#else
6664babd585Smrg    return NULL;
6674babd585Smrg#endif
66800a23bdaSmrg}
66900a23bdaSmrg
670bbff01ceSmrg#ifndef ARRAY_SIZE
671bbff01ceSmrg#define ARRAY_SIZE(_A) (sizeof(_A)/sizeof(_A[0]))
672bbff01ceSmrg#endif
673bbff01ceSmrg
674bbff01ceSmrgstatic void amdgpu_test_disable(long suite, long test)
675bbff01ceSmrg{
676bbff01ceSmrg	const char *suite_name;
677bbff01ceSmrg
678bbff01ceSmrg	if (suite < 1)
679bbff01ceSmrg		return;
680bbff01ceSmrg
681bbff01ceSmrg	/* The array is 0-based, so subract 1. */
682bbff01ceSmrg	suite--;
683bbff01ceSmrg	if (suite >= ARRAY_SIZE(suites) - 1)
684bbff01ceSmrg		return;
685bbff01ceSmrg
686bbff01ceSmrg	suite_name = suites[suite].pName;
687bbff01ceSmrg	if (test < 1) {
688bbff01ceSmrg		fprintf(stderr, "Deactivating suite %s\n", suite_name);
689bbff01ceSmrg		amdgpu_set_suite_active(suite_name, CU_FALSE);
690bbff01ceSmrg	} else {
691bbff01ceSmrg		int ii;
692bbff01ceSmrg
693bbff01ceSmrg		/* The array is 0-based so subtract 1. */
694bbff01ceSmrg		test--;
695bbff01ceSmrg		for (ii = 0; suites[suite].pTests[ii].pName; ii++) {
696bbff01ceSmrg			if (ii == test) {
697bbff01ceSmrg				fprintf(stderr, "Deactivating %s:%s\n",
698bbff01ceSmrg					suite_name,
699bbff01ceSmrg					suites[suite].pTests[ii].pName);
700bbff01ceSmrg				amdgpu_set_test_active(suite_name,
701bbff01ceSmrg						       suites[suite].pTests[ii].pName,
702bbff01ceSmrg						       CU_FALSE);
703bbff01ceSmrg				break;
704bbff01ceSmrg			}
705bbff01ceSmrg		}
706bbff01ceSmrg
707bbff01ceSmrg		if (suites[suite].pTests[ii].pName == NULL)
708bbff01ceSmrg			fprintf(stderr, "No such suite.test %ld.%ld\n", suite, test);
709bbff01ceSmrg	}
710bbff01ceSmrg}
711bbff01ceSmrg
7123f012e29Smrg/* The main() function for setting up and running the tests.
7133f012e29Smrg * Returns a CUE_SUCCESS on successful running, another
7143f012e29Smrg * CUnit error code on failure.
7153f012e29Smrg */
7163f012e29Smrgint main(int argc, char **argv)
7173f012e29Smrg{
7183f012e29Smrg	int c;			/* Character received from getopt */
7193f012e29Smrg	int i = 0;
7203f012e29Smrg	int suite_id = -1;	/* By default run everything */
7213f012e29Smrg	int test_id  = -1;	/* By default run all tests in the suite */
722037b3c26Smrg	int pci_bus_id = -1;    /* By default PC bus ID is not specified */
723037b3c26Smrg	int pci_device_id = 0;  /* By default PC device ID is zero */
724037b3c26Smrg	int display_devices = 0;/* By default not to display devices' info */
7253f012e29Smrg	CU_pSuite pSuite = NULL;
7263f012e29Smrg	CU_pTest  pTest  = NULL;
72700a23bdaSmrg	int display_list = 0;
72800a23bdaSmrg	int force_run = 0;
7293f012e29Smrg
730bbff01ceSmrg	/* Parse command line string.
731bbff01ceSmrg	 * Process various command line options as early as possible.
732bbff01ceSmrg	 */
7333f012e29Smrg	opterr = 0;		/* Do not print error messages from getopt */
7343f012e29Smrg	while ((c = getopt(argc, argv, options)) != -1) {
7353f012e29Smrg		switch (c) {
7363f012e29Smrg		case 'h':
7373f012e29Smrg			fprintf(stderr, usage, argv[0]);
7383f012e29Smrg			exit(EXIT_SUCCESS);
7393f012e29Smrg		}
7403f012e29Smrg	}
7413f012e29Smrg
742bbff01ceSmrg	for (i = 0; i < MAX_CARDS_SUPPORTED; i++)
743bbff01ceSmrg		drm_amdgpu[i] = -1;
744bbff01ceSmrg
745037b3c26Smrg	if (amdgpu_open_devices(open_render_node) <= 0) {
746037b3c26Smrg		perror("Cannot open AMDGPU device");
7473f012e29Smrg		exit(EXIT_FAILURE);
7483f012e29Smrg	}
7493f012e29Smrg
750037b3c26Smrg	if (drm_amdgpu[0] < 0) {
751037b3c26Smrg		perror("Cannot open AMDGPU device");
7523f012e29Smrg		exit(EXIT_FAILURE);
7533f012e29Smrg	}
7543f012e29Smrg
755bbff01ceSmrg	/* Parse command line string */
756bbff01ceSmrg	opterr = 0;		/* Do not print error messages from getopt */
757bbff01ceSmrg	optind = 1;
758bbff01ceSmrg	while ((c = getopt(argc, argv, options)) != -1) {
759bbff01ceSmrg		switch (c) {
760bbff01ceSmrg		case 'p':
761bbff01ceSmrg			display_devices = 1;
762bbff01ceSmrg			break;
763bbff01ceSmrg		}
764bbff01ceSmrg	}
765bbff01ceSmrg
766037b3c26Smrg	if (display_devices) {
767037b3c26Smrg		amdgpu_print_devices();
768037b3c26Smrg		amdgpu_close_devices();
769037b3c26Smrg		exit(EXIT_SUCCESS);
770037b3c26Smrg	}
7713f012e29Smrg
772bbff01ceSmrg	/* Parse command line string */
773bbff01ceSmrg	opterr = 0;		/* Do not print error messages from getopt */
774bbff01ceSmrg	optind = 1;
775bbff01ceSmrg	while ((c = getopt(argc, argv, options)) != -1) {
776bbff01ceSmrg		switch (c) {
777bbff01ceSmrg		case 'b':
778bbff01ceSmrg			pci_bus_id = atoi(optarg);
779bbff01ceSmrg			break;
780bbff01ceSmrg		case 'd':
781bbff01ceSmrg			sscanf(optarg, "%x", &pci_device_id);
782bbff01ceSmrg			break;
783bbff01ceSmrg		}
784bbff01ceSmrg	}
785bbff01ceSmrg
786d8807b2fSmrg	if (pci_bus_id > 0 || pci_device_id) {
787037b3c26Smrg		/* A device was specified to run the test */
788d8807b2fSmrg		test_device_index = amdgpu_find_device(pci_bus_id,
789d8807b2fSmrg						       pci_device_id);
790037b3c26Smrg
791037b3c26Smrg		if (test_device_index >= 0) {
792037b3c26Smrg			/* Most tests run on device of drm_amdgpu[0].
793037b3c26Smrg			 * Swap the chosen device to drm_amdgpu[0].
794037b3c26Smrg			 */
795037b3c26Smrg			i = drm_amdgpu[0];
796037b3c26Smrg			drm_amdgpu[0] = drm_amdgpu[test_device_index];
797037b3c26Smrg			drm_amdgpu[test_device_index] = i;
798037b3c26Smrg		} else {
799037b3c26Smrg			fprintf(stderr,
800037b3c26Smrg				"The specified GPU device does not exist.\n");
801037b3c26Smrg			exit(EXIT_FAILURE);
802037b3c26Smrg		}
803037b3c26Smrg	}
8043f012e29Smrg
8053f012e29Smrg	/* Initialize test suites to run */
8063f012e29Smrg
8073f012e29Smrg	/* initialize the CUnit test registry */
8083f012e29Smrg	if (CUE_SUCCESS != CU_initialize_registry()) {
809037b3c26Smrg		amdgpu_close_devices();
8103f012e29Smrg		return CU_get_error();
8113f012e29Smrg	}
8123f012e29Smrg
8133f012e29Smrg	/* Register suites. */
8143f012e29Smrg	if (CU_register_suites(suites) != CUE_SUCCESS) {
8153f012e29Smrg		fprintf(stderr, "suite registration failed - %s\n",
8163f012e29Smrg				CU_get_error_msg());
8173f012e29Smrg		CU_cleanup_registry();
818037b3c26Smrg		amdgpu_close_devices();
8193f012e29Smrg		exit(EXIT_FAILURE);
8203f012e29Smrg	}
8213f012e29Smrg
8223f012e29Smrg	/* Run tests using the CUnit Basic interface */
8233f012e29Smrg	CU_basic_set_mode(CU_BRM_VERBOSE);
8243f012e29Smrg
82500a23bdaSmrg	/* Disable suites and individual tests based on misc. conditions */
82600a23bdaSmrg	amdgpu_disable_suites();
82700a23bdaSmrg
828bbff01ceSmrg	/* Parse command line string */
829bbff01ceSmrg	opterr = 0;		/* Do not print error messages from getopt */
830bbff01ceSmrg	optind = 1;
831bbff01ceSmrg	while ((c = getopt(argc, argv, options)) != -1) {
832bbff01ceSmrg		switch (c) {
833bbff01ceSmrg		case 'l':
834bbff01ceSmrg			display_list = 1;
835bbff01ceSmrg			break;
836bbff01ceSmrg		}
837bbff01ceSmrg	}
838bbff01ceSmrg
83900a23bdaSmrg	if (display_list) {
84000a23bdaSmrg		display_test_suites();
84100a23bdaSmrg		goto end;
84200a23bdaSmrg	}
84300a23bdaSmrg
844bbff01ceSmrg	/* Parse command line string */
845bbff01ceSmrg	opterr = 0;		/* Do not print error messages from getopt */
846bbff01ceSmrg	optind = 1;
847bbff01ceSmrg	while ((c = getopt(argc, argv, options)) != -1) {
848bbff01ceSmrg		long esuite = -1;
849bbff01ceSmrg		long etest = -1;
850bbff01ceSmrg		char *endp;
851bbff01ceSmrg		switch (c) {
852bbff01ceSmrg		case 's':
853bbff01ceSmrg			suite_id = atoi(optarg);
854bbff01ceSmrg			break;
855bbff01ceSmrg		case 't':
856bbff01ceSmrg			test_id = atoi(optarg);
857bbff01ceSmrg			break;
858bbff01ceSmrg		case 'r':
859bbff01ceSmrg                       open_render_node = 1;
860bbff01ceSmrg                       break;
861bbff01ceSmrg		case 'f':
862bbff01ceSmrg			force_run = 1;
863bbff01ceSmrg			break;
864bbff01ceSmrg		case 'e':
865bbff01ceSmrg			esuite = strtol(optarg, &endp, 0);
866bbff01ceSmrg			if (endp == optarg) {
867bbff01ceSmrg				fprintf(stderr, "No digits given for -e argument\n");
868bbff01ceSmrg				goto end;
869bbff01ceSmrg			} else if (endp && *endp == '.' && esuite > 0) {
870bbff01ceSmrg				char *tt = endp + 1;
871bbff01ceSmrg				etest = strtol(tt, &endp, 0);
872bbff01ceSmrg				if (endp == tt) {
873bbff01ceSmrg					fprintf(stderr, "No digits given for test in -e s.t argument\n");
874bbff01ceSmrg					goto end;
875bbff01ceSmrg				} else if (endp && *endp != '\0') {
876bbff01ceSmrg					fprintf(stderr, "Bad input given for test in -e s.t argument\n");
877bbff01ceSmrg					goto end;
878bbff01ceSmrg				} else if (etest < 1) {
879bbff01ceSmrg					fprintf(stderr, "Test in -e s.t argument cannot be smaller than 1\n");
880bbff01ceSmrg					goto end;
881bbff01ceSmrg				}
882bbff01ceSmrg			} else if (endp && *endp != '\0') {
883bbff01ceSmrg				fprintf(stderr, "Bad input given for suite for -e s argument\n");
884bbff01ceSmrg				goto end;
885bbff01ceSmrg			} else if (esuite < 1) {
886bbff01ceSmrg				fprintf(stderr, "Suite in -e s argument cannot be smaller than 1\n");
887bbff01ceSmrg				goto end;
888bbff01ceSmrg			}
889bbff01ceSmrg			amdgpu_test_disable(esuite, etest);
890bbff01ceSmrg			break;
891bbff01ceSmrg		case 'h':
892bbff01ceSmrg		case 'p':
893bbff01ceSmrg		case 'b':
894bbff01ceSmrg		case 'd':
895bbff01ceSmrg		case 'l':
896bbff01ceSmrg			/* Those have been processed earlier.
897bbff01ceSmrg			 */
898bbff01ceSmrg			break;
899bbff01ceSmrg		case '?':
900bbff01ceSmrg		default:
901bbff01ceSmrg			fprintf(stderr, "Unknown command line option '%c'. Try -h.\n",
902bbff01ceSmrg				c == '?' ? optopt : c);
903bbff01ceSmrg			goto end;
904bbff01ceSmrg		}
905bbff01ceSmrg	}
906bbff01ceSmrg
9073f012e29Smrg	if (suite_id != -1) {	/* If user specify particular suite? */
9083f012e29Smrg		pSuite = CU_get_suite_by_index((unsigned int) suite_id,
9093f012e29Smrg						CU_get_registry());
9103f012e29Smrg
9113f012e29Smrg		if (pSuite) {
91200a23bdaSmrg
91300a23bdaSmrg			if (force_run)
91400a23bdaSmrg				CU_set_suite_active(pSuite, CU_TRUE);
91500a23bdaSmrg
9163f012e29Smrg			if (test_id != -1) {   /* If user specify test id */
9173f012e29Smrg				pTest = CU_get_test_by_index(
9183f012e29Smrg						(unsigned int) test_id,
9193f012e29Smrg						pSuite);
92000a23bdaSmrg				if (pTest) {
92100a23bdaSmrg					if (force_run)
92200a23bdaSmrg						CU_set_test_active(pTest, CU_TRUE);
92300a23bdaSmrg
9243f012e29Smrg					CU_basic_run_test(pSuite, pTest);
92500a23bdaSmrg				}
9263f012e29Smrg				else {
9273f012e29Smrg					fprintf(stderr, "Invalid test id: %d\n",
9283f012e29Smrg								test_id);
9293f012e29Smrg					CU_cleanup_registry();
930037b3c26Smrg					amdgpu_close_devices();
9313f012e29Smrg					exit(EXIT_FAILURE);
9323f012e29Smrg				}
9333f012e29Smrg			} else
9343f012e29Smrg				CU_basic_run_suite(pSuite);
9353f012e29Smrg		} else {
9363f012e29Smrg			fprintf(stderr, "Invalid suite id : %d\n",
9373f012e29Smrg					suite_id);
9383f012e29Smrg			CU_cleanup_registry();
939037b3c26Smrg			amdgpu_close_devices();
9403f012e29Smrg			exit(EXIT_FAILURE);
9413f012e29Smrg		}
9423f012e29Smrg	} else
9433f012e29Smrg		CU_basic_run_tests();
9443f012e29Smrg
94500a23bdaSmrgend:
9463f012e29Smrg	CU_cleanup_registry();
947037b3c26Smrg	amdgpu_close_devices();
9483f012e29Smrg	return CU_get_error();
9493f012e29Smrg}
950