|
@@ -65,25 +65,53 @@ static unsigned int regmap_debugfs_get_dump_start(struct regmap *map,
|
|
|
loff_t from,
|
|
|
loff_t *pos)
|
|
|
{
|
|
|
- loff_t p = *pos;
|
|
|
- unsigned int i;
|
|
|
-
|
|
|
- for (i = base; i <= map->max_register; i += map->reg_stride) {
|
|
|
- if (!regmap_readable(map, i))
|
|
|
- continue;
|
|
|
-
|
|
|
- if (regmap_precious(map, i))
|
|
|
- continue;
|
|
|
+ struct regmap_debugfs_off_cache *c = NULL;
|
|
|
+ loff_t p = 0;
|
|
|
+ unsigned int i, ret;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * If we don't have a cache build one so we don't have to do a
|
|
|
+ * linear scan each time.
|
|
|
+ */
|
|
|
+ if (list_empty(&map->debugfs_off_cache)) {
|
|
|
+ for (i = base; i <= map->max_register; i += map->reg_stride) {
|
|
|
+ /* Skip unprinted registers, closing off cache entry */
|
|
|
+ if (!regmap_readable(map, i) ||
|
|
|
+ regmap_precious(map, i)) {
|
|
|
+ if (c) {
|
|
|
+ c->max = p - 1;
|
|
|
+ list_add_tail(&c->list,
|
|
|
+ &map->debugfs_off_cache);
|
|
|
+ c = NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* No cache entry? Start a new one */
|
|
|
+ if (!c) {
|
|
|
+ c = kzalloc(sizeof(*c), GFP_KERNEL);
|
|
|
+ if (!c)
|
|
|
+ break;
|
|
|
+ c->min = p;
|
|
|
+ c->base_reg = i;
|
|
|
+ }
|
|
|
+
|
|
|
+ p += map->debugfs_tot_len;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- if (i >= from) {
|
|
|
- *pos = p;
|
|
|
- return i;
|
|
|
+ /* Find the relevant block */
|
|
|
+ list_for_each_entry(c, &map->debugfs_off_cache, list) {
|
|
|
+ if (*pos >= c->min && *pos <= c->max) {
|
|
|
+ *pos = c->min;
|
|
|
+ return c->base_reg;
|
|
|
}
|
|
|
|
|
|
- p += map->debugfs_tot_len;
|
|
|
+ ret = c->max;
|
|
|
}
|
|
|
|
|
|
- return base;
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
static ssize_t regmap_read_debugfs(struct regmap *map, unsigned int from,
|
|
@@ -309,6 +337,8 @@ void regmap_debugfs_init(struct regmap *map, const char *name)
|
|
|
struct rb_node *next;
|
|
|
struct regmap_range_node *range_node;
|
|
|
|
|
|
+ INIT_LIST_HEAD(&map->debugfs_off_cache);
|
|
|
+
|
|
|
if (name) {
|
|
|
map->debugfs_name = kasprintf(GFP_KERNEL, "%s-%s",
|
|
|
dev_name(map->dev), name);
|
|
@@ -357,7 +387,16 @@ void regmap_debugfs_init(struct regmap *map, const char *name)
|
|
|
|
|
|
void regmap_debugfs_exit(struct regmap *map)
|
|
|
{
|
|
|
+ struct regmap_debugfs_off_cache *c;
|
|
|
+
|
|
|
debugfs_remove_recursive(map->debugfs);
|
|
|
+ while (!list_empty(&map->debugfs_off_cache)) {
|
|
|
+ c = list_first_entry(&map->debugfs_off_cache,
|
|
|
+ struct regmap_debugfs_off_cache,
|
|
|
+ list);
|
|
|
+ list_del(&c->list);
|
|
|
+ kfree(c);
|
|
|
+ }
|
|
|
kfree(map->debugfs_name);
|
|
|
}
|
|
|
|