Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 364999
b: refs/heads/master
c: 0c7ed85
h: refs/heads/master
i:
  364997: 29c2e94
  364995: b06845d
  364991: 2bc8aaa
v: v3
  • Loading branch information
Dimitris Papastamos authored and Mark Brown committed Mar 26, 2013
1 parent 7130799 commit 6c35ed0
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 2 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 584de329ca43cc6d73eb74885e1d5d9fc0549423
refs/heads/master: 0c7ed8563a0282c032936ae1c667498d59691593
70 changes: 69 additions & 1 deletion trunk/drivers/base/regmap/regcache-rbtree.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ struct regcache_rbtree_node {
struct regcache_rbtree_ctx {
struct rb_root root;
struct regcache_rbtree_node *cached_rbnode;
unsigned long *reg_present;
unsigned int reg_present_nbits;
};

static inline void regcache_rbtree_get_base_top_reg(
Expand Down Expand Up @@ -146,6 +148,7 @@ static int rbtree_show(struct seq_file *s, void *ignored)
map->lock(map);

mem_size = sizeof(*rbtree_ctx);
mem_size += BITS_TO_LONGS(rbtree_ctx->reg_present_nbits) * sizeof(long);

for (node = rb_first(&rbtree_ctx->root); node != NULL;
node = rb_next(node)) {
Expand Down Expand Up @@ -196,6 +199,44 @@ static void rbtree_debugfs_init(struct regmap *map)
}
#endif

static int enlarge_reg_present_bitmap(struct regmap *map, unsigned int reg)
{
struct regcache_rbtree_ctx *rbtree_ctx;
unsigned long *reg_present;
unsigned int reg_present_size;
unsigned int nregs;
int i;

rbtree_ctx = map->cache;
nregs = reg + 1;
reg_present_size = BITS_TO_LONGS(nregs);
reg_present_size *= sizeof(long);

if (!rbtree_ctx->reg_present) {
reg_present = kmalloc(reg_present_size, GFP_KERNEL);
if (!reg_present)
return -ENOMEM;
bitmap_zero(reg_present, nregs);
rbtree_ctx->reg_present = reg_present;
rbtree_ctx->reg_present_nbits = nregs;
return 0;
}

if (nregs > rbtree_ctx->reg_present_nbits) {
reg_present = krealloc(rbtree_ctx->reg_present,
reg_present_size, GFP_KERNEL);
if (!reg_present)
return -ENOMEM;
for (i = 0; i < nregs; i++)
if (i >= rbtree_ctx->reg_present_nbits)
clear_bit(i, reg_present);
rbtree_ctx->reg_present = reg_present;
rbtree_ctx->reg_present_nbits = nregs;
}

return 0;
}

static int regcache_rbtree_init(struct regmap *map)
{
struct regcache_rbtree_ctx *rbtree_ctx;
Expand All @@ -209,6 +250,8 @@ static int regcache_rbtree_init(struct regmap *map)
rbtree_ctx = map->cache;
rbtree_ctx->root = RB_ROOT;
rbtree_ctx->cached_rbnode = NULL;
rbtree_ctx->reg_present = NULL;
rbtree_ctx->reg_present_nbits = 0;

for (i = 0; i < map->num_reg_defaults; i++) {
ret = regcache_rbtree_write(map,
Expand Down Expand Up @@ -238,6 +281,8 @@ static int regcache_rbtree_exit(struct regmap *map)
if (!rbtree_ctx)
return 0;

kfree(rbtree_ctx->reg_present);

/* free up the rbtree */
next = rb_first(&rbtree_ctx->root);
while (next) {
Expand All @@ -255,6 +300,17 @@ static int regcache_rbtree_exit(struct regmap *map)
return 0;
}

static int regcache_reg_present(struct regmap *map, unsigned int reg)
{
struct regcache_rbtree_ctx *rbtree_ctx;

rbtree_ctx = map->cache;
if (!(rbtree_ctx->reg_present[BIT_WORD(reg)] & BIT_MASK(reg)))
return 0;
return 1;

}

static int regcache_rbtree_read(struct regmap *map,
unsigned int reg, unsigned int *value)
{
Expand All @@ -264,6 +320,8 @@ static int regcache_rbtree_read(struct regmap *map,
rbnode = regcache_rbtree_lookup(map, reg);
if (rbnode) {
reg_tmp = (reg - rbnode->base_reg) / map->reg_stride;
if (!regcache_reg_present(map, reg))
return -ENOENT;
*value = regcache_rbtree_get_register(map, rbnode, reg_tmp);
} else {
return -ENOENT;
Expand Down Expand Up @@ -313,6 +371,12 @@ static int regcache_rbtree_write(struct regmap *map, unsigned int reg,
int ret;

rbtree_ctx = map->cache;
/* update the reg_present bitmap, make space if necessary */
ret = enlarge_reg_present_bitmap(map, reg);
if (ret < 0)
return ret;
set_bit(reg, rbtree_ctx->reg_present);

/* if we can't locate it in the cached rbnode we'll have
* to traverse the rbtree looking for it.
*/
Expand Down Expand Up @@ -354,7 +418,7 @@ static int regcache_rbtree_write(struct regmap *map, unsigned int reg,
rbnode = kzalloc(sizeof *rbnode, GFP_KERNEL);
if (!rbnode)
return -ENOMEM;
rbnode->blklen = 1;
rbnode->blklen = sizeof(*rbnode);
rbnode->base_reg = reg;
rbnode->block = kmalloc(rbnode->blklen * map->cache_word_size,
GFP_KERNEL);
Expand Down Expand Up @@ -404,6 +468,10 @@ static int regcache_rbtree_sync(struct regmap *map, unsigned int min,

for (i = base; i < end; i++) {
regtmp = rbnode->base_reg + (i * map->reg_stride);

if (!regcache_reg_present(map, regtmp))
continue;

val = regcache_rbtree_get_register(map, rbnode, i);

/* Is this the hardware default? If so skip. */
Expand Down

0 comments on commit 6c35ed0

Please sign in to comment.