drm/panfrost: Perform hard reset to recover GPU if soft reset fails
authorAngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Thu, 9 Nov 2023 10:25:38 +0000 (11:25 +0100)
committerSteven Price <steven.price@arm.com>
Fri, 10 Nov 2023 14:11:25 +0000 (14:11 +0000)
Even though soft reset should ideally never fail, during development of
some power management features I managed to get some bits wrong: this
resulted in GPU soft reset failures, where the GPU was never able to
recover, not even after suspend/resume cycles, meaning that the only
way to get functionality back was to reboot the machine.

Perform a hard reset after a soft reset failure to be able to recover
the GPU during runtime (so, without any machine reboot).

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Reviewed-by: Steven Price <steven.price@arm.com>
Signed-off-by: Steven Price <steven.price@arm.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20231109102543.42971-2-angelogioacchino.delregno@collabora.com
drivers/gpu/drm/panfrost/panfrost_gpu.c
drivers/gpu/drm/panfrost/panfrost_regs.h

index 97f097ee5c1da08372af3c6fa78f2b93746b6e20..c9469bf7770a454fe6c741484172fc088c0abf51 100644 (file)
@@ -60,14 +60,21 @@ int panfrost_gpu_soft_reset(struct panfrost_device *pfdev)
 
        gpu_write(pfdev, GPU_INT_MASK, 0);
        gpu_write(pfdev, GPU_INT_CLEAR, GPU_IRQ_RESET_COMPLETED);
-       gpu_write(pfdev, GPU_CMD, GPU_CMD_SOFT_RESET);
 
+       gpu_write(pfdev, GPU_CMD, GPU_CMD_SOFT_RESET);
        ret = readl_relaxed_poll_timeout(pfdev->iomem + GPU_INT_RAWSTAT,
                val, val & GPU_IRQ_RESET_COMPLETED, 100, 10000);
 
        if (ret) {
-               dev_err(pfdev->dev, "gpu soft reset timed out\n");
-               return ret;
+               dev_err(pfdev->dev, "gpu soft reset timed out, attempting hard reset\n");
+
+               gpu_write(pfdev, GPU_CMD, GPU_CMD_HARD_RESET);
+               ret = readl_relaxed_poll_timeout(pfdev->iomem + GPU_INT_RAWSTAT, val,
+                                                val & GPU_IRQ_RESET_COMPLETED, 100, 10000);
+               if (ret) {
+                       dev_err(pfdev->dev, "gpu hard reset timed out\n");
+                       return ret;
+               }
        }
 
        gpu_write(pfdev, GPU_INT_CLEAR, GPU_IRQ_MASK_ALL);
index 55ec807550b3fb0992245037764cb10682827801..c25743b05c551453cd6ee0ae3a26565168e05753 100644 (file)
@@ -44,6 +44,7 @@
         GPU_IRQ_MULTIPLE_FAULT)
 #define GPU_CMD                                0x30
 #define   GPU_CMD_SOFT_RESET           0x01
+#define   GPU_CMD_HARD_RESET           0x02
 #define   GPU_CMD_PERFCNT_CLEAR                0x03
 #define   GPU_CMD_PERFCNT_SAMPLE       0x04
 #define   GPU_CMD_CYCLE_COUNT_START    0x05