]> 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)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 1 Jun 2026 15:46:30 +0000 (17:46 +0200)
[ Upstream commit 76824d2467feb1828b745d6add2541918d7be3da ]

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>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/gpu/drm/msm/disp/msm_disp_snapshot_util.c

index 4d55e3cf570f0b818b9387f3e7763294e1f8e0f4..a966a03167cc0c7e263648e572f59374904011a3 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;
 
        if (!(*reg))
                *reg = kvzalloc(len_padded, GFP_KERNEL);
@@ -51,8 +51,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) {
@@ -61,6 +61,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++) {
@@ -70,6 +71,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)
@@ -189,7 +201,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);