summaryrefslogtreecommitdiffstats
path: root/drivers/base
diff options
context:
space:
mode:
authorCharles Keepax <ckeepax@opensource.cirrus.com>2018-02-15 18:52:18 +0100
committerMark Brown <broonie@kernel.org>2018-02-16 13:03:30 +0100
commit186ba2eec275a5e4ee09d4b6a77c619e46fab9fd (patch)
tree7131a29eed8fca67a833a37ea0bdcc54ccad6ddc /drivers/base
parentregmap: Tidy up regmap_raw_read chunking code (diff)
downloadlinux-186ba2eec275a5e4ee09d4b6a77c619e46fab9fd.tar.xz
linux-186ba2eec275a5e4ee09d4b6a77c619e46fab9fd.zip
regmap: Use _regmap_read in regmap_bulk_read
Bulk reads may potentially read a lot of registers and regmap_read will take and release the regmap lock for each register. Avoid bouncing the lock so frequently by holding the lock locally and calling _regmap_read instead. This also has the nice side-effect that all the reads will be done atomically so no other threads can sneak a write in during the regmap_bulk_read. Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com> Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/regmap/regmap.c18
1 files changed, 13 insertions, 5 deletions
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index ff30a9157de5..258a40e2a1d3 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -2674,6 +2674,8 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
if (!IS_ALIGNED(reg, map->reg_stride))
return -EINVAL;
+ if (val_count == 0)
+ return -EINVAL;
if (map->bus && map->format.parse_inplace && (vol || map->cache_type == REGCACHE_NONE)) {
ret = regmap_raw_read(map, reg, val, val_bytes * val_count);
@@ -2690,13 +2692,15 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
u16 *u16 = val;
u8 *u8 = val;
+ map->lock(map->lock_arg);
+
for (i = 0; i < val_count; i++) {
unsigned int ival;
- ret = regmap_read(map, reg + regmap_get_offset(map, i),
- &ival);
+ ret = _regmap_read(map, reg + regmap_get_offset(map, i),
+ &ival);
if (ret != 0)
- return ret;
+ goto out;
switch (map->format.val_bytes) {
#ifdef CONFIG_64BIT
@@ -2714,12 +2718,16 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
u8[i] = ival;
break;
default:
- return -EINVAL;
+ ret = -EINVAL;
+ goto out;
}
}
+
+out:
+ map->unlock(map->lock_arg);
}
- return 0;
+ return ret;
}
EXPORT_SYMBOL_GPL(regmap_bulk_read);