Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

regmap: irq: Set lockdep class for hierarchical IRQ domains

Lockdep gives a false positive splat as it can't distinguish the lock
which is taken by different IRQ descriptors from different IRQ chips
that are organized in a way of a hierarchy:

======================================================
WARNING: possible circular locking dependency detected
6.12.0-rc5-next-20241101-00148-g9fabf8160b53 #562 Tainted: G W
------------------------------------------------------
modprobe/141 is trying to acquire lock:
ffff899446947868 (intel_soc_pmic_bxtwc:502:(&bxtwc_regmap_config)->lock){+.+.}-{4:4}, at: regmap_update_bits_base+0x33/0x90

but task is already holding lock:
ffff899446947c68 (&d->lock){+.+.}-{4:4}, at: __setup_irq+0x682/0x790

which lock already depends on the new lock.

-> #3 (&d->lock){+.+.}-{4:4}:
-> #2 (&desc->request_mutex){+.+.}-{4:4}:
-> #1 (ipclock){+.+.}-{4:4}:
-> #0 (intel_soc_pmic_bxtwc:502:(&bxtwc_regmap_config)->lock){+.+.}-{4:4}:

Chain exists of:
intel_soc_pmic_bxtwc:502:(&bxtwc_regmap_config)->lock --> &desc->request_mutex --> &d->lock

Possible unsafe locking scenario:

CPU0 CPU1
---- ----
lock(&d->lock);
lock(&desc->request_mutex);
lock(&d->lock);
lock(intel_soc_pmic_bxtwc:502:(&bxtwc_regmap_config)->lock);

*** DEADLOCK ***

3 locks held by modprobe/141:
#0: ffff8994419368f8 (&dev->mutex){....}-{4:4}, at: __driver_attach+0xf6/0x250
#1: ffff89944690b250 (&desc->request_mutex){+.+.}-{4:4}, at: __setup_irq+0x1a2/0x790
#2: ffff899446947c68 (&d->lock){+.+.}-{4:4}, at: __setup_irq+0x682/0x790

Set a lockdep class when we map the IRQ so that it doesn't warn about
a lockdep bug that doesn't exist.

Fixes: 4af8be67fd99 ("regmap: Convert regmap_irq to use irq_domain")
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Link: https://patch.msgid.link/20241101165553.4055617-1-andriy.shevchenko@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Andy Shevchenko and committed by
Mark Brown
953e5494 1ed9b927

+4
+4
drivers/base/regmap/regmap-irq.c
··· 511 511 return IRQ_NONE; 512 512 } 513 513 514 + static struct lock_class_key regmap_irq_lock_class; 515 + static struct lock_class_key regmap_irq_request_class; 516 + 514 517 static int regmap_irq_map(struct irq_domain *h, unsigned int virq, 515 518 irq_hw_number_t hw) 516 519 { 517 520 struct regmap_irq_chip_data *data = h->host_data; 518 521 519 522 irq_set_chip_data(virq, data); 523 + irq_set_lockdep_class(virq, &regmap_irq_lock_class, &regmap_irq_request_class); 520 524 irq_set_chip(virq, &data->irq_chip); 521 525 irq_set_nested_thread(virq, 1); 522 526 irq_set_parent(virq, data->irq);