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

PCI: tegra: Convert struct tegra_msi mask_lock into raw spinlock

The tegra_msi_irq_unmask() function may be called from a PCI driver
request_threaded_irq() function. This triggers kernel/irq/manage.c
__setup_irq() which locks raw spinlock &desc->lock descriptor lock
and with that descriptor lock held, calls tegra_msi_irq_unmask().

Since the &desc->lock descriptor lock is a raw spinlock, and the tegra_msi
.mask_lock is not a raw spinlock, this setup triggers 'BUG: Invalid wait
context' with CONFIG_PROVE_RAW_LOCK_NESTING=y.

Use scoped_guard() to simplify the locking.

Fixes: 2c99e55f7955 ("PCI: tegra: Convert to MSI domains")
Reported-by: Geert Uytterhoeven <geert+renesas@glider.be>
Closes: https://patchwork.kernel.org/project/linux-pci/patch/20250909162707.13927-2-marek.vasut+renesas@mailbox.org/#26574451
Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
Signed-off-by: Manivannan Sadhasivam <mani@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20250922150811.88450-1-marek.vasut+renesas@mailbox.org

authored by

Marek Vasut and committed by
Bjorn Helgaas
26fda92d 4f152338

+13 -14
+13 -14
drivers/pci/controller/pci-tegra.c
··· 14 14 */ 15 15 16 16 #include <linux/clk.h> 17 + #include <linux/cleanup.h> 17 18 #include <linux/debugfs.h> 18 19 #include <linux/delay.h> 19 20 #include <linux/export.h> ··· 271 270 DECLARE_BITMAP(used, INT_PCI_MSI_NR); 272 271 struct irq_domain *domain; 273 272 struct mutex map_lock; 274 - spinlock_t mask_lock; 273 + raw_spinlock_t mask_lock; 275 274 void *virt; 276 275 dma_addr_t phys; 277 276 int irq; ··· 1582 1581 struct tegra_msi *msi = irq_data_get_irq_chip_data(d); 1583 1582 struct tegra_pcie *pcie = msi_to_pcie(msi); 1584 1583 unsigned int index = d->hwirq / 32; 1585 - unsigned long flags; 1586 1584 u32 value; 1587 1585 1588 - spin_lock_irqsave(&msi->mask_lock, flags); 1589 - value = afi_readl(pcie, AFI_MSI_EN_VEC(index)); 1590 - value &= ~BIT(d->hwirq % 32); 1591 - afi_writel(pcie, value, AFI_MSI_EN_VEC(index)); 1592 - spin_unlock_irqrestore(&msi->mask_lock, flags); 1586 + scoped_guard(raw_spinlock_irqsave, &msi->mask_lock) { 1587 + value = afi_readl(pcie, AFI_MSI_EN_VEC(index)); 1588 + value &= ~BIT(d->hwirq % 32); 1589 + afi_writel(pcie, value, AFI_MSI_EN_VEC(index)); 1590 + } 1593 1591 } 1594 1592 1595 1593 static void tegra_msi_irq_unmask(struct irq_data *d) ··· 1596 1596 struct tegra_msi *msi = irq_data_get_irq_chip_data(d); 1597 1597 struct tegra_pcie *pcie = msi_to_pcie(msi); 1598 1598 unsigned int index = d->hwirq / 32; 1599 - unsigned long flags; 1600 1599 u32 value; 1601 1600 1602 - spin_lock_irqsave(&msi->mask_lock, flags); 1603 - value = afi_readl(pcie, AFI_MSI_EN_VEC(index)); 1604 - value |= BIT(d->hwirq % 32); 1605 - afi_writel(pcie, value, AFI_MSI_EN_VEC(index)); 1606 - spin_unlock_irqrestore(&msi->mask_lock, flags); 1601 + scoped_guard(raw_spinlock_irqsave, &msi->mask_lock) { 1602 + value = afi_readl(pcie, AFI_MSI_EN_VEC(index)); 1603 + value |= BIT(d->hwirq % 32); 1604 + afi_writel(pcie, value, AFI_MSI_EN_VEC(index)); 1605 + } 1607 1606 } 1608 1607 1609 1608 static void tegra_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) ··· 1710 1711 int err; 1711 1712 1712 1713 mutex_init(&msi->map_lock); 1713 - spin_lock_init(&msi->mask_lock); 1714 + raw_spin_lock_init(&msi->mask_lock); 1714 1715 1715 1716 if (IS_ENABLED(CONFIG_PCI_MSI)) { 1716 1717 err = tegra_allocate_domains(msi);