diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2013-05-08 13:55:25 +0100 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2013-05-12 18:46:47 +0400 |
commit | 7278af5fb3eb7247449fd4489dacb75b9ba86f73 (patch) | |
tree | 760b3a912c3978c732f058a703156dc3a27aa41c /drivers/base | |
parent | 0186645d2549f94c3a8067c97cad261c678d6718 (diff) | |
download | linux-7278af5fb3eb7247449fd4489dacb75b9ba86f73.tar.gz linux-7278af5fb3eb7247449fd4489dacb75b9ba86f73.tar.bz2 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.c | 25 |
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) { |