Skip to content

Commit 21a1f19

Browse files
committed
Merge tag 'regmap-fix-v6.17-merge-window' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap
Pull regmap fixes from Mark Brown: "These patches fix a lockdep issue Russell King reported with nested regmap-irqs (unusual since regmap is generally for devices on slow buses so devices don't get nested), plus add a missing mutex free which I noticed while implementing a fix for that issue" * tag 'regmap-fix-v6.17-merge-window' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap: regmap: irq: Avoid lockdep warnings with nested regmap-irq chips regmap: irq: Free the regmap-irq mutex
2 parents 25046d5 + 76b6e14 commit 21a1f19

File tree

1 file changed

+21
-9
lines changed

1 file changed

+21
-9
lines changed

drivers/base/regmap/regmap-irq.c

Lines changed: 21 additions & 9 deletions
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]
@@ -816,7 +823,7 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
816823
d->mask_buf[i],
817824
chip->irq_drv_data);
818825
if (ret)
819-
goto err_alloc;
826+
goto err_mutex;
820827
}
821828

822829
if (chip->mask_base && !chip->handle_mask_sync) {
@@ -827,7 +834,7 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
827834
if (ret) {
828835
dev_err(map->dev, "Failed to set masks in 0x%x: %d\n",
829836
reg, ret);
830-
goto err_alloc;
837+
goto err_mutex;
831838
}
832839
}
833840

@@ -838,7 +845,7 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
838845
if (ret) {
839846
dev_err(map->dev, "Failed to set masks in 0x%x: %d\n",
840847
reg, ret);
841-
goto err_alloc;
848+
goto err_mutex;
842849
}
843850
}
844851

@@ -855,7 +862,7 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
855862
if (ret != 0) {
856863
dev_err(map->dev, "Failed to read IRQ status: %d\n",
857864
ret);
858-
goto err_alloc;
865+
goto err_mutex;
859866
}
860867
}
861868

@@ -879,7 +886,7 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
879886
if (ret != 0) {
880887
dev_err(map->dev, "Failed to ack 0x%x: %d\n",
881888
reg, ret);
882-
goto err_alloc;
889+
goto err_mutex;
883890
}
884891
}
885892
}
@@ -901,7 +908,7 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
901908
if (ret != 0) {
902909
dev_err(map->dev, "Failed to set masks in 0x%x: %d\n",
903910
reg, ret);
904-
goto err_alloc;
911+
goto err_mutex;
905912
}
906913
}
907914
}
@@ -910,15 +917,15 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
910917
if (chip->status_is_level) {
911918
ret = read_irq_data(d);
912919
if (ret < 0)
913-
goto err_alloc;
920+
goto err_mutex;
914921

915922
memcpy(d->prev_status_buf, d->status_buf,
916923
array_size(d->chip->num_regs, sizeof(d->prev_status_buf[0])));
917924
}
918925

919926
ret = regmap_irq_create_domain(fwnode, irq_base, chip, d);
920927
if (ret)
921-
goto err_alloc;
928+
goto err_mutex;
922929

923930
ret = request_threaded_irq(irq, NULL, regmap_irq_thread,
924931
irq_flags | IRQF_ONESHOT,
@@ -935,6 +942,9 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
935942

936943
err_domain:
937944
/* Should really dispose of the domain but... */
945+
err_mutex:
946+
mutex_destroy(&d->lock);
947+
lockdep_unregister_key(&d->lock_key);
938948
err_alloc:
939949
kfree(d->type_buf);
940950
kfree(d->type_buf_def);
@@ -1027,6 +1037,8 @@ void regmap_del_irq_chip(int irq, struct regmap_irq_chip_data *d)
10271037
kfree(d->config_buf[i]);
10281038
kfree(d->config_buf);
10291039
}
1040+
mutex_destroy(&d->lock);
1041+
lockdep_unregister_key(&d->lock_key);
10301042
kfree(d);
10311043
}
10321044
EXPORT_SYMBOL_GPL(regmap_del_irq_chip);

0 commit comments

Comments
 (0)