Loading msm/sde/sde_hw_util.c +2 −0 Original line number Diff line number Diff line Loading @@ -77,6 +77,8 @@ void sde_reg_write(struct sde_hw_blk_reg_map *c, SDE_DEBUG_DRIVER("[%s:0x%X] <= 0x%X\n", name, c->blk_off + reg_off, val); writel_relaxed(val, c->base_off + c->blk_off + reg_off); SDE_REG_LOG(c->log_mask ? ilog2(c->log_mask)+1 : 0, val, c->blk_off + reg_off); } int sde_reg_read(struct sde_hw_blk_reg_map *c, u32 reg_off) Loading msm/sde_dbg.c +15 −0 Original line number Diff line number Diff line Loading @@ -197,6 +197,7 @@ struct sde_dbg_regbuf { /** * struct sde_dbg_base - global sde debug base structure * @evtlog: event log instance * @reglog: reg log instance * @reg_base_list: list of register dumping regions * @dev: device pointer * @mutex: mutex to serialize access to serialze dumps, debugfs access Loading @@ -212,11 +213,13 @@ struct sde_dbg_regbuf { * @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 * @dbgbus_dump_idx: index used for tracking dbg-bus dump in hw recovery * @vbif_dbgbus_dump_idx: index for tracking vbif dumps in hw recovery */ static struct sde_dbg_base { struct sde_dbg_evtlog *evtlog; struct sde_dbg_reglog *reglog; struct list_head reg_base_list; void *reg_dump_addr; struct device *dev; Loading @@ -239,6 +242,7 @@ static struct sde_dbg_base { struct sde_dbg_regbuf regbuf; u32 cur_evt_index; u32 cur_reglog_index; u32 dbgbus_dump_idx; u32 vbif_dbgbus_dump_idx; enum sde_dbg_dump_context dump_mode; Loading @@ -247,6 +251,9 @@ static struct sde_dbg_base { /* sde_dbg_base_evtlog - global pointer to main sde event log for macro use */ struct sde_dbg_evtlog *sde_dbg_base_evtlog; /* sde_dbg_base_reglog - global pointer to main sde reg log for macro use */ struct sde_dbg_reglog *sde_dbg_base_reglog; static void _sde_debug_bus_xbar_dump(void __iomem *mem_base, struct sde_debug_bus_entry *entry, u32 val) { Loading Loading @@ -4727,6 +4734,12 @@ int sde_dbg_init(struct device *dev) sde_dbg_base_evtlog = sde_dbg_base.evtlog; sde_dbg_base.reglog = sde_reglog_init(); if (IS_ERR_OR_NULL(sde_dbg_base.reglog)) return PTR_ERR(sde_dbg_base.reglog); sde_dbg_base_reglog = sde_dbg_base.reglog; INIT_WORK(&sde_dbg_base.dump_work, _sde_dump_work); sde_dbg_base.work_panic = false; sde_dbg_base.panic_on_err = DEFAULT_PANIC; Loading Loading @@ -4771,6 +4784,8 @@ void sde_dbg_destroy(void) sde_dbg_base_evtlog = NULL; sde_evtlog_destroy(sde_dbg_base.evtlog); sde_dbg_base.evtlog = NULL; sde_reglog_destroy(sde_dbg_base.reglog); sde_dbg_base.reglog = NULL; sde_dbg_reg_base_destroy(); mutex_destroy(&sde_dbg_base.mutex); } Loading msm/sde_dbg.h +92 −0 Original line number Diff line number Diff line Loading @@ -49,6 +49,34 @@ enum sde_dbg_dump_context { SDE_DBG_DUMP_CLK_ENABLED_CTX, }; /* * Define blocks for register write logging. */ #define SDE_REG_LOG_DEFAULT 0 #define SDE_REG_LOG_NONE 1 #define SDE_REG_LOG_CDM 2 #define SDE_REG_LOG_DSPP 3 #define SDE_REG_LOG_INTF 4 #define SDE_REG_LOG_LM 5 #define SDE_REG_LOG_CTL 6 #define SDE_REG_LOG_PINGPONG 7 #define SDE_REG_LOG_SSPP 8 #define SDE_REG_LOG_WB 9 #define SDE_REG_LOG_TOP 10 #define SDE_REG_LOG_VBIF 11 #define SDE_REG_LOG_DSC 12 #define SDE_REG_LOG_ROT 13 #define SDE_REG_LOG_DS 14 #define SDE_REG_LOG_REGDMA 15 #define SDE_REG_LOG_UIDLE 16 #define SDE_REG_LOG_SID 16 #define SDE_REG_LOG_QDSS 17 /* * 0-32 are reserved for sde_reg_write due to log masks * Additional blocks are assigned from 33 to avoid conflict */ #define SDE_REG_LOG_RSCC 33 #define SDE_EVTLOG_DEFAULT_ENABLE (SDE_EVTLOG_CRITICAL | SDE_EVTLOG_IRQ | \ SDE_EVTLOG_EXTERNAL) Loading Loading @@ -103,6 +131,44 @@ struct sde_dbg_evtlog { extern struct sde_dbg_evtlog *sde_dbg_base_evtlog; /* * reglog keeps this number of entries in memory for debug purpose. This * number must be greater than number of possible writes in at least one * single commit. */ #define SDE_REGLOG_ENTRY 1024 struct sde_dbg_reglog_log { s64 time; u32 pid; u32 addr; u32 val; u8 blk_id; }; /** * @last_dump: Index of last entry to be output during reglog dumps * @filter_list: Linked list of currently active filter strings */ struct sde_dbg_reglog { struct sde_dbg_reglog_log logs[SDE_REGLOG_ENTRY]; u32 first; u32 last; u32 last_dump; u32 curr; u32 next; u32 enable; u32 enable_mask; spinlock_t spin_lock; }; extern struct sde_dbg_reglog *sde_dbg_base_reglog; /** * SDE_REG_LOG - Write register write to the register log */ #define SDE_REG_LOG(blk_id, val, addr) sde_reglog_log(blk_id, val, addr) /** * SDE_EVT32 - Write a list of 32bit values to the event log, default area * ... - variable arguments Loading Loading @@ -183,6 +249,12 @@ extern struct sde_dbg_evtlog *sde_dbg_base_evtlog; */ struct sde_dbg_evtlog *sde_evtlog_init(void); /** * sde_reglog_init - allocate a new reg log object * Returns: reglog or -ERROR */ struct sde_dbg_reglog *sde_reglog_init(void); /** * sde_evtlog_destroy - destroy previously allocated event log * @evtlog: pointer to evtlog Loading @@ -190,6 +262,13 @@ struct sde_dbg_evtlog *sde_evtlog_init(void); */ void sde_evtlog_destroy(struct sde_dbg_evtlog *evtlog); /** * sde_reglog_destroy - destroy previously allocated reg log * @reglog: pointer to reglog * Returns: none */ void sde_reglog_destroy(struct sde_dbg_reglog *reglog); /** * sde_evtlog_log - log an entry into the event log. * log collection may be enabled/disabled entirely via debugfs Loading @@ -203,6 +282,15 @@ void sde_evtlog_destroy(struct sde_dbg_evtlog *evtlog); void sde_evtlog_log(struct sde_dbg_evtlog *evtlog, const char *name, int line, int flag, ...); /** * sde_reglog_log - log an entry into the reg log. * log collection may be enabled/disabled entirely via debugfs * log area collection may be filtered by user provided flags via debugfs. * @reglog: pointer to evtlog * Returns: none */ void sde_reglog_log(u8 blk_id, u32 val, u32 addr); /** * sde_evtlog_dump_all - print all entries in event log to kernel log * @evtlog: pointer to evtlog Loading Loading @@ -386,6 +474,10 @@ static inline void sde_evtlog_log(struct sde_dbg_evtlog *evtlog, { } static inline void sde_reglog_log(u8 blk_id, u32 val, u32 addr) { } static inline void sde_evtlog_dump_all(struct sde_dbg_evtlog *evtlog) { } Loading msm/sde_dbg_evtlog.c +47 −1 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. */ #define pr_fmt(fmt) "sde_dbg:[%s] " fmt, __func__ Loading Loading @@ -101,6 +101,31 @@ void sde_evtlog_log(struct sde_dbg_evtlog *evtlog, const char *name, int line, spin_unlock_irqrestore(&evtlog->spin_lock, flags); } void sde_reglog_log(u8 blk_id, u32 val, u32 addr) { unsigned long flags; struct sde_dbg_reglog_log *log; struct sde_dbg_reglog *reglog = sde_dbg_base_reglog; if (!reglog) return; spin_lock_irqsave(®log->spin_lock, flags); log = ®log->logs[reglog->curr]; log->blk_id = blk_id; log->val = val; log->addr = addr; log->time = local_clock(); log->pid = current->pid; reglog->curr = (reglog->curr + 1) % SDE_REGLOG_ENTRY; reglog->last++; spin_unlock_irqrestore(®log->spin_lock, flags); } /* always dump the last entries which are not dumped yet */ static bool _sde_evtlog_dump_calc_range(struct sde_dbg_evtlog *evtlog, bool update_last_entry, bool full_dump) Loading Loading @@ -211,6 +236,19 @@ struct sde_dbg_evtlog *sde_evtlog_init(void) return evtlog; } struct sde_dbg_reglog *sde_reglog_init(void) { struct sde_dbg_reglog *reglog; reglog = kzalloc(sizeof(*reglog), GFP_KERNEL); if (!reglog) return ERR_PTR(-ENOMEM); spin_lock_init(®log->spin_lock); return reglog; } int sde_evtlog_get_filter(struct sde_dbg_evtlog *evtlog, int index, char *buf, size_t bufsz) { Loading Loading @@ -312,3 +350,11 @@ void sde_evtlog_destroy(struct sde_dbg_evtlog *evtlog) } kfree(evtlog); } void sde_reglog_destroy(struct sde_dbg_reglog *reglog) { if (!reglog) return; kfree(reglog); } msm/sde_io_util.c +2 −0 Original line number Diff line number Diff line Loading @@ -9,6 +9,7 @@ #include <linux/regulator/consumer.h> #include <linux/delay.h> #include <linux/sde_io_util.h> #include "sde_dbg.h" #define MAX_I2C_CMDS 16 void dss_reg_w(struct dss_io_data *io, u32 offset, u32 value, u32 debug) Loading @@ -34,6 +35,7 @@ void dss_reg_w(struct dss_io_data *io, u32 offset, u32 value, u32 debug) (u32)(unsigned long)(io->base + offset), value, in_val); } SDE_REG_LOG(SDE_REG_LOG_RSCC, value, offset); } /* dss_reg_w */ EXPORT_SYMBOL(dss_reg_w); Loading Loading
msm/sde/sde_hw_util.c +2 −0 Original line number Diff line number Diff line Loading @@ -77,6 +77,8 @@ void sde_reg_write(struct sde_hw_blk_reg_map *c, SDE_DEBUG_DRIVER("[%s:0x%X] <= 0x%X\n", name, c->blk_off + reg_off, val); writel_relaxed(val, c->base_off + c->blk_off + reg_off); SDE_REG_LOG(c->log_mask ? ilog2(c->log_mask)+1 : 0, val, c->blk_off + reg_off); } int sde_reg_read(struct sde_hw_blk_reg_map *c, u32 reg_off) Loading
msm/sde_dbg.c +15 −0 Original line number Diff line number Diff line Loading @@ -197,6 +197,7 @@ struct sde_dbg_regbuf { /** * struct sde_dbg_base - global sde debug base structure * @evtlog: event log instance * @reglog: reg log instance * @reg_base_list: list of register dumping regions * @dev: device pointer * @mutex: mutex to serialize access to serialze dumps, debugfs access Loading @@ -212,11 +213,13 @@ struct sde_dbg_regbuf { * @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 * @dbgbus_dump_idx: index used for tracking dbg-bus dump in hw recovery * @vbif_dbgbus_dump_idx: index for tracking vbif dumps in hw recovery */ static struct sde_dbg_base { struct sde_dbg_evtlog *evtlog; struct sde_dbg_reglog *reglog; struct list_head reg_base_list; void *reg_dump_addr; struct device *dev; Loading @@ -239,6 +242,7 @@ static struct sde_dbg_base { struct sde_dbg_regbuf regbuf; u32 cur_evt_index; u32 cur_reglog_index; u32 dbgbus_dump_idx; u32 vbif_dbgbus_dump_idx; enum sde_dbg_dump_context dump_mode; Loading @@ -247,6 +251,9 @@ static struct sde_dbg_base { /* sde_dbg_base_evtlog - global pointer to main sde event log for macro use */ struct sde_dbg_evtlog *sde_dbg_base_evtlog; /* sde_dbg_base_reglog - global pointer to main sde reg log for macro use */ struct sde_dbg_reglog *sde_dbg_base_reglog; static void _sde_debug_bus_xbar_dump(void __iomem *mem_base, struct sde_debug_bus_entry *entry, u32 val) { Loading Loading @@ -4727,6 +4734,12 @@ int sde_dbg_init(struct device *dev) sde_dbg_base_evtlog = sde_dbg_base.evtlog; sde_dbg_base.reglog = sde_reglog_init(); if (IS_ERR_OR_NULL(sde_dbg_base.reglog)) return PTR_ERR(sde_dbg_base.reglog); sde_dbg_base_reglog = sde_dbg_base.reglog; INIT_WORK(&sde_dbg_base.dump_work, _sde_dump_work); sde_dbg_base.work_panic = false; sde_dbg_base.panic_on_err = DEFAULT_PANIC; Loading Loading @@ -4771,6 +4784,8 @@ void sde_dbg_destroy(void) sde_dbg_base_evtlog = NULL; sde_evtlog_destroy(sde_dbg_base.evtlog); sde_dbg_base.evtlog = NULL; sde_reglog_destroy(sde_dbg_base.reglog); sde_dbg_base.reglog = NULL; sde_dbg_reg_base_destroy(); mutex_destroy(&sde_dbg_base.mutex); } Loading
msm/sde_dbg.h +92 −0 Original line number Diff line number Diff line Loading @@ -49,6 +49,34 @@ enum sde_dbg_dump_context { SDE_DBG_DUMP_CLK_ENABLED_CTX, }; /* * Define blocks for register write logging. */ #define SDE_REG_LOG_DEFAULT 0 #define SDE_REG_LOG_NONE 1 #define SDE_REG_LOG_CDM 2 #define SDE_REG_LOG_DSPP 3 #define SDE_REG_LOG_INTF 4 #define SDE_REG_LOG_LM 5 #define SDE_REG_LOG_CTL 6 #define SDE_REG_LOG_PINGPONG 7 #define SDE_REG_LOG_SSPP 8 #define SDE_REG_LOG_WB 9 #define SDE_REG_LOG_TOP 10 #define SDE_REG_LOG_VBIF 11 #define SDE_REG_LOG_DSC 12 #define SDE_REG_LOG_ROT 13 #define SDE_REG_LOG_DS 14 #define SDE_REG_LOG_REGDMA 15 #define SDE_REG_LOG_UIDLE 16 #define SDE_REG_LOG_SID 16 #define SDE_REG_LOG_QDSS 17 /* * 0-32 are reserved for sde_reg_write due to log masks * Additional blocks are assigned from 33 to avoid conflict */ #define SDE_REG_LOG_RSCC 33 #define SDE_EVTLOG_DEFAULT_ENABLE (SDE_EVTLOG_CRITICAL | SDE_EVTLOG_IRQ | \ SDE_EVTLOG_EXTERNAL) Loading Loading @@ -103,6 +131,44 @@ struct sde_dbg_evtlog { extern struct sde_dbg_evtlog *sde_dbg_base_evtlog; /* * reglog keeps this number of entries in memory for debug purpose. This * number must be greater than number of possible writes in at least one * single commit. */ #define SDE_REGLOG_ENTRY 1024 struct sde_dbg_reglog_log { s64 time; u32 pid; u32 addr; u32 val; u8 blk_id; }; /** * @last_dump: Index of last entry to be output during reglog dumps * @filter_list: Linked list of currently active filter strings */ struct sde_dbg_reglog { struct sde_dbg_reglog_log logs[SDE_REGLOG_ENTRY]; u32 first; u32 last; u32 last_dump; u32 curr; u32 next; u32 enable; u32 enable_mask; spinlock_t spin_lock; }; extern struct sde_dbg_reglog *sde_dbg_base_reglog; /** * SDE_REG_LOG - Write register write to the register log */ #define SDE_REG_LOG(blk_id, val, addr) sde_reglog_log(blk_id, val, addr) /** * SDE_EVT32 - Write a list of 32bit values to the event log, default area * ... - variable arguments Loading Loading @@ -183,6 +249,12 @@ extern struct sde_dbg_evtlog *sde_dbg_base_evtlog; */ struct sde_dbg_evtlog *sde_evtlog_init(void); /** * sde_reglog_init - allocate a new reg log object * Returns: reglog or -ERROR */ struct sde_dbg_reglog *sde_reglog_init(void); /** * sde_evtlog_destroy - destroy previously allocated event log * @evtlog: pointer to evtlog Loading @@ -190,6 +262,13 @@ struct sde_dbg_evtlog *sde_evtlog_init(void); */ void sde_evtlog_destroy(struct sde_dbg_evtlog *evtlog); /** * sde_reglog_destroy - destroy previously allocated reg log * @reglog: pointer to reglog * Returns: none */ void sde_reglog_destroy(struct sde_dbg_reglog *reglog); /** * sde_evtlog_log - log an entry into the event log. * log collection may be enabled/disabled entirely via debugfs Loading @@ -203,6 +282,15 @@ void sde_evtlog_destroy(struct sde_dbg_evtlog *evtlog); void sde_evtlog_log(struct sde_dbg_evtlog *evtlog, const char *name, int line, int flag, ...); /** * sde_reglog_log - log an entry into the reg log. * log collection may be enabled/disabled entirely via debugfs * log area collection may be filtered by user provided flags via debugfs. * @reglog: pointer to evtlog * Returns: none */ void sde_reglog_log(u8 blk_id, u32 val, u32 addr); /** * sde_evtlog_dump_all - print all entries in event log to kernel log * @evtlog: pointer to evtlog Loading Loading @@ -386,6 +474,10 @@ static inline void sde_evtlog_log(struct sde_dbg_evtlog *evtlog, { } static inline void sde_reglog_log(u8 blk_id, u32 val, u32 addr) { } static inline void sde_evtlog_dump_all(struct sde_dbg_evtlog *evtlog) { } Loading
msm/sde_dbg_evtlog.c +47 −1 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. */ #define pr_fmt(fmt) "sde_dbg:[%s] " fmt, __func__ Loading Loading @@ -101,6 +101,31 @@ void sde_evtlog_log(struct sde_dbg_evtlog *evtlog, const char *name, int line, spin_unlock_irqrestore(&evtlog->spin_lock, flags); } void sde_reglog_log(u8 blk_id, u32 val, u32 addr) { unsigned long flags; struct sde_dbg_reglog_log *log; struct sde_dbg_reglog *reglog = sde_dbg_base_reglog; if (!reglog) return; spin_lock_irqsave(®log->spin_lock, flags); log = ®log->logs[reglog->curr]; log->blk_id = blk_id; log->val = val; log->addr = addr; log->time = local_clock(); log->pid = current->pid; reglog->curr = (reglog->curr + 1) % SDE_REGLOG_ENTRY; reglog->last++; spin_unlock_irqrestore(®log->spin_lock, flags); } /* always dump the last entries which are not dumped yet */ static bool _sde_evtlog_dump_calc_range(struct sde_dbg_evtlog *evtlog, bool update_last_entry, bool full_dump) Loading Loading @@ -211,6 +236,19 @@ struct sde_dbg_evtlog *sde_evtlog_init(void) return evtlog; } struct sde_dbg_reglog *sde_reglog_init(void) { struct sde_dbg_reglog *reglog; reglog = kzalloc(sizeof(*reglog), GFP_KERNEL); if (!reglog) return ERR_PTR(-ENOMEM); spin_lock_init(®log->spin_lock); return reglog; } int sde_evtlog_get_filter(struct sde_dbg_evtlog *evtlog, int index, char *buf, size_t bufsz) { Loading Loading @@ -312,3 +350,11 @@ void sde_evtlog_destroy(struct sde_dbg_evtlog *evtlog) } kfree(evtlog); } void sde_reglog_destroy(struct sde_dbg_reglog *reglog) { if (!reglog) return; kfree(reglog); }
msm/sde_io_util.c +2 −0 Original line number Diff line number Diff line Loading @@ -9,6 +9,7 @@ #include <linux/regulator/consumer.h> #include <linux/delay.h> #include <linux/sde_io_util.h> #include "sde_dbg.h" #define MAX_I2C_CMDS 16 void dss_reg_w(struct dss_io_data *io, u32 offset, u32 value, u32 debug) Loading @@ -34,6 +35,7 @@ void dss_reg_w(struct dss_io_data *io, u32 offset, u32 value, u32 debug) (u32)(unsigned long)(io->base + offset), value, in_val); } SDE_REG_LOG(SDE_REG_LOG_RSCC, value, offset); } /* dss_reg_w */ EXPORT_SYMBOL(dss_reg_w); Loading