From afafffe4ac3a7308c7cc9f9d873ed71e71526f3e Mon Sep 17 00:00:00 2001 From: Andhavarapu Karthik Date: Sun, 14 Feb 2021 15:54:59 -0800 Subject: [PATCH 1/7] disp: msm: refactor debugbus to use same helpers Refactor the debugbus read/logging for sde/dsi/vbif/lutdma to use the same helpers. Use function pointers to read/write specific hw block operations. Remove the DBGBUS_FLAGS_DSPP and related checks as it is not used. Increase the debugbus block/test-point ranges for all the blocks to log all the test-points used by hardware. Change-Id: I07b23d21f9c556eb7575b892f87ab94adfe41116 Signed-off-by: Andhavarapu Karthik Signed-off-by: Veera Sundaram Sankaran --- msm/sde_dbg.c | 905 +++++++++++++++++--------------------------------- 1 file changed, 297 insertions(+), 608 deletions(-) diff --git a/msm/sde_dbg.c b/msm/sde_dbg.c index 12ca18734ebc..4841c3f32878 100644 --- a/msm/sde_dbg.c +++ b/msm/sde_dbg.c @@ -33,24 +33,24 @@ #define RANGE_NAME_LEN 40 #define REG_BASE_NAME_LEN 80 -#define DBGBUS_FLAGS_DSPP BIT(0) -#define DBGBUS_DSPP_STATUS 0x34C - #define DBGBUS_NAME_SDE "sde" #define DBGBUS_NAME_VBIF_RT "vbif_rt" #define DBGBUS_NAME_DSI "dsi" #define DBGBUS_NAME_LUTDMA "reg_dma" /* offsets from LUTDMA top address for the debug buses */ -#define DBGBUS_LUTDMA_0 0x1E8 -#define DBGBUS_LUTDMA_1 0x5E8 +#define LUTDMA_0_DEBUG_BUS_CTRL 0x1e8 +#define LUTDMA_0_DEBUG_BUS_STATUS 0x1ec +#define LUTDMA_1_DEBUG_BUS_CTRL 0x5e8 +#define LUTDMA_1_DEBUG_BUS_STATUS 0x5ec /* offsets from sde top address for the debug buses */ -#define DBGBUS_SSPP0 0x188 -#define DBGBUS_AXI_INTF 0x194 -#define DBGBUS_SSPP1 0x298 -#define DBGBUS_DSPP 0x348 -#define DBGBUS_PERIPH 0x418 +#define DBGBUS_SSPP0 0x188 +#define DBGBUS_AXI_INTF 0x194 +#define DBGBUS_SSPP1 0x298 +#define DBGBUS_DSPP 0x348 +#define DBGBUS_DSPP_STATUS 0x34C +#define DBGBUS_PERIPH 0x418 /* offsets from DSI CTRL base address for the DSI debug buses */ #define DSI_DEBUG_BUS_CTRL 0x0124 @@ -63,6 +63,8 @@ /* following offsets are with respect to MDP VBIF base for DBG BUS access */ #define MMSS_VBIF_CLKON 0x4 #define MMSS_VBIF_TEST_BUS_OUT_CTRL 0x210 +#define MMSS_VBIF_TEST_BUS1_CTRL0 0x214 +#define MMSS_VBIF_TEST_BUS2_CTRL0 0x21c #define MMSS_VBIF_TEST_BUS_OUT 0x230 /* Vbif error info */ @@ -152,6 +154,7 @@ struct sde_dbg_reg_base { struct sde_debug_bus_entry { u32 wr_addr; + u32 rd_addr; u32 block_id; u32 block_id_max; u32 test_id; @@ -161,26 +164,6 @@ struct sde_debug_bus_entry { u32 block_id_off, u32 test_id_off); }; -struct vbif_debug_bus_entry { - u32 disable_bus_addr; - u32 block_bus_addr; - u32 bit_offset; - u32 block_cnt; - u32 test_pnt_start; - u32 test_pnt_cnt; -}; - -struct dsi_debug_bus_entry { - u32 mux; - u32 sel; -}; - -struct lutdma_debug_bus_entry { - u32 wr_addr; - bool read_engine; - u32 indicies; -}; - struct sde_dbg_dsi_ctrl_list_entry { const char *name; void __iomem *base; @@ -191,7 +174,6 @@ struct sde_dbg_debug_bus_common { char *name; u32 enable_mask; bool include_in_deferred_work; - u32 flags; u32 entries_size; u32 *dumped_content; u32 content_idx; @@ -202,21 +184,9 @@ struct sde_dbg_sde_debug_bus { struct sde_dbg_debug_bus_common cmn; struct sde_debug_bus_entry *entries; u32 top_blk_off; -}; - -struct sde_dbg_vbif_debug_bus { - struct sde_dbg_debug_bus_common cmn; - struct vbif_debug_bus_entry *entries; -}; - -struct sde_dbg_dsi_debug_bus { - struct sde_dbg_debug_bus_common cmn; - struct dsi_debug_bus_entry *entries; -}; - -struct sde_dbg_lutdma_debug_bus { - struct sde_dbg_debug_bus_common cmn; - struct lutdma_debug_bus_entry *entries; + u32 (*read_tp)(void __iomem *mem_base, u32 wr_addr, u32 rd_addr, u32 block_id, u32 test_id); + void (*clear_tp)(void __iomem *mem_base, u32 wr_addr); + void (*disable_block)(void __iomem *mem_base, u32 wr_addr); }; /** @@ -251,10 +221,10 @@ struct sde_dbg_regbuf { * @enable_reg_dump: whether to dump registers into memory, kernel log, or both * @dbgbus_sde: debug bus structure for the sde * @dbgbus_vbif_rt: debug bus structure for the realtime vbif + * @dbgbus_dsi: debug bus structure for the dsi * @dbgbus_lutdma: debug bus structure for the lutdma hw * @dump_all: dump all entries in register dump * @dump_secure: dump entries excluding few as it is in secure-session - * @dsi_dbg_bus: dump dsi debug bus register * @regbuf: buffer data to track the register dumping in hw recovery * @cur_evt_index: index used for tracking event logs dump in hw recovery * @cur_reglog_index: index used for tracking register logs dump in hw recovery @@ -278,9 +248,9 @@ struct sde_dbg_base { u32 enable_reg_dump; struct sde_dbg_sde_debug_bus dbgbus_sde; - struct sde_dbg_vbif_debug_bus dbgbus_vbif_rt; - struct sde_dbg_dsi_debug_bus dbgbus_dsi; - struct sde_dbg_lutdma_debug_bus dbgbus_lutdma; + struct sde_dbg_sde_debug_bus dbgbus_vbif_rt; + struct sde_dbg_sde_debug_bus dbgbus_dsi; + struct sde_dbg_sde_debug_bus dbgbus_lutdma; bool dump_all; bool dump_secure; u32 debugfs_ctrl; @@ -359,109 +329,67 @@ static void _sde_debug_bus_ppb1_dump(void __iomem *mem_base, } static struct sde_debug_bus_entry dbg_bus_sde[] = { - - { DBGBUS_SSPP0, 0, 256, 0, 8 }, - { DBGBUS_AXI_INTF, 0, 256, 0, 8 }, - { DBGBUS_SSPP1, 0, 256, 0, 8 }, - { DBGBUS_DSPP, 0, 256, 0, 32 }, - { DBGBUS_PERIPH, 0, 256, 0, 8 }, + { DBGBUS_SSPP0, DBGBUS_DSPP_STATUS, 0, 74, 0, 32 }, + { DBGBUS_SSPP1, DBGBUS_DSPP_STATUS, 0, 74, 0, 32 }, + { DBGBUS_DSPP, DBGBUS_DSPP_STATUS, 0, 137, 0, 32 }, + { DBGBUS_PERIPH, DBGBUS_DSPP_STATUS, 0, 78, 0, 32 }, + { DBGBUS_AXI_INTF, DBGBUS_DSPP_STATUS, 0, 63, 0, 32 }, /* ppb_0 */ - { DBGBUS_DSPP, 31, 1, 0, 1, _sde_debug_bus_ppb0_dump }, - { DBGBUS_DSPP, 33, 1, 0, 1, _sde_debug_bus_ppb0_dump }, - { DBGBUS_DSPP, 35, 1, 0, 1, _sde_debug_bus_ppb0_dump }, - { DBGBUS_DSPP, 42, 1, 0, 1, _sde_debug_bus_ppb0_dump }, - { DBGBUS_DSPP, 47, 1, 0, 1, _sde_debug_bus_ppb0_dump }, - { DBGBUS_DSPP, 49, 1, 0, 1, _sde_debug_bus_ppb0_dump }, + { DBGBUS_DSPP, DBGBUS_DSPP_STATUS, 31, 1, 0, 1, _sde_debug_bus_ppb0_dump }, + { DBGBUS_DSPP, DBGBUS_DSPP_STATUS, 33, 1, 0, 1, _sde_debug_bus_ppb0_dump }, + { DBGBUS_DSPP, DBGBUS_DSPP_STATUS, 35, 1, 0, 1, _sde_debug_bus_ppb0_dump }, + { DBGBUS_DSPP, DBGBUS_DSPP_STATUS, 42, 1, 0, 1, _sde_debug_bus_ppb0_dump }, + { DBGBUS_DSPP, DBGBUS_DSPP_STATUS, 47, 1, 0, 1, _sde_debug_bus_ppb0_dump }, + { DBGBUS_DSPP, DBGBUS_DSPP_STATUS, 49, 1, 0, 1, _sde_debug_bus_ppb0_dump }, /* ppb_1 */ - { DBGBUS_DSPP, 32, 1, 0, 1, _sde_debug_bus_ppb1_dump }, - { DBGBUS_DSPP, 34, 1, 0, 1, _sde_debug_bus_ppb1_dump }, - { DBGBUS_DSPP, 36, 1, 0, 1, _sde_debug_bus_ppb1_dump }, - { DBGBUS_DSPP, 43, 1, 0, 1, _sde_debug_bus_ppb1_dump }, - { DBGBUS_DSPP, 48, 1, 0, 1, _sde_debug_bus_ppb1_dump }, - { DBGBUS_DSPP, 50, 1, 0, 1, _sde_debug_bus_ppb1_dump }, + { DBGBUS_DSPP, DBGBUS_DSPP_STATUS, 32, 1, 0, 1, _sde_debug_bus_ppb1_dump }, + { DBGBUS_DSPP, DBGBUS_DSPP_STATUS, 34, 1, 0, 1, _sde_debug_bus_ppb1_dump }, + { DBGBUS_DSPP, DBGBUS_DSPP_STATUS, 36, 1, 0, 1, _sde_debug_bus_ppb1_dump }, + { DBGBUS_DSPP, DBGBUS_DSPP_STATUS, 43, 1, 0, 1, _sde_debug_bus_ppb1_dump }, + { DBGBUS_DSPP, DBGBUS_DSPP_STATUS, 48, 1, 0, 1, _sde_debug_bus_ppb1_dump }, + { DBGBUS_DSPP, DBGBUS_DSPP_STATUS, 50, 1, 0, 1, _sde_debug_bus_ppb1_dump }, /* crossbar */ - { DBGBUS_DSPP, 0, 1, 0, 1, _sde_debug_bus_xbar_dump }, + { DBGBUS_DSPP, DBGBUS_DSPP_STATUS, 0, 1, 0, 1, _sde_debug_bus_xbar_dump }, /* blend */ - { DBGBUS_DSPP, 63, 1, 7, 1, _sde_debug_bus_lm_dump }, - { DBGBUS_DSPP, 70, 1, 7, 1, _sde_debug_bus_lm_dump }, - { DBGBUS_DSPP, 77, 1, 7, 1, _sde_debug_bus_lm_dump }, - { DBGBUS_DSPP, 110, 1, 7, 1, _sde_debug_bus_lm_dump }, - { DBGBUS_DSPP, 96, 1, 7, 1, _sde_debug_bus_lm_dump }, - { DBGBUS_DSPP, 124, 1, 7, 1, _sde_debug_bus_lm_dump }, - + { DBGBUS_DSPP, DBGBUS_DSPP_STATUS, 63, 1, 7, 1, _sde_debug_bus_lm_dump }, + { DBGBUS_DSPP, DBGBUS_DSPP_STATUS, 70, 1, 7, 1, _sde_debug_bus_lm_dump }, + { DBGBUS_DSPP, DBGBUS_DSPP_STATUS, 77, 1, 7, 1, _sde_debug_bus_lm_dump }, + { DBGBUS_DSPP, DBGBUS_DSPP_STATUS, 110, 1, 7, 1, _sde_debug_bus_lm_dump }, + { DBGBUS_DSPP, DBGBUS_DSPP_STATUS, 96, 1, 7, 1, _sde_debug_bus_lm_dump }, + { DBGBUS_DSPP, DBGBUS_DSPP_STATUS, 124, 1, 7, 1, _sde_debug_bus_lm_dump } }; -static struct vbif_debug_bus_entry vbif_dbg_bus[] = { - {0x214, 0x21c, 16, 2, 0x0, 0xd}, /* arb clients */ - {0x214, 0x21c, 16, 2, 0x80, 0xc0}, /* arb clients */ - {0x214, 0x21c, 16, 2, 0x100, 0x140}, /* arb clients */ - {0x214, 0x21c, 0, 16, 0x0, 0xf}, /* xin blocks - axi side */ - {0x214, 0x21c, 0, 16, 0x80, 0xa4}, /* xin blocks - axi side */ - {0x214, 0x21c, 0, 15, 0x100, 0x124}, /* xin blocks - axi side */ - {0x21c, 0x214, 0, 14, 0, 0xc}, /* xin blocks - clock side */ +static struct sde_debug_bus_entry vbif_dbg_bus[] = { + { MMSS_VBIF_TEST_BUS1_CTRL0, MMSS_VBIF_TEST_BUS_OUT, 0, 15, 0, 512}, + { MMSS_VBIF_TEST_BUS2_CTRL0, MMSS_VBIF_TEST_BUS_OUT, 0, 18, 0, 512}, }; -static struct dsi_debug_bus_entry dsi_dbg_bus[] = { - {0, 0x00}, {1, 0x00}, {2, 0x00}, {3, 0x00}, - {0, 0x01}, {1, 0x01}, {2, 0x01}, {3, 0x01}, - {0, 0x02}, {1, 0x02}, {2, 0x02}, {3, 0x02}, - {0, 0x03}, {1, 0x03}, {2, 0x03}, {3, 0x03}, - {0, 0x04}, {1, 0x04}, {2, 0x04}, {3, 0x04}, - {0, 0x05}, {1, 0x05}, {2, 0x05}, {3, 0x05}, - {0, 0x06}, {1, 0x06}, {2, 0x06}, {3, 0x06}, - {0, 0x07}, {1, 0x07}, {2, 0x07}, {3, 0x07}, - {0, 0x08}, {1, 0x08}, {2, 0x08}, {3, 0x08}, - {0, 0x0a}, {1, 0x0a}, {2, 0x0a}, {3, 0x0a}, - {0, 0x0b}, {1, 0x0b}, {2, 0x0b}, {3, 0x0b}, - {0, 0x0c}, {1, 0x0c}, {2, 0x0c}, {3, 0x0c}, - {0, 0x0d}, {1, 0x0d}, {2, 0x0d}, {3, 0x0d}, - {0, 0x0e}, {1, 0x0e}, {2, 0x0e}, {3, 0x0e}, - {0, 0x0f}, {1, 0x0f}, {2, 0x0f}, {3, 0x0f}, - {0, 0x10}, {1, 0x10}, {2, 0x10}, {3, 0x10}, - {0, 0x11}, {1, 0x11}, {2, 0x11}, {3, 0x11}, - {0, 0x14}, {1, 0x14}, {2, 0x14}, {3, 0x14}, - {0, 0x15}, {1, 0x15}, {2, 0x15}, {3, 0x15}, - {0, 0x16}, {1, 0x16}, {2, 0x16}, {3, 0x16}, - {0, 0x17}, {1, 0x17}, {2, 0x17}, {3, 0x17}, - {0, 0x18}, {1, 0x18}, {2, 0x18}, {3, 0x18}, - {0, 0x19}, {1, 0x19}, {2, 0x19}, {3, 0x19}, - {0, 0x1a}, {1, 0x1a}, {2, 0x1a}, {3, 0x1a}, - {0, 0x1b}, {1, 0x1b}, {2, 0x1b}, {3, 0x1b}, - {0, 0x1c}, {1, 0x1c}, {2, 0x1c}, {3, 0x1c}, - {0, 0x1d}, {1, 0x1d}, {2, 0x1d}, {3, 0x1d}, - {0, 0x1e}, {1, 0x1e}, {2, 0x1e}, {3, 0x1e}, - {0, 0x1f}, {1, 0x1f}, {2, 0x1f}, {3, 0x1f}, - {0, 0x20}, {1, 0x20}, {2, 0x20}, {3, 0x20}, - {0, 0x21}, {1, 0x21}, {2, 0x21}, {3, 0x21}, - {0, 0x22}, {1, 0x22}, {2, 0x22}, {3, 0x22}, - {0, 0x23}, {1, 0x23}, {2, 0x23}, {3, 0x23}, - {0, 0x24}, {1, 0x24}, {2, 0x24}, {3, 0x24}, - {0, 0x25}, {1, 0x25}, {2, 0x25}, {3, 0x25}, - {0, 0x28}, {1, 0x28}, {2, 0x28}, {3, 0x28}, - {0, 0x29}, {1, 0x29}, {2, 0x29}, {3, 0x29}, - {0, 0x2a}, {1, 0x2a}, {2, 0x2a}, {3, 0x2a}, - {0, 0x2b}, {1, 0x2b}, {2, 0x2b}, {3, 0x2b}, - {0, 0x2c}, {1, 0x2c}, {2, 0x2c}, {3, 0x2c}, - {0, 0x32}, {1, 0x32}, {2, 0x32}, {3, 0x32}, - {0, 0x33}, {1, 0x33}, {2, 0x33}, {3, 0x33}, - {0, 0x34}, {1, 0x34}, {2, 0x34}, {3, 0x34}, - {0, 0x35}, {1, 0x35}, {2, 0x35}, {3, 0x35}, - {0, 0x36}, {1, 0x36}, {2, 0x36}, {3, 0x36}, - {0, 0x37}, {1, 0x37}, {2, 0x37}, {3, 0x37}, - {0, 0x38}, {1, 0x38}, {2, 0x38}, {3, 0x38}, - {0, 0x39}, {1, 0x39}, {2, 0x39}, {3, 0x39}, - {0, 0x3c}, {0, 0x3d}, {0, 0x3e}, {0, 0x3f}, +static struct sde_debug_bus_entry dsi_dbg_bus[] = { + {DSI_DEBUG_BUS_CTRL, DSI_DEBUG_BUS, 0, 4, 0, 64}, }; -static struct lutdma_debug_bus_entry dbg_bus_lutdma_lahaina[] = { - { DBGBUS_LUTDMA_0, false, 1024 }, - { DBGBUS_LUTDMA_0, true, 1024 }, - { DBGBUS_LUTDMA_1, false, 1024 }, - { DBGBUS_LUTDMA_1, true, 1024 }, +static struct sde_debug_bus_entry dbg_bus_lutdma[] = { + { LUTDMA_0_DEBUG_BUS_CTRL, LUTDMA_0_DEBUG_BUS_STATUS, 0, 1, 0, 12 }, + { LUTDMA_0_DEBUG_BUS_CTRL, LUTDMA_0_DEBUG_BUS_STATUS, 0, 1, 256, 1 }, + { LUTDMA_0_DEBUG_BUS_CTRL, LUTDMA_0_DEBUG_BUS_STATUS, 0, 1, 512, 4 }, + { LUTDMA_0_DEBUG_BUS_CTRL, LUTDMA_0_DEBUG_BUS_STATUS, 0, 1, 768, 1 }, + { LUTDMA_0_DEBUG_BUS_CTRL, LUTDMA_0_DEBUG_BUS_STATUS, 0, 1, 8192, 2 }, + { LUTDMA_0_DEBUG_BUS_CTRL, LUTDMA_0_DEBUG_BUS_STATUS, 0, 1, 8448, 1 }, + { LUTDMA_0_DEBUG_BUS_CTRL, LUTDMA_0_DEBUG_BUS_STATUS, 0, 1, 8704, 1 }, + { LUTDMA_0_DEBUG_BUS_CTRL, LUTDMA_0_DEBUG_BUS_STATUS, 0, 1, 8960, 1 }, + + { LUTDMA_1_DEBUG_BUS_CTRL, LUTDMA_1_DEBUG_BUS_STATUS, 0, 1, 0, 12 }, + { LUTDMA_1_DEBUG_BUS_CTRL, LUTDMA_1_DEBUG_BUS_STATUS, 0, 1, 256, 1 }, + { LUTDMA_1_DEBUG_BUS_CTRL, LUTDMA_1_DEBUG_BUS_STATUS, 0, 1, 512, 4 }, + { LUTDMA_1_DEBUG_BUS_CTRL, LUTDMA_1_DEBUG_BUS_STATUS, 0, 1, 768, 1 }, + { LUTDMA_1_DEBUG_BUS_CTRL, LUTDMA_1_DEBUG_BUS_STATUS, 0, 1, 8192, 2 }, + { LUTDMA_1_DEBUG_BUS_CTRL, LUTDMA_1_DEBUG_BUS_STATUS, 0, 1, 8448, 1 }, + { LUTDMA_1_DEBUG_BUS_CTRL, LUTDMA_1_DEBUG_BUS_STATUS, 0, 1, 8704, 1 }, + { LUTDMA_1_DEBUG_BUS_CTRL, LUTDMA_1_DEBUG_BUS_STATUS, 0, 1, 8960, 1 }, }; /** @@ -803,283 +731,94 @@ static struct sde_dbg_reg_base *_sde_dump_get_blk_addr(const char *blk_name) return NULL; } -static void _sde_dbg_dump_sde_bus_entry( - struct sde_debug_bus_entry *head, void __iomem *mem_base, - u32 *dump_addr, struct sde_dbg_sde_debug_bus *bus, bool in_log, - bool in_mem) +static u32 _sde_dbg_cmn_read_test_point(void __iomem *mem_base, u32 wr_addr, u32 rd_addr, u32 val) { - int i, j; - u32 status = 0; - u32 offset; - - if (!dump_addr && !in_log && !in_mem) - return; - - for (i = 0; i < head->block_id_max; i++) { - for (j = 0; j < head->test_id_max; j++) { - if (head->test_id + j > EXT_TEST_GROUP_SEL_EN) - writel_relaxed(TEST_EXT_MASK( - (head->block_id + i), - (head->test_id + j)), - mem_base + head->wr_addr); - else - writel_relaxed(TEST_MASK((head->block_id + i), - (head->test_id + j)), - mem_base + head->wr_addr); - wmb(); /* make sure test bits were written */ - - if (bus->cmn.flags & DBGBUS_FLAGS_DSPP) { - offset = DBGBUS_DSPP_STATUS; - /* keep DSPP test point enabled */ - if (head->wr_addr != DBGBUS_DSPP) - writel_relaxed(DSPP_DEBUGBUS_CTRL_EN, - mem_base + DBGBUS_DSPP); - } else { - offset = head->wr_addr + 0x4; - } - - status = readl_relaxed(mem_base + offset); - - if (in_log) - dev_info(sde_dbg_base.dev, - "waddr=0x%x blk=%d tst=%d val=0x%x\n", - head->wr_addr, - head->block_id + i, - head->test_id + j, status); - - if (dump_addr && in_mem) { - *dump_addr++ = head->wr_addr; - *dump_addr++ = head->block_id + i; - *dump_addr++ = head->test_id + j; - *dump_addr++ = status; - } - - if (head->analyzer) - head->analyzer(mem_base, head, status, i, j); - /* Disable debug bus once we are done */ - writel_relaxed(0x0, mem_base + head->wr_addr); - if (bus->cmn.flags & DBGBUS_FLAGS_DSPP && - head->wr_addr != DBGBUS_DSPP) - writel_relaxed(0x0, mem_base + DBGBUS_DSPP); - } - } + writel_relaxed(val, mem_base + wr_addr); + wmb(); /* make sure debug-bus test point is enabled */ + return readl_relaxed(mem_base + rd_addr); } -static void _sde_dbg_dump_sde_dbg_bus(struct sde_dbg_sde_debug_bus *bus) +static void _sde_dbg_cmn_clear_test_point(void __iomem *mem_base, u32 wr_addr) { - bool in_log, in_mem; - u32 **dump_mem = NULL; - u32 *dump_addr = NULL; - u32 bus_size; - struct sde_debug_bus_entry *head; - int list_size = 0; - int i; - void __iomem *mem_base = NULL; - struct sde_dbg_reg_base *reg_base; - int rc; - - if (!bus || !bus->cmn.entries_size) - return; - list_for_each_entry(reg_base, &sde_dbg_base.reg_base_list, - reg_base_head) - if (strlen(reg_base->name) && - !strcmp(reg_base->name, bus->cmn.name)) - mem_base = reg_base->base + bus->top_blk_off; - - if (!mem_base) { - pr_err("unable to find mem_base for %s\n", bus->cmn.name); - return; - } - - bus_size = bus->cmn.entries_size; - dump_mem = &bus->cmn.dumped_content; - - if (!dump_mem || !bus->entries || !bus_size) - return; - /* allocate memory for each test id */ - for (i = 0; i < bus_size; i++) { - head = bus->entries + i; - list_size += (head->block_id_max * head->test_id_max); - } - - list_size *= 16; - - in_log = (bus->cmn.enable_mask & SDE_DBG_DUMP_IN_LOG); - in_mem = (bus->cmn.enable_mask & SDE_DBG_DUMP_IN_MEM); - - if (!in_log && !in_mem) - return; - - dev_info(sde_dbg_base.dev, "======== start %s dump =========\n", - bus->cmn.name); - - if (in_mem) { - if (!(*dump_mem)) { - *dump_mem = devm_kzalloc(sde_dbg_base.dev, list_size, - GFP_KERNEL); - bus->cmn.content_size = list_size / sizeof(u32); - } - - if (*dump_mem) { - dump_addr = *dump_mem; - dev_info(sde_dbg_base.dev, - "%s: start_addr:0x%pK len:0x%x\n", - __func__, dump_addr, list_size); - if (sde_mini_dump_add_region("sde_dbgbus", list_size, - *dump_mem) < 0) - pr_err("minidump add sde debug bus failed\n"); - } else { - in_mem = false; - pr_err("dump_mem: allocation fails\n"); - } - } - - rc = pm_runtime_get_sync(sde_dbg_base.dev); - if (rc < 0) { - pr_err("failed to enable power %d\n", rc); - return; - } - - for (i = 0; i < bus_size; i++) { - head = bus->entries + i; - _sde_dbg_dump_sde_bus_entry(head, mem_base, dump_addr, - bus, in_log, in_mem); - if (dump_addr) - dump_addr += (head->block_id_max * - head->test_id_max * 4); - } - pm_runtime_put_sync(sde_dbg_base.dev); - - dev_info(sde_dbg_base.dev, "======== end %s dump =========\n", - bus->cmn.name); + writel_relaxed(0, mem_base + wr_addr); } -static int _sde_dbg_dump_vbif_debug_bus_entry( - struct vbif_debug_bus_entry *head, void __iomem *mem_base, - u32 *dump_addr, bool in_log) +static u32 _sde_dbg_lutdma_read_test_point(void __iomem *mem_base, u32 wr_addr, u32 rd_addr, + u32 block_id, u32 test_id) { - int i, j, count = 0; - u32 val; + u32 val = (BIT(0) | (test_id << 1)) & 0xFFFF; - if (!dump_addr && !in_log) - return 0; - - for (i = 0; i < head->block_cnt; i++) { - writel_relaxed(1 << (i + head->bit_offset), - mem_base + head->block_bus_addr); - /* make sure that current bus blcok enable */ - wmb(); - for (j = head->test_pnt_start; j < head->test_pnt_cnt; j++) { - writel_relaxed(j, mem_base + head->block_bus_addr + 4); - /* make sure that test point is enabled */ - wmb(); - val = readl_relaxed(mem_base + MMSS_VBIF_TEST_BUS_OUT); - if (dump_addr) { - *dump_addr++ = head->block_bus_addr; - *dump_addr++ = i; - *dump_addr++ = j; - *dump_addr++ = val; - count += DUMP_CLMN_COUNT; - } - if (in_log) - dev_info(sde_dbg_base.dev, - "testpoint:%x arb/xin id=%d index=%d val=0x%x\n", - head->block_bus_addr, i, j, val); - } - } - - return count; + return _sde_dbg_cmn_read_test_point(mem_base, wr_addr, rd_addr, val); } -static void _sde_dbg_dump_vbif_dbg_bus(struct sde_dbg_vbif_debug_bus *bus) +static u32 _sde_dbg_dsi_read_test_point(void __iomem *mem_base, u32 wr_addr, u32 rd_addr, + u32 block_id, u32 test_id) +{ + u32 val = (((block_id & 0x3) << 12) | ((test_id & 0x3f) << 4) | BIT(0)); + + return _sde_dbg_cmn_read_test_point(mem_base, wr_addr, rd_addr, val); +} + +static void _sde_dbg_vbif_disable_block(void __iomem *mem_base, u32 wr_addr) +{ + u32 disable_addr; + + /* make sure that other bus is off */ + disable_addr = (wr_addr == MMSS_VBIF_TEST_BUS1_CTRL0) ? + MMSS_VBIF_TEST_BUS2_CTRL0 : MMSS_VBIF_TEST_BUS1_CTRL0; + writel_relaxed(0, mem_base + disable_addr); + writel_relaxed(BIT(0), mem_base + MMSS_VBIF_TEST_BUS_OUT_CTRL); +} + +static u32 _sde_dbg_vbif_read_test_point(void __iomem *mem_base, u32 wr_addr, u32 rd_addr, + u32 block_id, u32 test_id) +{ + writel_relaxed((1 << block_id), mem_base + wr_addr); + writel_relaxed(test_id, mem_base + wr_addr + 0x4); + wmb(); /* make sure debug-bus test point is enabled */ + return readl_relaxed(mem_base + rd_addr); +} + +static void _sde_dbg_vbif_clear_test_point(void __iomem *mem_base, u32 wr_addr) +{ + writel_relaxed(0, mem_base + wr_addr); + writel_relaxed(0, mem_base + wr_addr + 0x4); +} + +static u32 _sde_dbg_sde_read_test_point(void __iomem *mem_base, u32 wr_addr, u32 rd_addr, + u32 block_id, u32 test_id) +{ + if (block_id > EXT_TEST_GROUP_SEL_EN) + writel_relaxed(TEST_EXT_MASK(block_id, test_id), mem_base + wr_addr); + else + writel_relaxed(TEST_MASK(block_id, test_id), mem_base + wr_addr); + + /* keep DSPP test point enabled */ + if (wr_addr != DBGBUS_DSPP) + writel_relaxed(DSPP_DEBUGBUS_CTRL_EN, mem_base + DBGBUS_DSPP); + wmb(); /* make sure test bits were written */ + + return readl_relaxed(mem_base + rd_addr); +} + +static void _sde_dbg_sde_clear_test_point(void __iomem *mem_base, u32 wr_addr) +{ + writel_relaxed(0x0, mem_base + wr_addr); + if (wr_addr != DBGBUS_DSPP) + writel_relaxed(0x0, mem_base + DBGBUS_DSPP); +} + +static void _sde_dbg_dump_vbif_err_info(void __iomem *mem_base) { - bool in_log, in_mem; - u32 **dump_mem = NULL; - u32 *dump_addr = NULL; u32 value, d0, d1; unsigned long reg, reg1, reg2; - struct vbif_debug_bus_entry *head; - int i, list_size = 0; - void __iomem *mem_base = NULL; - struct vbif_debug_bus_entry *dbg_bus; - u32 bus_size; - struct sde_dbg_reg_base *reg_base; - int rc, count; - - if (!bus || !bus->cmn.entries_size) - return; - - list_for_each_entry(reg_base, &sde_dbg_base.reg_base_list, - reg_base_head) - if (strlen(reg_base->name) && - !strcmp(reg_base->name, bus->cmn.name)) - mem_base = reg_base->base; - - if (!mem_base) { - pr_err("unable to find mem_base for %s\n", bus->cmn.name); - return; - } - - dbg_bus = bus->entries; - bus_size = bus->cmn.entries_size; - dump_mem = &bus->cmn.dumped_content; - - dev_info(sde_dbg_base.dev, "======== start %s dump =========\n", - bus->cmn.name); - - if (!dump_mem || !dbg_bus || !bus_size) - return; - - /* allocate memory for each test point */ - for (i = 0; i < bus_size; i++) { - head = dbg_bus + i; - list_size += (head->block_cnt * (head->test_pnt_cnt - - head->test_pnt_start)); - } - - /* 4 bytes * 4 entries for each test point*/ - list_size *= DUMP_CLMN_COUNT * sizeof(u32); - - in_log = (bus->cmn.enable_mask & SDE_DBG_DUMP_IN_LOG); - in_mem = (bus->cmn.enable_mask & SDE_DBG_DUMP_IN_MEM); - - if (!in_log && !in_mem) - return; - - if (in_mem) { - if (!(*dump_mem)) { - *dump_mem = devm_kzalloc(sde_dbg_base.dev, list_size, - GFP_KERNEL); - bus->cmn.content_size = list_size / sizeof(u32); - } - - if (*dump_mem) { - dump_addr = *dump_mem; - dev_info(sde_dbg_base.dev, - "%s: start_addr:0x%pK len:0x%x\n", - __func__, dump_addr, list_size); - if (sde_mini_dump_add_region("vbif_dbgbus", list_size, - *dump_mem) < 0) - pr_err("minidump add vbif debug bus failed\n"); - } else { - in_mem = false; - pr_err("dump_mem: allocation fails\n"); - } - } - - rc = pm_runtime_get_sync(sde_dbg_base.dev); - if (rc < 0) { - pr_err("failed to enable power %d\n", rc); - return; - } + int i; value = readl_relaxed(mem_base + MMSS_VBIF_CLKON); writel_relaxed(value | BIT(1), mem_base + MMSS_VBIF_CLKON); + wmb(); /* make sure that vbif core is on */ - /* make sure that vbif core is on */ - wmb(); - - /** + /* * Extract VBIF error info based on XIN halt and error status. * If the XIN client is not in HALT state, or an error is detected, * then retrieve the VBIF error info for it. @@ -1087,242 +826,173 @@ static void _sde_dbg_dump_vbif_dbg_bus(struct sde_dbg_vbif_debug_bus *bus) reg = readl_relaxed(mem_base + MMSS_VBIF_XIN_HALT_CTRL1); reg1 = readl_relaxed(mem_base + MMSS_VBIF_PND_ERR); reg2 = readl_relaxed(mem_base + MMSS_VBIF_SRC_ERR); - dev_err(sde_dbg_base.dev, - "XIN HALT:0x%lX, PND ERR:0x%lX, SRC ERR:0x%lX\n", - reg, reg1, reg2); + dev_err(sde_dbg_base.dev, "xin halt:0x%lx, pnd err:0x%lx, src err:0x%lx\n", + reg, reg1, reg2); reg >>= 16; reg &= ~(reg1 | reg2); for (i = 0; i < MMSS_VBIF_CLIENT_NUM; i++) { if (!test_bit(0, ®)) { writel_relaxed(i, mem_base + MMSS_VBIF_ERR_INFO); - /* make sure reg write goes through */ - wmb(); + wmb(); /* make sure reg write goes through */ d0 = readl_relaxed(mem_base + MMSS_VBIF_ERR_INFO); d1 = readl_relaxed(mem_base + MMSS_VBIF_ERR_INFO_1); - - dev_err(sde_dbg_base.dev, - "Client:%d, errinfo=0x%X, errinfo1=0x%X\n", - i, d0, d1); + dev_err(sde_dbg_base.dev, "Client:%d, errinfo=0x%x, errinfo1=0x%x\n", + i, d0, d1); } reg >>= 1; } - - for (i = 0; i < bus_size; i++) { - head = dbg_bus + i; - - writel_relaxed(0, mem_base + head->disable_bus_addr); - writel_relaxed(BIT(0), mem_base + MMSS_VBIF_TEST_BUS_OUT_CTRL); - /* make sure that other bus is off */ - wmb(); - - count = _sde_dbg_dump_vbif_debug_bus_entry(head, mem_base, - dump_addr, in_log); - if (dump_addr && (count > 0)) - dump_addr += count; - } - - pm_runtime_put_sync(sde_dbg_base.dev); - - dev_info(sde_dbg_base.dev, "======== end %s dump =========\n", - bus->cmn.name); } -static void _sde_dbg_dump_dsi_dbg_bus(struct sde_dbg_dsi_debug_bus *bus) +static void _sde_dbg_dump_bus_entry(struct sde_dbg_sde_debug_bus *bus, + struct sde_debug_bus_entry *entries, u32 bus_size, + void __iomem *mem_base, u32 *dump_addr) { - struct sde_dbg_dsi_ctrl_list_entry *entry; - struct list_head *list; - int list_size = 0; - u32 reg; - bool in_log, in_mem; + u32 status = 0; + int i, j, k; + bool in_mem, in_log; + struct sde_debug_bus_entry *entry; + + if (!bus->read_tp || !bus->clear_tp) + return; + + in_mem = (bus->cmn.enable_mask & SDE_DBG_DUMP_IN_MEM); + in_log = (bus->cmn.enable_mask & SDE_DBG_DUMP_IN_LOG); + + for (k = 0; k < bus_size; k++) { + entry = entries + k; + if (bus->disable_block) + bus->disable_block(mem_base, entry->wr_addr); + + for (i = entry->block_id; i < (entry->block_id + entry->block_id_max); i++) { + for (j = entry->test_id; j < (entry->test_id + entry->test_id_max); j++) { + + status = bus->read_tp(mem_base, entry->wr_addr, + entry->rd_addr, i, j); + if (!entry->analyzer && in_log) + dev_info(sde_dbg_base.dev, "%08x %08x %08x %08x\n", + entry->wr_addr, i, j, status); + if (dump_addr && in_mem) { + *dump_addr++ = entry->wr_addr; + *dump_addr++ = i; + *dump_addr++ = j; + *dump_addr++ = status; + } + + if (entry->analyzer) + entry->analyzer(mem_base, entry, status, i, j); + } + } + /* Disable debug bus once we are done */ + bus->clear_tp(mem_base, entry->wr_addr); + } +} + +static void _sde_dbg_dump_sde_dbg_bus(struct sde_dbg_sde_debug_bus *bus) +{ + bool in_mem; u32 **dump_mem = NULL; u32 *dump_addr = NULL; - u32 *end_addr; - struct dsi_debug_bus_entry *dbg_bus; - u32 bus_size; - int i, rc, dsi_idx = 0; - - if (!bus || !bus->cmn.entries_size) - return; - - dbg_bus = bus->entries; - bus_size = bus->cmn.entries_size; - dump_mem = &bus->cmn.dumped_content; - - if (!dump_mem || !dbg_bus || list_empty(&sde_dbg_dsi_list)) - return; - - in_log = (bus->cmn.enable_mask & SDE_DBG_DUMP_IN_LOG); - in_mem = (bus->cmn.enable_mask & SDE_DBG_DUMP_IN_MEM); - - if (!in_log && !in_mem) - return; - - rc = pm_runtime_get_sync(sde_dbg_base.dev); - if (rc < 0) { - pr_err("failed to enable power %d\n", rc); - return; - } - - dev_info(sde_dbg_base.dev, "======== start %s dump =========\n", - bus->cmn.name); - - mutex_lock(&sde_dbg_dsi_mutex); - if (in_mem) { - /* 4 fields of 4 bytes each, per table entry, per dsi ctrl*/ - list_for_each(list, &sde_dbg_dsi_list) - list_size++; - list_size *= bus_size * sizeof(u32) * DUMP_CLMN_COUNT; - - if (!(*dump_mem)) { - *dump_mem = devm_kzalloc(sde_dbg_base.dev, list_size, - GFP_KERNEL); - bus->cmn.content_size = list_size / sizeof(u32); - } - - if (*dump_mem) { - dump_addr = *dump_mem; - end_addr = *dump_mem + bus->cmn.content_size; - dev_info(sde_dbg_base.dev, - "%s: start_addr:0x%pK len:0x%x\n", - __func__, dump_addr, list_size); - } else { - in_mem = false; - pr_err("dump_mem: allocation fails\n"); - } - } - - list_for_each_entry(entry, &sde_dbg_dsi_list, list) { - dev_info(sde_dbg_base.dev, "%s start_addr:0x%pK\n", - entry->name, dump_addr); - - for (i = 0; i < bus_size; i++) { - if (!entry->base) - break; - - reg = ((dbg_bus[i].mux << 12) | - (dbg_bus[i].sel << 4) | BIT(0)); - writel_relaxed(reg, entry->base + DSI_DEBUG_BUS_CTRL); - wmb(); /* make sure debug-bus test point is enabled */ - reg = readl_relaxed(entry->base + DSI_DEBUG_BUS); - if (dump_addr && (dump_addr < end_addr)) { - *dump_addr++ = dsi_idx; - *dump_addr++ = dbg_bus[i].mux; - *dump_addr++ = dbg_bus[i].sel; - *dump_addr++ = reg; - } - if (in_log) - dev_info(sde_dbg_base.dev, - "mux:0x%x sel:0x%x status:0x%x\n", - dbg_bus[i].mux, dbg_bus[i].sel, reg); - } - - /* Disable debug bus once we are done */ - writel_relaxed(0, entry->base + DSI_DEBUG_BUS_CTRL); - dsi_idx++; - } - mutex_unlock(&sde_dbg_dsi_mutex); - - pm_runtime_put_sync(sde_dbg_base.dev); - dev_info(sde_dbg_base.dev, "======== end %s dump =========\n", - bus->cmn.name); -} - -static void _sde_dbg_dump_lutdma_dbg_bus(struct sde_dbg_lutdma_debug_bus *bus) -{ + int i, list_size = 0; void __iomem *mem_base = NULL; struct sde_dbg_reg_base *reg_base; - struct lutdma_debug_bus_entry *entries; - bool dump_in_log, dump_in_mem; - u32 **dump_mem = NULL; - u32 *dump_addr = NULL; - u32 i, j, entry_count, addr, count, val, engine_bit, dump_mem_size = 0; - int rc; + struct sde_debug_bus_entry *entries; + u32 bus_size; - if (!bus || !bus->cmn.entries_size) - return; - - list_for_each_entry(reg_base, &sde_dbg_base.reg_base_list, - reg_base_head) { - if (strlen(reg_base->name) && - !strcmp(reg_base->name, bus->cmn.name)) - mem_base = reg_base->base; - } - - if (!mem_base) { + reg_base = _sde_dump_get_blk_addr(bus->cmn.name); + if (!reg_base || !reg_base->base) { pr_err("unable to find mem_base for %s\n", bus->cmn.name); return; } - entries = bus->entries; - entry_count = bus->cmn.entries_size; + mem_base = reg_base->base; + if (!strcmp(bus->cmn.name, DBGBUS_NAME_SDE)) + mem_base += bus->top_blk_off; - dump_in_log = (bus->cmn.enable_mask & SDE_DBG_DUMP_IN_LOG); - dump_in_mem = (bus->cmn.enable_mask & SDE_DBG_DUMP_IN_MEM); + if (!strcmp(bus->cmn.name, DBGBUS_NAME_VBIF_RT)) + _sde_dbg_dump_vbif_err_info(mem_base); + + entries = bus->entries; + bus_size = bus->cmn.entries_size; dump_mem = &bus->cmn.dumped_content; - if (!dump_in_log && !dump_in_mem) + if (!dump_mem || !entries || !bus_size) return; - rc = pm_runtime_get_sync(sde_dbg_base.dev); - if (rc < 0) { - pr_err("failed to enable power %d\n", rc); + /* allocate memory for each test id */ + for (i = 0; i < bus_size; i++) + list_size += (entries[i].block_id_max * entries[i].test_id_max); + list_size *= sizeof(u32) * DUMP_CLMN_COUNT; + + dev_info(sde_dbg_base.dev, "======== start %s dump =========\n", bus->cmn.name); + + in_mem = (bus->cmn.enable_mask & SDE_DBG_DUMP_IN_MEM); + if (in_mem && (!(*dump_mem))) { + *dump_mem = devm_kzalloc(sde_dbg_base.dev, list_size, GFP_KERNEL); + bus->cmn.content_size = list_size / sizeof(u32); + } + + if (sde_mini_dump_add_region(bus->cmn.name, list_size, *dump_mem) < 0) + pr_err("minidump add %s failed\n", bus->cmn.name); + + dump_addr = *dump_mem; + dev_info(sde_dbg_base.dev, "%s: start_addr:0x%pK len:0x%x\n", + bus->cmn.name, dump_addr, list_size); + + _sde_dbg_dump_bus_entry(bus, entries, bus_size, mem_base, dump_addr); + + dev_info(sde_dbg_base.dev, "======== end %s dump =========\n", bus->cmn.name); +} + +static void _sde_dbg_dump_dsi_dbg_bus(struct sde_dbg_sde_debug_bus *bus) +{ + struct sde_dbg_dsi_ctrl_list_entry *ctl_entry; + struct list_head *list; + int list_size = 0; + bool in_mem; + int i, dsi_count = 0; + u32 **dump_mem = NULL; + u32 *dump_addr = NULL; + struct sde_debug_bus_entry *entries; + u32 bus_size; + + entries = bus->entries; + bus_size = bus->cmn.entries_size; + dump_mem = &bus->cmn.dumped_content; + + if (!dump_mem || !entries || !bus_size || list_empty(&sde_dbg_dsi_list)) return; + + list_for_each(list, &sde_dbg_dsi_list) + dsi_count++; + + for (i = 0; i < bus_size; i++) + list_size += (entries[i].block_id_max * entries[i].test_id_max); + list_size *= sizeof(u32) * DUMP_CLMN_COUNT * dsi_count; + + dev_info(sde_dbg_base.dev, "======== start %s dump =========\n", bus->cmn.name); + + mutex_lock(&sde_dbg_dsi_mutex); + in_mem = (bus->cmn.enable_mask & SDE_DBG_DUMP_IN_MEM); + if (in_mem && (!(*dump_mem))) { + *dump_mem = devm_kzalloc(sde_dbg_base.dev, list_size, GFP_KERNEL); + bus->cmn.content_size = list_size / sizeof(u32); } - dev_info(sde_dbg_base.dev, "======== start %s dump =========\n", - bus->cmn.name); + if (sde_mini_dump_add_region(bus->cmn.name, list_size, *dump_mem) < 0) + pr_err("minidump add %s failed\n", bus->cmn.name); - if (dump_in_mem) { - if (*dump_mem == NULL) { - for (i = 0; i < entry_count; i++) - dump_mem_size += (entries[i].indicies * - sizeof(u32)); + dump_addr = *dump_mem; - //Ensure enough chunks for debugfs dumping - dump_mem_size += dump_mem_size % (DUMP_CLMN_COUNT * 4); - *dump_mem = devm_kzalloc(sde_dbg_base.dev, - dump_mem_size, GFP_KERNEL); - bus->cmn.content_size = dump_mem_size / sizeof(u32); - } + list_for_each_entry(ctl_entry, &sde_dbg_dsi_list, list) { + dev_info(sde_dbg_base.dev, "%s: start_addr:0x%pK len:0x%x\n", + ctl_entry->name, dump_addr, list_size / dsi_count); - if (*dump_mem) { - dump_addr = *dump_mem; - dev_info(sde_dbg_base.dev, - "%s: start_addr:0x%pK len:0x%x\n", - __func__, dump_addr, dump_mem_size); - } else { - dump_in_mem = false; - pr_err("dump_mem: allocation fails\n"); - } + _sde_dbg_dump_bus_entry(bus, entries, bus_size, ctl_entry->base, dump_addr); } + mutex_unlock(&sde_dbg_dsi_mutex); - for (i = 0; i < entry_count; i++) { - addr = entries[i].wr_addr; - count = entries[i].indicies; - engine_bit = entries[i].read_engine ? BIT(14) : 0; - - for (j = 0 ; j < count; j++) { - val = (BIT(0) | engine_bit | (j << 1)) & 0xFFFF; - writel_relaxed(val, mem_base + addr); - wmb(); /* Ensure dbgbus setup occurs before read */ - val = readl_relaxed(mem_base + addr + 0x4); - - if (dump_in_log) - dev_info(sde_dbg_base.dev, - "lutdma_waddr=0x%x index=0x%x val=0x%x\n", - addr, j, val); - - if (dump_in_mem) - dump_addr[i * count + j] = val; - } - - //Disable debug bus when done - writel_relaxed(0, mem_base + addr); - } - - dev_info(sde_dbg_base.dev, "======== end %s dump =========\n", - bus->cmn.name); + dev_info(sde_dbg_base.dev, "======== end %s dump =========\n", bus->cmn.name); } /** @@ -1342,7 +1012,7 @@ static void _sde_dump_array(struct sde_dbg_reg_base *blk_arr[], bool dump_dbgbus_vbif_rt, bool dump_dbgbus_dsi, bool dump_all, bool dump_secure) { - int i; + int i, rc; u32 reg_dump_size; struct sde_dbg_base *dbg_base = &sde_dbg_base; @@ -1371,17 +1041,27 @@ static void _sde_dump_array(struct sde_dbg_reg_base *blk_arr[], } } - if (dump_dbgbus_sde) + if (_sde_power_check(sde_dbg_base.dump_mode)) { + rc = pm_runtime_get_sync(sde_dbg_base.dev); + if (rc < 0) { + pr_err("failed to enable power %d\n", rc); + return; + } + } + + if (dump_dbgbus_sde) { _sde_dbg_dump_sde_dbg_bus(&sde_dbg_base.dbgbus_sde); + _sde_dbg_dump_sde_dbg_bus(&sde_dbg_base.dbgbus_lutdma); + } if (dump_dbgbus_vbif_rt) - _sde_dbg_dump_vbif_dbg_bus(&sde_dbg_base.dbgbus_vbif_rt); + _sde_dbg_dump_sde_dbg_bus(&sde_dbg_base.dbgbus_vbif_rt); - if (dump_all || dump_dbgbus_dsi) + if (dump_dbgbus_dsi) _sde_dbg_dump_dsi_dbg_bus(&sde_dbg_base.dbgbus_dsi); - if (dump_all || dump_dbgbus_sde) - _sde_dbg_dump_lutdma_dbg_bus(&sde_dbg_base.dbgbus_lutdma); + if (_sde_power_check(sde_dbg_base.dump_mode)) + pm_runtime_put_sync(sde_dbg_base.dev); if (do_panic && sde_dbg_base.panic_on_err) panic(name); @@ -2550,30 +2230,39 @@ void sde_dbg_init_dbg_buses(u32 hwversion) memset(&dbg->dbgbus_sde, 0, sizeof(dbg->dbgbus_sde)); memset(&dbg->dbgbus_vbif_rt, 0, sizeof(dbg->dbgbus_vbif_rt)); + memset(&dbg->dbgbus_dsi, 0, sizeof(dbg->dbgbus_dsi)); dbg->dbgbus_sde.entries = dbg_bus_sde; dbg->dbgbus_sde.cmn.entries_size = ARRAY_SIZE(dbg_bus_sde); - dbg->dbgbus_sde.cmn.flags = DBGBUS_FLAGS_DSPP; dbg->dbgbus_sde.cmn.name = DBGBUS_NAME_SDE; dbg->dbgbus_sde.cmn.enable_mask = DEFAULT_DBGBUS_SDE; + dbg->dbgbus_sde.read_tp = _sde_dbg_sde_read_test_point; + dbg->dbgbus_sde.clear_tp = _sde_dbg_sde_clear_test_point; dbg->dbgbus_vbif_rt.entries = vbif_dbg_bus; dbg->dbgbus_vbif_rt.cmn.entries_size = ARRAY_SIZE(vbif_dbg_bus); dbg->dbgbus_vbif_rt.cmn.name = DBGBUS_NAME_VBIF_RT; dbg->dbgbus_vbif_rt.cmn.enable_mask = DEFAULT_DBGBUS_VBIFRT; + dbg->dbgbus_vbif_rt.read_tp = _sde_dbg_vbif_read_test_point; + dbg->dbgbus_vbif_rt.clear_tp = _sde_dbg_vbif_clear_test_point; + dbg->dbgbus_vbif_rt.disable_block = _sde_dbg_vbif_disable_block; dbg->dbgbus_dsi.entries = dsi_dbg_bus; dbg->dbgbus_dsi.cmn.entries_size = ARRAY_SIZE(dsi_dbg_bus); dbg->dbgbus_dsi.cmn.name = DBGBUS_NAME_DSI; dbg->dbgbus_dsi.cmn.enable_mask = DEFAULT_DBGBUS_DSI; + dbg->dbgbus_dsi.read_tp = _sde_dbg_dsi_read_test_point; + dbg->dbgbus_dsi.clear_tp = _sde_dbg_cmn_clear_test_point; if (SDE_HW_REV_MAJOR(hwversion) >= 0x7) { - dbg->dbgbus_lutdma.entries = dbg_bus_lutdma_lahaina; + dbg->dbgbus_lutdma.entries = dbg_bus_lutdma; dbg->dbgbus_lutdma.cmn.name = DBGBUS_NAME_LUTDMA; dbg->dbgbus_lutdma.cmn.entries_size = - ARRAY_SIZE(dbg_bus_lutdma_lahaina); + ARRAY_SIZE(dbg_bus_lutdma); dbg->dbgbus_lutdma.cmn.enable_mask = DEFAULT_DBGBUS_LUTDMA; dbg->dbgbus_lutdma.cmn.include_in_deferred_work = true; + dbg->dbgbus_lutdma.read_tp = _sde_dbg_lutdma_read_test_point; + dbg->dbgbus_lutdma.clear_tp = _sde_dbg_cmn_clear_test_point; } } From 75fa44a8ab46be0df8374876706f3616a0fc4695 Mon Sep 17 00:00:00 2001 From: Andhavarapu Karthik Date: Thu, 18 Feb 2021 13:19:27 -0800 Subject: [PATCH 2/7] disp: msm: format register/debugbus dumping in logs Add macros for logging the registers/debugbus, so all blocks can use the same macros to keep the log format consistent. Change-Id: Ie28ce83a742f24f3091bedab66c8cf1454bbb943 Signed-off-by: Andhavarapu Karthik Signed-off-by: Veera Sundaram Sankaran --- msm/sde_dbg.c | 122 ++++++++++++++++++++++---------------------------- 1 file changed, 54 insertions(+), 68 deletions(-) diff --git a/msm/sde_dbg.c b/msm/sde_dbg.c index 4841c3f32878..4d7f5c668aa1 100644 --- a/msm/sde_dbg.c +++ b/msm/sde_dbg.c @@ -94,6 +94,23 @@ #define SDE_HW_REV_MAJOR(rev) ((rev) >> 28) +#define SDE_DBG_LOG_START "start" +#define SDE_DBG_LOG_END "end" + +#define SDE_DBG_LOG_MARKER(name, marker) \ + dev_info(sde_dbg_base.dev, "======== %s %s dump =========\n", marker, name) + +#define SDE_DBG_LOG_ENTRY(off, x0, x4, x8, xc) \ + dev_info(sde_dbg_base.dev, "0x%lx : %08x %08x %08x %08x\n", off, x0, x4, x8, xc) + +#define SDE_DBG_LOG_DUMP_ADDR(name, addr, size, off) \ + dev_info(sde_dbg_base.dev, "%s: start_addr:0x%pK len:0x%x offset=0x%lx\n", \ + name, addr, size, off) + +#define SDE_DBG_LOG_DEBUGBUS(name, addr, block_id, test_id, val) \ + dev_err(sde_dbg_base.dev, "%s 0x%x %d %d 0x%x\n", \ + name, addr, block_id, test_id, val) + /** * struct sde_dbg_reg_offset - tracking for start and end of region * @start: start offset @@ -159,9 +176,7 @@ struct sde_debug_bus_entry { u32 block_id_max; u32 test_id; u32 test_id_max; - void (*analyzer)(void __iomem *mem_base, - struct sde_debug_bus_entry *entry, u32 val, - u32 block_id_off, u32 test_id_off); + void (*analyzer)(u32 wr_addr, u32 block_id, u32 test_id, u32 val); }; struct sde_dbg_dsi_ctrl_list_entry { @@ -283,49 +298,33 @@ u32 sde_mini_dump_add_region(const char *name, u32 size, void *virt_addr) return msm_minidump_add_region(&md_entry); } -static void _sde_debug_bus_xbar_dump(void __iomem *mem_base, - struct sde_debug_bus_entry *entry, u32 val, u32 block_id_off, - u32 test_id_off) +static void _sde_debug_bus_xbar_dump(u32 wr_addr, u32 block_id, u32 test_id, u32 val) { - dev_err(sde_dbg_base.dev, "xbar 0x%x %d %d 0x%x\n", - entry->wr_addr, entry->block_id + block_id_off, - entry->test_id + test_id_off, val); + SDE_DBG_LOG_DEBUGBUS("xbar", wr_addr, block_id, test_id, val); } -static void _sde_debug_bus_lm_dump(void __iomem *mem_base, - struct sde_debug_bus_entry *entry, u32 val, u32 block_id_off, - u32 test_id_off) +static void _sde_debug_bus_lm_dump(u32 wr_addr, u32 block_id, u32 test_id, u32 val) { if (!(val & 0xFFF000)) return; - dev_err(sde_dbg_base.dev, "lm 0x%x %d %d 0x%x\n", - entry->wr_addr, entry->block_id + block_id_off, - entry->test_id + test_id_off, val); + SDE_DBG_LOG_DEBUGBUS("lm", wr_addr, block_id, test_id, val); } -static void _sde_debug_bus_ppb0_dump(void __iomem *mem_base, - struct sde_debug_bus_entry *entry, u32 val, u32 block_id_off, - u32 test_id_off) +static void _sde_debug_bus_ppb0_dump(u32 wr_addr, u32 block_id, u32 test_id, u32 val) { if (!(val & BIT(15))) return; - dev_err(sde_dbg_base.dev, "ppb0 0x%x %d %d 0x%x\n", - entry->wr_addr, entry->block_id + block_id_off, - entry->test_id + test_id_off, val); + SDE_DBG_LOG_DEBUGBUS("pp0", wr_addr, block_id, test_id, val); } -static void _sde_debug_bus_ppb1_dump(void __iomem *mem_base, - struct sde_debug_bus_entry *entry, u32 val, u32 block_id_off, - u32 test_id_off) +static void _sde_debug_bus_ppb1_dump(u32 wr_addr, u32 block_id, u32 test_id, u32 val) { if (!(val & BIT(15))) return; - dev_err(sde_dbg_base.dev, "ppb1 0x%x %d %d 0x%x\n", - entry->wr_addr, entry->block_id + block_id_off, - entry->test_id + test_id_off, val); + SDE_DBG_LOG_DEBUGBUS("pp1", wr_addr, block_id, test_id, val); } static struct sde_debug_bus_entry dbg_bus_sde[] = { @@ -423,7 +422,7 @@ static void _sde_dump_reg(const char *dump_name, u32 reg_dump_flag, int i; int rc; - if (!len_bytes) + if (!len_bytes || !dump_mem) return; in_log = (reg_dump_flag & SDE_DBG_DUMP_IN_LOG); @@ -435,32 +434,15 @@ static void _sde_dump_reg(const char *dump_name, u32 reg_dump_flag, if (!in_log && !in_mem) return; - if (in_log) - dev_info(sde_dbg_base.dev, "%s: start_offset 0x%lx len 0x%zx\n", - dump_name, (unsigned long)(addr - base_addr), - len_bytes); - len_align = (len_bytes + REG_DUMP_ALIGN - 1) / REG_DUMP_ALIGN; len_padded = len_align * REG_DUMP_ALIGN; end_addr = addr + len_bytes; - if (in_mem) { - if (dump_mem && !(*dump_mem)) { - *dump_mem = dbg_base->reg_dump_addr; - dbg_base->reg_dump_addr += len_padded; - } + *dump_mem = dbg_base->reg_dump_addr; + dbg_base->reg_dump_addr += len_padded; - if (dump_mem && *dump_mem) { - dump_addr = *dump_mem; - dev_info(sde_dbg_base.dev, - "%s: start_addr:0x%pK len:0x%x reg_offset=0x%lx\n", - dump_name, dump_addr, len_padded, - (unsigned long)(addr - base_addr)); - } else { - in_mem = 0; - pr_err("dump_mem: kzalloc fails!\n"); - } - } + dump_addr = *dump_mem; + SDE_DBG_LOG_DUMP_ADDR(dump_name, dump_addr, len_padded, (unsigned long)(addr - base_addr)); if (_sde_power_check(sde_dbg_base.dump_mode)) { rc = pm_runtime_get_sync(sde_dbg_base.dev); @@ -479,10 +461,7 @@ static void _sde_dump_reg(const char *dump_name, u32 reg_dump_flag, xc = (addr + 0xc < end_addr) ? readl_relaxed(addr + 0xc) : 0; if (in_log) - dev_info(sde_dbg_base.dev, - "0x%lx : %08x %08x %08x %08x\n", - (unsigned long)(addr - base_addr), - x0, x4, x8, xc); + SDE_DBG_LOG_ENTRY((unsigned long)(addr - base_addr), x0, x4, x8, xc); if (dump_addr) { dump_addr[i * 4] = x0; @@ -616,8 +595,7 @@ static void _sde_dump_reg_by_ranges(struct sde_dbg_reg_base *dbg, return; } - dev_info(sde_dbg_base.dev, "%s:=========%s DUMP=========\n", __func__, - dbg->name); + SDE_DBG_LOG_MARKER(dbg->name, SDE_DBG_LOG_START); if (dbg->cb) { dbg->cb(dbg->cb_ptr); /* If there is a list to dump the registers by ranges, use the ranges */ @@ -653,8 +631,7 @@ static void _sde_dump_reg_by_ranges(struct sde_dbg_reg_base *dbg, /* If there is no list to dump ranges, dump all registers */ dev_info(sde_dbg_base.dev, "Ranges not found, will dump full registers\n"); - dev_info(sde_dbg_base.dev, "base:0x%pK len:0x%zx\n", dbg->base, - dbg->max_offset); + SDE_DBG_LOG_DUMP_ADDR("base", dbg->base, dbg->max_offset, 0); addr = dbg->base; len = dbg->max_offset; scnprintf(dbg_base->reg_dump_addr, REG_BASE_NAME_LEN, @@ -870,8 +847,8 @@ static void _sde_dbg_dump_bus_entry(struct sde_dbg_sde_debug_bus *bus, status = bus->read_tp(mem_base, entry->wr_addr, entry->rd_addr, i, j); if (!entry->analyzer && in_log) - dev_info(sde_dbg_base.dev, "%08x %08x %08x %08x\n", - entry->wr_addr, i, j, status); + SDE_DBG_LOG_ENTRY(0, entry->wr_addr, i, j, status); + if (dump_addr && in_mem) { *dump_addr++ = entry->wr_addr; *dump_addr++ = i; @@ -880,7 +857,7 @@ static void _sde_dbg_dump_bus_entry(struct sde_dbg_sde_debug_bus *bus, } if (entry->analyzer) - entry->analyzer(mem_base, entry, status, i, j); + entry->analyzer(entry->wr_addr, i, j, status); } } /* Disable debug bus once we are done */ @@ -898,6 +875,7 @@ static void _sde_dbg_dump_sde_dbg_bus(struct sde_dbg_sde_debug_bus *bus) struct sde_dbg_reg_base *reg_base; struct sde_debug_bus_entry *entries; u32 bus_size; + char name[20]; reg_base = _sde_dump_get_blk_addr(bus->cmn.name); if (!reg_base || !reg_base->base) { @@ -924,7 +902,8 @@ static void _sde_dbg_dump_sde_dbg_bus(struct sde_dbg_sde_debug_bus *bus) list_size += (entries[i].block_id_max * entries[i].test_id_max); list_size *= sizeof(u32) * DUMP_CLMN_COUNT; - dev_info(sde_dbg_base.dev, "======== start %s dump =========\n", bus->cmn.name); + snprintf(name, sizeof(name), "%s-debugbus", bus->cmn.name); + SDE_DBG_LOG_MARKER(name, SDE_DBG_LOG_START); in_mem = (bus->cmn.enable_mask & SDE_DBG_DUMP_IN_MEM); if (in_mem && (!(*dump_mem))) { @@ -936,12 +915,11 @@ static void _sde_dbg_dump_sde_dbg_bus(struct sde_dbg_sde_debug_bus *bus) pr_err("minidump add %s failed\n", bus->cmn.name); dump_addr = *dump_mem; - dev_info(sde_dbg_base.dev, "%s: start_addr:0x%pK len:0x%x\n", - bus->cmn.name, dump_addr, list_size); + SDE_DBG_LOG_DUMP_ADDR(bus->cmn.name, dump_addr, list_size, 0); _sde_dbg_dump_bus_entry(bus, entries, bus_size, mem_base, dump_addr); - dev_info(sde_dbg_base.dev, "======== end %s dump =========\n", bus->cmn.name); + SDE_DBG_LOG_MARKER(name, SDE_DBG_LOG_END); } static void _sde_dbg_dump_dsi_dbg_bus(struct sde_dbg_sde_debug_bus *bus) @@ -955,6 +933,7 @@ static void _sde_dbg_dump_dsi_dbg_bus(struct sde_dbg_sde_debug_bus *bus) u32 *dump_addr = NULL; struct sde_debug_bus_entry *entries; u32 bus_size; + char name[20]; entries = bus->entries; bus_size = bus->cmn.entries_size; @@ -970,7 +949,8 @@ static void _sde_dbg_dump_dsi_dbg_bus(struct sde_dbg_sde_debug_bus *bus) list_size += (entries[i].block_id_max * entries[i].test_id_max); list_size *= sizeof(u32) * DUMP_CLMN_COUNT * dsi_count; - dev_info(sde_dbg_base.dev, "======== start %s dump =========\n", bus->cmn.name); + snprintf(name, sizeof(name), "%s-debugbus", bus->cmn.name); + SDE_DBG_LOG_MARKER(name, SDE_DBG_LOG_START); mutex_lock(&sde_dbg_dsi_mutex); in_mem = (bus->cmn.enable_mask & SDE_DBG_DUMP_IN_MEM); @@ -985,14 +965,13 @@ static void _sde_dbg_dump_dsi_dbg_bus(struct sde_dbg_sde_debug_bus *bus) dump_addr = *dump_mem; list_for_each_entry(ctl_entry, &sde_dbg_dsi_list, list) { - dev_info(sde_dbg_base.dev, "%s: start_addr:0x%pK len:0x%x\n", - ctl_entry->name, dump_addr, list_size / dsi_count); + SDE_DBG_LOG_DUMP_ADDR(ctl_entry->name, dump_addr, list_size / dsi_count, 0); _sde_dbg_dump_bus_entry(bus, entries, bus_size, ctl_entry->base, dump_addr); } mutex_unlock(&sde_dbg_dsi_mutex); - dev_info(sde_dbg_base.dev, "======== end %s dump =========\n", bus->cmn.name); + SDE_DBG_LOG_MARKER(name, SDE_DBG_LOG_END); } /** @@ -1015,6 +994,7 @@ static void _sde_dump_array(struct sde_dbg_reg_base *blk_arr[], int i, rc; u32 reg_dump_size; struct sde_dbg_base *dbg_base = &sde_dbg_base; + ktime_t start, end; mutex_lock(&sde_dbg_base.mutex); @@ -1049,6 +1029,7 @@ static void _sde_dump_array(struct sde_dbg_reg_base *blk_arr[], } } + start = ktime_get(); if (dump_dbgbus_sde) { _sde_dbg_dump_sde_dbg_bus(&sde_dbg_base.dbgbus_sde); _sde_dbg_dump_sde_dbg_bus(&sde_dbg_base.dbgbus_lutdma); @@ -1060,6 +1041,11 @@ static void _sde_dump_array(struct sde_dbg_reg_base *blk_arr[], if (dump_dbgbus_dsi) _sde_dbg_dump_dsi_dbg_bus(&sde_dbg_base.dbgbus_dsi); + end = ktime_get(); + dev_info(sde_dbg_base.dev, + "debug-bus logging time start_us:%llu, end_us:%llu , duration_us:%llu\n", + ktime_to_us(start), ktime_to_us(end), ktime_us_delta(end, start)); + if (_sde_power_check(sde_dbg_base.dump_mode)) pm_runtime_put_sync(sde_dbg_base.dev); From b8a5bf949af280bf73634bfbb913801f03048b47 Mon Sep 17 00:00:00 2001 From: Veera Sundaram Sankaran Date: Wed, 17 Feb 2021 09:55:11 -0800 Subject: [PATCH 3/7] disp: msm: add capability to dump limited debugbus info in logs Add a flag SDE_DBG_DUMP_IN_LOG_LIMITED based on which the debug bus registers dumped in log can be limited. In memory logging will continue to dump the full range of configured registers if that flag is set. Currently the in-log limited support is enabled only for the sde/vbif debugbus and both IN_LOG & IN_LOG_LIMITED will be treated the same way for other blocks. Change-Id: Ie85d3d16955cfa507bb3e02954d9b313851eef78 Signed-off-by: Veera Sundaram Sankaran Signed-off-by: Andhavarapu Karthik --- msm/sde_dbg.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++-- msm/sde_dbg.h | 1 + 2 files changed, 81 insertions(+), 3 deletions(-) diff --git a/msm/sde_dbg.c b/msm/sde_dbg.c index 4d7f5c668aa1..2c70c017df77 100644 --- a/msm/sde_dbg.c +++ b/msm/sde_dbg.c @@ -190,6 +190,7 @@ struct sde_dbg_debug_bus_common { u32 enable_mask; bool include_in_deferred_work; u32 entries_size; + u32 limited_entries_size; u32 *dumped_content; u32 content_idx; u32 content_size; @@ -198,6 +199,7 @@ struct sde_dbg_debug_bus_common { struct sde_dbg_sde_debug_bus { struct sde_dbg_debug_bus_common cmn; struct sde_debug_bus_entry *entries; + struct sde_debug_bus_entry *limited_entries; u32 top_blk_off; u32 (*read_tp)(void __iomem *mem_base, u32 wr_addr, u32 rd_addr, u32 block_id, u32 test_id); void (*clear_tp)(void __iomem *mem_base, u32 wr_addr); @@ -327,6 +329,34 @@ static void _sde_debug_bus_ppb1_dump(u32 wr_addr, u32 block_id, u32 test_id, u32 SDE_DBG_LOG_DEBUGBUS("pp1", wr_addr, block_id, test_id, val); } +static struct sde_debug_bus_entry dbg_bus_sde_limited[] = { + { DBGBUS_SSPP0, DBGBUS_DSPP_STATUS, 0, 9, 0, 8 }, + { DBGBUS_SSPP0, DBGBUS_DSPP_STATUS, 20, 34, 0, 8 }, + { DBGBUS_SSPP0, DBGBUS_DSPP_STATUS, 60, 4, 0, 8 }, + { DBGBUS_SSPP0, DBGBUS_DSPP_STATUS, 70, 4, 0, 8 }, + + { DBGBUS_SSPP1, DBGBUS_DSPP_STATUS, 0, 9, 0, 8 }, + { DBGBUS_SSPP1, DBGBUS_DSPP_STATUS, 20, 34, 0, 8 }, + { DBGBUS_SSPP1, DBGBUS_DSPP_STATUS, 60, 4, 0, 8 }, + { DBGBUS_SSPP1, DBGBUS_DSPP_STATUS, 70, 4, 0, 8 }, + + { DBGBUS_DSPP, DBGBUS_DSPP_STATUS, 0, 1, 0, 8 }, + { DBGBUS_DSPP, DBGBUS_DSPP_STATUS, 9, 1, 0, 8 }, + { DBGBUS_DSPP, DBGBUS_DSPP_STATUS, 13, 2, 0, 8 }, + { DBGBUS_DSPP, DBGBUS_DSPP_STATUS, 19, 2, 0, 8 }, + { DBGBUS_DSPP, DBGBUS_DSPP_STATUS, 24, 2, 0, 8 }, + { DBGBUS_DSPP, DBGBUS_DSPP_STATUS, 31, 8, 0, 8 }, + { DBGBUS_DSPP, DBGBUS_DSPP_STATUS, 42, 12, 0, 8 }, + { DBGBUS_DSPP, DBGBUS_DSPP_STATUS, 54, 2, 0, 32 }, + { DBGBUS_DSPP, DBGBUS_DSPP_STATUS, 56, 2, 0, 8 }, + { DBGBUS_DSPP, DBGBUS_DSPP_STATUS, 63, 73, 0, 8 }, + + { DBGBUS_PERIPH, DBGBUS_DSPP_STATUS, 0, 1, 0, 8 }, + { DBGBUS_PERIPH, DBGBUS_DSPP_STATUS, 47, 7, 0, 8 }, + { DBGBUS_PERIPH, DBGBUS_DSPP_STATUS, 60, 14, 0, 8 }, + { DBGBUS_PERIPH, DBGBUS_DSPP_STATUS, 80, 3, 0, 8 }, +}; + static struct sde_debug_bus_entry dbg_bus_sde[] = { { DBGBUS_SSPP0, DBGBUS_DSPP_STATUS, 0, 74, 0, 32 }, { DBGBUS_SSPP1, DBGBUS_DSPP_STATUS, 0, 74, 0, 32 }, @@ -362,6 +392,21 @@ static struct sde_debug_bus_entry dbg_bus_sde[] = { { DBGBUS_DSPP, DBGBUS_DSPP_STATUS, 124, 1, 7, 1, _sde_debug_bus_lm_dump } }; +static struct sde_debug_bus_entry vbif_dbg_bus_limited[] = { + { MMSS_VBIF_TEST_BUS1_CTRL0, MMSS_VBIF_TEST_BUS_OUT, 0, 2, 0, 12}, + { MMSS_VBIF_TEST_BUS1_CTRL0, MMSS_VBIF_TEST_BUS_OUT, 4, 6, 0, 12}, + { MMSS_VBIF_TEST_BUS1_CTRL0, MMSS_VBIF_TEST_BUS_OUT, 12, 2, 0, 12}, + + { MMSS_VBIF_TEST_BUS2_CTRL0, MMSS_VBIF_TEST_BUS_OUT, 0, 2, 0, 16}, + { MMSS_VBIF_TEST_BUS2_CTRL0, MMSS_VBIF_TEST_BUS_OUT, 0, 2, 128, 208}, + { MMSS_VBIF_TEST_BUS2_CTRL0, MMSS_VBIF_TEST_BUS_OUT, 4, 6, 0, 16}, + { MMSS_VBIF_TEST_BUS2_CTRL0, MMSS_VBIF_TEST_BUS_OUT, 4, 6, 128, 208}, + { MMSS_VBIF_TEST_BUS2_CTRL0, MMSS_VBIF_TEST_BUS_OUT, 12, 2, 0, 16}, + { MMSS_VBIF_TEST_BUS2_CTRL0, MMSS_VBIF_TEST_BUS_OUT, 12, 2, 128, 208}, + { MMSS_VBIF_TEST_BUS2_CTRL0, MMSS_VBIF_TEST_BUS_OUT, 16, 2, 0, 16}, + { MMSS_VBIF_TEST_BUS2_CTRL0, MMSS_VBIF_TEST_BUS_OUT, 16, 2, 128, 208}, +}; + static struct sde_debug_bus_entry vbif_dbg_bus[] = { { MMSS_VBIF_TEST_BUS1_CTRL0, MMSS_VBIF_TEST_BUS_OUT, 0, 15, 0, 512}, { MMSS_VBIF_TEST_BUS2_CTRL0, MMSS_VBIF_TEST_BUS_OUT, 0, 18, 0, 512}, @@ -425,7 +470,8 @@ static void _sde_dump_reg(const char *dump_name, u32 reg_dump_flag, if (!len_bytes || !dump_mem) return; - in_log = (reg_dump_flag & SDE_DBG_DUMP_IN_LOG); + in_log = (reg_dump_flag & SDE_DBG_DUMP_IN_LOG) + | (reg_dump_flag & SDE_DBG_DUMP_IN_LOG_LIMITED); in_mem = (reg_dump_flag & SDE_DBG_DUMP_IN_MEM); pr_debug("%s: reg_dump_flag=%d in_log=%d in_mem=%d\n", @@ -821,13 +867,37 @@ static void _sde_dbg_dump_vbif_err_info(void __iomem *mem_base) } } +static bool _is_dbg_bus_limited_valid(struct sde_dbg_sde_debug_bus *bus, + u32 wr_addr, u32 block_id, u32 test_id) +{ + struct sde_debug_bus_entry *entry; + u32 block_id_max, test_id_max; + int i; + + if (!bus->limited_entries || !bus->cmn.limited_entries_size) + return true; + + for (i = 0; i < bus->cmn.limited_entries_size; i++) { + entry = bus->limited_entries + i; + block_id_max = entry->block_id + entry->block_id_max; + test_id_max = entry->test_id + entry->test_id_max; + + if ((wr_addr == entry->wr_addr) + && ((block_id >= entry->block_id) && (block_id < block_id_max)) + && ((test_id >= entry->test_id) && (test_id < test_id_max))) + return true; + } + + return false; +} + static void _sde_dbg_dump_bus_entry(struct sde_dbg_sde_debug_bus *bus, struct sde_debug_bus_entry *entries, u32 bus_size, void __iomem *mem_base, u32 *dump_addr) { u32 status = 0; int i, j, k; - bool in_mem, in_log; + bool in_mem, in_log, in_log_limited; struct sde_debug_bus_entry *entry; if (!bus->read_tp || !bus->clear_tp) @@ -835,6 +905,7 @@ static void _sde_dbg_dump_bus_entry(struct sde_dbg_sde_debug_bus *bus, in_mem = (bus->cmn.enable_mask & SDE_DBG_DUMP_IN_MEM); in_log = (bus->cmn.enable_mask & SDE_DBG_DUMP_IN_LOG); + in_log_limited = (bus->cmn.enable_mask & SDE_DBG_DUMP_IN_LOG_LIMITED); for (k = 0; k < bus_size; k++) { entry = entries + k; @@ -846,7 +917,9 @@ static void _sde_dbg_dump_bus_entry(struct sde_dbg_sde_debug_bus *bus, status = bus->read_tp(mem_base, entry->wr_addr, entry->rd_addr, i, j); - if (!entry->analyzer && in_log) + + if (!entry->analyzer && (in_log || (in_log_limited && + _is_dbg_bus_limited_valid(bus, entry->wr_addr, i, j)))) SDE_DBG_LOG_ENTRY(0, entry->wr_addr, i, j, status); if (dump_addr && in_mem) { @@ -2220,6 +2293,8 @@ void sde_dbg_init_dbg_buses(u32 hwversion) dbg->dbgbus_sde.entries = dbg_bus_sde; dbg->dbgbus_sde.cmn.entries_size = ARRAY_SIZE(dbg_bus_sde); + dbg->dbgbus_sde.limited_entries = dbg_bus_sde_limited; + dbg->dbgbus_sde.cmn.limited_entries_size = ARRAY_SIZE(dbg_bus_sde_limited); dbg->dbgbus_sde.cmn.name = DBGBUS_NAME_SDE; dbg->dbgbus_sde.cmn.enable_mask = DEFAULT_DBGBUS_SDE; dbg->dbgbus_sde.read_tp = _sde_dbg_sde_read_test_point; @@ -2227,6 +2302,8 @@ void sde_dbg_init_dbg_buses(u32 hwversion) dbg->dbgbus_vbif_rt.entries = vbif_dbg_bus; dbg->dbgbus_vbif_rt.cmn.entries_size = ARRAY_SIZE(vbif_dbg_bus); + dbg->dbgbus_vbif_rt.limited_entries = vbif_dbg_bus_limited; + dbg->dbgbus_vbif_rt.cmn.limited_entries_size = ARRAY_SIZE(vbif_dbg_bus_limited); dbg->dbgbus_vbif_rt.cmn.name = DBGBUS_NAME_VBIF_RT; dbg->dbgbus_vbif_rt.cmn.enable_mask = DEFAULT_DBGBUS_VBIFRT; dbg->dbgbus_vbif_rt.read_tp = _sde_dbg_vbif_read_test_point; diff --git a/msm/sde_dbg.h b/msm/sde_dbg.h index 4e3dbdbb9b7b..988d264bc1d7 100644 --- a/msm/sde_dbg.h +++ b/msm/sde_dbg.h @@ -43,6 +43,7 @@ enum sde_dbg_evtlog_flag { enum sde_dbg_dump_flag { SDE_DBG_DUMP_IN_LOG = BIT(0), SDE_DBG_DUMP_IN_MEM = BIT(1), + SDE_DBG_DUMP_IN_LOG_LIMITED = BIT(2), }; enum sde_dbg_dump_context { From 2a15e531a36fdaedcb66f8b4b32e605dc0473685 Mon Sep 17 00:00:00 2001 From: Veera Sundaram Sankaran Date: Tue, 27 Apr 2021 15:56:02 -0700 Subject: [PATCH 4/7] disp: msm: fix dsi debugbus in-mem logging Update the dump_mem pointer offset while storing the debugbus data for the second DSI to avoid overwriting to same memory. As part of the change, register the DSI ctrl with sde_dbg from ctrl_init directly, instead of debugfs_init to avoid code replication. Change-Id: I4089f3038ffa89136eaea956d27270f638a99043 Signed-off-by: Veera Sundaram Sankaran Signed-off-by: Andhavarapu Karthik --- msm/dsi/dsi_ctrl.c | 20 ++++++-------------- msm/sde_dbg.c | 2 ++ 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/msm/dsi/dsi_ctrl.c b/msm/dsi/dsi_ctrl.c index d3d5cd20a203..506181bc8776 100644 --- a/msm/dsi/dsi_ctrl.c +++ b/msm/dsi/dsi_ctrl.c @@ -266,7 +266,6 @@ static int dsi_ctrl_debugfs_init(struct dsi_ctrl *dsi_ctrl, { int rc = 0; struct dentry *dir, *state_file, *reg_dump, *cmd_dma_logs; - char dbg_name[DSI_DEBUG_NAME_LEN]; if (!dsi_ctrl || !parent) { DSI_CTRL_ERR(dsi_ctrl, "Invalid params\n"); @@ -329,10 +328,6 @@ static int dsi_ctrl_debugfs_init(struct dsi_ctrl *dsi_ctrl, dsi_ctrl->debugfs_root = dir; - snprintf(dbg_name, DSI_DEBUG_NAME_LEN, "dsi%d_ctrl", - dsi_ctrl->cell_index); - sde_dbg_reg_register_base(dbg_name, dsi_ctrl->hw.base, - msm_iomap_size(dsi_ctrl->pdev, "dsi_ctrl")); error_remove_dir: debugfs_remove(dir); error: @@ -345,16 +340,8 @@ static int dsi_ctrl_debugfs_deinit(struct dsi_ctrl *dsi_ctrl) return 0; } #else -static int dsi_ctrl_debugfs_init(struct dsi_ctrl *dsi_ctrl, - struct dentry *parent) +static int dsi_ctrl_debugfs_init(struct dsi_ctrl *dsi_ctrl, struct dentry *parent) { - char dbg_name[DSI_DEBUG_NAME_LEN]; - - snprintf(dbg_name, DSI_DEBUG_NAME_LEN, "dsi%d_ctrl", - dsi_ctrl->cell_index); - sde_dbg_reg_register_base(dbg_name, - dsi_ctrl->hw.base, - msm_iomap_size(dsi_ctrl->pdev, "dsi_ctrl")); return 0; } static int dsi_ctrl_debugfs_deinit(struct dsi_ctrl *dsi_ctrl) @@ -2350,6 +2337,7 @@ void dsi_ctrl_put(struct dsi_ctrl *dsi_ctrl) */ int dsi_ctrl_drv_init(struct dsi_ctrl *dsi_ctrl, struct dentry *parent) { + char dbg_name[DSI_DEBUG_NAME_LEN]; int rc = 0; if (!dsi_ctrl) { @@ -2371,6 +2359,10 @@ int dsi_ctrl_drv_init(struct dsi_ctrl *dsi_ctrl, struct dentry *parent) goto error; } + snprintf(dbg_name, DSI_DEBUG_NAME_LEN, "dsi%d_ctrl", dsi_ctrl->cell_index); + sde_dbg_reg_register_base(dbg_name, dsi_ctrl->hw.base, + msm_iomap_size(dsi_ctrl->pdev, "dsi_ctrl")); + error: mutex_unlock(&dsi_ctrl->ctrl_lock); return rc; diff --git a/msm/sde_dbg.c b/msm/sde_dbg.c index 2c70c017df77..57acfd87d5d5 100644 --- a/msm/sde_dbg.c +++ b/msm/sde_dbg.c @@ -1041,6 +1041,8 @@ static void _sde_dbg_dump_dsi_dbg_bus(struct sde_dbg_sde_debug_bus *bus) SDE_DBG_LOG_DUMP_ADDR(ctl_entry->name, dump_addr, list_size / dsi_count, 0); _sde_dbg_dump_bus_entry(bus, entries, bus_size, ctl_entry->base, dump_addr); + if (dump_addr) + dump_addr += list_size / (sizeof(u32) * dsi_count); } mutex_unlock(&sde_dbg_dsi_mutex); From 77d385f62dbcd359a4a11be2a037e2065fe97f5d Mon Sep 17 00:00:00 2001 From: Steve Cohen Date: Wed, 24 Mar 2021 16:14:46 -0400 Subject: [PATCH 5/7] disp: msm: sde: remove idle time from Qsync threshold calculation Remove idle time from the Qsync calculation, round down to the nearest multiple of 4 and remove a couple of extra lines to compensate for possible latencies. This helps to reduce the possibility of causing tearing due to the driver calculation mismatching with the DDIC's expected timeout value. Change-Id: I8a53a989e26cbd7f0e2b94caa8df8f5bee3ad26c Signed-off-by: Steve Cohen --- msm/sde/sde_encoder.c | 18 ------------------ msm/sde/sde_encoder_phys.h | 8 -------- msm/sde/sde_encoder_phys_cmd.c | 30 +++++++++++++----------------- 3 files changed, 13 insertions(+), 43 deletions(-) diff --git a/msm/sde/sde_encoder.c b/msm/sde/sde_encoder.c index 14da4f5d952e..14643150ee75 100644 --- a/msm/sde/sde_encoder.c +++ b/msm/sde/sde_encoder.c @@ -4286,24 +4286,6 @@ void sde_encoder_helper_get_pp_line_count(struct drm_encoder *drm_enc, } } -void sde_encoder_helper_get_transfer_time(struct drm_encoder *drm_enc, - u32 *transfer_time_us) -{ - struct sde_encoder_virt *sde_enc; - struct msm_mode_info *info; - - if (!drm_enc || !transfer_time_us) { - SDE_ERROR("bad arg: encoder:%d transfer_time:%d\n", !drm_enc, - !transfer_time_us); - return; - } - - sde_enc = to_sde_encoder_virt(drm_enc); - info = &sde_enc->mode_info; - - *transfer_time_us = info->mdp_transfer_time_us; -} - int sde_encoder_helper_reset_mixers(struct sde_encoder_phys *phys_enc, struct drm_framebuffer *fb) { diff --git a/msm/sde/sde_encoder_phys.h b/msm/sde/sde_encoder_phys.h index 710c1aff62b0..802140bd28c0 100644 --- a/msm/sde/sde_encoder_phys.h +++ b/msm/sde/sde_encoder_phys.h @@ -541,14 +541,6 @@ void sde_encoder_phys_setup_cdm(struct sde_encoder_phys *phys_enc, void sde_encoder_helper_get_pp_line_count(struct drm_encoder *drm_enc, struct sde_hw_pp_vsync_info *info); -/** - * sde_encoder_helper_get_transfer_time - get the mdp transfer time in usecs - * @drm_enc: Pointer to drm encoder structure - * @transfer_time_us: Pointer to store the output value - */ -void sde_encoder_helper_get_transfer_time(struct drm_encoder *drm_enc, - u32 *transfer_time_us); - /** * sde_encoder_helper_trigger_flush - control flush helper function * This helper function may be optionally specified by physical diff --git a/msm/sde/sde_encoder_phys_cmd.c b/msm/sde/sde_encoder_phys_cmd.c index e9c456aaa6d8..8dd05021abac 100644 --- a/msm/sde/sde_encoder_phys_cmd.c +++ b/msm/sde/sde_encoder_phys_cmd.c @@ -963,8 +963,6 @@ static int _get_tearcheck_threshold(struct sde_encoder_phys *phys_enc) u32 default_time_ns; u32 extra_time_ns; u32 default_line_time_ns; - u32 idle_time_ns = 0; - u32 transfer_time_us = 0; if (phys_enc->parent_ops.get_qsync_fps) phys_enc->parent_ops.get_qsync_fps( @@ -985,28 +983,26 @@ static int _get_tearcheck_threshold(struct sde_encoder_phys *phys_enc) } /* Calculate the number of extra lines*/ - slow_time_ns = (1 * 1000000000) / qsync_min_fps; - default_time_ns = (1 * 1000000000) / default_fps; - sde_encoder_helper_get_transfer_time(phys_enc->parent, - &transfer_time_us); - if (transfer_time_us) - idle_time_ns = default_time_ns - - (1000 * transfer_time_us); - - extra_time_ns = slow_time_ns - default_time_ns + idle_time_ns; - default_line_time_ns = (1 * 1000000000) / (default_fps * yres); + slow_time_ns = 1000000000 / qsync_min_fps; + default_time_ns = 1000000000 / default_fps; + extra_time_ns = slow_time_ns - default_time_ns; + default_line_time_ns = default_time_ns / yres; threshold_lines = extra_time_ns / default_line_time_ns; + /* round down to nearest multiple of 4 to compensate for rounding in DDIC */ + threshold_lines &= ~(4 - 1); + /* additional compensation for latency */ + if (threshold_lines - 2 > DEFAULT_TEARCHECK_SYNC_THRESH_START) + threshold_lines -= 2; + SDE_DEBUG_CMDENC(cmd_enc, "slow:%d default:%d extra:%d(ns)\n", slow_time_ns, default_time_ns, extra_time_ns); - SDE_DEBUG_CMDENC(cmd_enc, "xfer:%d(us) idle:%d(ns) lines:%d\n", - transfer_time_us, idle_time_ns, threshold_lines); - SDE_DEBUG_CMDENC(cmd_enc, "min_fps:%d fps:%d yres:%d\n", - qsync_min_fps, default_fps, yres); + SDE_DEBUG_CMDENC(cmd_enc, "min_fps:%d fps:%d yres:%d lines:%d\n", + qsync_min_fps, default_fps, yres, threshold_lines); SDE_EVT32(qsync_mode, qsync_min_fps, extra_time_ns, default_fps, - yres, transfer_time_us, threshold_lines); + yres, threshold_lines); } exit: From d7d8a487cae98ace0d88ae64cf2991a2c360d172 Mon Sep 17 00:00:00 2001 From: Yashwanth Date: Wed, 28 Jul 2021 17:11:15 +0530 Subject: [PATCH 6/7] disp: msm: assign aspace to gem object for mmap buffer During gem fault, if aspace value is found to be NULL pages map request will be failed. This change assigns nonsecure aspace to gem object before mapping the pages in such cases. Change-Id: Ia838fd8a446e21771742ec9d51e30fe08c989e6e Signed-off-by: Yashwanth --- msm/msm_gem.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/msm/msm_gem.c b/msm/msm_gem.c index 9ccff79644fb..c8185bacde1b 100644 --- a/msm/msm_gem.c +++ b/msm/msm_gem.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark * @@ -275,6 +275,8 @@ vm_fault_t msm_gem_fault(struct vm_fault *vmf) return VM_FAULT_SIGBUS; } + msm_obj->aspace = msm_gem_smmu_address_space_get(obj->dev, + MSM_SMMU_DOMAIN_UNSECURE); /* make sure we have pages attached now */ pages = get_pages(obj); if (IS_ERR(pages)) { From 9021984e1451af71b8bf8dd2dad63805cc7a33a1 Mon Sep 17 00:00:00 2001 From: Yashwanth Date: Thu, 26 Aug 2021 09:22:07 +0530 Subject: [PATCH 7/7] disp: msm: sde: add checks to avoid null pointer dereference This change adds required checks to avoid accessing the null pointer in case where memory allocation fails while dumping the registers in memory. Change-Id: Ic087a1bd041d193820289672d325a78795c48c14 Signed-off-by: Yashwanth --- msm/sde_dbg.c | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/msm/sde_dbg.c b/msm/sde_dbg.c index 12ca18734ebc..bffdeb93f4b3 100644 --- a/msm/sde_dbg.c +++ b/msm/sde_dbg.c @@ -504,6 +504,9 @@ static void _sde_dump_reg(const char *dump_name, u32 reg_dump_flag, pr_debug("%s: reg_dump_flag=%d in_log=%d in_mem=%d\n", dump_name, reg_dump_flag, in_log, in_mem); + if (!dbg_base->reg_dump_addr) + in_mem = 0; + if (!in_log && !in_mem) return; @@ -711,12 +714,15 @@ static void _sde_dump_reg_by_ranges(struct sde_dbg_reg_base *dbg, addr, range_node->offset.start, range_node->offset.end); - scnprintf(dbg_base->reg_dump_addr, REG_BASE_NAME_LEN, - dbg->name); - dbg_base->reg_dump_addr += REG_BASE_NAME_LEN; - scnprintf(dbg_base->reg_dump_addr, RANGE_NAME_LEN, - range_node->range_name); - dbg_base->reg_dump_addr += RANGE_NAME_LEN; + if (dbg_base->reg_dump_addr) { + scnprintf(dbg_base->reg_dump_addr, REG_BASE_NAME_LEN, + dbg->name); + dbg_base->reg_dump_addr += REG_BASE_NAME_LEN; + scnprintf(dbg_base->reg_dump_addr, RANGE_NAME_LEN, + range_node->range_name); + dbg_base->reg_dump_addr += RANGE_NAME_LEN; + } + _sde_dump_reg(range_node->range_name, reg_dump_flag, dbg->base, addr, len, &range_node->reg_dump); @@ -729,10 +735,13 @@ static void _sde_dump_reg_by_ranges(struct sde_dbg_reg_base *dbg, dbg->max_offset); addr = dbg->base; len = dbg->max_offset; - scnprintf(dbg_base->reg_dump_addr, REG_BASE_NAME_LEN, - dbg->name); - dbg_base->reg_dump_addr += REG_BASE_NAME_LEN; - dbg_base->reg_dump_addr += RANGE_NAME_LEN; + if (dbg_base->reg_dump_addr) { + scnprintf(dbg_base->reg_dump_addr, REG_BASE_NAME_LEN, + dbg->name); + dbg_base->reg_dump_addr += REG_BASE_NAME_LEN; + dbg_base->reg_dump_addr += RANGE_NAME_LEN; + } + _sde_dump_reg(dbg->name, reg_dump_flag, dbg->base, addr, len, &dbg->reg_dump); } @@ -1352,6 +1361,10 @@ static void _sde_dump_array(struct sde_dbg_reg_base *blk_arr[], dbg_base->reg_dump_addr = devm_kzalloc(sde_dbg_base.dev, reg_dump_size, GFP_KERNEL); + if (!dbg_base->reg_dump_addr) + pr_err("Failed to allocate memory for reg_dump_addr size:%d\n", + reg_dump_size); + if (dbg_base->reg_dump_addr && sde_mini_dump_add_region("reg_dump", reg_dump_size, dbg_base->reg_dump_addr) < 0)