diff options
Diffstat (limited to 'drivers/base/regmap/regmap-debugfs.c')
-rw-r--r-- | drivers/base/regmap/regmap-debugfs.c | 67 |
1 files changed, 53 insertions, 14 deletions
diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c index 749a1dc5bbfb..07aad786f817 100644 --- a/drivers/base/regmap/regmap-debugfs.c +++ b/drivers/base/regmap/regmap-debugfs.c | |||
@@ -65,25 +65,53 @@ static unsigned int regmap_debugfs_get_dump_start(struct regmap *map, | |||
65 | loff_t from, | 65 | loff_t from, |
66 | loff_t *pos) | 66 | loff_t *pos) |
67 | { | 67 | { |
68 | loff_t p = *pos; | 68 | struct regmap_debugfs_off_cache *c = NULL; |
69 | unsigned int i; | 69 | loff_t p = 0; |
70 | 70 | unsigned int i, ret; | |
71 | for (i = base; i <= map->max_register; i += map->reg_stride) { | 71 | |
72 | if (!regmap_readable(map, i)) | 72 | /* |
73 | continue; | 73 | * If we don't have a cache build one so we don't have to do a |
74 | 74 | * linear scan each time. | |
75 | if (regmap_precious(map, i)) | 75 | */ |
76 | continue; | 76 | if (list_empty(&map->debugfs_off_cache)) { |
77 | for (i = base; i <= map->max_register; i += map->reg_stride) { | ||
78 | /* Skip unprinted registers, closing off cache entry */ | ||
79 | if (!regmap_readable(map, i) || | ||
80 | regmap_precious(map, i)) { | ||
81 | if (c) { | ||
82 | c->max = p - 1; | ||
83 | list_add_tail(&c->list, | ||
84 | &map->debugfs_off_cache); | ||
85 | c = NULL; | ||
86 | } | ||
87 | |||
88 | continue; | ||
89 | } | ||
90 | |||
91 | /* No cache entry? Start a new one */ | ||
92 | if (!c) { | ||
93 | c = kzalloc(sizeof(*c), GFP_KERNEL); | ||
94 | if (!c) | ||
95 | break; | ||
96 | c->min = p; | ||
97 | c->base_reg = i; | ||
98 | } | ||
99 | |||
100 | p += map->debugfs_tot_len; | ||
101 | } | ||
102 | } | ||
77 | 103 | ||
78 | if (i >= from) { | 104 | /* Find the relevant block */ |
79 | *pos = p; | 105 | list_for_each_entry(c, &map->debugfs_off_cache, list) { |
80 | return i; | 106 | if (*pos >= c->min && *pos <= c->max) { |
107 | *pos = c->min; | ||
108 | return c->base_reg; | ||
81 | } | 109 | } |
82 | 110 | ||
83 | p += map->debugfs_tot_len; | 111 | ret = c->max; |
84 | } | 112 | } |
85 | 113 | ||
86 | return base; | 114 | return ret; |
87 | } | 115 | } |
88 | 116 | ||
89 | static ssize_t regmap_read_debugfs(struct regmap *map, unsigned int from, | 117 | 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) | |||
309 | struct rb_node *next; | 337 | struct rb_node *next; |
310 | struct regmap_range_node *range_node; | 338 | struct regmap_range_node *range_node; |
311 | 339 | ||
340 | INIT_LIST_HEAD(&map->debugfs_off_cache); | ||
341 | |||
312 | if (name) { | 342 | if (name) { |
313 | map->debugfs_name = kasprintf(GFP_KERNEL, "%s-%s", | 343 | map->debugfs_name = kasprintf(GFP_KERNEL, "%s-%s", |
314 | dev_name(map->dev), name); | 344 | dev_name(map->dev), name); |
@@ -357,7 +387,16 @@ void regmap_debugfs_init(struct regmap *map, const char *name) | |||
357 | 387 | ||
358 | void regmap_debugfs_exit(struct regmap *map) | 388 | void regmap_debugfs_exit(struct regmap *map) |
359 | { | 389 | { |
390 | struct regmap_debugfs_off_cache *c; | ||
391 | |||
360 | debugfs_remove_recursive(map->debugfs); | 392 | debugfs_remove_recursive(map->debugfs); |
393 | while (!list_empty(&map->debugfs_off_cache)) { | ||
394 | c = list_first_entry(&map->debugfs_off_cache, | ||
395 | struct regmap_debugfs_off_cache, | ||
396 | list); | ||
397 | list_del(&c->list); | ||
398 | kfree(c); | ||
399 | } | ||
361 | kfree(map->debugfs_name); | 400 | kfree(map->debugfs_name); |
362 | } | 401 | } |
363 | 402 | ||