Skip to content

Commit 76b6e14

Browse files
committed
regmap: irq: Avoid lockdep warnings with nested regmap-irq chips
While handling interrupts through regmap-irq we use a mutex to protect the updates we are caching while genirq runs in atomic context. Russell King reported that while running on the nVidia Jetson Xavier NX this generates lockdep warnings since that platform has a regmap-irq for the max77686 RTC which is a child of a max77620 which also uses regmap-irq. [ 46.723127] rtcwake/3984 is trying to acquire lock: [ 46.723235] ffff0000813b2c68 (&d->lock){+.+.}-{4:4}, at: regmap_irq_lock+0x18/0x24 [ 46.723452] but task is already holding lock: [ 46.723556] ffff00008504dc68 (&d->lock){+.+.}-{4:4}, at: regmap_irq_lock+0x18/0x24 This happens because by default lockdep uses a single lockdep class for all mutexes initialised from a single mutex_init() call and is unable to tell that two distinct mutex are being taken and verify that the ordering of operations is safe. This should be a very rare situation since normally anything using regmap-irq will be a leaf interrupt controller due to being on a slow bus like I2C. We can avoid these warnings by providing the lockdep key for the regmap-irq explicitly, allocating one for each chip so that lockdep can distinguish between them. Thanks to Russell for the report and analysis. Reported-by: Russell King (Oracle) <[email protected]> Tested-by: Russell King (Oracle) <[email protected]> Reviewed-by: Russell King (Oracle) <[email protected]> Signed-off-by: Mark Brown <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent 1da3385 commit 76b6e14

File tree

1 file changed

+10
-1
lines changed

1 file changed

+10
-1
lines changed

drivers/base/regmap/regmap-irq.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
struct regmap_irq_chip_data {
2323
struct mutex lock;
24+
struct lock_class_key lock_key;
2425
struct irq_chip irq_chip;
2526

2627
struct regmap *map;
@@ -801,7 +802,13 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
801802
goto err_alloc;
802803
}
803804

804-
mutex_init(&d->lock);
805+
/*
806+
* If one regmap-irq is the parent of another then we'll try
807+
* to lock the child with the parent locked, use an explicit
808+
* lock_key so lockdep can figure out what's going on.
809+
*/
810+
lockdep_register_key(&d->lock_key);
811+
mutex_init_with_key(&d->lock, &d->lock_key);
805812

806813
for (i = 0; i < chip->num_irqs; i++)
807814
d->mask_buf_def[chip->irqs[i].reg_offset / map->reg_stride]
@@ -937,6 +944,7 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
937944
/* Should really dispose of the domain but... */
938945
err_mutex:
939946
mutex_destroy(&d->lock);
947+
lockdep_unregister_key(&d->lock_key);
940948
err_alloc:
941949
kfree(d->type_buf);
942950
kfree(d->type_buf_def);
@@ -1030,6 +1038,7 @@ void regmap_del_irq_chip(int irq, struct regmap_irq_chip_data *d)
10301038
kfree(d->config_buf);
10311039
}
10321040
mutex_destroy(&d->lock);
1041+
lockdep_unregister_key(&d->lock_key);
10331042
kfree(d);
10341043
}
10351044
EXPORT_SYMBOL_GPL(regmap_del_irq_chip);

0 commit comments

Comments
 (0)