]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
drm/msm/snapshot: fix dumping of the unaligned regions
authorDmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Sat, 16 May 2026 11:53:45 +0000 (14:53 +0300)
committerRob Clark <robin.clark@oss.qualcomm.com>
Sat, 16 May 2026 14:20:04 +0000 (07:20 -0700)
The snapshotting code internally aligns data segment to 16 bytes. This
works fine for DPU code (where most of the regions are aligned), but
fails for snapshotting of the DSI data (because DSI data region is
shifted by 4 bytes). Fix the code by removing length alignment and by
accurately printing last registers in the region. While reworking the
code also fix the 16x memory overallocation in
msm_disp_state_dump_regs().

Fixes: 98659487b845 ("drm/msm: add support to take dpu snapshot")
Reported-by: Salendarsingh Gaud <sgaud@qti.qualcomm.com>
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Patchwork: https://patchwork.freedesktop.org/patch/725449/
Message-ID: <20260516-msm-fix-dsi-dump-2-v2-1-9e49fb2d240e@oss.qualcomm.com>
Signed-off-by: Rob Clark <robin.clark@oss.qualcomm.com>
drivers/gpu/drm/msm/disp/msm_disp_snapshot_util.c

index 636bcb65a2a4b9a0051b4ce084c008bb3f1a033a..01a7019f5d67dd83024b5c221421e91f315aa802 100644 (file)
@@ -9,7 +9,7 @@
 
 #include "msm_disp_snapshot.h"
 
-static void msm_disp_state_dump_regs(u32 **reg, u32 aligned_len, void __iomem *base_addr)
+static void msm_disp_state_dump_regs(u32 **reg, u32 len, void __iomem *base_addr)
 {
        u32 len_padded;
        u32 num_rows;
@@ -19,11 +19,11 @@ static void msm_disp_state_dump_regs(u32 **reg, u32 aligned_len, void __iomem *b
        void __iomem *end_addr;
        int i;
 
-       len_padded = aligned_len * REG_DUMP_ALIGN;
-       num_rows = aligned_len / REG_DUMP_ALIGN;
+       len_padded = round_up(len, REG_DUMP_ALIGN);
+       num_rows = DIV_ROUND_UP(len, REG_DUMP_ALIGN);
 
        addr = base_addr;
-       end_addr = base_addr + aligned_len;
+       end_addr = base_addr + len;
 
        *reg = kvzalloc(len_padded, GFP_KERNEL);
        if (!*reg)
@@ -48,8 +48,8 @@ static void msm_disp_state_dump_regs(u32 **reg, u32 aligned_len, void __iomem *b
 static void msm_disp_state_print_regs(const u32 *dump_addr, u32 len,
                void __iomem *base_addr, struct drm_printer *p)
 {
+       void __iomem *addr, *end_addr;
        int i;
-       void __iomem *addr;
        u32 num_rows;
 
        if (!dump_addr) {
@@ -58,6 +58,7 @@ static void msm_disp_state_print_regs(const u32 *dump_addr, u32 len,
        }
 
        addr = base_addr;
+       end_addr = base_addr + len;
        num_rows = len / REG_DUMP_ALIGN;
 
        for (i = 0; i < num_rows; i++) {
@@ -67,6 +68,17 @@ static void msm_disp_state_print_regs(const u32 *dump_addr, u32 len,
                                dump_addr[i * 4 + 2], dump_addr[i * 4 + 3]);
                addr += REG_DUMP_ALIGN;
        }
+
+       if (addr != end_addr) {
+               drm_printf(p, "0x%lx : %08x",
+                          (unsigned long)(addr - base_addr),
+                          dump_addr[i * 4]);
+               if (addr + 0x4 < end_addr)
+                       drm_printf(p, " %08x", dump_addr[i * 4 + 1]);
+               if (addr + 0x8 < end_addr)
+                       drm_printf(p, " %08x", dump_addr[i * 4 + 2]);
+               drm_printf(p, "\n");
+       }
 }
 
 void msm_disp_state_print(struct msm_disp_state *state, struct drm_printer *p)
@@ -185,7 +197,7 @@ void msm_disp_snapshot_add_block(struct msm_disp_state *disp_state, u32 len,
        va_end(va);
 
        INIT_LIST_HEAD(&new_blk->node);
-       new_blk->size = ALIGN(len, REG_DUMP_ALIGN);
+       new_blk->size = len;
        new_blk->base_addr = base_addr;
 
        msm_disp_state_dump_regs(&new_blk->state, new_blk->size, base_addr);