After a hotplug, it is mandatory for userspace to reprobe (and maybe retrain the links). Currently igt doesn't do this and so we may cause spurious test failures (likely to be EINVAL when trying to apply a mode). Detect the hotplug uevent and die loudly so that the actual failure is logged. Signed-off-by: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx> --- lib/igt_kms.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/igt_kms.h | 3 +++ 2 files changed, 79 insertions(+) diff --git a/lib/igt_kms.c b/lib/igt_kms.c index 5312f8d8..3c16547e 100644 --- a/lib/igt_kms.c +++ b/lib/igt_kms.c @@ -1512,6 +1512,8 @@ void igt_display_init(igt_display_t *display, int drm_fd) drmModeFreePlaneResources(plane_resources); drmModeFreeResources(resources); + igt_kms_disallow_hotplug(drm_fd); + LOG_UNINDENT(display); } @@ -2777,3 +2779,77 @@ uint32_t kmstest_get_vbl_flag(uint32_t pipe_id) return pipe_flag; } } + +#if HAVE_UDEV +#include <sys/poll.h> +#include <libudev.h> +#include <signal.h> + +static struct igt_helper_process hpd_helper; +static void __attribute__((noreturn)) +hpd_process(pid_t pid, dev_t rdev) +{ + struct udev_monitor *mon = + udev_monitor_new_from_netlink(udev_new(), "kernel"); + struct pollfd pfd; + + udev_monitor_filter_add_match_subsystem_devtype(mon, "drm", NULL); + udev_monitor_enable_receiving(mon); + + pfd.fd = udev_monitor_get_fd(mon); + pfd.events = POLLIN; + + while (poll(&pfd, 1, -1) > 0) { + struct udev_device *dev = udev_monitor_receive_device(mon); + dev_t devnum; + + if (dev == NULL) + continue; + + devnum = udev_device_get_devnum(dev); + if (memcmp(&rdev, &devnum, sizeof(dev_t)) == 0) { + const char *str; + + str = udev_device_get_property_value(dev, "HOTPLUG"); + if (str && atoi(str) == 1) + kill(pid, SIGIO); + } + + udev_device_unref(dev); + if (kill(pid, 0)) /* Parent has died, so must we. */ + break; + } + + exit(0); +} + +static void sig_abort(int sig) +{ + errno = 0; /* inside a signal, last errno reporting is confusing */ + igt_assert(!"Hotplug detected"); +} + +void igt_kms_disallow_hotplug(int fd) +{ + struct stat st; + + igt_assert(fstat(fd, &st) == 0); + + signal(SIGIO, sig_abort); + igt_fork_helper(&hpd_helper) + hpd_process(getppid(), st.st_rdev); +} + +void igt_kms_allow_hotplug(void) +{ + igt_stop_helper(&hpd_helper); +} +#else +void igt_kms_disallow_hotplug(int fd) +{ +} + +void igt_kms_allow_hotplug(void) +{ +} +#endif diff --git a/lib/igt_kms.h b/lib/igt_kms.h index 5234f6c1..788b7457 100644 --- a/lib/igt_kms.h +++ b/lib/igt_kms.h @@ -473,6 +473,9 @@ static inline bool igt_output_is_connected(igt_output_t *output) void igt_enable_connectors(void); void igt_reset_connectors(void); +void igt_kms_disallow_hotplug(int fd); +void igt_kms_allow_hotplug(void); + uint32_t kmstest_get_vbl_flag(uint32_t pipe_id); #define EDID_LENGTH 128 -- 2.11.0 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx