regmap: Remove debugfs before cache teardown

regmap_exit() and regmap_reinit_cache() destroy the register cache before
removing debugfs. A concurrent debugfs cache operation can therefore
access cache state after the backend exit callback starts freeing it.

Remove debugfs before cache teardown, and clear the debugfs pointer after
removal. During cache reinitialization, recreate debugfs only after the
new cache initializes successfully.

Signed-off-by: Michael Reeves <michael.reeves077@gmail.com>
Reviewed-by: Peng Fan <peng.fan@nxp.com>
Link: https://patch.msgid.link/20261006-regcache-lifecycle-submit-v3-1-37bdd82fd47c@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Michael Reeves 2026-10-06 18:03:15 +11:00 committed by Mark Brown
parent 24a19b953e
commit 834035934c
No known key found for this signature in database
GPG Key ID: 2FEF73B0B3D03889
2 changed files with 10 additions and 6 deletions

View File

@ -664,6 +664,7 @@ void regmap_debugfs_exit(struct regmap *map)
{
if (map->debugfs) {
debugfs_remove_recursive(map->debugfs);
map->debugfs = NULL;
mutex_lock(&map->cache_lock);
regmap_debugfs_free_dump_cache(map);
mutex_unlock(&map->cache_lock);

View File

@ -1422,8 +1422,8 @@ int regmap_reinit_cache(struct regmap *map, const struct regmap_config *config)
{
int ret;
regcache_exit(map);
regmap_debugfs_exit(map);
regcache_exit(map);
map->max_register = config->max_register;
map->max_register_is_set = map->max_register ?: config->max_register_is_0;
@ -1440,12 +1440,16 @@ int regmap_reinit_cache(struct regmap *map, const struct regmap_config *config)
if (ret)
return ret;
regmap_debugfs_init(map);
map->cache_bypass = false;
map->cache_only = false;
return regcache_init(map, config);
ret = regcache_init(map, config);
if (ret)
return ret;
regmap_debugfs_init(map);
return 0;
}
EXPORT_SYMBOL_GPL(regmap_reinit_cache);
@ -1459,9 +1463,8 @@ void regmap_exit(struct regmap *map)
struct regmap_async *async;
regmap_detach_dev(map->dev, map);
regcache_exit(map);
regmap_debugfs_exit(map);
regcache_exit(map);
regmap_range_exit(map);
if (map->bus && map->bus->free_context)
map->bus->free_context(map->bus_context);