[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 10:43:59 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..bc23e8c05 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_dev < 0) {
+ priv->fd.sysfs_drv = openat(priv->fd.sysfs_dev, "driver",
+ O_DIRECTORY);
+ igt_assert_fd(priv->fd.sysfs_drv);
+ }
+
+ if (priv->fd.sysfs_dev < 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);
+
+ igt_fail_on_f(faccessat(priv->fd.sysfs_drv, priv->dev_bus_addr,
+ F_OK, 0),
+ "Device not restored!\n");
+
+ if (priv->fd.sysfs_dev == -1)
+ prepare(priv);
+}
+
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