summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuenter Roeck <linux@roeck-us.net>2015-07-26 21:34:50 -0700
committerSasha Levin <sasha.levin@oracle.com>2015-09-17 01:29:53 -0400
commitec692f3cba064b4aa03ce6537ed6d4ae505d3217 (patch)
treeb35b84bca3d17a2e8d6e330c9d4958347eb6a072
parent86e467779a160702ae922578e316babc0cf178c8 (diff)
downloadlinux-stable-ec692f3cba064b4aa03ce6537ed6d4ae505d3217.tar.gz
linux-stable-ec692f3cba064b4aa03ce6537ed6d4ae505d3217.tar.bz2
linux-stable-ec692f3cba064b4aa03ce6537ed6d4ae505d3217.zip
regmap: regcache-rbtree: Clean new present bits on present bitmap resize
[ Upstream commit 8ef9724bf9718af81cfc5132253372f79c71b7e2 ] When inserting a new register into a block, the present bit map size is increased using krealloc. krealloc does not clear the additionally allocated memory, leaving it filled with random values. Result is that some registers are considered cached even though this is not the case. Fix the problem by clearing the additionally allocated memory. Also, if the bitmap size does not increase, do not reallocate the bitmap at all to reduce overhead. Fixes: 3f4ff561bc88 ("regmap: rbtree: Make cache_present bitmap per node") Signed-off-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Mark Brown <broonie@kernel.org> Cc: stable@vger.kernel.org Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
-rw-r--r--drivers/base/regmap/regcache-rbtree.c19
1 files changed, 14 insertions, 5 deletions
diff --git a/drivers/base/regmap/regcache-rbtree.c b/drivers/base/regmap/regcache-rbtree.c
index 9d09c5bb5874..bb39181e4c33 100644
--- a/drivers/base/regmap/regcache-rbtree.c
+++ b/drivers/base/regmap/regcache-rbtree.c
@@ -296,11 +296,20 @@ static int regcache_rbtree_insert_to_block(struct regmap *map,
if (!blk)
return -ENOMEM;
- present = krealloc(rbnode->cache_present,
- BITS_TO_LONGS(blklen) * sizeof(*present), GFP_KERNEL);
- if (!present) {
- kfree(blk);
- return -ENOMEM;
+ if (BITS_TO_LONGS(blklen) > BITS_TO_LONGS(rbnode->blklen)) {
+ present = krealloc(rbnode->cache_present,
+ BITS_TO_LONGS(blklen) * sizeof(*present),
+ GFP_KERNEL);
+ if (!present) {
+ kfree(blk);
+ return -ENOMEM;
+ }
+
+ memset(present + BITS_TO_LONGS(rbnode->blklen), 0,
+ (BITS_TO_LONGS(blklen) - BITS_TO_LONGS(rbnode->blklen))
+ * sizeof(*present));
+ } else {
+ present = rbnode->cache_present;
}
/* insert the register value in the correct place in the rbnode block */