Commit 38a817965d2d624b0db68f3bf5ae783ad7f2087a
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
Merge remote-tracking branch 'regmap/topic/range' into regmap-next
Showing 2 changed files Side-by-side Diff
drivers/base/regmap/internal.h
drivers/base/regmap/regmap-debugfs.c
... | ... | @@ -88,16 +88,16 @@ |
88 | 88 | * If we don't have a cache build one so we don't have to do a |
89 | 89 | * linear scan each time. |
90 | 90 | */ |
91 | + mutex_lock(&map->cache_lock); | |
92 | + i = base; | |
91 | 93 | if (list_empty(&map->debugfs_off_cache)) { |
92 | - for (i = base; i <= map->max_register; i += map->reg_stride) { | |
94 | + for (; i <= map->max_register; i += map->reg_stride) { | |
93 | 95 | /* Skip unprinted registers, closing off cache entry */ |
94 | 96 | if (!regmap_readable(map, i) || |
95 | 97 | regmap_precious(map, i)) { |
96 | 98 | if (c) { |
97 | 99 | c->max = p - 1; |
98 | - fpos_offset = c->max - c->min; | |
99 | - reg_offset = fpos_offset / map->debugfs_tot_len; | |
100 | - c->max_reg = c->base_reg + reg_offset; | |
100 | + c->max_reg = i - map->reg_stride; | |
101 | 101 | list_add_tail(&c->list, |
102 | 102 | &map->debugfs_off_cache); |
103 | 103 | c = NULL; |
... | ... | @@ -111,6 +111,7 @@ |
111 | 111 | c = kzalloc(sizeof(*c), GFP_KERNEL); |
112 | 112 | if (!c) { |
113 | 113 | regmap_debugfs_free_dump_cache(map); |
114 | + mutex_unlock(&map->cache_lock); | |
114 | 115 | return base; |
115 | 116 | } |
116 | 117 | c->min = p; |
... | ... | @@ -124,9 +125,7 @@ |
124 | 125 | /* Close the last entry off if we didn't scan beyond it */ |
125 | 126 | if (c) { |
126 | 127 | c->max = p - 1; |
127 | - fpos_offset = c->max - c->min; | |
128 | - reg_offset = fpos_offset / map->debugfs_tot_len; | |
129 | - c->max_reg = c->base_reg + reg_offset; | |
128 | + c->max_reg = i - map->reg_stride; | |
130 | 129 | list_add_tail(&c->list, |
131 | 130 | &map->debugfs_off_cache); |
132 | 131 | } |
133 | 132 | |
... | ... | @@ -145,12 +144,14 @@ |
145 | 144 | fpos_offset = from - c->min; |
146 | 145 | reg_offset = fpos_offset / map->debugfs_tot_len; |
147 | 146 | *pos = c->min + (reg_offset * map->debugfs_tot_len); |
147 | + mutex_unlock(&map->cache_lock); | |
148 | 148 | return c->base_reg + reg_offset; |
149 | 149 | } |
150 | 150 | |
151 | 151 | *pos = c->max; |
152 | 152 | ret = c->max_reg; |
153 | 153 | } |
154 | + mutex_unlock(&map->cache_lock); | |
154 | 155 | |
155 | 156 | return ret; |
156 | 157 | } |
... | ... | @@ -311,6 +312,79 @@ |
311 | 312 | .llseek = default_llseek, |
312 | 313 | }; |
313 | 314 | |
315 | +static ssize_t regmap_reg_ranges_read_file(struct file *file, | |
316 | + char __user *user_buf, size_t count, | |
317 | + loff_t *ppos) | |
318 | +{ | |
319 | + struct regmap *map = file->private_data; | |
320 | + struct regmap_debugfs_off_cache *c; | |
321 | + loff_t p = 0; | |
322 | + size_t buf_pos = 0; | |
323 | + char *buf; | |
324 | + char *entry; | |
325 | + int ret; | |
326 | + | |
327 | + if (*ppos < 0 || !count) | |
328 | + return -EINVAL; | |
329 | + | |
330 | + buf = kmalloc(count, GFP_KERNEL); | |
331 | + if (!buf) | |
332 | + return -ENOMEM; | |
333 | + | |
334 | + entry = kmalloc(PAGE_SIZE, GFP_KERNEL); | |
335 | + if (!entry) { | |
336 | + kfree(buf); | |
337 | + return -ENOMEM; | |
338 | + } | |
339 | + | |
340 | + /* While we are at it, build the register dump cache | |
341 | + * now so the read() operation on the `registers' file | |
342 | + * can benefit from using the cache. We do not care | |
343 | + * about the file position information that is contained | |
344 | + * in the cache, just about the actual register blocks */ | |
345 | + regmap_calc_tot_len(map, buf, count); | |
346 | + regmap_debugfs_get_dump_start(map, 0, *ppos, &p); | |
347 | + | |
348 | + /* Reset file pointer as the fixed-format of the `registers' | |
349 | + * file is not compatible with the `range' file */ | |
350 | + p = 0; | |
351 | + mutex_lock(&map->cache_lock); | |
352 | + list_for_each_entry(c, &map->debugfs_off_cache, list) { | |
353 | + snprintf(entry, PAGE_SIZE, "%x-%x", | |
354 | + c->base_reg, c->max_reg); | |
355 | + if (p >= *ppos) { | |
356 | + if (buf_pos + 1 + strlen(entry) > count) | |
357 | + break; | |
358 | + snprintf(buf + buf_pos, count - buf_pos, | |
359 | + "%s", entry); | |
360 | + buf_pos += strlen(entry); | |
361 | + buf[buf_pos] = '\n'; | |
362 | + buf_pos++; | |
363 | + } | |
364 | + p += strlen(entry) + 1; | |
365 | + } | |
366 | + mutex_unlock(&map->cache_lock); | |
367 | + | |
368 | + kfree(entry); | |
369 | + ret = buf_pos; | |
370 | + | |
371 | + if (copy_to_user(user_buf, buf, buf_pos)) { | |
372 | + ret = -EFAULT; | |
373 | + goto out_buf; | |
374 | + } | |
375 | + | |
376 | + *ppos += buf_pos; | |
377 | +out_buf: | |
378 | + kfree(buf); | |
379 | + return ret; | |
380 | +} | |
381 | + | |
382 | +static const struct file_operations regmap_reg_ranges_fops = { | |
383 | + .open = simple_open, | |
384 | + .read = regmap_reg_ranges_read_file, | |
385 | + .llseek = default_llseek, | |
386 | +}; | |
387 | + | |
314 | 388 | static ssize_t regmap_access_read_file(struct file *file, |
315 | 389 | char __user *user_buf, size_t count, |
316 | 390 | loff_t *ppos) |
... | ... | @@ -385,6 +459,7 @@ |
385 | 459 | struct regmap_range_node *range_node; |
386 | 460 | |
387 | 461 | INIT_LIST_HEAD(&map->debugfs_off_cache); |
462 | + mutex_init(&map->cache_lock); | |
388 | 463 | |
389 | 464 | if (name) { |
390 | 465 | map->debugfs_name = kasprintf(GFP_KERNEL, "%s-%s", |
... | ... | @@ -403,6 +478,9 @@ |
403 | 478 | debugfs_create_file("name", 0400, map->debugfs, |
404 | 479 | map, ®map_name_fops); |
405 | 480 | |
481 | + debugfs_create_file("range", 0400, map->debugfs, | |
482 | + map, ®map_reg_ranges_fops); | |
483 | + | |
406 | 484 | if (map->max_register) { |
407 | 485 | debugfs_create_file("registers", 0400, map->debugfs, |
408 | 486 | map, ®map_map_fops); |
409 | 487 | |
... | ... | @@ -435,7 +513,9 @@ |
435 | 513 | void regmap_debugfs_exit(struct regmap *map) |
436 | 514 | { |
437 | 515 | debugfs_remove_recursive(map->debugfs); |
516 | + mutex_lock(&map->cache_lock); | |
438 | 517 | regmap_debugfs_free_dump_cache(map); |
518 | + mutex_unlock(&map->cache_lock); | |
439 | 519 | kfree(map->debugfs_name); |
440 | 520 | } |
441 | 521 |