From: Andy Shevchenko Date: Thu, 5 Mar 2026 08:53:01 +0000 (+0100) Subject: regcache: Allocate and free reg_defaults on the same level X-Git-Tag: v7.1-rc1~155^2~5 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=0cb7ae981894ff1fd0283813a17253250a747cf5;p=thirdparty%2Fkernel%2Flinux.git regcache: Allocate and free reg_defaults on the same level Currently reg_defaults buffer may be allocated on two different levels when the user provided them and we duplicate it in regcache_init() or when user wants us to read back from HW in regcache_hw_init(). This inconsistency makes code harder to follow and maintain. Allocate and free reg_defaults on the same level in regcache_init() to improve the readability and maintenance efforts. Signed-off-by: Andy Shevchenko Link: https://patch.msgid.link/20260305085449.3184020-3-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c index b73de70bbf3f7..e9d95aa639388 100644 --- a/drivers/base/regmap/regcache.c +++ b/drivers/base/regmap/regcache.c @@ -56,17 +56,12 @@ static int regcache_count_cacheable_registers(struct regmap *map) return count; } -static int regcache_hw_init(struct regmap *map, int count) +static int regcache_hw_init(struct regmap *map) { int ret; unsigned int reg, val; void *tmp_buf; - map->num_reg_defaults = count; - map->reg_defaults = kmalloc_objs(struct reg_default, count); - if (!map->reg_defaults) - return -ENOMEM; - if (!map->reg_defaults_raw) { bool cache_bypass = map->cache_bypass; dev_dbg(map->dev, "No cache defaults, reading back from HW\n"); @@ -74,10 +69,8 @@ static int regcache_hw_init(struct regmap *map, int count) /* Bypass the cache access till data read from HW */ map->cache_bypass = true; tmp_buf = kmalloc(map->cache_size_raw, GFP_KERNEL); - if (!tmp_buf) { - ret = -ENOMEM; - goto err_free; - } + if (!tmp_buf) + return -ENOMEM; ret = regmap_raw_read(map, 0, tmp_buf, map->cache_size_raw); map->cache_bypass = cache_bypass; @@ -110,7 +103,7 @@ static int regcache_hw_init(struct regmap *map, int count) if (ret != 0) { dev_err(map->dev, "Failed to read %x: %d\n", reg, ret); - goto err_free; + return ret; } } @@ -120,16 +113,10 @@ static int regcache_hw_init(struct regmap *map, int count) } return 0; - -err_free: - kfree(map->reg_defaults); - - return ret; } static void regcache_hw_exit(struct regmap *map) { - kfree(map->reg_defaults); if (map->cache_free) kfree(map->reg_defaults_raw); } @@ -209,13 +196,18 @@ int regcache_init(struct regmap *map, const struct regmap_config *config) if (map->cache_bypass) return 0; + map->num_reg_defaults = count; + map->reg_defaults = kmalloc_objs(struct reg_default, count); + if (!map->reg_defaults) + return -ENOMEM; + /* Some devices such as PMICs don't have cache defaults, * we cope with this by reading back the HW registers and * crafting the cache defaults by hand. */ - ret = regcache_hw_init(map, count); + ret = regcache_hw_init(map); if (ret < 0) - return ret; + goto err_free_reg_defaults; } if (!map->max_register_is_set && map->num_reg_defaults_raw) { @@ -253,6 +245,8 @@ err_exit: } err_free: regcache_hw_exit(map); +err_free_reg_defaults: + kfree(map->reg_defaults); return ret; } @@ -273,6 +267,8 @@ void regcache_exit(struct regmap *map) map->cache_ops->exit(map); map->unlock(map->lock_arg); } + + kfree(map->reg_defaults); } /**