summaryrefslogtreecommitdiff
path: root/lib/igt_debugfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/igt_debugfs.c')
-rw-r--r--lib/igt_debugfs.c197
1 files changed, 121 insertions, 76 deletions
diff --git a/lib/igt_debugfs.c b/lib/igt_debugfs.c
index 12ee34e0..628443a1 100644
--- a/lib/igt_debugfs.c
+++ b/lib/igt_debugfs.c
@@ -131,39 +131,34 @@ const char *igt_debugfs_mount(void)
return "/sys/kernel/debug";
}
-static bool __igt_debugfs_init(igt_debugfs_t *debugfs)
+static char *
+igt_get_debugfs_path(int fd)
{
struct stat st;
- int n;
-
- strcpy(debugfs->root, igt_debugfs_mount());
- for (n = 0; n < 16; n++) {
- int len = sprintf(debugfs->dri_path, "%s/dri/%d", debugfs->root, n);
- sprintf(debugfs->dri_path + len, "/i915_error_state");
- if (stat(debugfs->dri_path, &st) == 0) {
- debugfs->dri_path[len] = '\0';
- return true;
- }
- }
-
- debugfs->dri_path[0] = '\0';
- return false;
-}
-
-static igt_debugfs_t *__igt_debugfs_singleton(void)
-{
- static igt_debugfs_t singleton;
- static bool init_done = false;
+ const char *debugfs_root;
+ char *debugfs_dri_path;
+ int len;
- if (init_done)
- return &singleton;
+ if (fstat(fd, &st)) {
+ igt_debug("Couldn't stat FD for DRM device: %s\n", strerror(errno));
+ return NULL;
+ }
- if (__igt_debugfs_init(&singleton)) {
- init_done = true;
- return &singleton;
- } else {
+ if (!S_ISCHR(st.st_mode)) {
+ igt_debug("FD for DRM device not a char device!\n");
return NULL;
}
+
+ debugfs_root = igt_debugfs_mount();
+ debugfs_dri_path = calloc(1, strlen(debugfs_root) + 100);
+ len = sprintf(debugfs_dri_path, "%s/dri/%d", debugfs_root, minor(st.st_rdev));
+ sprintf(debugfs_dri_path + len, "/name");
+ if (stat(debugfs_dri_path, &st) == 0) {
+ debugfs_dri_path[len] = '\0';
+ return debugfs_dri_path;
+ }
+
+ return NULL;
}
/**
@@ -177,15 +172,19 @@ static igt_debugfs_t *__igt_debugfs_singleton(void)
* Returns:
* The Unix file descriptor for the debugfs file or -1 if that didn't work out.
*/
-int igt_debugfs_open(const char *filename, int mode)
+int igt_debugfs_open(int fd, const char *filename, int mode)
{
char buf[1024];
- igt_debugfs_t *debugfs = __igt_debugfs_singleton();
+ char *debugfs_dri_path;
- if (!debugfs)
+ debugfs_dri_path = igt_get_debugfs_path(fd);
+ if (!debugfs_dri_path)
return -1;
- sprintf(buf, "%s/%s", debugfs->dri_path, filename);
+ sprintf(buf, "%s/%s", debugfs_dri_path, filename);
+
+ free(debugfs_dri_path);
+
return open(buf, mode);
}
@@ -200,17 +199,21 @@ int igt_debugfs_open(const char *filename, int mode)
* Returns:
* The libc FILE pointer for the debugfs file or NULL if that didn't work out.
*/
-FILE *igt_debugfs_fopen(const char *filename,
+FILE *igt_debugfs_fopen(int fd,
+ const char *filename,
const char *mode)
{
char buf[1024];
+ char *debugfs_dri_path;
- igt_debugfs_t *debugfs = __igt_debugfs_singleton();
-
- if (!debugfs)
+ debugfs_dri_path = igt_get_debugfs_path(fd);
+ if (!debugfs_dri_path)
return NULL;
- sprintf(buf, "%s/%s", debugfs->dri_path, filename);
+ sprintf(buf, "%s/%s", debugfs_dri_path, filename);
+
+ free(debugfs_dri_path);
+
return fopen(buf, mode);
}
@@ -224,12 +227,12 @@ FILE *igt_debugfs_fopen(const char *filename,
* provided buffer, then closes the file. Users should make sure that the buffer
* provided is big enough to fit the whole file, plus one byte.
*/
-void __igt_debugfs_read(const char *filename, char *buf, int buf_size)
+void __igt_debugfs_read(int fd, const char *filename, char *buf, int buf_size)
{
FILE *file;
size_t n_read;
- file = igt_debugfs_fopen(filename, "r");
+ file = igt_debugfs_fopen(fd, filename, "r");
igt_assert(file);
n_read = fread(buf, 1, buf_size - 1, file);
@@ -250,14 +253,14 @@ void __igt_debugfs_read(const char *filename, char *buf, int buf_size)
*
* Returns: True if the @substring is found to occur in @filename
*/
-bool igt_debugfs_search(const char *filename, const char *substring)
+bool igt_debugfs_search(int fd, const char *filename, const char *substring)
{
FILE *file;
size_t n = 0;
char *line = NULL;
bool matched = false;
- file = igt_debugfs_fopen(filename, "r");
+ file = igt_debugfs_fopen(fd, filename, "r");
igt_assert(file);
while (getline(&line, &n, file) >= 0) {
@@ -322,6 +325,7 @@ char *igt_crc_to_string(igt_crc_t *crc)
#define LEGACY_LINE_LEN (6 * 8 + 5 + 1)
struct _igt_pipe_crc {
+ int fd;
int ctl_fd;
int crc_fd;
int flags;
@@ -370,7 +374,7 @@ static bool igt_pipe_crc_do_start(igt_pipe_crc_t *pipe_crc)
if (!pipe_crc->is_legacy) {
sprintf(buf, "crtc-%d/crc/data", pipe_crc->pipe);
errno = 0;
- pipe_crc->crc_fd = igt_debugfs_open(buf, pipe_crc->flags);
+ pipe_crc->crc_fd = igt_debugfs_open(pipe_crc->fd, buf, pipe_crc->flags);
if (pipe_crc->crc_fd == -1 && errno == EINVAL)
return false;
igt_assert_eq(errno, 0);
@@ -387,23 +391,27 @@ static void igt_pipe_crc_pipe_off(int fd, enum pipe pipe)
igt_assert_eq(write(fd, buf, strlen(buf)), strlen(buf));
}
-static void igt_pipe_crc_reset(void)
+static void igt_pipe_crc_reset(int drm_fd)
{
- igt_debugfs_t *debugfs = __igt_debugfs_singleton();
int fd;
struct dirent *dirent;
char buf[128];
const char *cmd = "none";
bool done = false;
DIR *dir;
+ char *debugfs_dri_path;
+
+ debugfs_dri_path = igt_get_debugfs_path(drm_fd);
+ if (!debugfs_dri_path)
+ return;
- dir = opendir(debugfs->dri_path);
+ dir = opendir(debugfs_dri_path);
if (dir) {
while ((dirent = readdir(dir))) {
if (strcmp(dirent->d_name, "crtc-") != 0)
continue;
- sprintf(buf, "%s/%s/crc/control", debugfs->dri_path,
+ sprintf(buf, "%s/%s/crc/control", debugfs_dri_path,
dirent->d_name);
fd = open(buf, O_WRONLY);
if (fd == -1)
@@ -416,11 +424,12 @@ static void igt_pipe_crc_reset(void)
}
closedir(dir);
}
+ free(debugfs_dri_path);
if (done)
return;
- fd = igt_debugfs_open("i915_display_crc_ctl", O_WRONLY);
+ fd = igt_debugfs_open(drm_fd, "i915_display_crc_ctl", O_WRONLY);
if (fd != -1) {
igt_pipe_crc_pipe_off(fd, PIPE_A);
igt_pipe_crc_pipe_off(fd, PIPE_B);
@@ -432,7 +441,32 @@ static void igt_pipe_crc_reset(void)
static void pipe_crc_exit_handler(int sig)
{
- igt_pipe_crc_reset();
+ struct dirent *dirent;
+ char buf[128];
+ DIR *dir;
+ int fd;
+
+ dir = opendir("/dev/dri");
+ if (!dir)
+ return;
+
+ /*
+ * Try to reset CRC capture for all DRM devices, this is only needed
+ * for the legacy CRC ABI and can be completely removed once the
+ * legacy codepaths are removed.
+ */
+ while ((dirent = readdir(dir))) {
+ if (strncmp(dirent->d_name, "card", 4) != 0)
+ continue;
+
+ sprintf(buf, "/dev/dri/%s", dirent->d_name);
+ fd = open(buf, O_WRONLY);
+
+ igt_pipe_crc_reset(fd);
+
+ close(fd);
+ }
+ closedir(dir);
}
/**
@@ -442,16 +476,16 @@ static void pipe_crc_exit_handler(int sig)
* kernel. Uses igt_skip to automatically skip the test/subtest if this isn't
* the case.
*/
-void igt_require_pipe_crc(void)
+void igt_require_pipe_crc(int fd)
{
const char *cmd = "pipe A none";
FILE *ctl;
size_t written;
int ret;
- ctl = igt_debugfs_fopen("crtc-0/crc/control", "r+");
+ ctl = igt_debugfs_fopen(fd, "crtc-0/crc/control", "r+");
if (!ctl) {
- ctl = igt_debugfs_fopen("i915_display_crc_ctl", "r+");
+ ctl = igt_debugfs_fopen(fd, "i915_display_crc_ctl", "r+");
igt_require_f(ctl,
"No display_crc_ctl found, kernel too old\n");
written = fwrite(cmd, 1, strlen(cmd), ctl);
@@ -463,6 +497,16 @@ void igt_require_pipe_crc(void)
fclose(ctl);
}
+static void igt_hpd_storm_exit_handler(int sig)
+{
+ int fd = drm_open_driver_master(DRIVER_INTEL);
+
+ /* Here we assume that only one i915 device will be ever present */
+ igt_hpd_storm_reset(fd);
+
+ close(fd);
+}
+
/**
* igt_hpd_storm_set_threshold:
* @threshold: How many hotplugs per second required to trigger an HPD storm,
@@ -477,9 +521,9 @@ void igt_require_pipe_crc(void)
*
* See: https://01.org/linuxgraphics/gfx-docs/drm/gpu/i915.html#hotplug
*/
-void igt_hpd_storm_set_threshold(unsigned int threshold)
+void igt_hpd_storm_set_threshold(int drm_fd, unsigned int threshold)
{
- int fd = igt_debugfs_open("i915_hpd_storm_ctl", O_WRONLY);
+ int fd = igt_debugfs_open(drm_fd, "i915_hpd_storm_ctl", O_WRONLY);
char buf[16];
if (fd < 0)
@@ -490,7 +534,7 @@ void igt_hpd_storm_set_threshold(unsigned int threshold)
igt_assert_eq(write(fd, buf, strlen(buf)), strlen(buf));
close(fd);
- igt_install_exit_handler((igt_exit_handler_t)igt_hpd_storm_reset);
+ igt_install_exit_handler(igt_hpd_storm_exit_handler);
}
/**
@@ -506,9 +550,9 @@ void igt_hpd_storm_set_threshold(unsigned int threshold)
*
* See: https://01.org/linuxgraphics/gfx-docs/drm/gpu/i915.html#hotplug
*/
-void igt_hpd_storm_reset(void)
+void igt_hpd_storm_reset(int drm_fd)
{
- int fd = igt_debugfs_open("i915_hpd_storm_ctl", O_WRONLY);
+ int fd = igt_debugfs_open(drm_fd, "i915_hpd_storm_ctl", O_WRONLY);
const char *buf = "reset";
if (fd < 0)
@@ -533,9 +577,9 @@ void igt_hpd_storm_reset(void)
*
* Returns: Whether or not an HPD storm has been detected.
*/
-bool igt_hpd_storm_detected(void)
+bool igt_hpd_storm_detected(int drm_fd)
{
- int fd = igt_debugfs_open("i915_hpd_storm_ctl", O_RDONLY);
+ int fd = igt_debugfs_open(drm_fd, "i915_hpd_storm_ctl", O_RDONLY);
char *start_loc;
char buf[32] = {0}, detected_str[4];
bool ret;
@@ -566,16 +610,16 @@ bool igt_hpd_storm_detected(void)
*
* See: https://01.org/linuxgraphics/gfx-docs/drm/gpu/i915.html#hotplug
*/
-void igt_require_hpd_storm_ctl(void)
+void igt_require_hpd_storm_ctl(int drm_fd)
{
- int fd = igt_debugfs_open("i915_hpd_storm_ctl", O_RDONLY);
+ int fd = igt_debugfs_open(drm_fd, "i915_hpd_storm_ctl", O_RDONLY);
igt_require_f(fd > 0, "No i915_hpd_storm_ctl found in debugfs\n");
close(fd);
}
static igt_pipe_crc_t *
-pipe_crc_new(enum pipe pipe, enum intel_pipe_crc_source source, int flags)
+pipe_crc_new(int fd, enum pipe pipe, enum intel_pipe_crc_source source, int flags)
{
igt_pipe_crc_t *pipe_crc;
char buf[128];
@@ -585,9 +629,9 @@ pipe_crc_new(enum pipe pipe, enum intel_pipe_crc_source source, int flags)
pipe_crc = calloc(1, sizeof(struct _igt_pipe_crc));
sprintf(buf, "crtc-%d/crc/control", pipe);
- pipe_crc->ctl_fd = igt_debugfs_open(buf, O_WRONLY);
+ pipe_crc->ctl_fd = igt_debugfs_open(fd, buf, O_WRONLY);
if (pipe_crc->ctl_fd == -1) {
- pipe_crc->ctl_fd = igt_debugfs_open("i915_display_crc_ctl",
+ pipe_crc->ctl_fd = igt_debugfs_open(fd, "i915_display_crc_ctl",
O_WRONLY);
igt_assert(pipe_crc->ctl_fd != -1);
pipe_crc->is_legacy = true;
@@ -595,7 +639,7 @@ pipe_crc_new(enum pipe pipe, enum intel_pipe_crc_source source, int flags)
if (pipe_crc->is_legacy) {
sprintf(buf, "i915_pipe_%s_crc", kmstest_pipe_name(pipe));
- pipe_crc->crc_fd = igt_debugfs_open(buf, flags);
+ pipe_crc->crc_fd = igt_debugfs_open(fd, buf, flags);
igt_assert(pipe_crc->crc_fd != -1);
igt_debug("Using legacy frame CRC ABI\n");
} else {
@@ -603,6 +647,7 @@ pipe_crc_new(enum pipe pipe, enum intel_pipe_crc_source source, int flags)
igt_debug("Using generic frame CRC ABI\n");
}
+ pipe_crc->fd = fd;
pipe_crc->pipe = pipe;
pipe_crc->source = source;
pipe_crc->flags = flags;
@@ -623,9 +668,9 @@ pipe_crc_new(enum pipe pipe, enum intel_pipe_crc_source source, int flags)
* least INTEL_PIPE_CRC_SOURCE_AUTO everywhere.
*/
igt_pipe_crc_t *
-igt_pipe_crc_new(enum pipe pipe, enum intel_pipe_crc_source source)
+igt_pipe_crc_new(int fd, enum pipe pipe, enum intel_pipe_crc_source source)
{
- return pipe_crc_new(pipe, source, O_RDONLY);
+ return pipe_crc_new(fd, pipe, source, O_RDONLY);
}
/**
@@ -641,9 +686,9 @@ igt_pipe_crc_new(enum pipe pipe, enum intel_pipe_crc_source source)
* least INTEL_PIPE_CRC_SOURCE_AUTO everywhere.
*/
igt_pipe_crc_t *
-igt_pipe_crc_new_nonblock(enum pipe pipe, enum intel_pipe_crc_source source)
+igt_pipe_crc_new_nonblock(int fd, enum pipe pipe, enum intel_pipe_crc_source source)
{
- return pipe_crc_new(pipe, source, O_RDONLY | O_NONBLOCK);
+ return pipe_crc_new(fd, pipe, source, O_RDONLY | O_NONBLOCK);
}
/**
@@ -879,13 +924,13 @@ void igt_pipe_crc_collect_crc(igt_pipe_crc_t *pipe_crc, igt_crc_t *out_crc)
* This queries the debugfs to see if it supports the full set of desired
* operations.
*/
-bool igt_drop_caches_has(uint64_t val)
+bool igt_drop_caches_has(int drm_fd, uint64_t val)
{
FILE *file;
uint64_t mask;
mask = 0;
- file = igt_debugfs_fopen("i915_gem_drop_caches", "r");
+ file = igt_debugfs_fopen(drm_fd, "i915_gem_drop_caches", "r");
if (file) {
igt_ignore_warn(fscanf(file, "0x%" PRIx64, &mask));
fclose(file);
@@ -901,7 +946,7 @@ bool igt_drop_caches_has(uint64_t val)
* This calls the debugfs interface the drm/i915 GEM driver exposes to drop or
* evict certain classes of gem buffer objects.
*/
-void igt_drop_caches_set(uint64_t val)
+void igt_drop_caches_set(int drm_fd, uint64_t val)
{
int fd;
char data[19];
@@ -909,7 +954,7 @@ void igt_drop_caches_set(uint64_t val)
sprintf(data, "0x%" PRIx64, val);
- fd = igt_debugfs_open("i915_gem_drop_caches", O_WRONLY);
+ fd = igt_debugfs_open(drm_fd, "i915_gem_drop_caches", O_WRONLY);
igt_assert(fd >= 0);
do {
@@ -975,14 +1020,14 @@ void igt_enable_prefault(void)
igt_prefault_control(true);
}
-static int get_object_count(void)
+static int get_object_count(int fd)
{
FILE *file;
int ret, scanned;
- igt_drop_caches_set(DROP_RETIRE | DROP_ACTIVE | DROP_FREED);
+ igt_drop_caches_set(fd, DROP_RETIRE | DROP_ACTIVE | DROP_FREED);
- file = igt_debugfs_fopen("i915_gem_objects", "r");
+ file = igt_debugfs_fopen(fd, "i915_gem_objects", "r");
scanned = fscanf(file, "%i objects", &ret);
igt_assert_eq(scanned, 1);
@@ -1002,7 +1047,7 @@ int igt_get_stable_obj_count(int driver)
{
int obj_count;
gem_quiescent_gpu(driver);
- obj_count = get_object_count();
+ obj_count = get_object_count(driver);
/* The test relies on the system being in the same state before and
* after the test so any difference in the object count is a result of
* leaks during the test. gem_quiescent_gpu() mostly achieves this but
@@ -1016,7 +1061,7 @@ int igt_get_stable_obj_count(int driver)
while (loop_count < 4) {
usleep(200000);
gem_quiescent_gpu(driver);
- obj_count = get_object_count();
+ obj_count = get_object_count(driver);
if (obj_count == prev_obj_count) {
loop_count++;
} else {