mirror of
https://gitlab.freedesktop.org/mesa/drm.git
synced 2025-12-20 16:20:11 +01:00
The test is as following: 1) Create context A & B 2) Send a command submission using context A which fires up a compute shader. 3) The shader wait a bit and then write a value to a memory location. 4) Send a command submission using context B which writes another value to the same memory location, but having an explicit dependency on the first command submission. 5) Wait with the CPU for both submissions to finish and inspect the written value. Test passes if the value seen in the memory location after both submissions is from command B. Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@amd.com> Acked-by: Christian König <christian.koenig@amd.com>
609 lines
15 KiB
C
609 lines
15 KiB
C
/*
|
|
* Copyright 2014 Advanced Micro Devices, Inc.
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
* to deal in the Software without restriction, including without limitation
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
* OTHER DEALINGS IN THE SOFTWARE.
|
|
*
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include <fcntl.h>
|
|
#include <errno.h>
|
|
#include <signal.h>
|
|
#include <time.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/ioctl.h>
|
|
#include <sys/time.h>
|
|
#include <stdarg.h>
|
|
#include <stdint.h>
|
|
|
|
#include "drm.h"
|
|
#include "xf86drmMode.h"
|
|
#include "xf86drm.h"
|
|
|
|
#include "CUnit/Basic.h"
|
|
|
|
#include "amdgpu_test.h"
|
|
#include "amdgpu_internal.h"
|
|
|
|
/* Test suit names */
|
|
#define BASIC_TESTS_STR "Basic Tests"
|
|
#define BO_TESTS_STR "BO Tests"
|
|
#define CS_TESTS_STR "CS Tests"
|
|
#define VCE_TESTS_STR "VCE Tests"
|
|
#define VCN_TESTS_STR "VCN Tests"
|
|
#define UVD_ENC_TESTS_STR "UVD ENC Tests"
|
|
#define DEADLOCK_TESTS_STR "Deadlock Tests"
|
|
#define VM_TESTS_STR "VM Tests"
|
|
|
|
/**
|
|
* Open handles for amdgpu devices
|
|
*
|
|
*/
|
|
int drm_amdgpu[MAX_CARDS_SUPPORTED];
|
|
|
|
/** Open render node to test */
|
|
int open_render_node = 0; /* By default run most tests on primary node */
|
|
|
|
/** The table of all known test suites to run */
|
|
static CU_SuiteInfo suites[] = {
|
|
{
|
|
.pName = BASIC_TESTS_STR,
|
|
.pInitFunc = suite_basic_tests_init,
|
|
.pCleanupFunc = suite_basic_tests_clean,
|
|
.pTests = basic_tests,
|
|
},
|
|
{
|
|
.pName = BO_TESTS_STR,
|
|
.pInitFunc = suite_bo_tests_init,
|
|
.pCleanupFunc = suite_bo_tests_clean,
|
|
.pTests = bo_tests,
|
|
},
|
|
{
|
|
.pName = CS_TESTS_STR,
|
|
.pInitFunc = suite_cs_tests_init,
|
|
.pCleanupFunc = suite_cs_tests_clean,
|
|
.pTests = cs_tests,
|
|
},
|
|
{
|
|
.pName = VCE_TESTS_STR,
|
|
.pInitFunc = suite_vce_tests_init,
|
|
.pCleanupFunc = suite_vce_tests_clean,
|
|
.pTests = vce_tests,
|
|
},
|
|
{
|
|
.pName = VCN_TESTS_STR,
|
|
.pInitFunc = suite_vcn_tests_init,
|
|
.pCleanupFunc = suite_vcn_tests_clean,
|
|
.pTests = vcn_tests,
|
|
},
|
|
{
|
|
.pName = UVD_ENC_TESTS_STR,
|
|
.pInitFunc = suite_uvd_enc_tests_init,
|
|
.pCleanupFunc = suite_uvd_enc_tests_clean,
|
|
.pTests = uvd_enc_tests,
|
|
},
|
|
{
|
|
.pName = DEADLOCK_TESTS_STR,
|
|
.pInitFunc = suite_deadlock_tests_init,
|
|
.pCleanupFunc = suite_deadlock_tests_clean,
|
|
.pTests = deadlock_tests,
|
|
},
|
|
{
|
|
.pName = VM_TESTS_STR,
|
|
.pInitFunc = suite_vm_tests_init,
|
|
.pCleanupFunc = suite_vm_tests_clean,
|
|
.pTests = vm_tests,
|
|
},
|
|
|
|
CU_SUITE_INFO_NULL,
|
|
};
|
|
|
|
typedef CU_BOOL (*active__stat_func)(void);
|
|
|
|
typedef struct Suites_Active_Status {
|
|
char* pName;
|
|
active__stat_func pActive;
|
|
}Suites_Active_Status;
|
|
|
|
static CU_BOOL always_active()
|
|
{
|
|
return CU_TRUE;
|
|
}
|
|
|
|
static Suites_Active_Status suites_active_stat[] = {
|
|
{
|
|
.pName = BASIC_TESTS_STR,
|
|
.pActive = always_active,
|
|
},
|
|
{
|
|
.pName = BO_TESTS_STR,
|
|
.pActive = always_active,
|
|
},
|
|
{
|
|
.pName = CS_TESTS_STR,
|
|
.pActive = suite_cs_tests_enable,
|
|
},
|
|
{
|
|
.pName = VCE_TESTS_STR,
|
|
.pActive = suite_vce_tests_enable,
|
|
},
|
|
{
|
|
.pName = VCN_TESTS_STR,
|
|
.pActive = suite_vcn_tests_enable,
|
|
},
|
|
{
|
|
.pName = UVD_ENC_TESTS_STR,
|
|
.pActive = suite_uvd_enc_tests_enable,
|
|
},
|
|
{
|
|
.pName = DEADLOCK_TESTS_STR,
|
|
.pActive = suite_deadlock_tests_enable,
|
|
},
|
|
{
|
|
.pName = VM_TESTS_STR,
|
|
.pActive = always_active,
|
|
},
|
|
};
|
|
|
|
|
|
/*
|
|
* Display information about all suites and their tests
|
|
*
|
|
* NOTE: Must be run after registry is initialized and suites registered.
|
|
*/
|
|
static void display_test_suites(void)
|
|
{
|
|
int iSuite;
|
|
int iTest;
|
|
CU_pSuite pSuite = NULL;
|
|
CU_pTest pTest = NULL;
|
|
|
|
printf("Suites\n");
|
|
|
|
for (iSuite = 0; suites[iSuite].pName != NULL; iSuite++) {
|
|
|
|
pSuite = CU_get_suite_by_index((unsigned int) iSuite + 1,
|
|
CU_get_registry());
|
|
|
|
if (!pSuite) {
|
|
fprintf(stderr, "Invalid suite id : %d\n", iSuite + 1);
|
|
continue;
|
|
}
|
|
|
|
printf("Suite id = %d: Name '%s status: %s'\n",
|
|
iSuite + 1, suites[iSuite].pName,
|
|
pSuite->fActive ? "ENABLED" : "DISABLED");
|
|
|
|
|
|
|
|
for (iTest = 0; suites[iSuite].pTests[iTest].pName != NULL;
|
|
iTest++) {
|
|
|
|
pTest = CU_get_test_by_index((unsigned int) iTest + 1,
|
|
pSuite);
|
|
|
|
if (!pTest) {
|
|
fprintf(stderr, "Invalid test id : %d\n", iTest + 1);
|
|
continue;
|
|
}
|
|
|
|
printf("Test id %d: Name: '%s status: %s'\n", iTest + 1,
|
|
suites[iSuite].pTests[iTest].pName,
|
|
pSuite->fActive && pTest->fActive ?
|
|
"ENABLED" : "DISABLED");
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/** Help string for command line parameters */
|
|
static const char usage[] =
|
|
"Usage: %s [-hlpr] [<-s <suite id>> [-t <test id>] [-f]] "
|
|
"[-b <pci_bus_id> [-d <pci_device_id>]]\n"
|
|
"where:\n"
|
|
" l - Display all suites and their tests\n"
|
|
" r - Run the tests on render node\n"
|
|
" b - Specify device's PCI bus id to run tests\n"
|
|
" d - Specify device's PCI device id to run tests (optional)\n"
|
|
" p - Display information of AMDGPU devices in system\n"
|
|
" f - Force executing inactive suite or test\n"
|
|
" h - Display this help\n";
|
|
/** Specified options strings for getopt */
|
|
static const char options[] = "hlrps:t:b:d:f";
|
|
|
|
/* Open AMD devices.
|
|
* Return the number of AMD device openned.
|
|
*/
|
|
static int amdgpu_open_devices(int open_render_node)
|
|
{
|
|
drmDevicePtr devices[MAX_CARDS_SUPPORTED];
|
|
int ret;
|
|
int i;
|
|
int drm_node;
|
|
int amd_index = 0;
|
|
int drm_count;
|
|
int fd;
|
|
drmVersionPtr version;
|
|
|
|
drm_count = drmGetDevices2(0, devices, MAX_CARDS_SUPPORTED);
|
|
|
|
if (drm_count < 0) {
|
|
fprintf(stderr,
|
|
"drmGetDevices2() returned an error %d\n",
|
|
drm_count);
|
|
return 0;
|
|
}
|
|
|
|
for (i = 0; i < drm_count; i++) {
|
|
/* If this is not PCI device, skip*/
|
|
if (devices[i]->bustype != DRM_BUS_PCI)
|
|
continue;
|
|
|
|
/* If this is not AMD GPU vender ID, skip*/
|
|
if (devices[i]->deviceinfo.pci->vendor_id != 0x1002)
|
|
continue;
|
|
|
|
if (open_render_node)
|
|
drm_node = DRM_NODE_RENDER;
|
|
else
|
|
drm_node = DRM_NODE_PRIMARY;
|
|
|
|
fd = -1;
|
|
if (devices[i]->available_nodes & 1 << drm_node)
|
|
fd = open(
|
|
devices[i]->nodes[drm_node],
|
|
O_RDWR | O_CLOEXEC);
|
|
|
|
/* This node is not available. */
|
|
if (fd < 0) continue;
|
|
|
|
version = drmGetVersion(fd);
|
|
if (!version) {
|
|
fprintf(stderr,
|
|
"Warning: Cannot get version for %s."
|
|
"Error is %s\n",
|
|
devices[i]->nodes[drm_node],
|
|
strerror(errno));
|
|
close(fd);
|
|
continue;
|
|
}
|
|
|
|
if (strcmp(version->name, "amdgpu")) {
|
|
/* This is not AMDGPU driver, skip.*/
|
|
drmFreeVersion(version);
|
|
close(fd);
|
|
continue;
|
|
}
|
|
|
|
drmFreeVersion(version);
|
|
|
|
drm_amdgpu[amd_index] = fd;
|
|
amd_index++;
|
|
}
|
|
|
|
drmFreeDevices(devices, drm_count);
|
|
return amd_index;
|
|
}
|
|
|
|
/* Close AMD devices.
|
|
*/
|
|
static void amdgpu_close_devices()
|
|
{
|
|
int i;
|
|
for (i = 0; i < MAX_CARDS_SUPPORTED; i++)
|
|
if (drm_amdgpu[i] >=0)
|
|
close(drm_amdgpu[i]);
|
|
}
|
|
|
|
/* Print AMD devices information */
|
|
static void amdgpu_print_devices()
|
|
{
|
|
int i;
|
|
drmDevicePtr device;
|
|
|
|
/* Open the first AMD devcie to print driver information. */
|
|
if (drm_amdgpu[0] >=0) {
|
|
/* Display AMD driver version information.*/
|
|
drmVersionPtr retval = drmGetVersion(drm_amdgpu[0]);
|
|
|
|
if (retval == NULL) {
|
|
perror("Cannot get version for AMDGPU device");
|
|
return;
|
|
}
|
|
|
|
printf("Driver name: %s, Date: %s, Description: %s.\n",
|
|
retval->name, retval->date, retval->desc);
|
|
drmFreeVersion(retval);
|
|
}
|
|
|
|
/* Display information of AMD devices */
|
|
printf("Devices:\n");
|
|
for (i = 0; i < MAX_CARDS_SUPPORTED && drm_amdgpu[i] >=0; i++)
|
|
if (drmGetDevice2(drm_amdgpu[i],
|
|
DRM_DEVICE_GET_PCI_REVISION,
|
|
&device) == 0) {
|
|
if (device->bustype == DRM_BUS_PCI) {
|
|
printf("PCI ");
|
|
printf(" domain:%04x",
|
|
device->businfo.pci->domain);
|
|
printf(" bus:%02x",
|
|
device->businfo.pci->bus);
|
|
printf(" device:%02x",
|
|
device->businfo.pci->dev);
|
|
printf(" function:%01x",
|
|
device->businfo.pci->func);
|
|
printf(" vendor_id:%04x",
|
|
device->deviceinfo.pci->vendor_id);
|
|
printf(" device_id:%04x",
|
|
device->deviceinfo.pci->device_id);
|
|
printf(" subvendor_id:%04x",
|
|
device->deviceinfo.pci->subvendor_id);
|
|
printf(" subdevice_id:%04x",
|
|
device->deviceinfo.pci->subdevice_id);
|
|
printf(" revision_id:%02x",
|
|
device->deviceinfo.pci->revision_id);
|
|
printf("\n");
|
|
}
|
|
drmFreeDevice(&device);
|
|
}
|
|
}
|
|
|
|
/* Find a match AMD device in PCI bus
|
|
* Return the index of the device or -1 if not found
|
|
*/
|
|
static int amdgpu_find_device(uint8_t bus, uint16_t dev)
|
|
{
|
|
int i;
|
|
drmDevicePtr device;
|
|
|
|
for (i = 0; i < MAX_CARDS_SUPPORTED && drm_amdgpu[i] >= 0; i++) {
|
|
if (drmGetDevice2(drm_amdgpu[i],
|
|
DRM_DEVICE_GET_PCI_REVISION,
|
|
&device) == 0) {
|
|
if (device->bustype == DRM_BUS_PCI)
|
|
if ((bus == 0xFF || device->businfo.pci->bus == bus) &&
|
|
device->deviceinfo.pci->device_id == dev) {
|
|
drmFreeDevice(&device);
|
|
return i;
|
|
}
|
|
|
|
drmFreeDevice(&device);
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
static void amdgpu_disable_suits()
|
|
{
|
|
amdgpu_device_handle device_handle;
|
|
uint32_t major_version, minor_version, family_id;
|
|
int i;
|
|
int size = sizeof(suites_active_stat) / sizeof(suites_active_stat[0]);
|
|
|
|
if (amdgpu_device_initialize(drm_amdgpu[0], &major_version,
|
|
&minor_version, &device_handle))
|
|
return;
|
|
|
|
family_id = device_handle->info.family_id;
|
|
|
|
if (amdgpu_device_deinitialize(device_handle))
|
|
return;
|
|
|
|
/* Set active status for suits based on their policies */
|
|
for (i = 0; i < size; ++i)
|
|
if (amdgpu_set_suite_active(suites_active_stat[i].pName,
|
|
suites_active_stat[i].pActive()))
|
|
fprintf(stderr, "suit deactivation failed - %s\n", CU_get_error_msg());
|
|
|
|
/* Explicitly disable specific tests due to known bugs or preferences */
|
|
/*
|
|
* BUG: Compute ring stalls and never recovers when the address is
|
|
* written after the command already submitted
|
|
*/
|
|
if (amdgpu_set_test_active(DEADLOCK_TESTS_STR, "compute ring block test", CU_FALSE))
|
|
fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg());
|
|
|
|
if (amdgpu_set_test_active(BO_TESTS_STR, "Metadata", CU_FALSE))
|
|
fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg());
|
|
|
|
|
|
/* This test was ran on GFX8 and GFX9 only */
|
|
if (family_id < AMDGPU_FAMILY_VI || family_id > AMDGPU_FAMILY_RV)
|
|
if (amdgpu_set_test_active(BASIC_TESTS_STR, "Sync dependency Test", CU_FALSE))
|
|
fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg());
|
|
}
|
|
|
|
/* The main() function for setting up and running the tests.
|
|
* Returns a CUE_SUCCESS on successful running, another
|
|
* CUnit error code on failure.
|
|
*/
|
|
int main(int argc, char **argv)
|
|
{
|
|
int c; /* Character received from getopt */
|
|
int i = 0;
|
|
int suite_id = -1; /* By default run everything */
|
|
int test_id = -1; /* By default run all tests in the suite */
|
|
int pci_bus_id = -1; /* By default PC bus ID is not specified */
|
|
int pci_device_id = 0; /* By default PC device ID is zero */
|
|
int display_devices = 0;/* By default not to display devices' info */
|
|
CU_pSuite pSuite = NULL;
|
|
CU_pTest pTest = NULL;
|
|
int test_device_index;
|
|
int display_list = 0;
|
|
int force_run = 0;
|
|
|
|
for (i = 0; i < MAX_CARDS_SUPPORTED; i++)
|
|
drm_amdgpu[i] = -1;
|
|
|
|
|
|
/* Parse command line string */
|
|
opterr = 0; /* Do not print error messages from getopt */
|
|
while ((c = getopt(argc, argv, options)) != -1) {
|
|
switch (c) {
|
|
case 'l':
|
|
display_list = 1;
|
|
break;
|
|
case 's':
|
|
suite_id = atoi(optarg);
|
|
break;
|
|
case 't':
|
|
test_id = atoi(optarg);
|
|
break;
|
|
case 'b':
|
|
pci_bus_id = atoi(optarg);
|
|
break;
|
|
case 'd':
|
|
sscanf(optarg, "%x", &pci_device_id);
|
|
break;
|
|
case 'p':
|
|
display_devices = 1;
|
|
break;
|
|
case 'r':
|
|
open_render_node = 1;
|
|
break;
|
|
case 'f':
|
|
force_run = 1;
|
|
break;
|
|
case '?':
|
|
case 'h':
|
|
fprintf(stderr, usage, argv[0]);
|
|
exit(EXIT_SUCCESS);
|
|
default:
|
|
fprintf(stderr, usage, argv[0]);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
|
|
if (amdgpu_open_devices(open_render_node) <= 0) {
|
|
perror("Cannot open AMDGPU device");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
if (drm_amdgpu[0] < 0) {
|
|
perror("Cannot open AMDGPU device");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
if (display_devices) {
|
|
amdgpu_print_devices();
|
|
amdgpu_close_devices();
|
|
exit(EXIT_SUCCESS);
|
|
}
|
|
|
|
if (pci_bus_id > 0 || pci_device_id) {
|
|
/* A device was specified to run the test */
|
|
test_device_index = amdgpu_find_device(pci_bus_id,
|
|
pci_device_id);
|
|
|
|
if (test_device_index >= 0) {
|
|
/* Most tests run on device of drm_amdgpu[0].
|
|
* Swap the chosen device to drm_amdgpu[0].
|
|
*/
|
|
i = drm_amdgpu[0];
|
|
drm_amdgpu[0] = drm_amdgpu[test_device_index];
|
|
drm_amdgpu[test_device_index] = i;
|
|
} else {
|
|
fprintf(stderr,
|
|
"The specified GPU device does not exist.\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
|
|
/* Initialize test suites to run */
|
|
|
|
/* initialize the CUnit test registry */
|
|
if (CUE_SUCCESS != CU_initialize_registry()) {
|
|
amdgpu_close_devices();
|
|
return CU_get_error();
|
|
}
|
|
|
|
/* Register suites. */
|
|
if (CU_register_suites(suites) != CUE_SUCCESS) {
|
|
fprintf(stderr, "suite registration failed - %s\n",
|
|
CU_get_error_msg());
|
|
CU_cleanup_registry();
|
|
amdgpu_close_devices();
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
/* Run tests using the CUnit Basic interface */
|
|
CU_basic_set_mode(CU_BRM_VERBOSE);
|
|
|
|
/* Disable suits and individual tests based on misc. conditions */
|
|
amdgpu_disable_suits();
|
|
|
|
if (display_list) {
|
|
display_test_suites();
|
|
goto end;
|
|
}
|
|
|
|
if (suite_id != -1) { /* If user specify particular suite? */
|
|
pSuite = CU_get_suite_by_index((unsigned int) suite_id,
|
|
CU_get_registry());
|
|
|
|
if (pSuite) {
|
|
|
|
if (force_run)
|
|
CU_set_suite_active(pSuite, CU_TRUE);
|
|
|
|
if (test_id != -1) { /* If user specify test id */
|
|
pTest = CU_get_test_by_index(
|
|
(unsigned int) test_id,
|
|
pSuite);
|
|
if (pTest) {
|
|
if (force_run)
|
|
CU_set_test_active(pTest, CU_TRUE);
|
|
|
|
CU_basic_run_test(pSuite, pTest);
|
|
}
|
|
else {
|
|
fprintf(stderr, "Invalid test id: %d\n",
|
|
test_id);
|
|
CU_cleanup_registry();
|
|
amdgpu_close_devices();
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
} else
|
|
CU_basic_run_suite(pSuite);
|
|
} else {
|
|
fprintf(stderr, "Invalid suite id : %d\n",
|
|
suite_id);
|
|
CU_cleanup_registry();
|
|
amdgpu_close_devices();
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
} else
|
|
CU_basic_run_tests();
|
|
|
|
end:
|
|
CU_cleanup_registry();
|
|
amdgpu_close_devices();
|
|
return CU_get_error();
|
|
}
|