[PATCH v3 08/13] iommu/arm-smmu-v3: Disable PRI when no IRQ handler is registered
Nicolin Chen
nicolinc at nvidia.com
Mon Aug 31 17:33:33 PDT 2026
arm_smmu_setup_irqs() has three failure paths that leave the priq without
a handler: a missing priq IRQ line, devm_request_threaded_irq() failure on
the priq IRQ, and devm_request_threaded_irq() failure on the combined IRQ.
Each path warned but kept ARM_SMMU_FEAT_PRI set in smmu->features.
With FEAT_PRI still set, arm_smmu_setup_irqs() enables IRQ_CTRL_PRIQ_IRQEN
against a handler that does not exist, and a later change would then have
arm_smmu_probe_device() call pci_enable_pri() on PCIe endpoints, allowing
them to issue PRI Page Requests that pile up in the priq with no drainer.
Separately, arm_smmu_device_reset() has already enabled CR0_PRIQEN before
it invoked arm_smmu_setup_irqs(), so the hardware queue would stay enabled
regardless of what setup_irqs decides.
Clear ARM_SMMU_FEAT_PRI in all three failure paths, so that subsequent code
treats PRI as unavailable. And disable CR0_PRIQEN after the setup function
returns.
A kdump kernel cannot service page requests: strip FEAT_PRI when detecting
features, so downstream PRI setup is skipped.
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Nicolin Chen <nicolinc at nvidia.com>
---
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index d45d97f356cf0..60f21591de9e8 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -4937,9 +4937,11 @@ static void arm_smmu_setup_unique_irqs(struct arm_smmu_device *smmu)
dev_warn(smmu->dev,
"failed to enable priq irq\n");
smmu->priq.q.irq = 0;
+ smmu->features &= ~ARM_SMMU_FEAT_PRI;
}
} else {
dev_warn(smmu->dev, "no priq irq - PRI will be broken\n");
+ smmu->features &= ~ARM_SMMU_FEAT_PRI;
}
} else {
/* An unrequested IRQ (e.g. set by DT) must not be disabled */
@@ -4974,6 +4976,7 @@ static int arm_smmu_setup_irqs(struct arm_smmu_device *smmu)
if (ret < 0) {
dev_warn(smmu->dev, "failed to enable combined irq\n");
smmu->combined_irq = 0;
+ smmu->features &= ~ARM_SMMU_FEAT_PRI;
}
} else
arm_smmu_setup_unique_irqs(smmu);
@@ -5154,6 +5157,10 @@ static int arm_smmu_device_reset(struct arm_smmu_device *smmu)
return ret;
}
+ /* arm_smmu_setup_irqs() might have unset the ARM_SMMU_FEAT_PRI */
+ if (!(smmu->features & ARM_SMMU_FEAT_PRI))
+ enables &= ~CR0_PRIQEN;
+
if (is_kdump_kernel())
enables &= ~(CR0_EVTQEN | CR0_PRIQEN);
@@ -5295,7 +5302,7 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
}
/* Boolean feature flags */
- if (IS_ENABLED(CONFIG_PCI_PRI) && reg & IDR0_PRI)
+ if (IS_ENABLED(CONFIG_PCI_PRI) && reg & IDR0_PRI && !is_kdump_kernel())
smmu->features |= ARM_SMMU_FEAT_PRI;
if (IS_ENABLED(CONFIG_PCI_ATS) && reg & IDR0_ATS)
--
2.43.0
More information about the linux-arm-kernel
mailing list