diff options
author | Lars-Peter Clausen <lars@metafoo.de> | 2013-08-27 07:03:03 -0400 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2013-08-27 11:23:00 -0400 |
commit | b6752123ccef4eec3c70c20dbdfc05d1674319c5 (patch) | |
tree | eac40c4ea69182004640ad13488c58e77c560ef8 /drivers/base/regmap | |
parent | d8dfad3876e4386666b759da3c833d62fb8b2267 (diff) |
regcache-rbtree: Fix reg_stride != 1
There are a couple of calculations, which convert between register addresses and
block indices, in regcache_rbtree_sync() and regcache_rbtree_node_alloc() which
assume that reg_stride is 1. This will break the rb cache for configurations
which do not use a reg_stride of 1.
Also rename 'base' in regcache_rbtree_sync() to 'start' to avoid confusion with
'base_reg'.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'drivers/base/regmap')
-rw-r--r-- | drivers/base/regmap/regcache-rbtree.c | 25 |
1 files changed, 14 insertions, 11 deletions
diff --git a/drivers/base/regmap/regcache-rbtree.c b/drivers/base/regmap/regcache-rbtree.c index 5c1435c4e210..f2384a816cc4 100644 --- a/drivers/base/regmap/regcache-rbtree.c +++ b/drivers/base/regmap/regcache-rbtree.c | |||
@@ -325,8 +325,8 @@ regcache_rbtree_node_alloc(struct regmap *map, unsigned int reg) | |||
325 | 325 | ||
326 | if (i != map->rd_table->n_yes_ranges) { | 326 | if (i != map->rd_table->n_yes_ranges) { |
327 | range = &map->rd_table->yes_ranges[i]; | 327 | range = &map->rd_table->yes_ranges[i]; |
328 | rbnode->blklen = range->range_max - range->range_min | 328 | rbnode->blklen = (range->range_max - range->range_min) / |
329 | + 1; | 329 | map->reg_stride + 1; |
330 | rbnode->base_reg = range->range_min; | 330 | rbnode->base_reg = range->range_min; |
331 | } | 331 | } |
332 | } | 332 | } |
@@ -418,30 +418,33 @@ static int regcache_rbtree_sync(struct regmap *map, unsigned int min, | |||
418 | struct regcache_rbtree_ctx *rbtree_ctx; | 418 | struct regcache_rbtree_ctx *rbtree_ctx; |
419 | struct rb_node *node; | 419 | struct rb_node *node; |
420 | struct regcache_rbtree_node *rbnode; | 420 | struct regcache_rbtree_node *rbnode; |
421 | unsigned int base_reg, top_reg; | ||
422 | unsigned int start, end; | ||
421 | int ret; | 423 | int ret; |
422 | int base, end; | ||
423 | 424 | ||
424 | rbtree_ctx = map->cache; | 425 | rbtree_ctx = map->cache; |
425 | for (node = rb_first(&rbtree_ctx->root); node; node = rb_next(node)) { | 426 | for (node = rb_first(&rbtree_ctx->root); node; node = rb_next(node)) { |
426 | rbnode = rb_entry(node, struct regcache_rbtree_node, node); | 427 | rbnode = rb_entry(node, struct regcache_rbtree_node, node); |
427 | 428 | ||
428 | if (rbnode->base_reg > max) | 429 | regcache_rbtree_get_base_top_reg(map, rbnode, &base_reg, |
430 | &top_reg); | ||
431 | if (base_reg > max) | ||
429 | break; | 432 | break; |
430 | if (rbnode->base_reg + rbnode->blklen < min) | 433 | if (top_reg < min) |
431 | continue; | 434 | continue; |
432 | 435 | ||
433 | if (min > rbnode->base_reg) | 436 | if (min > base_reg) |
434 | base = min - rbnode->base_reg; | 437 | start = (min - base_reg) / map->reg_stride; |
435 | else | 438 | else |
436 | base = 0; | 439 | start = 0; |
437 | 440 | ||
438 | if (max < rbnode->base_reg + rbnode->blklen) | 441 | if (max < top_reg) |
439 | end = max - rbnode->base_reg + 1; | 442 | end = (max - base_reg) / map->reg_stride + 1; |
440 | else | 443 | else |
441 | end = rbnode->blklen; | 444 | end = rbnode->blklen; |
442 | 445 | ||
443 | ret = regcache_sync_block(map, rbnode->block, rbnode->base_reg, | 446 | ret = regcache_sync_block(map, rbnode->block, rbnode->base_reg, |
444 | base, end); | 447 | start, end); |
445 | if (ret != 0) | 448 | if (ret != 0) |
446 | return ret; | 449 | return ret; |
447 | } | 450 | } |