summaryrefslogtreecommitdiff
path: root/drivers/base
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2021-08-26 13:40:35 +0100
committerMark Brown <broonie@kernel.org>2021-08-26 13:40:35 +0100
commitd287801c497151a44e5577fb3bbab673fe52e7b0 (patch)
tree95aa0c6ea6eb1b3b0894987d140fa0f425430946 /drivers/base
parent29c34975c9391d3ad1fd5dd3c92ba0d41afe9549 (diff)
parent67021f25d95292d285dd213c58401642b98eaf24 (diff)
Merge series "Use raw spinlocks in the ls-extirq driver" from Vladimir Oltean <vladimir.oltean@nxp.com>:
The ls-extirq irqchip driver accesses regmap inside its implementation of the struct irq_chip :: irq_set_type method, and currently regmap only knows to lock using normal spinlocks. But the method above wants raw spinlock context, so this isn't going to work and triggers a "[ BUG: Invalid wait context ]" splat. The best we can do given the arrangement of the code is to patch regmap and the syscon driver: regmap to support raw spinlocks, and syscon to request them on behalf of its ls-extirq consumer. Link: https://lore.kernel.org/lkml/20210825135438.ubcuxm5vctt6ne2q@skbuf/T/#u Vladimir Oltean (2): regmap: teach regmap to use raw spinlocks if requested in the config mfd: syscon: request a regmap with raw spinlocks for some devices drivers/base/regmap/internal.h | 4 ++++ drivers/base/regmap/regmap.c | 35 +++++++++++++++++++++++++++++----- drivers/mfd/syscon.c | 16 ++++++++++++++++ include/linux/regmap.h | 2 ++ 4 files changed, 52 insertions(+), 5 deletions(-) -- 2.25.1 base-commit: 6efb943b8616ec53a5e444193dccf1af9ad627b5
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/regmap/internal.h4
-rw-r--r--drivers/base/regmap/regmap.c35
2 files changed, 34 insertions, 5 deletions
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
index 0097696c31de..b1905916f7af 100644
--- a/drivers/base/regmap/internal.h
+++ b/drivers/base/regmap/internal.h
@@ -53,6 +53,10 @@ struct regmap {
spinlock_t spinlock;
unsigned long spinlock_flags;
};
+ struct {
+ raw_spinlock_t raw_spinlock;
+ unsigned long raw_spinlock_flags;
+ };
};
regmap_lock lock;
regmap_unlock unlock;
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 6ad41d0720ba..21a0c2562ec0 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -533,6 +533,23 @@ __releases(&map->spinlock)
spin_unlock_irqrestore(&map->spinlock, map->spinlock_flags);
}
+static void regmap_lock_raw_spinlock(void *__map)
+__acquires(&map->raw_spinlock)
+{
+ struct regmap *map = __map;
+ unsigned long flags;
+
+ raw_spin_lock_irqsave(&map->raw_spinlock, flags);
+ map->raw_spinlock_flags = flags;
+}
+
+static void regmap_unlock_raw_spinlock(void *__map)
+__releases(&map->raw_spinlock)
+{
+ struct regmap *map = __map;
+ raw_spin_unlock_irqrestore(&map->raw_spinlock, map->raw_spinlock_flags);
+}
+
static void dev_get_regmap_release(struct device *dev, void *res)
{
/*
@@ -770,11 +787,19 @@ struct regmap *__regmap_init(struct device *dev,
} else {
if ((bus && bus->fast_io) ||
config->fast_io) {
- spin_lock_init(&map->spinlock);
- map->lock = regmap_lock_spinlock;
- map->unlock = regmap_unlock_spinlock;
- lockdep_set_class_and_name(&map->spinlock,
- lock_key, lock_name);
+ if (config->use_raw_spinlock) {
+ raw_spin_lock_init(&map->raw_spinlock);
+ map->lock = regmap_lock_raw_spinlock;
+ map->unlock = regmap_unlock_raw_spinlock;
+ lockdep_set_class_and_name(&map->raw_spinlock,
+ lock_key, lock_name);
+ } else {
+ spin_lock_init(&map->spinlock);
+ map->lock = regmap_lock_spinlock;
+ map->unlock = regmap_unlock_spinlock;
+ lockdep_set_class_and_name(&map->spinlock,
+ lock_key, lock_name);
+ }
} else {
mutex_init(&map->mutex);
map->lock = regmap_lock_mutex;