mirror of https://gitee.com/openkylin/linux.git
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: 6efb943b86
This commit is contained in:
commit
d287801c49
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -344,6 +344,7 @@ typedef void (*regmap_unlock)(void *);
|
|||
* @ranges: Array of configuration entries for virtual address ranges.
|
||||
* @num_ranges: Number of range configuration entries.
|
||||
* @use_hwlock: Indicate if a hardware spinlock should be used.
|
||||
* @use_raw_spinlock: Indicate if a raw spinlock should be used.
|
||||
* @hwlock_id: Specify the hardware spinlock id.
|
||||
* @hwlock_mode: The hardware spinlock mode, should be HWLOCK_IRQSTATE,
|
||||
* HWLOCK_IRQ or 0.
|
||||
|
@ -403,6 +404,7 @@ struct regmap_config {
|
|||
unsigned int num_ranges;
|
||||
|
||||
bool use_hwlock;
|
||||
bool use_raw_spinlock;
|
||||
unsigned int hwlock_id;
|
||||
unsigned int hwlock_mode;
|
||||
|
||||
|
|
Loading…
Reference in New Issue