summaryrefslogtreecommitdiff
path: root/lib/igt_debugfs.c
diff options
context:
space:
mode:
authorTomeu Vizoso <tomeu.vizoso@collabora.com>2017-03-02 10:37:11 +0100
committerTomeu Vizoso <tomeu.vizoso@collabora.com>2017-03-21 15:50:54 +0100
commit301ad44cdf1b868b1ab89096721da91fa8541fdc (patch)
treeef18781db6cadae7f8f49f1fc449dc56b33448ec /lib/igt_debugfs.c
parente7a0d06730f77842998368660fb45fe5c1738fda (diff)
lib: Open debugfs files for the given DRM device
When opening a DRM debugfs file, locate the right path based on the given DRM device FD. This is needed so, in setups with more than one DRM device, any operations on debugfs files affect the expected DRM device. v2: - rebased and fixed new API additions v3: - updated chamelium test, which was missed previously - use the minor of the device for the debugfs path, not the major - have a proper exit handler for calling igt_hpd_storm_reset with the right device fd. Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com> Reviewed-by: Robert Foss <robert.foss@collabora.com> Acked-by: Chris Wilson <chris@chris-wilson.co.uk>
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 {