Loading drivers/gpu/drm/msm/sde_dbg.c +89 −13 Original line number Diff line number Diff line Loading @@ -168,6 +168,7 @@ struct sde_dbg_vbif_debug_bus { * @evtlog: event log instance * @reg_base_list: list of register dumping regions * @dev: device pointer * @mutex: mutex to serialize access to serialze dumps, debugfs access * @power_ctrl: callback structure for enabling power for reading hw registers * @req_dump_blks: list of blocks requested for dumping * @panic_on_err: whether to kernel panic after triggering dump via debugfs Loading @@ -183,6 +184,7 @@ static struct sde_dbg_base { struct sde_dbg_evtlog *evtlog; struct list_head reg_base_list; struct device *dev; struct mutex mutex; struct sde_dbg_power_ctrl power_ctrl; struct sde_dbg_reg_base *req_dump_blks[SDE_DBG_BASE_MAX]; Loading Loading @@ -2554,6 +2556,8 @@ static void _sde_dump_array(struct sde_dbg_reg_base *blk_arr[], { int i; mutex_lock(&sde_dbg_base.mutex); sde_evtlog_dump_all(sde_dbg_base.evtlog); if (dump_all || !blk_arr || !len) { Loading @@ -2577,6 +2581,8 @@ static void _sde_dump_array(struct sde_dbg_reg_base *blk_arr[], if (do_panic && sde_dbg_base.panic_on_err) panic(name); mutex_unlock(&sde_dbg_base.mutex); } /** Loading Loading @@ -2679,6 +2685,9 @@ void sde_dbg_dump(bool queue_work, const char *name, ...) */ static int sde_dbg_debugfs_open(struct inode *inode, struct file *file) { if (!inode || !file) return -EINVAL; /* non-seekable */ file->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE); file->private_data = inode->i_private; Loading @@ -2698,6 +2707,9 @@ static ssize_t sde_evtlog_dump_read(struct file *file, char __user *buff, ssize_t len = 0; char evtlog_buf[SDE_EVTLOG_BUF_MAX]; if (!buff || !ppos) return -EINVAL; len = sde_evtlog_dump_to_buffer(sde_dbg_base.evtlog, evtlog_buf, SDE_EVTLOG_BUF_MAX); if (copy_to_user(buff, evtlog_buf, len)) Loading Loading @@ -2759,7 +2771,7 @@ static int sde_evtlog_filter_show(struct seq_file *s, void *data) */ static int sde_evtlog_filter_open(struct inode *inode, struct file *file) { if (!file) if (!inode || !file) return -EINVAL; return single_open(file, sde_evtlog_filter_show, inode->i_private); Loading @@ -2778,6 +2790,9 @@ static ssize_t sde_evtlog_filter_write(struct file *file, char *tmp_filter = NULL; ssize_t rc = 0; if (!user_buf) return -EINVAL; if (count > 0) { /* copy user provided string and null terminate it */ tmp_filter = kzalloc(count + 1, GFP_KERNEL); Loading Loading @@ -2813,13 +2828,23 @@ static const struct file_operations sde_evtlog_filter_fops = { */ static int sde_dbg_reg_base_release(struct inode *inode, struct file *file) { struct sde_dbg_reg_base *dbg = file->private_data; struct sde_dbg_reg_base *dbg; if (!file) return -EINVAL; dbg = file->private_data; if (!dbg) return -ENODEV; mutex_lock(&sde_dbg_base.mutex); if (dbg && dbg->buf) { kfree(dbg->buf); dbg->buf_len = 0; dbg->buf = NULL; } mutex_unlock(&sde_dbg_base.mutex); return 0; } Loading @@ -2834,11 +2859,15 @@ static int sde_dbg_reg_base_release(struct inode *inode, struct file *file) static ssize_t sde_dbg_reg_base_offset_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { struct sde_dbg_reg_base *dbg = file->private_data; struct sde_dbg_reg_base *dbg; u32 off = 0; u32 cnt = DEFAULT_BASE_REG_CNT; char buf[24]; if (!file) return -EINVAL; dbg = file->private_data; if (!dbg) return -ENODEV; Loading @@ -2862,8 +2891,13 @@ static ssize_t sde_dbg_reg_base_offset_write(struct file *file, if (cnt > (dbg->max_offset - off)) cnt = dbg->max_offset - off; if (cnt == 0) return -EINVAL; mutex_lock(&sde_dbg_base.mutex); dbg->off = off; dbg->cnt = cnt; mutex_unlock(&sde_dbg_base.mutex); pr_debug("offset=%x cnt=%x\n", off, cnt); Loading @@ -2880,27 +2914,42 @@ static ssize_t sde_dbg_reg_base_offset_write(struct file *file, static ssize_t sde_dbg_reg_base_offset_read(struct file *file, char __user *buff, size_t count, loff_t *ppos) { struct sde_dbg_reg_base *dbg = file->private_data; struct sde_dbg_reg_base *dbg; int len = 0; char buf[24] = {'\0'}; if (!file) return -EINVAL; dbg = file->private_data; if (!dbg) return -ENODEV; if (!ppos) return -EINVAL; if (*ppos) return 0; /* the end */ if (dbg->off % sizeof(u32)) mutex_lock(&sde_dbg_base.mutex); if (dbg->off % sizeof(u32)) { mutex_unlock(&sde_dbg_base.mutex); return -EFAULT; } len = snprintf(buf, sizeof(buf), "0x%08zx %zx\n", dbg->off, dbg->cnt); if (len < 0 || len >= sizeof(buf)) if (len < 0 || len >= sizeof(buf)) { mutex_unlock(&sde_dbg_base.mutex); return 0; } if ((count < sizeof(buf)) || copy_to_user(buff, buf, len)) if ((count < sizeof(buf)) || copy_to_user(buff, buf, len)) { mutex_unlock(&sde_dbg_base.mutex); return -EFAULT; } *ppos += len; /* increase offset */ mutex_unlock(&sde_dbg_base.mutex); return len; } Loading @@ -2915,11 +2964,15 @@ static ssize_t sde_dbg_reg_base_offset_read(struct file *file, static ssize_t sde_dbg_reg_base_reg_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { struct sde_dbg_reg_base *dbg = file->private_data; struct sde_dbg_reg_base *dbg; size_t off; u32 data, cnt; char buf[24]; if (!file) return -EINVAL; dbg = file->private_data; if (!dbg) return -ENODEV; Loading @@ -2939,8 +2992,11 @@ static ssize_t sde_dbg_reg_base_reg_write(struct file *file, if (off % sizeof(u32)) return -EFAULT; if (off >= dbg->max_offset) mutex_lock(&sde_dbg_base.mutex); if (off >= dbg->max_offset) { mutex_unlock(&sde_dbg_base.mutex); return -EFAULT; } _sde_dbg_enable_power(true); Loading @@ -2948,6 +3004,8 @@ static ssize_t sde_dbg_reg_base_reg_write(struct file *file, _sde_dbg_enable_power(false); mutex_unlock(&sde_dbg_base.mutex); pr_debug("addr=%zx data=%x\n", off, data); return count; Loading @@ -2963,14 +3021,22 @@ static ssize_t sde_dbg_reg_base_reg_write(struct file *file, static ssize_t sde_dbg_reg_base_reg_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct sde_dbg_reg_base *dbg = file->private_data; struct sde_dbg_reg_base *dbg; size_t len; if (!file) return -EINVAL; dbg = file->private_data; if (!dbg) { pr_err("invalid handle\n"); return -ENODEV; } if (!ppos) return -EINVAL; mutex_lock(&sde_dbg_base.mutex); if (!dbg->buf) { char dump_buf[64]; char *ptr; Loading @@ -2980,11 +3046,15 @@ static ssize_t sde_dbg_reg_base_reg_read(struct file *file, DIV_ROUND_UP(dbg->cnt, ROW_BYTES); dbg->buf = kzalloc(dbg->buf_len, GFP_KERNEL); if (!dbg->buf) if (!dbg->buf) { mutex_unlock(&sde_dbg_base.mutex); return -ENOMEM; } if (dbg->off % sizeof(u32)) if (dbg->off % sizeof(u32)) { mutex_unlock(&sde_dbg_base.mutex); return -EFAULT; } ptr = dbg->base + dbg->off; tot = 0; Loading Loading @@ -3012,16 +3082,20 @@ static ssize_t sde_dbg_reg_base_reg_read(struct file *file, dbg->buf_len = tot; } if (*ppos >= dbg->buf_len) if (*ppos >= dbg->buf_len) { mutex_unlock(&sde_dbg_base.mutex); return 0; /* done reading */ } len = min(count, dbg->buf_len - (size_t) *ppos); if (copy_to_user(user_buf, dbg->buf + *ppos, len)) { mutex_unlock(&sde_dbg_base.mutex); pr_err("failed to copy to user\n"); return -EFAULT; } *ppos += len; /* increase offset */ mutex_unlock(&sde_dbg_base.mutex); return len; } Loading Loading @@ -3135,6 +3209,7 @@ int sde_dbg_init(struct device *dev, struct sde_dbg_power_ctrl *power_ctrl) return -EINVAL; } mutex_init(&sde_dbg_base.mutex); INIT_LIST_HEAD(&sde_dbg_base.reg_base_list); sde_dbg_base.dev = dev; sde_dbg_base.power_ctrl = *power_ctrl; Loading Loading @@ -3187,6 +3262,7 @@ void sde_dbg_destroy(void) sde_evtlog_destroy(sde_dbg_base.evtlog); sde_dbg_base.evtlog = NULL; sde_dbg_reg_base_destroy(); mutex_destroy(&sde_dbg_base.mutex); } int sde_dbg_reg_register_base(const char *name, void __iomem *base, Loading Loading
drivers/gpu/drm/msm/sde_dbg.c +89 −13 Original line number Diff line number Diff line Loading @@ -168,6 +168,7 @@ struct sde_dbg_vbif_debug_bus { * @evtlog: event log instance * @reg_base_list: list of register dumping regions * @dev: device pointer * @mutex: mutex to serialize access to serialze dumps, debugfs access * @power_ctrl: callback structure for enabling power for reading hw registers * @req_dump_blks: list of blocks requested for dumping * @panic_on_err: whether to kernel panic after triggering dump via debugfs Loading @@ -183,6 +184,7 @@ static struct sde_dbg_base { struct sde_dbg_evtlog *evtlog; struct list_head reg_base_list; struct device *dev; struct mutex mutex; struct sde_dbg_power_ctrl power_ctrl; struct sde_dbg_reg_base *req_dump_blks[SDE_DBG_BASE_MAX]; Loading Loading @@ -2554,6 +2556,8 @@ static void _sde_dump_array(struct sde_dbg_reg_base *blk_arr[], { int i; mutex_lock(&sde_dbg_base.mutex); sde_evtlog_dump_all(sde_dbg_base.evtlog); if (dump_all || !blk_arr || !len) { Loading @@ -2577,6 +2581,8 @@ static void _sde_dump_array(struct sde_dbg_reg_base *blk_arr[], if (do_panic && sde_dbg_base.panic_on_err) panic(name); mutex_unlock(&sde_dbg_base.mutex); } /** Loading Loading @@ -2679,6 +2685,9 @@ void sde_dbg_dump(bool queue_work, const char *name, ...) */ static int sde_dbg_debugfs_open(struct inode *inode, struct file *file) { if (!inode || !file) return -EINVAL; /* non-seekable */ file->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE); file->private_data = inode->i_private; Loading @@ -2698,6 +2707,9 @@ static ssize_t sde_evtlog_dump_read(struct file *file, char __user *buff, ssize_t len = 0; char evtlog_buf[SDE_EVTLOG_BUF_MAX]; if (!buff || !ppos) return -EINVAL; len = sde_evtlog_dump_to_buffer(sde_dbg_base.evtlog, evtlog_buf, SDE_EVTLOG_BUF_MAX); if (copy_to_user(buff, evtlog_buf, len)) Loading Loading @@ -2759,7 +2771,7 @@ static int sde_evtlog_filter_show(struct seq_file *s, void *data) */ static int sde_evtlog_filter_open(struct inode *inode, struct file *file) { if (!file) if (!inode || !file) return -EINVAL; return single_open(file, sde_evtlog_filter_show, inode->i_private); Loading @@ -2778,6 +2790,9 @@ static ssize_t sde_evtlog_filter_write(struct file *file, char *tmp_filter = NULL; ssize_t rc = 0; if (!user_buf) return -EINVAL; if (count > 0) { /* copy user provided string and null terminate it */ tmp_filter = kzalloc(count + 1, GFP_KERNEL); Loading Loading @@ -2813,13 +2828,23 @@ static const struct file_operations sde_evtlog_filter_fops = { */ static int sde_dbg_reg_base_release(struct inode *inode, struct file *file) { struct sde_dbg_reg_base *dbg = file->private_data; struct sde_dbg_reg_base *dbg; if (!file) return -EINVAL; dbg = file->private_data; if (!dbg) return -ENODEV; mutex_lock(&sde_dbg_base.mutex); if (dbg && dbg->buf) { kfree(dbg->buf); dbg->buf_len = 0; dbg->buf = NULL; } mutex_unlock(&sde_dbg_base.mutex); return 0; } Loading @@ -2834,11 +2859,15 @@ static int sde_dbg_reg_base_release(struct inode *inode, struct file *file) static ssize_t sde_dbg_reg_base_offset_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { struct sde_dbg_reg_base *dbg = file->private_data; struct sde_dbg_reg_base *dbg; u32 off = 0; u32 cnt = DEFAULT_BASE_REG_CNT; char buf[24]; if (!file) return -EINVAL; dbg = file->private_data; if (!dbg) return -ENODEV; Loading @@ -2862,8 +2891,13 @@ static ssize_t sde_dbg_reg_base_offset_write(struct file *file, if (cnt > (dbg->max_offset - off)) cnt = dbg->max_offset - off; if (cnt == 0) return -EINVAL; mutex_lock(&sde_dbg_base.mutex); dbg->off = off; dbg->cnt = cnt; mutex_unlock(&sde_dbg_base.mutex); pr_debug("offset=%x cnt=%x\n", off, cnt); Loading @@ -2880,27 +2914,42 @@ static ssize_t sde_dbg_reg_base_offset_write(struct file *file, static ssize_t sde_dbg_reg_base_offset_read(struct file *file, char __user *buff, size_t count, loff_t *ppos) { struct sde_dbg_reg_base *dbg = file->private_data; struct sde_dbg_reg_base *dbg; int len = 0; char buf[24] = {'\0'}; if (!file) return -EINVAL; dbg = file->private_data; if (!dbg) return -ENODEV; if (!ppos) return -EINVAL; if (*ppos) return 0; /* the end */ if (dbg->off % sizeof(u32)) mutex_lock(&sde_dbg_base.mutex); if (dbg->off % sizeof(u32)) { mutex_unlock(&sde_dbg_base.mutex); return -EFAULT; } len = snprintf(buf, sizeof(buf), "0x%08zx %zx\n", dbg->off, dbg->cnt); if (len < 0 || len >= sizeof(buf)) if (len < 0 || len >= sizeof(buf)) { mutex_unlock(&sde_dbg_base.mutex); return 0; } if ((count < sizeof(buf)) || copy_to_user(buff, buf, len)) if ((count < sizeof(buf)) || copy_to_user(buff, buf, len)) { mutex_unlock(&sde_dbg_base.mutex); return -EFAULT; } *ppos += len; /* increase offset */ mutex_unlock(&sde_dbg_base.mutex); return len; } Loading @@ -2915,11 +2964,15 @@ static ssize_t sde_dbg_reg_base_offset_read(struct file *file, static ssize_t sde_dbg_reg_base_reg_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { struct sde_dbg_reg_base *dbg = file->private_data; struct sde_dbg_reg_base *dbg; size_t off; u32 data, cnt; char buf[24]; if (!file) return -EINVAL; dbg = file->private_data; if (!dbg) return -ENODEV; Loading @@ -2939,8 +2992,11 @@ static ssize_t sde_dbg_reg_base_reg_write(struct file *file, if (off % sizeof(u32)) return -EFAULT; if (off >= dbg->max_offset) mutex_lock(&sde_dbg_base.mutex); if (off >= dbg->max_offset) { mutex_unlock(&sde_dbg_base.mutex); return -EFAULT; } _sde_dbg_enable_power(true); Loading @@ -2948,6 +3004,8 @@ static ssize_t sde_dbg_reg_base_reg_write(struct file *file, _sde_dbg_enable_power(false); mutex_unlock(&sde_dbg_base.mutex); pr_debug("addr=%zx data=%x\n", off, data); return count; Loading @@ -2963,14 +3021,22 @@ static ssize_t sde_dbg_reg_base_reg_write(struct file *file, static ssize_t sde_dbg_reg_base_reg_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct sde_dbg_reg_base *dbg = file->private_data; struct sde_dbg_reg_base *dbg; size_t len; if (!file) return -EINVAL; dbg = file->private_data; if (!dbg) { pr_err("invalid handle\n"); return -ENODEV; } if (!ppos) return -EINVAL; mutex_lock(&sde_dbg_base.mutex); if (!dbg->buf) { char dump_buf[64]; char *ptr; Loading @@ -2980,11 +3046,15 @@ static ssize_t sde_dbg_reg_base_reg_read(struct file *file, DIV_ROUND_UP(dbg->cnt, ROW_BYTES); dbg->buf = kzalloc(dbg->buf_len, GFP_KERNEL); if (!dbg->buf) if (!dbg->buf) { mutex_unlock(&sde_dbg_base.mutex); return -ENOMEM; } if (dbg->off % sizeof(u32)) if (dbg->off % sizeof(u32)) { mutex_unlock(&sde_dbg_base.mutex); return -EFAULT; } ptr = dbg->base + dbg->off; tot = 0; Loading Loading @@ -3012,16 +3082,20 @@ static ssize_t sde_dbg_reg_base_reg_read(struct file *file, dbg->buf_len = tot; } if (*ppos >= dbg->buf_len) if (*ppos >= dbg->buf_len) { mutex_unlock(&sde_dbg_base.mutex); return 0; /* done reading */ } len = min(count, dbg->buf_len - (size_t) *ppos); if (copy_to_user(user_buf, dbg->buf + *ppos, len)) { mutex_unlock(&sde_dbg_base.mutex); pr_err("failed to copy to user\n"); return -EFAULT; } *ppos += len; /* increase offset */ mutex_unlock(&sde_dbg_base.mutex); return len; } Loading Loading @@ -3135,6 +3209,7 @@ int sde_dbg_init(struct device *dev, struct sde_dbg_power_ctrl *power_ctrl) return -EINVAL; } mutex_init(&sde_dbg_base.mutex); INIT_LIST_HEAD(&sde_dbg_base.reg_base_list); sde_dbg_base.dev = dev; sde_dbg_base.power_ctrl = *power_ctrl; Loading Loading @@ -3187,6 +3262,7 @@ void sde_dbg_destroy(void) sde_evtlog_destroy(sde_dbg_base.evtlog); sde_dbg_base.evtlog = NULL; sde_dbg_reg_base_destroy(); mutex_destroy(&sde_dbg_base.mutex); } int sde_dbg_reg_register_base(const char *name, void __iomem *base, Loading