When request_irq() fails, iommu->irq remains set, so later teardown
attempts to free an IRQ that was never registered.
Release the reserved vector and clear iommu->irq on the failure path.
The failure path was reproduced with an x86_64 kernel under QEMU using a
q35 machine and an Intel IOMMU with interrupt remapping enabled. A
test-only failure injection makes request_irq() return -EBUSY after
dmar_alloc_hwirq() assigns a vector, then attempts to allocate the same
vector again.
On the unfixed kernel, the failed request leaves iommu->irq set and the
second allocation returns -EEXIST. With this change, iommu->irq is cleared
and the second allocation reuses the vector. The failure is deliberately
injected to exercise this error path and is not expected during normal
QEMU operation.
Fixes: 34742db8eaf9 ("iommu/vt-d: Refine the interfaces to create IRQ for DMAR unit")
Cc: stable@vger.kernel.org
Assisted-by: LLM
Signed-off-by: Runyu Xiao <runyu.xiao@seu.edu.cn>
---
drivers/iommu/intel/dmar.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c
index ba675b08c..d479e70c5 100644
--- a/drivers/iommu/intel/dmar.c
+++ b/drivers/iommu/intel/dmar.c
@@ -2098,8 +2098,11 @@ int dmar_set_interrupt(struct intel_iommu *iommu)
}
ret = request_irq(irq, dmar_fault, IRQF_NO_THREAD, iommu->name, iommu);
- if (ret)
+ if (ret) {
pr_err("Can't request irq\n");
+ dmar_free_hwirq(iommu->irq);
+ iommu->irq = 0;
+ }
return ret;
}
--
2.34.1