Skip to content

Commit d60b49f

Browse files
AngeloGioacchino Del Regnotobhe
authored andcommitted
PCI: mediatek-gen3: Stop acquiring spinlocks in {suspend,resume}_noirq
In mtk_pcie_suspend_noirq() and mtk_pcie_resume_noirq() we are, respectively, disabling and enabling generation of interrupts and then saving and restoring the enabled interrupts register: since we're using noirq PM callbacks, that can be safely done without holding any spin lock. That was noticed because of, and solves, the following issue: <4>[ 74.185982] ======================================================== <4>[ 74.192629] WARNING: possible irq lock inversion dependency detected <4>[ 74.199276] 6.3.0-next-20230428+ torvalds#51 Tainted: G W <4>[ 74.205664] -------------------------------------------------------- <4>[ 74.212309] systemd-sleep/809 just changed the state of lock: <4>[ 74.218347] ffff65a5c34c65a0 (&pcie->irq_lock){+...}-{2:2}, at: mtk_pcie_resume+0x50/0xa8 <4>[ 74.226870] but this lock was taken by another, HARDIRQ-safe lock in the past: <4>[ 74.234389] (&irq_desc_lock_class){-.-.}-{2:2} <4>[ 74.234409] <4>[ 74.234409] <4>[ 74.234409] and interrupts could create inverse lock ordering between them. <4>[ 74.234409] <4>[ 74.251704] <4>[ 74.251704] other info that might help us debug this: <4>[ 74.258785] Possible interrupt unsafe locking scenario: <4>[ 74.258785] <4>[ 74.266126] CPU0 CPU1 <4>[ 74.270942] ---- ---- <4>[ 74.275758] lock(&pcie->irq_lock); <4>[ 74.279627] local_irq_disable(); <4>[ 74.285836] lock(&irq_desc_lock_class); <4>[ 74.292667] lock(&pcie->irq_lock); <4>[ 74.299061] <Interrupt> <4>[ 74.301960] lock(&irq_desc_lock_class); <4>[ 74.306438] <4>[ 74.306438] *** DEADLOCK *** Fixes: d537dc1 ("PCI: mediatek-gen3: Add system PM support") Signed-off-by: AngeloGioacchino Del Regno <[email protected]>
1 parent f56156d commit d60b49f

File tree

1 file changed

+2
-10
lines changed

1 file changed

+2
-10
lines changed

drivers/pci/controller/pcie-mediatek-gen3.c

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -976,8 +976,6 @@ static void mtk_pcie_irq_save(struct mtk_gen3_pcie *pcie)
976976
{
977977
int i;
978978

979-
raw_spin_lock(&pcie->irq_lock);
980-
981979
pcie->saved_irq_state = readl_relaxed(pcie->base + PCIE_INT_ENABLE_REG);
982980

983981
for (i = 0; i < PCIE_MSI_SET_NUM; i++) {
@@ -986,16 +984,12 @@ static void mtk_pcie_irq_save(struct mtk_gen3_pcie *pcie)
986984
msi_set->saved_irq_state = readl_relaxed(msi_set->base +
987985
PCIE_MSI_SET_ENABLE_OFFSET);
988986
}
989-
990-
raw_spin_unlock(&pcie->irq_lock);
991987
}
992988

993989
static void mtk_pcie_irq_restore(struct mtk_gen3_pcie *pcie)
994990
{
995991
int i;
996992

997-
raw_spin_lock(&pcie->irq_lock);
998-
999993
writel_relaxed(pcie->saved_irq_state, pcie->base + PCIE_INT_ENABLE_REG);
1000994

1001995
for (i = 0; i < PCIE_MSI_SET_NUM; i++) {
@@ -1004,8 +998,6 @@ static void mtk_pcie_irq_restore(struct mtk_gen3_pcie *pcie)
1004998
writel_relaxed(msi_set->saved_irq_state,
1005999
msi_set->base + PCIE_MSI_SET_ENABLE_OFFSET);
10061000
}
1007-
1008-
raw_spin_unlock(&pcie->irq_lock);
10091001
}
10101002

10111003
static int mtk_pcie_turn_off_link(struct mtk_gen3_pcie *pcie)
@@ -1070,8 +1062,8 @@ static int mtk_pcie_resume_noirq(struct device *dev)
10701062
}
10711063

10721064
static const struct dev_pm_ops mtk_pcie_pm_ops = {
1073-
NOIRQ_SYSTEM_SLEEP_PM_OPS(mtk_pcie_suspend_noirq,
1074-
mtk_pcie_resume_noirq)
1065+
.suspend_noirq = mtk_pcie_suspend_noirq,
1066+
.resume_noirq = mtk_pcie_resume_noirq,
10751067
};
10761068

10771069
static const struct of_device_id mtk_pcie_of_match[] = {

0 commit comments

Comments
 (0)