diff options
author | Linus Torvalds | 2023-11-07 16:56:10 -0800 |
---|---|---|
committer | Linus Torvalds | 2023-11-07 16:56:10 -0800 |
commit | eaec7c9892bd565ffc7dcd32515b157011ca2323 (patch) | |
tree | 8a077b95ccc50a0b27957362c1737b0e28be1b42 /drivers/base | |
parent | b8dd631fcabe2656c8d3751ad4836131d51fb63b (diff) | |
parent | 984a4afdc87a1fc226fd657b1cd8255c13d3fc1a (diff) |
Merge tag 'regmap-fix-v6.7-merge-window' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap
Pull regmap fix from Mark Brown:
"One fix here, for an interaction between noinc registers and caches.
If a device uses noinc registers (which is rare) then we could corrupt
registers after the noinc register in the cache"
* tag 'regmap-fix-v6.7-merge-window' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap:
regmap: prevent noinc writes from clobbering cache
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/regmap/regmap.c | 16 |
1 files changed, 9 insertions, 7 deletions
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 234a84ecde8b..ea6157747199 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -1620,17 +1620,19 @@ static int _regmap_raw_write_impl(struct regmap *map, unsigned int reg, } if (!map->cache_bypass && map->format.parse_val) { - unsigned int ival; + unsigned int ival, offset; int val_bytes = map->format.val_bytes; - for (i = 0; i < val_len / val_bytes; i++) { - ival = map->format.parse_val(val + (i * val_bytes)); - ret = regcache_write(map, - reg + regmap_get_offset(map, i), - ival); + + /* Cache the last written value for noinc writes */ + i = noinc ? val_len - val_bytes : 0; + for (; i < val_len; i += val_bytes) { + ival = map->format.parse_val(val + i); + offset = noinc ? 0 : regmap_get_offset(map, i / val_bytes); + ret = regcache_write(map, reg + offset, ival); if (ret) { dev_err(map->dev, "Error in caching of register: %x ret: %d\n", - reg + regmap_get_offset(map, i), ret); + reg + offset, ret); return ret; } } |