[PATCH v5 09/15] iommu/arm-smmu-v3: Disable PRI when no IRQ handler is registered
From: Nicolin Chen
Date: Tue Sep 15 2026 - 12:41:10 EST
arm_smmu_setup_irqs() can leave the PRIQ without any registered handler if
its IRQ is missing, its request fails, or the combined IRQ request fails.
These paths warn but leave ARM_SMMU_FEAT_PRI set.
This function itself would then go on to enable IRQ_CTRL_PRIQ_IRQEN, even
though no handler will drain the queue. A later patch also enables PRI on
such endpoints. The caller already enabled CR0_PRIQEN before this function
even runs.
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 doesn't service page requests: strip FEAT_PRI when detecting
features, so downstream PRI setup is skipped.
Reviewed-by: Jonathan Cameron <jonathan.cameron@xxxxxxxxxxxxxxxx>
Assisted-by: LLM
Signed-off-by: Nicolin Chen <nicolinc@xxxxxxxxxx>
---
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 d2a6dc756c783..40ea5bd382d89 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -4944,9 +4944,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 */
@@ -4981,6 +4983,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);
@@ -5161,6 +5164,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);
@@ -5302,7 +5309,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