This is a note to let you know that I've just added the patch titled regmap: prevent noinc writes from clobbering cache to the 6.5-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: regmap-prevent-noinc-writes-from-clobbering-cache.patch and it can be found in the queue-6.5 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@xxxxxxxxxxxxxxx> know about it. commit defecb0594f0191f41914f80ea719acf99455384 Author: Ben Wolsieffer <ben.wolsieffer@xxxxxxxxxxx> Date: Wed Nov 1 10:29:27 2023 -0400 regmap: prevent noinc writes from clobbering cache [ Upstream commit 984a4afdc87a1fc226fd657b1cd8255c13d3fc1a ] Currently, noinc writes are cached as if they were standard incrementing writes, overwriting unrelated register values in the cache. Instead, we want to cache the last value written to the register, as is done in the accelerated noinc handler (regmap_noinc_readwrite). Fixes: cdf6b11daa77 ("regmap: Add regmap_noinc_write API") Signed-off-by: Ben Wolsieffer <ben.wolsieffer@xxxxxxxxxxx> Link: https://lore.kernel.org/r/20231101142926.2722603-2-ben.wolsieffer@xxxxxxxxxxx Signed-off-by: Mark Brown <broonie@xxxxxxxxxx> Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx> diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index bb2f41043f602..0d7ed11b089c3 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -1714,17 +1714,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; } }