summaryrefslogtreecommitdiffstats
path: root/drivers/base
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2013-05-08 14:55:25 +0200
committerMark Brown <broonie@opensource.wolfsonmicro.com>2013-05-12 16:46:47 +0200
commit7278af5fb3eb7247449fd4489dacb75b9ba86f73 (patch)
tree760b3a912c3978c732f058a703156dc3a27aa41c /drivers/base
parentregmap: rbtree: Factor out node allocation (diff)
downloadlinux-7278af5fb3eb7247449fd4489dacb75b9ba86f73.tar.xz
linux-7278af5fb3eb7247449fd4489dacb75b9ba86f73.zip
regmap: rbtree: Use range information to allocate nodes
If range information has been provided then when we allocate a rbnode within a range allocate the entire range. The goal is to minimise the number of reallocations done when combining or extending blocks. At present only readability and yes_ranges are taken into account, this is expected to cover most cases efficiently. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/regmap/regcache-rbtree.c25
1 files changed, 23 insertions, 2 deletions
diff --git a/drivers/base/regmap/regcache-rbtree.c b/drivers/base/regmap/regcache-rbtree.c
index 3a000145ac6e..4e131c5df844 100644
--- a/drivers/base/regmap/regcache-rbtree.c
+++ b/drivers/base/regmap/regcache-rbtree.c
@@ -308,13 +308,34 @@ static struct regcache_rbtree_node *
regcache_rbtree_node_alloc(struct regmap *map, unsigned int reg)
{
struct regcache_rbtree_node *rbnode;
+ const struct regmap_range *range;
+ int i;
rbnode = kzalloc(sizeof(*rbnode), GFP_KERNEL);
if (!rbnode)
return NULL;
- rbnode->blklen = sizeof(*rbnode);
- rbnode->base_reg = reg;
+ /* If there is a read table then use it to guess at an allocation */
+ if (map->rd_table) {
+ for (i = 0; i < map->rd_table->n_yes_ranges; i++) {
+ if (regmap_reg_in_range(reg,
+ &map->rd_table->yes_ranges[i]))
+ break;
+ }
+
+ if (i != map->rd_table->n_yes_ranges) {
+ range = &map->rd_table->yes_ranges[i];
+ rbnode->blklen = range->range_max - range->range_min
+ + 1;
+ rbnode->base_reg = range->range_min;
+ }
+ }
+
+ if (!rbnode->blklen) {
+ rbnode->blklen = sizeof(*rbnode);
+ rbnode->base_reg = reg;
+ }
+
rbnode->block = kmalloc(rbnode->blklen * map->cache_word_size,
GFP_KERNEL);
if (!rbnode->block) {