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)
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ 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] 8+ 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)
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 8+ 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] 8+ 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)
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 8+ 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] 8+ 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)
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 8+ 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] 8+ 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)
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 8+ 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] 8+ 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)
  2026-10-02 13:11 ` [PATCH v2 7/7] regmap: debugfs: Use guard to simplify code Peng Fan (OSS)
  6 siblings, 0 replies; 8+ 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] 8+ 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)
  6 siblings, 0 replies; 8+ 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] 8+ 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)
  6 siblings, 0 replies; 8+ 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] 8+ messages in thread

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

Thread overview: 8+ 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)

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®