diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-10-18 08:36:29 -1000 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-10-18 08:36:29 -1000 |
| commit | 3d679a244e0deb65d31cb02f1d1dcb790fcfcae2 (patch) | |
| tree | 999347cc0270dbcb800ae0242cbd6eb1fac17558 | |
| parent | 72732cbee632b1be22b636813c9be3df55c72bd9 (diff) | |
| parent | d5a821f66047c2effd06147b84775f9b2ce0f4aa (diff) | |
| download | linux-next-3d679a244e0deb65d31cb02f1d1dcb790fcfcae2.tar.gz linux-next-3d679a244e0deb65d31cb02f1d1dcb790fcfcae2.zip | |
Merge tag 'regmap-fix-v7.3-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap
Pull regmap fixes from Mark Brown:
"The main thing here is a fix for lockdep warnings with MMIO regmaps
that use a raw spinlock and a cache, some other lockdep fixes we'd
done for the benefit of the maple tree on sleeping buses meant that we
were doing allocations for those MMIO regmaps under a raw spinlock.
While fixing that Michael Reeves also noticed that the debugfs files
were briefly available without the cache structures backing them.
There's also a fix for interrupt freeing on error in regmap-irq which
had been hanging around because it's not super urgent"
* tag 'regmap-fix-v7.3-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap:
regmap: Drop map lock during cache init and exit
regmap: Remove debugfs before cache teardown
regmap: irq: Free the irqdomain we create
| -rw-r--r-- | drivers/base/regmap/regcache-maple.c | 9 | ||||
| -rw-r--r-- | drivers/base/regmap/regcache.c | 6 | ||||
| -rw-r--r-- | drivers/base/regmap/regmap-debugfs.c | 1 | ||||
| -rw-r--r-- | drivers/base/regmap/regmap-irq.c | 2 | ||||
| -rw-r--r-- | drivers/base/regmap/regmap.c | 15 | ||||
| -rw-r--r-- | include/linux/maple_tree.h | 4 |
6 files changed, 22 insertions, 15 deletions
diff --git a/drivers/base/regmap/regcache-maple.c b/drivers/base/regmap/regcache-maple.c index e46fe5c32b7f..16e488da5f23 100644 --- a/drivers/base/regmap/regcache-maple.c +++ b/drivers/base/regmap/regcache-maple.c @@ -312,16 +312,21 @@ static void regcache_maple_exit(struct regmap *map) struct maple_tree *mt = map->cache; MA_STATE(mas, mt, 0, UINT_MAX); unsigned int *entry; + unsigned long flags; /* if we've already been called then just return */ if (!mt) return; - mas_lock(&mas); + /* + * Register access may take the Maple lock from hard IRQ context, so + * preserve its IRQ-safe lockdep state during teardown. + */ + mas_lock_irqsave(&mas, flags); mas_for_each(&mas, entry, UINT_MAX) kfree(entry); __mt_destroy(mt); - mas_unlock(&mas); + mas_unlock_irqrestore(&mas, flags); kfree(mt); map->cache = NULL; diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c index 0d58d900a2ca..b137ded7fdd4 100644 --- a/drivers/base/regmap/regcache.c +++ b/drivers/base/regmap/regcache.c @@ -225,9 +225,7 @@ int regcache_init(struct regmap *map, const struct regmap_config *config) 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; } @@ -259,9 +257,7 @@ err_free: 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); } err_free_reg_defaults: kfree(map->reg_defaults); @@ -281,9 +277,7 @@ void regcache_exit(struct regmap *map) 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); } kfree(map->reg_defaults); diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c index 18f1c60749fe..9a09df2ba847 100644 --- a/drivers/base/regmap/regmap-debugfs.c +++ b/drivers/base/regmap/regmap-debugfs.c @@ -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); diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c index 99b55b1053ee..715eb9e7aa2a 100644 --- a/drivers/base/regmap/regmap-irq.c +++ b/drivers/base/regmap/regmap-irq.c @@ -963,7 +963,7 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode, return 0; err_domain: - /* Should really dispose of the domain but... */ + irq_domain_remove(d->domain); err_mutex: mutex_destroy(&d->lock); lockdep_unregister_key(&d->lock_key); diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index e6e022b02637..8e50a05ff087 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -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); diff --git a/include/linux/maple_tree.h b/include/linux/maple_tree.h index e595ae5cd0ee..f6491a92ead1 100644 --- a/include/linux/maple_tree.h +++ b/include/linux/maple_tree.h @@ -507,9 +507,13 @@ struct ma_wr_state { }; #define mas_lock(mas) spin_lock(&((mas)->tree->ma_lock)) +#define mas_lock_irqsave(mas, flags) \ + spin_lock_irqsave(&((mas)->tree->ma_lock), flags) #define mas_lock_nested(mas, subclass) \ spin_lock_nested(&((mas)->tree->ma_lock), subclass) #define mas_unlock(mas) spin_unlock(&((mas)->tree->ma_lock)) +#define mas_unlock_irqrestore(mas, flags) \ + spin_unlock_irqrestore(&((mas)->tree->ma_lock), flags) /* * Special values for ma_state.node. |
