Unplug failures are almost impossible to reproduce in practice, so let's
add a debugfs knob to simulate those.

With this new knob, we can check this error case with the following
sequence:

 # echo 1 > /sys/kernel/debug/dri/128/fake_unplug_failure
 # <start-some-GPU-workload>
 # echo fb000000.gpu > /sys/module/panthor/drivers/platform\:panthor/unbind
 # <stop-the-GPU-workload>

Signed-off-by: Boris Brezillon <[email protected]>
---
 drivers/gpu/drm/panthor/panthor_device.c | 28 ++++++++++++++++++++++++++++
 drivers/gpu/drm/panthor/panthor_device.h |  8 ++++++++
 2 files changed, 36 insertions(+)

diff --git a/drivers/gpu/drm/panthor/panthor_device.c 
b/drivers/gpu/drm/panthor/panthor_device.c
index d037c89e6198..012edf5d590c 100644
--- a/drivers/gpu/drm/panthor/panthor_device.c
+++ b/drivers/gpu/drm/panthor/panthor_device.c
@@ -4,6 +4,7 @@
 /* Copyright 2023 Collabora ltd. */
 /* Copyright 2025 ARM Limited. All rights reserved. */
 
+#include <linux/debugfs.h>
 #include <linux/clk.h>
 #include <linux/mm.h>
 #include <linux/platform_device.h>
@@ -81,6 +82,8 @@ static int panthor_device_stop_before_unplug(struct 
panthor_device *ptdev)
         * procedure.
         */
        ret = panthor_hw_soft_reset(ptdev);
+       if (!ret && ptdev->unplug.fake_failure)
+               ret = -EIO;
 
        clk_disable_unprepare(ptdev->clks.core);
        return ret;
@@ -676,8 +679,33 @@ int panthor_device_suspend(struct device *dev)
 }
 
 #ifdef CONFIG_DEBUG_FS
+static int panthor_device_fake_unplug_failure_get(void *data, u64 *val)
+{
+       struct panthor_device *ptdev = data;
+
+       *val = ptdev->unplug.fake_failure ? 1 : 0;
+       return 0;
+}
+
+static int panthor_device_fake_unplug_failure_set(void *data, u64 val)
+{
+       struct panthor_device *ptdev = data;
+
+       ptdev->unplug.fake_failure = val ? true : false;
+       return 0;
+}
+
+DEFINE_DEBUGFS_ATTRIBUTE(panthor_device_fake_unplug_failure_fops,
+                        panthor_device_fake_unplug_failure_get,
+                        panthor_device_fake_unplug_failure_set, "%llu\n");
+
 void panthor_device_debugfs_init(struct drm_minor *minor)
 {
+       struct panthor_device *ptdev = container_of(minor->dev, struct 
panthor_device, base);
+
+       debugfs_create_file("fake_unplug_failure", 0644,
+                           minor->debugfs_root, ptdev,
+                           &panthor_device_fake_unplug_failure_fops);
        panthor_mmu_debugfs_init(minor);
        panthor_gem_debugfs_init(minor);
 }
diff --git a/drivers/gpu/drm/panthor/panthor_device.h 
b/drivers/gpu/drm/panthor/panthor_device.h
index 8c9177cf5da2..b2788373bfa9 100644
--- a/drivers/gpu/drm/panthor/panthor_device.h
+++ b/drivers/gpu/drm/panthor/panthor_device.h
@@ -282,6 +282,14 @@ struct panthor_device {
                 * any BO attached to an active VM, ...).
                 */
                bool leak_active_resources;
+
+               /**
+                * @fake_failure: When true, pretend the SOFT_RESET in the 
unplug path failed.
+                *
+                * This is important to check that we're doing the right thing 
in this very
+                * unlikely case.
+                */
+               bool fake_failure;
        } unplug;
 
        /** @reset: Reset related fields. */

-- 
2.55.0

Reply via email to