From 186ba2eec275a5e4ee09d4b6a77c619e46fab9fd Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 15 Feb 2018 17:52:18 +0000 Subject: [PATCH] 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 Signed-off-by: Mark Brown --- drivers/base/regmap/regmap.c | 18 +++++++++++++----- 1 file 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);