[PATCH i-g-t v5 22/22] tests/core_hotunplug: A few more fixes

Janusz Krzysztofik janusz.krzysztofik at linux.intel.com
Thu Aug 27 06:48:16 UTC 2020


To be split and squashed with other patches of the series:
- detect inaccessible i915 debugfs,
- unbind the driver from unhealthy device before recovery,
- drop subtests with no health checks, adjust timeouts in successors,
- perform health checks of hot restored devices also before late close.

Signed-off-by: Janusz Krzysztofik <janusz.krzysztofik at linux.intel.com>
---
 tests/core_hotunplug.c | 139 ++++++++++++++++++++++-------------------
 1 file changed, 75 insertions(+), 64 deletions(-)

diff --git a/tests/core_hotunplug.c b/tests/core_hotunplug.c
index 368aa2484..ccba9ede5 100644
--- a/tests/core_hotunplug.c
+++ b/tests/core_hotunplug.c
@@ -97,6 +97,39 @@ static int close_sysfs(int fd_sysfs_dev)
 	return local_close(fd_sysfs_dev, "Device sysfs node close failed");
 }
 
+/* FIXME: fix "i915 raw-wakerefs=1 wakelocks=1 on cleanup" kernel warning */
+static int local_hswbdw_audio_workaround(int fd_drm)
+{
+	bool closed = fd_drm < 0;
+
+	if (closed) {
+		fd_drm = __drm_open_driver(DRIVER_ANY);
+		if (fd_drm < 0)
+			return fd_drm;
+	}
+
+	if (is_i915_device(fd_drm)) {
+		uint32_t devid = intel_get_drm_devid(fd_drm);
+
+		if (IS_HASWELL(devid) || IS_BROADWELL(devid))
+			igt_pm_enable_audio_runtime_pm();
+	}
+
+	if (closed)
+		return close_device(fd_drm);
+
+	return fd_drm;
+}
+
+static int late_close(int fd_drm)
+{
+	if (fd_drm < 0)	/* not open - return current status */
+		return fd_drm;
+
+	fd_drm = local_hswbdw_audio_workaround(fd_drm);
+	return local_close(fd_drm, "Device late close failed");
+}
+
 static void prepare(struct hotunplug *priv)
 {
 	const char *filter = igt_device_filter_get(0), *sysfs_path;
@@ -199,7 +232,7 @@ static void bus_rescan(struct hotunplug *priv, int timeout)
 
 static void cleanup(struct hotunplug *priv)
 {
-	priv->fd.drm = close_device(priv->fd.drm);
+	priv->fd.drm = late_close(priv->fd.drm);
 	priv->fd.sysfs_dev = close_sysfs(priv->fd.sysfs_dev);
 }
 
@@ -281,21 +314,26 @@ static int local_i915_recover(int i915)
 
 static void healthcheck(struct hotunplug *priv, bool recover)
 {
-	/* preserve error code potentially stored before in priv->fd.drm */
+	/* preserve device fd / close status stored in priv->fd.drm */
+	int fd_drm, saved_fd_drm = priv->fd.drm;
 	bool closed = priv->fd.drm == -1;
-	int fd_drm;
 
 	/* device name may have changed, rebuild IGT device list */
 	igt_devices_scan(true);
 
 	priv->failure = "Device reopen failure!";
 	fd_drm = local_drm_open_driver("re", " for healthcheck");
-	if (closed)	/* store for cleanup if no error code to preserve */
+	if (closed)	/* store for cleanup if not dirty */
 		priv->fd.drm = fd_drm;
+	else		/* force close error should we fail prematurely */
+		priv->fd.drm = -EBADF;
 
 	if (is_i915_device(fd_drm)) {
 		/* don't report library failed asserts as healthcheck failure */
 		priv->failure = "Unrecoverable test failure";
+
+		gem_quiescent_gpu(fd_drm);
+
 		if (local_i915_healthcheck(fd_drm, "") &&
 		    (!recover || local_i915_recover(fd_drm)))
 			priv->failure = "Healthcheck failure!";
@@ -307,18 +345,25 @@ static void healthcheck(struct hotunplug *priv, bool recover)
 		priv->failure = NULL;
 	}
 
-	/* not only request igt_abort on failure, also fail the health check */
-	igt_fail_on_f(priv->failure, "%s\n", priv->failure);
-
 	fd_drm = close_device(fd_drm);
-	if (closed)	/* store result if no error code to preserve */
+	if (closed)	/* store result if no dirty status to preserve */
 		priv->fd.drm = fd_drm;
+	else if (fd_drm == -1)	/* cancel fake error, restore saved status */
+		priv->fd.drm = saved_fd_drm;
+
+	/* not only request igt_abort on failure, also fail the health check */
+	igt_fail_on_f(priv->failure, "%s\n", priv->failure);
 }
 
 static void recover(struct hotunplug *priv)
 {
 	cleanup(priv);
 
+	/* unbind the driver from a possibly hot rebound unhealthy device */
+	if (priv->failure && priv->fd.drm == -1 &&
+	    !faccessat(priv->fd.sysfs_drv, priv->dev_bus_addr, F_OK, 0))
+		driver_unbind(priv, "post ", 60);
+
 	if (faccessat(priv->fd.sysfs_bus, priv->dev_bus_addr, F_OK, 0))
 		bus_rescan(priv, 60);
 
@@ -356,6 +401,9 @@ static void set_filter_from_device(int fd)
 
 static void unbind_rebind(struct hotunplug *priv)
 {
+	priv->fd.drm = local_hswbdw_audio_workaround(priv->fd.drm);
+	igt_assert_eq(priv->fd.drm, -1);
+
 	driver_unbind(priv, "", 0);
 
 	driver_bind(priv, 0);
@@ -365,6 +413,9 @@ static void unbind_rebind(struct hotunplug *priv)
 
 static void unplug_rescan(struct hotunplug *priv)
 {
+	priv->fd.drm = local_hswbdw_audio_workaround(priv->fd.drm);
+	igt_assert_eq(priv->fd.drm, -1);
+
 	device_unplug(priv, "", 0);
 
 	bus_rescan(priv, 0);
@@ -372,36 +423,15 @@ static void unplug_rescan(struct hotunplug *priv)
 	healthcheck(priv, false);
 }
 
-static void hotunbind_lateclose(struct hotunplug *priv)
-{
-	priv->fd.drm = local_drm_open_driver("", " for hotunbind");
-
-	driver_unbind(priv, "hot ", 0);
-
-	local_debug("%s\n", "late closing the unbound device instance");
-	priv->fd.drm = close_device(priv->fd.drm);
-	igt_assert_eq(priv->fd.drm, -1);
-}
-
-static void hotunplug_lateclose(struct hotunplug *priv)
-{
-	priv->fd.drm = local_drm_open_driver("", " for hotunplug");
-
-	device_unplug(priv, "hot ", 0);
-
-	local_debug("%s\n", "late closing the removed device instance");
-	priv->fd.drm = close_device(priv->fd.drm);
-	igt_assert_eq(priv->fd.drm, -1);
-}
-
 static void hotunbind_rebind(struct hotunplug *priv)
 {
+	igt_assert_eq(priv->fd.drm, -1);
 	priv->fd.drm = local_drm_open_driver("", " for hotrebind");
 
-	driver_unbind(priv, "hot ", 60);
+	driver_unbind(priv, "hot ", 0);
 
 	local_debug("%s\n", "late closing the unbound device instance");
-	priv->fd.drm = close_device(priv->fd.drm);
+	priv->fd.drm = late_close(priv->fd.drm);
 	igt_assert_eq(priv->fd.drm, -1);
 
 	driver_bind(priv, 0);
@@ -411,12 +441,13 @@ static void hotunbind_rebind(struct hotunplug *priv)
 
 static void hotunplug_rescan(struct hotunplug *priv)
 {
+	igt_assert_eq(priv->fd.drm, -1);
 	priv->fd.drm = local_drm_open_driver("", " for hotreplug");
 
-	device_unplug(priv, "hot ", 60);
+	device_unplug(priv, "hot ", 0);
 
 	local_debug("%s\n", "late closing the removed device instance");
-	priv->fd.drm = close_device(priv->fd.drm);
+	priv->fd.drm = late_close(priv->fd.drm);
 	igt_assert_eq(priv->fd.drm, -1);
 
 	bus_rescan(priv, 0);
@@ -426,14 +457,17 @@ static void hotunplug_rescan(struct hotunplug *priv)
 
 static void hotrebind_lateclose(struct hotunplug *priv)
 {
+	igt_assert_eq(priv->fd.drm, -1);
 	priv->fd.drm = local_drm_open_driver("", " for hotrebind");
 
 	driver_unbind(priv, "hot ", 60);
 
 	driver_bind(priv, 0);
 
+	healthcheck(priv, false);
+
 	local_debug("%s\n", "late closing the unbound device instance");
-	priv->fd.drm = close_device(priv->fd.drm);
+	priv->fd.drm = late_close(priv->fd.drm);
 	igt_assert_eq(priv->fd.drm, -1);
 
 	healthcheck(priv, false);
@@ -441,14 +475,17 @@ static void hotrebind_lateclose(struct hotunplug *priv)
 
 static void hotreplug_lateclose(struct hotunplug *priv)
 {
+	igt_assert_eq(priv->fd.drm, -1);
 	priv->fd.drm = local_drm_open_driver("", " for hotreplug");
 
 	device_unplug(priv, "hot ", 60);
 
 	bus_rescan(priv, 0);
 
+	healthcheck(priv, false);
+
 	local_debug("%s\n", "late closing the removed device instance");
-	priv->fd.drm = close_device(priv->fd.drm);
+	priv->fd.drm = late_close(priv->fd.drm);
 	igt_assert_eq(priv->fd.drm, -1);
 
 	healthcheck(priv, false);
@@ -481,8 +518,6 @@ igt_main
 		igt_assert_eq(close_device(fd_drm), -1);
 
 		prepare(&priv);
-
-		igt_pm_enable_audio_runtime_pm();
 	}
 
 	igt_subtest_group {
@@ -510,31 +545,7 @@ igt_main
 		post_healthcheck(&priv);
 
 	igt_subtest_group {
-		igt_describe("Check if the driver can be cleanly unbound from a still open device, then released");
-		igt_subtest("hotunbind-lateclose")
-			hotunbind_lateclose(&priv);
-
-		igt_fixture
-			recover(&priv);
-	}
-
-	igt_fixture
-		post_healthcheck(&priv);
-
-	igt_subtest_group {
-		igt_describe("Check if a still open device can be cleanly unplugged, then released");
-		igt_subtest("hotunplug-lateclose")
-			hotunplug_lateclose(&priv);
-
-		igt_fixture
-			recover(&priv);
-	}
-
-	igt_fixture
-		post_healthcheck(&priv);
-
-	igt_subtest_group {
-		igt_describe("Check if the driver can be cleanly rebound to a device after hotunbind-lateclose");
+		igt_describe("Check if the driver can be cleanly unbound from an open device, then released and rebound");
 		igt_subtest("hotunbind-rebind")
 			hotunbind_rebind(&priv);
 
@@ -546,7 +557,7 @@ igt_main
 		post_healthcheck(&priv);
 
 	igt_subtest_group {
-		igt_describe("Check if a device can be cleanly restored after hotunplug-lateclose");
+		igt_describe("Check if an open device can be cleanly unplugged, then released and restored");
 		igt_subtest("hotunplug-rescan")
 			hotunplug_rescan(&priv);
 
-- 
2.21.1



More information about the Intel-gfx-trybot mailing list