Skip to content

Commit 78493f2

Browse files
committed
regmap: cache: Factor out reg_present support from rbtree cache
The idea of maintaining a bitmap of present registers is something that can usefully be used by other cache types that maintain blocks of cached registers so move the code out of the rbtree cache and into the generic regcache code. Refactor the interface slightly as we go to wrap the set bit and enlarge bitmap operations (since we never do one without the other) and make it more robust for reads of uncached registers by bounds checking before we look at the bitmap. Signed-off-by: Mark Brown <[email protected]> Reviewed-by: Dimitris Papastamos <[email protected]>
1 parent 137b833 commit 78493f2

File tree

3 files changed

+54
-58
lines changed

3 files changed

+54
-58
lines changed

drivers/base/regmap/internal.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,9 @@ struct regmap {
126126
void *cache;
127127
u32 cache_dirty;
128128

129+
unsigned long *cache_present;
130+
unsigned int cache_present_nbits;
131+
129132
struct reg_default *patch;
130133
int patch_regs;
131134

@@ -201,6 +204,16 @@ unsigned int regcache_get_val(struct regmap *map, const void *base,
201204
bool regcache_set_val(struct regmap *map, void *base, unsigned int idx,
202205
unsigned int val);
203206
int regcache_lookup_reg(struct regmap *map, unsigned int reg);
207+
int regcache_set_reg_present(struct regmap *map, unsigned int reg);
208+
209+
static inline bool regcache_reg_present(struct regmap *map, unsigned int reg)
210+
{
211+
if (!map->cache_present)
212+
return true;
213+
if (reg > map->cache_present_nbits)
214+
return false;
215+
return map->cache_present[BIT_WORD(reg)] & BIT_MASK(reg);
216+
}
204217

205218
int _regmap_raw_write(struct regmap *map, unsigned int reg,
206219
const void *val, size_t val_len, bool async);

drivers/base/regmap/regcache-rbtree.c

Lines changed: 2 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,6 @@ struct regcache_rbtree_node {
3636
struct regcache_rbtree_ctx {
3737
struct rb_root root;
3838
struct regcache_rbtree_node *cached_rbnode;
39-
unsigned long *reg_present;
40-
unsigned int reg_present_nbits;
4139
};
4240

4341
static inline void regcache_rbtree_get_base_top_reg(
@@ -154,7 +152,7 @@ static int rbtree_show(struct seq_file *s, void *ignored)
154152
map->lock(map);
155153

156154
mem_size = sizeof(*rbtree_ctx);
157-
mem_size += BITS_TO_LONGS(rbtree_ctx->reg_present_nbits) * sizeof(long);
155+
mem_size += BITS_TO_LONGS(map->cache_present_nbits) * sizeof(long);
158156

159157
for (node = rb_first(&rbtree_ctx->root); node != NULL;
160158
node = rb_next(node)) {
@@ -205,44 +203,6 @@ static void rbtree_debugfs_init(struct regmap *map)
205203
}
206204
#endif
207205

208-
static int enlarge_reg_present_bitmap(struct regmap *map, unsigned int reg)
209-
{
210-
struct regcache_rbtree_ctx *rbtree_ctx;
211-
unsigned long *reg_present;
212-
unsigned int reg_present_size;
213-
unsigned int nregs;
214-
int i;
215-
216-
rbtree_ctx = map->cache;
217-
nregs = reg + 1;
218-
reg_present_size = BITS_TO_LONGS(nregs);
219-
reg_present_size *= sizeof(long);
220-
221-
if (!rbtree_ctx->reg_present) {
222-
reg_present = kmalloc(reg_present_size, GFP_KERNEL);
223-
if (!reg_present)
224-
return -ENOMEM;
225-
bitmap_zero(reg_present, nregs);
226-
rbtree_ctx->reg_present = reg_present;
227-
rbtree_ctx->reg_present_nbits = nregs;
228-
return 0;
229-
}
230-
231-
if (nregs > rbtree_ctx->reg_present_nbits) {
232-
reg_present = krealloc(rbtree_ctx->reg_present,
233-
reg_present_size, GFP_KERNEL);
234-
if (!reg_present)
235-
return -ENOMEM;
236-
for (i = 0; i < nregs; i++)
237-
if (i >= rbtree_ctx->reg_present_nbits)
238-
clear_bit(i, reg_present);
239-
rbtree_ctx->reg_present = reg_present;
240-
rbtree_ctx->reg_present_nbits = nregs;
241-
}
242-
243-
return 0;
244-
}
245-
246206
static int regcache_rbtree_init(struct regmap *map)
247207
{
248208
struct regcache_rbtree_ctx *rbtree_ctx;
@@ -256,8 +216,6 @@ static int regcache_rbtree_init(struct regmap *map)
256216
rbtree_ctx = map->cache;
257217
rbtree_ctx->root = RB_ROOT;
258218
rbtree_ctx->cached_rbnode = NULL;
259-
rbtree_ctx->reg_present = NULL;
260-
rbtree_ctx->reg_present_nbits = 0;
261219

262220
for (i = 0; i < map->num_reg_defaults; i++) {
263221
ret = regcache_rbtree_write(map,
@@ -287,8 +245,6 @@ static int regcache_rbtree_exit(struct regmap *map)
287245
if (!rbtree_ctx)
288246
return 0;
289247

290-
kfree(rbtree_ctx->reg_present);
291-
292248
/* free up the rbtree */
293249
next = rb_first(&rbtree_ctx->root);
294250
while (next) {
@@ -306,17 +262,6 @@ static int regcache_rbtree_exit(struct regmap *map)
306262
return 0;
307263
}
308264

309-
static int regcache_reg_present(struct regmap *map, unsigned int reg)
310-
{
311-
struct regcache_rbtree_ctx *rbtree_ctx;
312-
313-
rbtree_ctx = map->cache;
314-
if (!(rbtree_ctx->reg_present[BIT_WORD(reg)] & BIT_MASK(reg)))
315-
return 0;
316-
return 1;
317-
318-
}
319-
320265
static int regcache_rbtree_read(struct regmap *map,
321266
unsigned int reg, unsigned int *value)
322267
{
@@ -378,10 +323,9 @@ static int regcache_rbtree_write(struct regmap *map, unsigned int reg,
378323

379324
rbtree_ctx = map->cache;
380325
/* update the reg_present bitmap, make space if necessary */
381-
ret = enlarge_reg_present_bitmap(map, reg);
326+
ret = regcache_set_reg_present(map, reg);
382327
if (ret < 0)
383328
return ret;
384-
set_bit(reg, rbtree_ctx->reg_present);
385329

386330
/* if we can't locate it in the cached rbnode we'll have
387331
* to traverse the rbtree looking for it.

drivers/base/regmap/regcache.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,8 @@ int regcache_init(struct regmap *map, const struct regmap_config *config)
121121
map->reg_defaults_raw = config->reg_defaults_raw;
122122
map->cache_word_size = DIV_ROUND_UP(config->val_bits, 8);
123123
map->cache_size_raw = map->cache_word_size * config->num_reg_defaults_raw;
124+
map->cache_present = NULL;
125+
map->cache_present_nbits = 0;
124126

125127
map->cache = NULL;
126128
map->cache_ops = cache_types[i];
@@ -179,6 +181,7 @@ void regcache_exit(struct regmap *map)
179181

180182
BUG_ON(!map->cache_ops);
181183

184+
kfree(map->cache_present);
182185
kfree(map->reg_defaults);
183186
if (map->cache_free)
184187
kfree(map->reg_defaults_raw);
@@ -415,6 +418,42 @@ void regcache_cache_bypass(struct regmap *map, bool enable)
415418
}
416419
EXPORT_SYMBOL_GPL(regcache_cache_bypass);
417420

421+
int regcache_set_reg_present(struct regmap *map, unsigned int reg)
422+
{
423+
unsigned long *cache_present;
424+
unsigned int cache_present_size;
425+
unsigned int nregs;
426+
int i;
427+
428+
nregs = reg + 1;
429+
cache_present_size = BITS_TO_LONGS(nregs);
430+
cache_present_size *= sizeof(long);
431+
432+
if (!map->cache_present) {
433+
cache_present = kmalloc(cache_present_size, GFP_KERNEL);
434+
if (!cache_present)
435+
return -ENOMEM;
436+
bitmap_zero(cache_present, nregs);
437+
map->cache_present = cache_present;
438+
map->cache_present_nbits = nregs;
439+
}
440+
441+
if (nregs > map->cache_present_nbits) {
442+
cache_present = krealloc(map->cache_present,
443+
cache_present_size, GFP_KERNEL);
444+
if (!cache_present)
445+
return -ENOMEM;
446+
for (i = 0; i < nregs; i++)
447+
if (i >= map->cache_present_nbits)
448+
clear_bit(i, cache_present);
449+
map->cache_present = cache_present;
450+
map->cache_present_nbits = nregs;
451+
}
452+
453+
set_bit(reg, map->cache_present);
454+
return 0;
455+
}
456+
418457
bool regcache_set_val(struct regmap *map, void *base, unsigned int idx,
419458
unsigned int val)
420459
{

0 commit comments

Comments
 (0)