* [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[] = {
®cache_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(®map_debugfs_early_lock);
- list_add(&node->link, ®map_debugfs_early_list);
- mutex_unlock(®map_debugfs_early_lock);
+ scoped_guard(mutex, ®map_debugfs_early_lock)
+ list_add(&node->link, ®map_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(®map_debugfs_early_lock);
- list_for_each_entry_safe(node, tmp, ®map_debugfs_early_list,
- link) {
+ return;
+ }
+
+ scoped_guard(mutex, ®map_debugfs_early_lock) {
+ list_for_each_entry_safe(node, tmp, ®map_debugfs_early_list, link) {
if (node->map == map) {
list_del(&node->link);
kfree(node);
}
}
- mutex_unlock(®map_debugfs_early_lock);
}
}
@@ -685,11 +681,10 @@ void regmap_debugfs_initcall(void)
regmap_debugfs_root = debugfs_create_dir("regmap", NULL);
- mutex_lock(®map_debugfs_early_lock);
+ guard(mutex)(®map_debugfs_early_lock);
list_for_each_entry_safe(node, tmp, ®map_debugfs_early_list, link) {
regmap_debugfs_init(node->map);
list_del(&node->link);
kfree(node);
}
- mutex_unlock(®map_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®