diff options
author | Mark Brown <broonie@linaro.org> | 2013-06-30 07:40:01 -0400 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2013-06-30 07:40:01 -0400 |
commit | feff98f5507f98c0422252caec41c3be9e6b6399 (patch) | |
tree | d014206d6ecc095ceb8e03ea2b17b42bf1ce786a /drivers/base/regmap/regcache-rbtree.c | |
parent | 9e895ace5d82df8929b16f58e9f515f6d54ab82d (diff) | |
parent | d6814a7dafa590ec5fe0597922ea76354f9bec59 (diff) |
Merge remote-tracking branch 'regmap/topic/cache' into regmap-next
Diffstat (limited to 'drivers/base/regmap/regcache-rbtree.c')
-rw-r--r-- | drivers/base/regmap/regcache-rbtree.c | 62 |
1 files changed, 48 insertions, 14 deletions
diff --git a/drivers/base/regmap/regcache-rbtree.c b/drivers/base/regmap/regcache-rbtree.c index 02f490bad30f..5c1435c4e210 100644 --- a/drivers/base/regmap/regcache-rbtree.c +++ b/drivers/base/regmap/regcache-rbtree.c | |||
@@ -304,6 +304,48 @@ static int regcache_rbtree_insert_to_block(struct regmap *map, | |||
304 | return 0; | 304 | return 0; |
305 | } | 305 | } |
306 | 306 | ||
307 | static struct regcache_rbtree_node * | ||
308 | regcache_rbtree_node_alloc(struct regmap *map, unsigned int reg) | ||
309 | { | ||
310 | struct regcache_rbtree_node *rbnode; | ||
311 | const struct regmap_range *range; | ||
312 | int i; | ||
313 | |||
314 | rbnode = kzalloc(sizeof(*rbnode), GFP_KERNEL); | ||
315 | if (!rbnode) | ||
316 | return NULL; | ||
317 | |||
318 | /* If there is a read table then use it to guess at an allocation */ | ||
319 | if (map->rd_table) { | ||
320 | for (i = 0; i < map->rd_table->n_yes_ranges; i++) { | ||
321 | if (regmap_reg_in_range(reg, | ||
322 | &map->rd_table->yes_ranges[i])) | ||
323 | break; | ||
324 | } | ||
325 | |||
326 | if (i != map->rd_table->n_yes_ranges) { | ||
327 | range = &map->rd_table->yes_ranges[i]; | ||
328 | rbnode->blklen = range->range_max - range->range_min | ||
329 | + 1; | ||
330 | rbnode->base_reg = range->range_min; | ||
331 | } | ||
332 | } | ||
333 | |||
334 | if (!rbnode->blklen) { | ||
335 | rbnode->blklen = sizeof(*rbnode); | ||
336 | rbnode->base_reg = reg; | ||
337 | } | ||
338 | |||
339 | rbnode->block = kmalloc(rbnode->blklen * map->cache_word_size, | ||
340 | GFP_KERNEL); | ||
341 | if (!rbnode->block) { | ||
342 | kfree(rbnode); | ||
343 | return NULL; | ||
344 | } | ||
345 | |||
346 | return rbnode; | ||
347 | } | ||
348 | |||
307 | static int regcache_rbtree_write(struct regmap *map, unsigned int reg, | 349 | static int regcache_rbtree_write(struct regmap *map, unsigned int reg, |
308 | unsigned int value) | 350 | unsigned int value) |
309 | { | 351 | { |
@@ -354,23 +396,15 @@ static int regcache_rbtree_write(struct regmap *map, unsigned int reg, | |||
354 | return 0; | 396 | return 0; |
355 | } | 397 | } |
356 | } | 398 | } |
357 | /* we did not manage to find a place to insert it in an existing | 399 | |
358 | * block so create a new rbnode with a single register in its block. | 400 | /* We did not manage to find a place to insert it in |
359 | * This block will get populated further if any other adjacent | 401 | * an existing block so create a new rbnode. |
360 | * registers get modified in the future. | ||
361 | */ | 402 | */ |
362 | rbnode = kzalloc(sizeof *rbnode, GFP_KERNEL); | 403 | rbnode = regcache_rbtree_node_alloc(map, reg); |
363 | if (!rbnode) | 404 | if (!rbnode) |
364 | return -ENOMEM; | 405 | return -ENOMEM; |
365 | rbnode->blklen = sizeof(*rbnode); | 406 | regcache_rbtree_set_register(map, rbnode, |
366 | rbnode->base_reg = reg; | 407 | reg - rbnode->base_reg, value); |
367 | rbnode->block = kmalloc(rbnode->blklen * map->cache_word_size, | ||
368 | GFP_KERNEL); | ||
369 | if (!rbnode->block) { | ||
370 | kfree(rbnode); | ||
371 | return -ENOMEM; | ||
372 | } | ||
373 | regcache_rbtree_set_register(map, rbnode, 0, value); | ||
374 | regcache_rbtree_insert(map, &rbtree_ctx->root, rbnode); | 408 | regcache_rbtree_insert(map, &rbtree_ctx->root, rbnode); |
375 | rbtree_ctx->cached_rbnode = rbnode; | 409 | rbtree_ctx->cached_rbnode = rbnode; |
376 | } | 410 | } |