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/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.