[PATCH i-g-t 16/20] tests/core_hotunplug: Reload driver module on device restore

Janusz Krzysztofik janusz.krzysztofik at linux.intel.com
Fri Jul 24 12:09:00 UTC 2020


Potential workaround for DMAR errors on immediate driver binding to a
rediscovered device.

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

diff --git a/tests/core_hotunplug.c b/tests/core_hotunplug.c
index b4f2a2c5a..ccf680c18 100644
--- a/tests/core_hotunplug.c
+++ b/tests/core_hotunplug.c
@@ -64,25 +64,36 @@ static int local_close(int fd)
 
 static void prepare(struct hotunplug *priv)
 {
-	const char *filter = igt_device_filter_get(0), *sysfs_path;
+	const char *filter = igt_device_filter_get(0);
 
 	igt_assert(filter);
 
-	priv->dev_bus_addr = strrchr(filter, '/');
-	igt_assert(priv->dev_bus_addr++);
+	if (!priv->dev_bus_addr) {
+		priv->dev_bus_addr = strrchr(filter, '/');
+		igt_assert(priv->dev_bus_addr++);
+	}
 
-	sysfs_path = strchr(filter, ':');
-	igt_assert(sysfs_path++);
+	if (priv->fd.sysfs_dev < 0) {
+		const char *sysfs_path = strchr(filter, ':');
 
-	priv->fd.sysfs_dev = open(sysfs_path, O_DIRECTORY);
-	igt_assert_fd(priv->fd.sysfs_dev);
+		igt_assert(sysfs_path++);
 
-	priv->fd.sysfs_drv = openat(priv->fd.sysfs_dev, "driver", O_DIRECTORY);
-	igt_assert_fd(priv->fd.sysfs_drv);
+		priv->fd.sysfs_dev = open(sysfs_path, O_DIRECTORY);
+		igt_assert_fd(priv->fd.sysfs_dev);
+	}
 
-	priv->fd.sysfs_bus = openat(priv->fd.sysfs_dev, "subsystem/devices",
-				    O_DIRECTORY);
-	igt_assert_fd(priv->fd.sysfs_bus);
+	if (priv->fd.sysfs_drv < 0) {
+		priv->fd.sysfs_drv = openat(priv->fd.sysfs_dev, "driver",
+					    O_DIRECTORY);
+		igt_assert_fd(priv->fd.sysfs_drv);
+	}
+
+	if (priv->fd.sysfs_bus < 0) {
+		priv->fd.sysfs_bus = openat(priv->fd.sysfs_dev,
+					    "subsystem/devices",
+					    O_DIRECTORY);
+		igt_assert_fd(priv->fd.sysfs_bus);
+	}
 
 	priv->fd.sysfs_dev = local_close(priv->fd.sysfs_dev);
 	igt_warn_on_f(priv->fd.sysfs_dev != -1,
@@ -92,6 +103,9 @@ static void prepare(struct hotunplug *priv)
 /* Unbind the driver from the device */
 static void driver_unbind(struct hotunplug *priv, const char *prefix)
 {
+	igt_require_f(priv->fd.sysfs_drv >= 0,
+		      "Driver sysfs node file descriptor not available\n");
+
 	igt_debug("%sunbinding the driver from the device\n", prefix);
 
 	igt_set_timeout(60, "Driver unbind timeout!");
@@ -107,6 +121,9 @@ static void driver_unbind(struct hotunplug *priv, const char *prefix)
 /* Re-bind the driver to the device */
 static void driver_bind(struct hotunplug *priv)
 {
+	igt_require_f(priv->fd.sysfs_drv >= 0,
+		      "Driver sysfs node file descriptor not available\n");
+
 	igt_debug("rebinding the driver to the device\n");
 
 	igt_set_timeout(60, "Driver re-bind timeout!");
@@ -160,6 +177,26 @@ static void bus_rescan(struct hotunplug *priv)
 		      "Fakely unplugged device not rediscovered!\n");
 }
 
+static void device_restore(struct hotunplug *priv)
+{
+	priv->fd.sysfs_drv = local_close(priv->fd.sysfs_drv);
+	igt_assert_f(priv->fd.sysfs_drv == -1,
+		     "Driver sysfs node close failed\n");
+
+	igt_assert_eq(igt_i915_driver_unload(), IGT_EXIT_SUCCESS);
+
+	bus_rescan(priv);
+
+	igt_assert_eq(igt_i915_driver_load(NULL), IGT_EXIT_SUCCESS);
+
+	if (priv->fd.sysfs_dev == -1)
+		prepare(priv);
+
+	igt_fail_on_f(faccessat(priv->fd.sysfs_drv, priv->dev_bus_addr,
+				F_OK, 0),
+		      "Device not restored!\n");
+}
+
 static void cleanup(struct hotunplug *priv)
 {
 	priv->fd.drm = local_close(priv->fd.drm);
@@ -173,11 +210,10 @@ static void healthcheck(struct hotunplug *priv)
 
 	if (faccessat(priv->fd.sysfs_bus, priv->dev_bus_addr, F_OK, 0)) {
 		priv->failure = "Bus rescan failed!";
-		bus_rescan(priv);
+		device_restore(priv);
 		priv->failure = NULL;
-	}
 
-	if (faccessat(priv->fd.sysfs_drv, priv->dev_bus_addr, F_OK, 0)) {
+	} else if (faccessat(priv->fd.sysfs_drv, priv->dev_bus_addr, F_OK, 0)) {
 		priv->failure = "Driver re-bind failed!";
 		driver_bind(priv);
 		priv->failure = NULL;
@@ -246,6 +282,15 @@ static void unbind_rebind(struct hotunplug *priv)
 	driver_bind(priv);
 }
 
+static void unplug_restore(struct hotunplug *priv)
+{
+	priv->failure = "subtest failure";
+
+	device_unplug(priv, "");
+
+	device_restore(priv);
+}
+
 static void unplug_rescan(struct hotunplug *priv)
 {
 	priv->failure = "subtest failure";
@@ -282,7 +327,7 @@ static void hotunplug_lateclose(struct hotunplug *priv)
 
 	device_unplug(priv, "hot ");
 
-	bus_rescan(priv);
+	device_restore(priv);
 
 	igt_debug("late closing the removed device instance\n");
 	priv->fd.drm = local_close(priv->fd.drm);
@@ -294,7 +339,13 @@ static void hotunplug_lateclose(struct hotunplug *priv)
 igt_main
 {
 	struct hotunplug priv = {
-		.fd		= { .drm = -1, .sysfs_dev = -1, },
+		.fd		= {
+					.drm =		-1,
+					.sysfs_dev =	-1,
+					.sysfs_drv =	-1,
+					.sysfs_bus =	-1,
+		},
+		.dev_bus_addr	= NULL,
 		.failure	= NULL,
 	};
 
@@ -321,7 +372,7 @@ igt_main
 	}
 
 	igt_subtest_group {
-		igt_describe("Check if the driver can be cleanly unbound from a device believed to be closed");
+		igt_describe("Check if the driver can be cleanly unbound from a device believed to be closed, then rebound");
 		igt_subtest("unbind-rebind")
 			unbind_rebind(&priv);
 
@@ -333,7 +384,19 @@ igt_main
 		post_healthcheck(&priv);
 
 	igt_subtest_group {
-		igt_describe("Check if a device believed to be closed can be cleanly unplugged");
+		igt_describe("Check if a device believed to be closed can be cleanly unplugged, then restored");
+		igt_subtest("unplug-restore")
+			unplug_restore(&priv);
+
+		igt_fixture
+			healthcheck(&priv);
+	}
+
+	igt_fixture
+		post_healthcheck(&priv);
+
+	igt_subtest_group {
+		igt_describe("Check if a device believed to be closed can be cleanly unplugged, then rediscovered");
 		igt_subtest("unplug-rescan")
 			unplug_rescan(&priv);
 
-- 
2.21.1



More information about the Intel-gfx-trybot mailing list