drm/msm/snapshot: fix dumping of the unaligned regions

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: 98659487b8 ("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>
This commit is contained in:
Dmitry Baryshkov 2026-05-16 14:53:45 +03:00 committed by Rob Clark
parent 3392291fc5
commit 76824d2467

View 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);