aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/base/regmap/internal.h10
-rw-r--r--drivers/base/regmap/regmap-debugfs.c67
2 files changed, 63 insertions, 14 deletions
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
index 1abcd27e2d0f..9c3b0e7a6c7d 100644
--- a/drivers/base/regmap/internal.h
+++ b/drivers/base/regmap/internal.h
@@ -15,10 +15,18 @@
15 15
16#include <linux/regmap.h> 16#include <linux/regmap.h>
17#include <linux/fs.h> 17#include <linux/fs.h>
18#include <linux/list.h>
18 19
19struct regmap; 20struct regmap;
20struct regcache_ops; 21struct regcache_ops;
21 22
23struct regmap_debugfs_off_cache {
24 struct list_head list;
25 off_t min;
26 off_t max;
27 unsigned int base_reg;
28};
29
22struct regmap_format { 30struct regmap_format {
23 size_t buf_size; 31 size_t buf_size;
24 size_t reg_bytes; 32 size_t reg_bytes;
@@ -54,6 +62,8 @@ struct regmap {
54 unsigned int debugfs_reg_len; 62 unsigned int debugfs_reg_len;
55 unsigned int debugfs_val_len; 63 unsigned int debugfs_val_len;
56 unsigned int debugfs_tot_len; 64 unsigned int debugfs_tot_len;
65
66 struct list_head debugfs_off_cache;
57#endif 67#endif
58 68
59 unsigned int max_register; 69 unsigned int max_register;
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
89static ssize_t regmap_read_debugfs(struct regmap *map, unsigned int from, 117static 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
358void regmap_debugfs_exit(struct regmap *map) 388void 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