]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
regmap: prevent noinc writes from clobbering cache
authorBen Wolsieffer <ben.wolsieffer@hefring.com>
Wed, 1 Nov 2023 14:29:27 +0000 (10:29 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 20 Nov 2023 10:08:27 +0000 (11:08 +0100)
[ 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@hefring.com>
Link: https://lore.kernel.org/r/20231101142926.2722603-2-ben.wolsieffer@hefring.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/base/regmap/regmap.c

index 617d51a278497ec77c9e04f276958921aad3020b..7621b54975b576121660bbd3c2780cb8e46d59ca 100644 (file)
@@ -1683,17 +1683,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;
                        }
                }