mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v2 0/7] regmap: cleanups for regcache and regmap init paths
@ 2026-10-02 13:11 Peng Fan (OSS)
  2026-10-02 13:11 ` [PATCH v2 1/7] regcache: extract locked helpers to replace open-coded lock/unlock pairs Peng Fan (OSS)
                   ` (7 more replies)
  0 siblings, 8 replies; 10+ messages in thread
From: Peng Fan (OSS) @ 2026-10-02 13:11 UTC (permalink / raw)
  To: Mark Brown, Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich
  Cc: linux-kernel, driver-core, Peng Fan

Following up the previous regmap guard lock patchset [1].

[1] https://lore.kernel.org/all/179062150526.139547.3870545428656485907.b4-ty@b4/#r

This is the 2nd batch to do more cleanup.

This series tidies up locking, error handling, and resource management
across the regmap core and regcache.

- Extract regcache_locked_op() and regcache_locked_exit() helpers to
  replace open-coded lock/unlock pairs in regcache_init() and
  regcache_exit(), avoiding the cleanup.h-vs-goto concern that
  prevented the earlier scoped lock guard conversion.

- Extract __regcache_sync() to deduplicate the sync dispatch logic
  shared between regcache_sync() and regcache_sync_region().

- Flatten control flow in regcache_init(), regcache_lookup_reg(), and
  regcache_sync_block() by using early returns, moving guards into
  helpers, and merging redundant sanity checks.

- Switch regmap_register_patch() from krealloc() to krealloc_array()
  for overflow-safe element-count arithmetic.

- NULL map->reg_defaults after freeing in regcache_exit() to prevent
  a potential double-free if regmap_reinit_cache() later fails during
  cache re-initialisation.

Tested with the regmap KUnit suite (drivers/base/regmap/regmap-kunit.c)
with lockdep (PROVE_LOCKING, DEBUG_LOCK_ALLOC, DEBUG_ATOMIC_SLEEP) enabled.
Built clean with sparse (C=1).

Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
Changes in v2:
- Drop patches:
  [PATCH 5/7] regmap: use devm_kmemdup() for bus copies and remove free_on_exit
  [PATCH 6/7] regmap: return errors directly before map allocation in __regmap_init()
  sashiko reports a potential UAF issue regarding patch 5, so drop it.
  Patch 6 depends on patch 5, so also drop patch 6
- Add two new patches to do some cleanup to debugfs
  Patch v2 6/7 and 7/7
- Link to v1: https://patch.msgid.link/20260930-regmap-lock-2nd-v1-0-33a8a482f9ae@nxp.com

---
Peng Fan (7):
      regcache: extract locked helpers to replace open-coded lock/unlock pairs
      regcache: extract __regcache_sync() to deduplicate sync dispatch
      regcache: simplify control flow and reduce nesting
      regmap: use krealloc_array() in regmap_register_patch()
      regmap: fix potential double-free of map->reg_defaults on cache reinit
      regmap: debugfs: Use __free(kfree) in regmap_name_read_file()
      regmap: debugfs: Use guard to simplify code

 drivers/base/regmap/regcache.c       | 132 +++++++++++++++++------------------
 drivers/base/regmap/regmap-debugfs.c |  74 +++++++++-----------
 drivers/base/regmap/regmap.c         |  15 ++--
 3 files changed, 103 insertions(+), 118 deletions(-)
---
base-commit: 6474fa070f2b8013b4b87350b775b8c3be6e8aac
change-id: 20260930-regmap-lock-2nd-f481885c24d6

Best regards,
--  
Peng Fan <peng.fan@nxp.com>


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH v2 1/7] regcache: extract locked helpers to replace open-coded lock/unlock pairs
  2026-10-02 13:11 [PATCH v2 0/7] regmap: cleanups for regcache and regmap init paths Peng Fan (OSS)
@ 2026-10-02 13:11 ` Peng Fan (OSS)
  2026-10-02 13:11 ` [PATCH v2 2/7] regcache: extract __regcache_sync() to deduplicate sync dispatch Peng Fan (OSS)
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: Peng Fan (OSS) @ 2026-10-02 13:11 UTC (permalink / raw)
  To: Mark Brown, Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich
  Cc: linux-kernel, driver-core, Peng Fan

From: Peng Fan <peng.fan@nxp.com>

The previous patch ("regcache: use the regmap scoped lock guard")
deliberately left regcache_init() with explicit map->lock()/unlock()
calls because the function has a goto err_* cleanup ladder and mixing
goto with cleanup helpers in the same function is discouraged by
cleanup.h.

Solve this by extracting two static helpers:

  regcache_locked_op()  - acquires the regmap lock via guard(regmap),
                          invokes an int-returning cache_ops callback
                          (init, populate), and returns its result.
                          Returns 0 when the callback is NULL.

  regcache_locked_exit() - acquires the regmap lock via guard(regmap)
                           and invokes the void-returning exit
                           callback.  Returns immediately when the
                           callback is NULL.

Because the lock scope is now entirely inside the helper functions,
it never crosses a goto target in the caller, so the cleanup.h
concern does not apply.

Convert all four remaining open-coded lock/unlock sites in
regcache_init() (init, populate, error-path exit) and the
scoped_guard in regcache_exit() to use these helpers.

No functional change.

Assisted-by: LLM
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 drivers/base/regmap/regcache.c | 57 +++++++++++++++++++++---------------------
 1 file changed, 29 insertions(+), 28 deletions(-)

diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c
index 4c80db5d6f6f..ebfa27bb6f54 100644
--- a/drivers/base/regmap/regcache.c
+++ b/drivers/base/regmap/regcache.c
@@ -121,6 +121,28 @@ static void regcache_hw_exit(struct regmap *map)
 		kfree(map->reg_defaults_raw);
 }
 
+static int regcache_locked_op(struct regmap *map,
+			      int (*op)(struct regmap *map),
+			      const char *action)
+{
+	if (!op)
+		return 0;
+
+	dev_dbg(map->dev, "%s %s cache\n", action, map->cache_ops->name);
+	guard(regmap)(map);
+	return op(map);
+}
+
+static void regcache_locked_exit(struct regmap *map)
+{
+	if (!map->cache_ops->exit)
+		return;
+
+	dev_dbg(map->dev, "Destroying %s cache\n", map->cache_ops->name);
+	guard(regmap)(map);
+	map->cache_ops->exit(map);
+}
+
 int regcache_init(struct regmap *map, const struct regmap_config *config)
 {
 	bool sort_defaults = false;
@@ -222,15 +244,9 @@ int regcache_init(struct regmap *map, const struct regmap_config *config)
 		map->max_register_is_set = true;
 	}
 
-	if (map->cache_ops->init) {
-		dev_dbg(map->dev, "Initializing %s cache\n",
-			map->cache_ops->name);
-		map->lock(map->lock_arg);
-		ret = map->cache_ops->init(map);
-		map->unlock(map->lock_arg);
-		if (ret)
-			goto err_free_reg_defaults;
-	}
+	ret = regcache_locked_op(map, map->cache_ops->init, "Initializing");
+	if (ret)
+		goto err_free_reg_defaults;
 
 	/*
 	 * Some devices such as PMICs don't have cache defaults,
@@ -243,12 +259,8 @@ int regcache_init(struct regmap *map, const struct regmap_config *config)
 			goto err_exit;
 	}
 
-	if (map->cache_ops->populate &&
-	    (map->num_reg_defaults || map->reg_default_cb)) {
-		dev_dbg(map->dev, "Populating %s cache\n", map->cache_ops->name);
-		map->lock(map->lock_arg);
-		ret = map->cache_ops->populate(map);
-		map->unlock(map->lock_arg);
+	if (map->num_reg_defaults || map->reg_default_cb) {
+		ret = regcache_locked_op(map, map->cache_ops->populate, "Populating");
 		if (ret)
 			goto err_free;
 	}
@@ -257,12 +269,7 @@ int regcache_init(struct regmap *map, const struct regmap_config *config)
 err_free:
 	regcache_hw_exit(map);
 err_exit:
-	if (map->cache_ops->exit) {
-		dev_dbg(map->dev, "Destroying %s cache\n", map->cache_ops->name);
-		map->lock(map->lock_arg);
-		map->cache_ops->exit(map);
-		map->unlock(map->lock_arg);
-	}
+	regcache_locked_exit(map);
 err_free_reg_defaults:
 	kfree(map->reg_defaults);
 
@@ -277,13 +284,7 @@ void regcache_exit(struct regmap *map)
 	BUG_ON(!map->cache_ops);
 
 	regcache_hw_exit(map);
-
-	if (map->cache_ops->exit) {
-		dev_dbg(map->dev, "Destroying %s cache\n",
-			map->cache_ops->name);
-		scoped_guard(regmap, map)
-			map->cache_ops->exit(map);
-	}
+	regcache_locked_exit(map);
 
 	kfree(map->reg_defaults);
 }

-- 
2.51.0


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH v2 2/7] regcache: extract __regcache_sync() to deduplicate sync dispatch
  2026-10-02 13:11 [PATCH v2 0/7] regmap: cleanups for regcache and regmap init paths Peng Fan (OSS)
  2026-10-02 13:11 ` [PATCH v2 1/7] regcache: extract locked helpers to replace open-coded lock/unlock pairs Peng Fan (OSS)
@ 2026-10-02 13:11 ` Peng Fan (OSS)
  2026-10-02 13:11 ` [PATCH v2 3/7] regcache: simplify control flow and reduce nesting Peng Fan (OSS)
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: Peng Fan (OSS) @ 2026-10-02 13:11 UTC (permalink / raw)
  To: Mark Brown, Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich
  Cc: linux-kernel, driver-core, Peng Fan

From: Peng Fan <peng.fan@nxp.com>

regcache_sync() and regcache_sync_region() both open-code the same
pattern: check cache_dirty, then dispatch to either cache_ops->sync()
or regcache_default_sync().

Extract this into a static __regcache_sync() helper that both callers
share. The helper checks cache_dirty and returns 0 early when the
cache is clean, dispatches to the backend sync callback when present,
and falls back to regcache_default_sync() otherwise.

In regcache_sync_region(), the cache_dirty early-exit previously
skipped setting map->async. With the helper, map->async is set to
true before the call and restored to false unconditionally afterward,
so when cache_dirty is false the flag is toggled and immediately
restored - functionally equivalent.

No functional change.

Assisted-by: LLM
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 drivers/base/regmap/regcache.c | 28 +++++++++++++++-------------
 1 file changed, 15 insertions(+), 13 deletions(-)

diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c
index ebfa27bb6f54..b486cd826b3c 100644
--- a/drivers/base/regmap/regcache.c
+++ b/drivers/base/regmap/regcache.c
@@ -22,6 +22,8 @@ static const struct regcache_ops *cache_types[] = {
 	&regcache_flat_ops,
 };
 
+static int regcache_default_sync(struct regmap *map, unsigned int min, unsigned int max);
+
 static int regcache_defaults_cmp(const void *a, const void *b)
 {
 	const struct reg_default *x = a;
@@ -143,6 +145,17 @@ static void regcache_locked_exit(struct regmap *map)
 	map->cache_ops->exit(map);
 }
 
+static int __regcache_sync(struct regmap *map, unsigned int min, unsigned int max)
+{
+	if (!map->cache_dirty)
+		return 0;
+
+	if (map->cache_ops->sync)
+		return map->cache_ops->sync(map, min, max);
+
+	return regcache_default_sync(map, min, max);
+}
+
 int regcache_init(struct regmap *map, const struct regmap_config *config)
 {
 	bool sort_defaults = false;
@@ -461,11 +474,7 @@ int regcache_sync(struct regmap *map)
 	}
 	map->cache_bypass = false;
 
-	if (map->cache_ops->sync)
-		sync_ret = map->cache_ops->sync(map, 0, map->max_register);
-	else
-		sync_ret = regcache_default_sync(map, 0, map->max_register);
-
+	sync_ret = __regcache_sync(map, 0, map->max_register);
 	if (sync_ret == 0)
 		map->cache_dirty = false;
 
@@ -545,17 +554,10 @@ int regcache_sync_region(struct regmap *map, unsigned int min,
 
 	trace_regcache_sync(map, name, "start region");
 
-	if (!map->cache_dirty)
-		goto out;
-
 	map->async = true;
 
-	if (map->cache_ops->sync)
-		ret = map->cache_ops->sync(map, min, max);
-	else
-		ret = regcache_default_sync(map, min, max);
+	ret = __regcache_sync(map, min, max);
 
-out:
 	/* Restore the bypass state */
 	map->cache_bypass = bypass;
 	map->async = false;

-- 
2.51.0


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH v2 3/7] regcache: simplify control flow and reduce nesting
  2026-10-02 13:11 [PATCH v2 0/7] regmap: cleanups for regcache and regmap init paths Peng Fan (OSS)
  2026-10-02 13:11 ` [PATCH v2 1/7] regcache: extract locked helpers to replace open-coded lock/unlock pairs Peng Fan (OSS)
  2026-10-02 13:11 ` [PATCH v2 2/7] regcache: extract __regcache_sync() to deduplicate sync dispatch Peng Fan (OSS)
@ 2026-10-02 13:11 ` Peng Fan (OSS)
  2026-10-02 13:11 ` [PATCH v2 4/7] regmap: use krealloc_array() in regmap_register_patch() Peng Fan (OSS)
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: Peng Fan (OSS) @ 2026-10-02 13:11 UTC (permalink / raw)
  To: Mark Brown, Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich
  Cc: linux-kernel, driver-core, Peng Fan

From: Peng Fan <peng.fan@nxp.com>

Move the count guard into regcache_hw_init() so callers don't need to
check before calling, and flatten conditional blocks that wrap a single
call by using early returns instead.

Merge the two separate reg_defaults / num_reg_defaults sanity checks
into a single expression, and drop unnecessary else-after-return in
regcache_lookup_reg() and regcache_sync_block().

No functional change.

Assisted-by: LLM
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 drivers/base/regmap/regcache.c | 50 +++++++++++++++++++-----------------------
 1 file changed, 22 insertions(+), 28 deletions(-)

diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c
index b486cd826b3c..136d6adf3120 100644
--- a/drivers/base/regmap/regcache.c
+++ b/drivers/base/regmap/regcache.c
@@ -58,12 +58,15 @@ static int regcache_count_cacheable_registers(struct regmap *map)
 	return count;
 }
 
-static int regcache_hw_init(struct regmap *map)
+static int regcache_hw_init(struct regmap *map, int count)
 {
 	int ret;
 	unsigned int reg, val;
 	void *tmp_buf;
 
+	if (!count)
+		return 0;
+
 	if (!map->reg_defaults_raw) {
 		bool cache_bypass = map->cache_bypass;
 		dev_dbg(map->dev, "No cache defaults, reading back from HW\n");
@@ -174,15 +177,8 @@ int regcache_init(struct regmap *map, const struct regmap_config *config)
 		return 0;
 	}
 
-	if (config->reg_defaults && !config->num_reg_defaults) {
-		dev_err(map->dev,
-			 "Register defaults are set without the number!\n");
-		return -EINVAL;
-	}
-
-	if (config->num_reg_defaults && !config->reg_defaults) {
-		dev_err(map->dev,
-			"Register defaults number are set without the reg!\n");
+	if (!!config->reg_defaults != !!config->num_reg_defaults) {
+		dev_err(map->dev, "reg_defaults and num_reg_defaults must both be specified\n");
 		return -EINVAL;
 	}
 
@@ -215,9 +211,7 @@ int regcache_init(struct regmap *map, const struct regmap_config *config)
 	map->cache = NULL;
 	map->cache_ops = cache_types[i];
 
-	if (!map->cache_ops->read ||
-	    !map->cache_ops->write ||
-	    !map->cache_ops->name)
+	if (!map->cache_ops->read || !map->cache_ops->write || !map->cache_ops->name)
 		return -EINVAL;
 
 	/* We still need to ensure that the reg_defaults
@@ -266,17 +260,17 @@ int regcache_init(struct regmap *map, const struct regmap_config *config)
 	 * we cope with this by reading back the HW registers and
 	 * crafting the cache defaults by hand.
 	 */
-	if (count) {
-		ret = regcache_hw_init(map);
-		if (ret)
-			goto err_exit;
-	}
+	ret = regcache_hw_init(map, count);
+	if (ret)
+		goto err_exit;
+
+	if (!map->num_reg_defaults && !map->reg_default_cb)
+		return 0;
+
+	ret = regcache_locked_op(map, map->cache_ops->populate, "Populating");
+	if (ret)
+		goto err_free;
 
-	if (map->num_reg_defaults || map->reg_default_cb) {
-		ret = regcache_locked_op(map, map->cache_ops->populate, "Populating");
-		if (ret)
-			goto err_free;
-	}
 	return 0;
 
 err_free:
@@ -762,8 +756,8 @@ int regcache_lookup_reg(struct regmap *map, unsigned int reg)
 
 	if (r)
 		return r - map->reg_defaults;
-	else
-		return -ENOENT;
+
+	return -ENOENT;
 }
 
 static bool regcache_reg_present(unsigned long *cache_present, unsigned int idx)
@@ -900,7 +894,7 @@ int regcache_sync_block(struct regmap *map, void *block,
 	if (regmap_can_raw_write(map) && !map->use_single_write)
 		return regcache_sync_block_raw(map, block, cache_present,
 					       block_base, start, end);
-	else
-		return regcache_sync_block_single(map, block, cache_present,
-						  block_base, start, end);
+
+	return regcache_sync_block_single(map, block, cache_present,
+					  block_base, start, end);
 }

-- 
2.51.0


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH v2 4/7] regmap: use krealloc_array() in regmap_register_patch()
  2026-10-02 13:11 [PATCH v2 0/7] regmap: cleanups for regcache and regmap init paths Peng Fan (OSS)
                   ` (2 preceding siblings ...)
  2026-10-02 13:11 ` [PATCH v2 3/7] regcache: simplify control flow and reduce nesting Peng Fan (OSS)
@ 2026-10-02 13:11 ` Peng Fan (OSS)
  2026-10-02 13:11 ` [PATCH v2 5/7] regmap: fix potential double-free of map->reg_defaults on cache reinit Peng Fan (OSS)
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: Peng Fan (OSS) @ 2026-10-02 13:11 UTC (permalink / raw)
  To: Mark Brown, Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich
  Cc: linux-kernel, driver-core, Peng Fan

From: Peng Fan <peng.fan@nxp.com>

Replace krealloc() with krealloc_array() in regmap_register_patch() to
gain the built-in overflow check on the element-count * element-size
multiplication, and switch to the early-return error style to reduce
nesting.

Assisted-by: LLM
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 drivers/base/regmap/regmap.c | 15 ++++++---------
 1 file changed, 6 insertions(+), 9 deletions(-)

diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 0b40e1e7817c..b9830afa6d8e 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -3379,16 +3379,13 @@ int regmap_register_patch(struct regmap *map, const struct reg_sequence *regs,
 	    num_regs))
 		return 0;
 
-	p = krealloc(map->patch,
-		     sizeof(struct reg_sequence) * (map->patch_regs + num_regs),
-		     GFP_KERNEL);
-	if (p) {
-		memcpy(p + map->patch_regs, regs, num_regs * sizeof(*regs));
-		map->patch = p;
-		map->patch_regs += num_regs;
-	} else {
+	p = krealloc_array(map->patch, map->patch_regs + num_regs, sizeof(*p), GFP_KERNEL);
+	if (!p)
 		return -ENOMEM;
-	}
+
+	memcpy(p + map->patch_regs, regs, num_regs * sizeof(*regs));
+	map->patch = p;
+	map->patch_regs += num_regs;
 
 	scoped_guard(regmap, map) {
 		bypass = map->cache_bypass;

-- 
2.51.0


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH v2 5/7] regmap: fix potential double-free of map->reg_defaults on cache reinit
  2026-10-02 13:11 [PATCH v2 0/7] regmap: cleanups for regcache and regmap init paths Peng Fan (OSS)
                   ` (3 preceding siblings ...)
  2026-10-02 13:11 ` [PATCH v2 4/7] regmap: use krealloc_array() in regmap_register_patch() Peng Fan (OSS)
@ 2026-10-02 13:11 ` Peng Fan (OSS)
  2026-10-02 13:11 ` [PATCH v2 6/7] regmap: debugfs: Use __free(kfree) in regmap_name_read_file() Peng Fan (OSS)
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: Peng Fan (OSS) @ 2026-10-02 13:11 UTC (permalink / raw)
  To: Mark Brown, Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich
  Cc: linux-kernel, driver-core, Peng Fan

From: Peng Fan <peng.fan@nxp.com>

regcache_exit() frees map->reg_defaults but does not NULL the pointer.
If regmap_reinit_cache() is later called with a config that has neither
reg_defaults nor num_reg_defaults_raw, regcache_init() skips both
allocation branches and leaves the stale pointer in place.  Should
cache_ops->init then fail, the err_free_reg_defaults error path calls
kfree(map->reg_defaults) a second time.

NULL the pointer after freeing so the error-path kfree() is a harmless
no-op.

Assisted-by: LLM
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 drivers/base/regmap/regcache.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c
index 136d6adf3120..3b1c2f28d585 100644
--- a/drivers/base/regmap/regcache.c
+++ b/drivers/base/regmap/regcache.c
@@ -294,6 +294,7 @@ void regcache_exit(struct regmap *map)
 	regcache_locked_exit(map);
 
 	kfree(map->reg_defaults);
+	map->reg_defaults = NULL;
 }
 
 /**

-- 
2.51.0


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH v2 6/7] regmap: debugfs: Use __free(kfree) in regmap_name_read_file()
  2026-10-02 13:11 [PATCH v2 0/7] regmap: cleanups for regcache and regmap init paths Peng Fan (OSS)
                   ` (4 preceding siblings ...)
  2026-10-02 13:11 ` [PATCH v2 5/7] regmap: fix potential double-free of map->reg_defaults on cache reinit Peng Fan (OSS)
@ 2026-10-02 13:11 ` Peng Fan (OSS)
  2026-10-02 13:11 ` [PATCH v2 7/7] regmap: debugfs: Use guard to simplify code Peng Fan (OSS)
  2026-10-06 16:08 ` [PATCH v2 0/7] regmap: cleanups for regcache and regmap init paths Mark Brown
  7 siblings, 0 replies; 10+ messages in thread
From: Peng Fan (OSS) @ 2026-10-02 13:11 UTC (permalink / raw)
  To: Mark Brown, Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich
  Cc: linux-kernel, driver-core, Peng Fan

From: Peng Fan <peng.fan@nxp.com>

Use the __free(kfree) cleanup helper for the temporary buffer allocated
by regmap_name_read_file().

Remove the explicit kfree() calls from the error and success paths.

No functional change.

Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 drivers/base/regmap/regmap-debugfs.c | 11 +++--------
 1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c
index ec207548a6bb..0a9c27426f15 100644
--- a/drivers/base/regmap/regmap-debugfs.c
+++ b/drivers/base/regmap/regmap-debugfs.c
@@ -38,10 +38,9 @@ static ssize_t regmap_name_read_file(struct file *file,
 {
 	struct regmap *map = file->private_data;
 	const char *name = "nodev";
+	char *buf __free(kfree) = kmalloc(PAGE_SIZE, GFP_KERNEL);
 	int ret;
-	char *buf;
 
-	buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
 	if (!buf)
 		return -ENOMEM;
 
@@ -49,14 +48,10 @@ static ssize_t regmap_name_read_file(struct file *file,
 		name = map->dev->driver->name;
 
 	ret = snprintf(buf, PAGE_SIZE, "%s\n", name);
-	if (ret >= PAGE_SIZE) {
-		kfree(buf);
+	if (ret >= PAGE_SIZE)
 		return ret;
-	}
 
-	ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
-	kfree(buf);
-	return ret;
+	return simple_read_from_buffer(user_buf, count, ppos, buf, ret);
 }
 
 static const struct file_operations regmap_name_fops = {

-- 
2.51.0


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH v2 7/7] regmap: debugfs: Use guard to simplify code
  2026-10-02 13:11 [PATCH v2 0/7] regmap: cleanups for regcache and regmap init paths Peng Fan (OSS)
                   ` (5 preceding siblings ...)
  2026-10-02 13:11 ` [PATCH v2 6/7] regmap: debugfs: Use __free(kfree) in regmap_name_read_file() Peng Fan (OSS)
@ 2026-10-02 13:11 ` Peng Fan (OSS)
  2026-10-06 16:08 ` [PATCH v2 0/7] regmap: cleanups for regcache and regmap init paths Mark Brown
  7 siblings, 0 replies; 10+ messages in thread
From: Peng Fan (OSS) @ 2026-10-02 13:11 UTC (permalink / raw)
  To: Mark Brown, Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich
  Cc: linux-kernel, driver-core, Peng Fan

From: Peng Fan <peng.fan@nxp.com>

Replace open-coded mutex_lock()/unlock() pairs with guard() and
scoped_guard() across the debugfs code.

 - regmap_debugfs_get_dump_start(): guard(mutex) replaces three
   unlock sites (kzalloc failure, cache hit, end-of-function).

 - regmap_next_readable_reg(): early return for the common case
   and scoped_guard for the cache fallback path.

 - regmap_reg_ranges_read_file(): scoped_guard wraps the cache
   iteration loop.

 - regmap_debugfs_init(): scoped_guard for single list_add.

 - regmap_debugfs_exit(): flatten if/else into early return and
   scoped_guard for the early-list cleanup.

 - regmap_debugfs_initcall(): guard(mutex) held to function end.

No functional change.

Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 drivers/base/regmap/regmap-debugfs.c | 63 +++++++++++++++++-------------------
 1 file changed, 29 insertions(+), 34 deletions(-)

diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c
index 0a9c27426f15..b2ae52a21331 100644
--- a/drivers/base/regmap/regmap-debugfs.c
+++ b/drivers/base/regmap/regmap-debugfs.c
@@ -107,7 +107,7 @@ static unsigned int regmap_debugfs_get_dump_start(struct regmap *map,
 	 * If we don't have a cache build one so we don't have to do a
 	 * linear scan each time.
 	 */
-	mutex_lock(&map->cache_lock);
+	guard(mutex)(&map->cache_lock);
 	i = base;
 	if (list_empty(&map->debugfs_off_cache)) {
 		for (; i <= map->max_register; i += map->reg_stride) {
@@ -129,7 +129,6 @@ static unsigned int regmap_debugfs_get_dump_start(struct regmap *map,
 				c = kzalloc_obj(*c);
 				if (!c) {
 					regmap_debugfs_free_dump_cache(map);
-					mutex_unlock(&map->cache_lock);
 					return base;
 				}
 				c->min = p;
@@ -162,14 +161,12 @@ static unsigned int regmap_debugfs_get_dump_start(struct regmap *map,
 			fpos_offset = from - c->min;
 			reg_offset = fpos_offset / map->debugfs_tot_len;
 			*pos = c->min + (reg_offset * map->debugfs_tot_len);
-			mutex_unlock(&map->cache_lock);
 			return c->base_reg + (reg_offset * map->reg_stride);
 		}
 
 		*pos = c->max;
 		ret = c->max_reg;
 	}
-	mutex_unlock(&map->cache_lock);
 
 	return ret;
 }
@@ -191,10 +188,10 @@ static int regmap_next_readable_reg(struct regmap *map, int reg)
 	struct regmap_debugfs_off_cache *c;
 	int ret = -EINVAL;
 
-	if (regmap_printable(map, reg + map->reg_stride)) {
-		ret = reg + map->reg_stride;
-	} else {
-		mutex_lock(&map->cache_lock);
+	if (regmap_printable(map, reg + map->reg_stride))
+		return reg + map->reg_stride;
+
+	scoped_guard(mutex, &map->cache_lock) {
 		list_for_each_entry(c, &map->debugfs_off_cache, list) {
 			if (reg > c->max_reg)
 				continue;
@@ -203,8 +200,8 @@ static int regmap_next_readable_reg(struct regmap *map, int reg)
 				break;
 			}
 		}
-		mutex_unlock(&map->cache_lock);
 	}
+
 	return ret;
 }
 
@@ -393,19 +390,19 @@ static ssize_t regmap_reg_ranges_read_file(struct file *file,
 	/* Reset file pointer as the fixed-format of the `registers'
 	 * file is not compatible with the `range' file */
 	p = 0;
-	mutex_lock(&map->cache_lock);
-	list_for_each_entry(c, &map->debugfs_off_cache, list) {
-		entry_len = snprintf(entry, PAGE_SIZE, "%x-%x\n",
-				     c->base_reg, c->max_reg);
-		if (p >= *ppos) {
-			if (buf_pos + entry_len > count)
-				break;
-			memcpy(buf + buf_pos, entry, entry_len);
-			buf_pos += entry_len;
+	scoped_guard(mutex, &map->cache_lock) {
+		list_for_each_entry(c, &map->debugfs_off_cache, list) {
+			entry_len = snprintf(entry, PAGE_SIZE, "%x-%x\n",
+					     c->base_reg, c->max_reg);
+			if (p >= *ppos) {
+				if (buf_pos + entry_len > count)
+					break;
+				memcpy(buf + buf_pos, entry, entry_len);
+				buf_pos += entry_len;
+			}
+			p += entry_len;
 		}
-		p += entry_len;
 	}
-	mutex_unlock(&map->cache_lock);
 
 	kfree(entry);
 	ret = buf_pos;
@@ -552,9 +549,8 @@ void regmap_debugfs_init(struct regmap *map)
 		if (!node)
 			return;
 		node->map = map;
-		mutex_lock(&regmap_debugfs_early_lock);
-		list_add(&node->link, &regmap_debugfs_early_list);
-		mutex_unlock(&regmap_debugfs_early_lock);
+		scoped_guard(mutex, &regmap_debugfs_early_lock)
+			list_add(&node->link, &regmap_debugfs_early_list);
 		return;
 	}
 
@@ -653,29 +649,29 @@ void regmap_debugfs_init(struct regmap *map)
 
 void regmap_debugfs_exit(struct regmap *map)
 {
+	struct regmap_debugfs_node *node, *tmp;
+
 	if (map->debugfs) {
 		debugfs_remove_recursive(map->debugfs);
-		mutex_lock(&map->cache_lock);
-		regmap_debugfs_free_dump_cache(map);
-		mutex_unlock(&map->cache_lock);
+		scoped_guard(mutex, &map->cache_lock)
+			regmap_debugfs_free_dump_cache(map);
 		if (map->debugfs_dummy_id >= 0) {
 			ida_free(&dummy_ida, map->debugfs_dummy_id);
 			map->debugfs_dummy_id = -1;
 		}
 		kfree(map->debugfs_name);
 		map->debugfs_name = NULL;
-	} else {
-		struct regmap_debugfs_node *node, *tmp;
 
-		mutex_lock(&regmap_debugfs_early_lock);
-		list_for_each_entry_safe(node, tmp, &regmap_debugfs_early_list,
-					 link) {
+		return;
+	}
+
+	scoped_guard(mutex, &regmap_debugfs_early_lock) {
+		list_for_each_entry_safe(node, tmp, &regmap_debugfs_early_list, link) {
 			if (node->map == map) {
 				list_del(&node->link);
 				kfree(node);
 			}
 		}
-		mutex_unlock(&regmap_debugfs_early_lock);
 	}
 }
 
@@ -685,11 +681,10 @@ void regmap_debugfs_initcall(void)
 
 	regmap_debugfs_root = debugfs_create_dir("regmap", NULL);
 
-	mutex_lock(&regmap_debugfs_early_lock);
+	guard(mutex)(&regmap_debugfs_early_lock);
 	list_for_each_entry_safe(node, tmp, &regmap_debugfs_early_list, link) {
 		regmap_debugfs_init(node->map);
 		list_del(&node->link);
 		kfree(node);
 	}
-	mutex_unlock(&regmap_debugfs_early_lock);
 }

-- 
2.51.0


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 0/7] regmap: cleanups for regcache and regmap init paths
  2026-10-02 13:11 [PATCH v2 0/7] regmap: cleanups for regcache and regmap init paths Peng Fan (OSS)
                   ` (6 preceding siblings ...)
  2026-10-02 13:11 ` [PATCH v2 7/7] regmap: debugfs: Use guard to simplify code Peng Fan (OSS)
@ 2026-10-06 16:08 ` Mark Brown
  2026-10-07 13:21   ` Peng Fan
  7 siblings, 1 reply; 10+ messages in thread
From: Mark Brown @ 2026-10-06 16:08 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich, Peng Fan (OSS)
  Cc: linux-kernel, driver-core, Peng Fan

On Fri, 02 Oct 2026 21:11:16 +0800, Peng Fan (OSS) wrote:
> regmap: cleanups for regcache and regmap init paths
> 
> Following up the previous regmap guard lock patchset [1].
> 
> [1] https://lore.kernel.org/all/179062150526.139547.3870545428656485907.b4-ty@b4/#r
> 
> This is the 2nd batch to do more cleanup.
> 
> [...]

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap.git for-7.4

Thanks!

[1/7] regcache: extract locked helpers to replace open-coded lock/unlock pairs
      https://git.kernel.org/broonie/regmap/c/81556a7aec22
[2/7] regcache: extract __regcache_sync() to deduplicate sync dispatch
      https://git.kernel.org/broonie/regmap/c/7ca8aa98e2ba
[3/7] regcache: simplify control flow and reduce nesting
      https://git.kernel.org/broonie/regmap/c/4e1b5ccf1eab
[4/7] regmap: use krealloc_array() in regmap_register_patch()
      https://git.kernel.org/broonie/regmap/c/8a889c83e478
[5/7] regmap: fix potential double-free of map->reg_defaults on cache reinit
      https://git.kernel.org/broonie/regmap/c/ca685a42b0fd
[6/7] regmap: debugfs: Use __free(kfree) in regmap_name_read_file()
      https://git.kernel.org/broonie/regmap/c/d64967dee82b
[7/7] regmap: debugfs: Use guard to simplify code
      https://git.kernel.org/broonie/regmap/c/a93de1d65c6b

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 0/7] regmap: cleanups for regcache and regmap init paths
  2026-10-06 16:08 ` [PATCH v2 0/7] regmap: cleanups for regcache and regmap init paths Mark Brown
@ 2026-10-07 13:21   ` Peng Fan
  0 siblings, 0 replies; 10+ messages in thread
From: Peng Fan @ 2026-10-07 13:21 UTC (permalink / raw)
  To: Mark Brown
  Cc: Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
	linux-kernel, driver-core, Peng Fan

Hi Mark,

On Tue, Oct 06, 2026 at 06:08:33PM +0200, Mark Brown wrote:
>On Fri, 02 Oct 2026 21:11:16 +0800, Peng Fan (OSS) wrote:
>> regmap: cleanups for regcache and regmap init paths
>> 
>> Following up the previous regmap guard lock patchset [1].
>> 
>> [1] https://lore.kernel.org/all/179062150526.139547.3870545428656485907.b4-ty@b4/#r
>> 
>> This is the 2nd batch to do more cleanup.
>> 
>> [...]
>
>Applied to
>
>   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap.git for-7.4

Thanks for picking up this series.

Sashiko report a minor issue that I should not use scoped_guard inside
a function has goto.

Actually it is not an bug. The goto logic and the scoped area are not mixed,
but anyway I just posted out v3 to address the issue:
https://lore.kernel.org/all/20261007-regmap-lock-2nd-v3-0-0e590c4125be@nxp.com/

If you would keep v2, I could post a incremental patch to address the
Sashiko's findings. Or you may pick v3.

Thanks
Peng

>
>Thanks!
>
>[1/7] regcache: extract locked helpers to replace open-coded lock/unlock pairs
>      https://git.kernel.org/broonie/regmap/c/81556a7aec22
>[2/7] regcache: extract __regcache_sync() to deduplicate sync dispatch
>      https://git.kernel.org/broonie/regmap/c/7ca8aa98e2ba
>[3/7] regcache: simplify control flow and reduce nesting
>      https://git.kernel.org/broonie/regmap/c/4e1b5ccf1eab
>[4/7] regmap: use krealloc_array() in regmap_register_patch()
>      https://git.kernel.org/broonie/regmap/c/8a889c83e478
>[5/7] regmap: fix potential double-free of map->reg_defaults on cache reinit
>      https://git.kernel.org/broonie/regmap/c/ca685a42b0fd
>[6/7] regmap: debugfs: Use __free(kfree) in regmap_name_read_file()
>      https://git.kernel.org/broonie/regmap/c/d64967dee82b
>[7/7] regmap: debugfs: Use guard to simplify code
>      https://git.kernel.org/broonie/regmap/c/a93de1d65c6b
>
>All being well this means that it will be integrated into the linux-next
>tree (usually sometime in the next 24 hours) and sent to Linus during
>the next merge window (or sooner if it is a bug fix), however if
>problems are discovered then the patch may be dropped or reverted.
>
>You may get further e-mails resulting from automated or manual testing
>and review of the tree, please engage with people reporting problems and
>send followup patches addressing any issues that are reported if needed.
>
>If any updates are required or you are submitting further changes they
>should be sent as incremental updates against current git, existing
>patches will not be replaced.
>
>Please add any relevant lists and maintainers to the CCs when replying
>to this mail.
>
>Thanks,
>Mark
>
>
>

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2026-10-07 13:16 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-02 13:11 [PATCH v2 0/7] regmap: cleanups for regcache and regmap init paths Peng Fan (OSS)
2026-10-02 13:11 ` [PATCH v2 1/7] regcache: extract locked helpers to replace open-coded lock/unlock pairs Peng Fan (OSS)
2026-10-02 13:11 ` [PATCH v2 2/7] regcache: extract __regcache_sync() to deduplicate sync dispatch Peng Fan (OSS)
2026-10-02 13:11 ` [PATCH v2 3/7] regcache: simplify control flow and reduce nesting Peng Fan (OSS)
2026-10-02 13:11 ` [PATCH v2 4/7] regmap: use krealloc_array() in regmap_register_patch() Peng Fan (OSS)
2026-10-02 13:11 ` [PATCH v2 5/7] regmap: fix potential double-free of map->reg_defaults on cache reinit Peng Fan (OSS)
2026-10-02 13:11 ` [PATCH v2 6/7] regmap: debugfs: Use __free(kfree) in regmap_name_read_file() Peng Fan (OSS)
2026-10-02 13:11 ` [PATCH v2 7/7] regmap: debugfs: Use guard to simplify code Peng Fan (OSS)
2026-10-06 16:08 ` [PATCH v2 0/7] regmap: cleanups for regcache and regmap init paths Mark Brown
2026-10-07 13:21   ` Peng Fan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®