Merge "regmap: improve debugfs interface to dump specific addresses"

This commit is contained in:
qctecmdr 2019-11-06 06:31:14 -08:00 • committed by Gerrit - the friendly Code Review server
commit 686d21586a
3 changed files with 87 additions and 0 deletions

View file

@ -53,3 +53,12 @@ config REGMAP_SCCB
config REGMAP_I3C
tristate
depends on I3C
config REGMAP_QTI_DEBUG
bool "Regmap QTI debug feature support"
depends on REGMAP && DEBUG_FS && QGKI
help
Say yes to enable QTI debug features. This provides a runtime debugfs
interface to read and write a subset of regmap registers. This
interface is more performant and easier to use than the traditional
method which dumps all registers defined in a given regmap.

View file

@ -84,6 +84,11 @@ struct regmap {
struct list_head debugfs_off_cache;
struct mutex cache_lock;
#ifdef CONFIG_REGMAP_QTI_DEBUG
unsigned int dump_address;
unsigned int dump_count;
#endif
#endif
unsigned int max_register;

View file

@ -339,6 +339,69 @@ static const struct file_operations regmap_map_fops = {
.llseek = default_llseek,
};
#ifdef CONFIG_REGMAP_QTI_DEBUG
static ssize_t regmap_data_read_file(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct regmap *map = file->private_data;
int new_count;
regmap_calc_tot_len(map, NULL, 0);
new_count = map->dump_count * map->debugfs_tot_len;
if (new_count > count)
new_count = count;
if (*ppos == 0)
*ppos = map->dump_address * map->debugfs_tot_len;
else if (*ppos >= map->dump_address * map->debugfs_tot_len
+ map->dump_count * map->debugfs_tot_len)
return 0;
return regmap_read_debugfs(map, 0, map->max_register, user_buf,
new_count, ppos);
}
#ifdef REGMAP_ALLOW_WRITE_DEBUGFS
static ssize_t regmap_data_write_file(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
{
char buf[32];
size_t buf_size;
char *start = buf;
unsigned long value;
struct regmap *map = file->private_data;
int ret;
buf_size = min(count, (sizeof(buf)-1));
if (copy_from_user(buf, user_buf, buf_size))
return -EFAULT;
buf[buf_size] = 0;
while (*start == ' ')
start++;
if (kstrtoul(start, 16, &value))
return -EINVAL;
/* Userspace has been fiddling around behind the kernel's back */
add_taint(TAINT_USER, LOCKDEP_STILL_OK);
ret = regmap_write(map, map->dump_address, value);
if (ret < 0)
return ret;
return buf_size;
}
#else
#define regmap_data_write_file NULL
#endif
static const struct file_operations regmap_data_fops = {
.open = simple_open,
.read = regmap_data_read_file,
.write = regmap_data_write_file,
.llseek = default_llseek,
};
#endif
static ssize_t regmap_range_read_file(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
@ -608,6 +671,16 @@ void regmap_debugfs_init(struct regmap *map, const char *name)
map, &regmap_map_fops);
debugfs_create_file("access", 0400, map->debugfs,
map, &regmap_access_fops);
#ifdef CONFIG_REGMAP_QTI_DEBUG
debugfs_create_x32("address", 0600, map->debugfs,
&map->dump_address);
map->dump_count = 1;
debugfs_create_u32("count", 0600, map->debugfs,
&map->dump_count);
debugfs_create_file("data", registers_mode, map->debugfs,
map, &regmap_data_fops);
#endif
}
if (map->cache_type) {