drm/etnaviv: print MMU exception cause
authorChristian Gmeiner <christian.gmeiner@gmail.com>
Fri, 2 Dec 2022 09:19:29 +0000 (10:19 +0100)
committerJaehoon Chung <jh80.chung@samsung.com>
Wed, 13 Mar 2024 06:58:55 +0000 (15:58 +0900)
The MMU tells us the fault status. While the raw register value is
already printed, it's a bit more user friendly to translate the
fault reasons into human readable format.

Signed-off-by: Christian Gmeiner <christian.gmeiner@gmail.com>
Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de>
Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
(cherry picked from commit c32beb855feb23005a8599eca46174334fdf9e71)
Signed-off-by: Jaehoon Chung <jh80.chung@samsung.com>
drivers/gpu/drm/etnaviv/etnaviv_gpu.c

index 8f34e54658a09c6fa1a562f8d491844b2a453389..7a64386befc182b51ca092bc1a67dbb9164ce5ac 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/regulator/consumer.h>
+#include <linux/string_helpers.h>
 #include <linux/thermal.h>
 
 #include "etnaviv_cmdbuf.h"
@@ -1443,6 +1444,15 @@ static void sync_point_worker(struct work_struct *work)
 
 static void dump_mmu_fault(struct etnaviv_gpu *gpu)
 {
+       static const char *fault_reasons[] = {
+               "slave not present",
+               "page not present",
+               "write violation",
+               "out of bounds",
+               "read security violation",
+               "write security violation",
+       };
+
        u32 status_reg, status;
        int i;
 
@@ -1455,18 +1465,25 @@ static void dump_mmu_fault(struct etnaviv_gpu *gpu)
        dev_err_ratelimited(gpu->dev, "MMU fault status 0x%08x\n", status);
 
        for (i = 0; i < 4; i++) {
+               const char *reason = "unknown";
                u32 address_reg;
+               u32 mmu_status;
 
-               if (!(status & (VIVS_MMUv2_STATUS_EXCEPTION0__MASK << (i * 4))))
+               mmu_status = (status >> (i * 4)) & VIVS_MMUv2_STATUS_EXCEPTION0__MASK;
+               if (!mmu_status)
                        continue;
 
+               if ((mmu_status - 1) < ARRAY_SIZE(fault_reasons))
+                       reason = fault_reasons[mmu_status - 1];
+
                if (gpu->sec_mode == ETNA_SEC_NONE)
                        address_reg = VIVS_MMUv2_EXCEPTION_ADDR(i);
                else
                        address_reg = VIVS_MMUv2_SEC_EXCEPTION_ADDR;
 
-               dev_err_ratelimited(gpu->dev, "MMU %d fault addr 0x%08x\n", i,
-                                   gpu_read(gpu, address_reg));
+               dev_err_ratelimited(gpu->dev,
+                                   "MMU %d fault (%s) addr 0x%08x\n",
+                                   i, reason, gpu_read(gpu, address_reg));
        }
 }