diff options
author | Marc Zyngier <marc.zyngier@arm.com> | 2018-08-24 11:06:37 -0400 |
---|---|---|
committer | Olof Johansson <olof@lixom.net> | 2018-08-24 11:50:32 -0400 |
commit | 1aa55ca9b14af6cfd987ce4fdaf548f7067a5d07 (patch) | |
tree | befb285272e15e7e782a146ad853667ba7c4fab4 | |
parent | 3fc7c5c0cff3150e471f5fd12f59971c6d2c6513 (diff) |
iommu/rockchip: Move irq request past pm_runtime_enable
Enabling the interrupt early, before power has been applied to the
device, can result in an interrupt being delivered too early if:
- the IOMMU shares an interrupt with a VOP
- the VOP has a pending interrupt (after a kexec, for example)
In these conditions, we end-up taking the interrupt without
the IOMMU being ready to handle the interrupt (not powered on).
Moving the interrupt request past the pm_runtime_enable() call
makes sure we can at least access the IOMMU registers. Note that
this is only a partial fix, and that the VOP interrupt will still
be screaming until the VOP driver kicks in, which advocates for
a more synchronized interrupt enabling/disabling approach.
Fixes: 0f181d3cf7d98 ("iommu/rockchip: Add runtime PM support")
Reviewed-by: Heiko Stuebner <heiko@sntech.de>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Olof Johansson <olof@lixom.net>
-rw-r--r-- | drivers/iommu/rockchip-iommu.c | 24 |
1 files changed, 13 insertions, 11 deletions
diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c index 4e0f9b61cd7f..2b1724e8d307 100644 --- a/drivers/iommu/rockchip-iommu.c +++ b/drivers/iommu/rockchip-iommu.c | |||
@@ -1161,17 +1161,6 @@ static int rk_iommu_probe(struct platform_device *pdev) | |||
1161 | if (iommu->num_mmu == 0) | 1161 | if (iommu->num_mmu == 0) |
1162 | return PTR_ERR(iommu->bases[0]); | 1162 | return PTR_ERR(iommu->bases[0]); |
1163 | 1163 | ||
1164 | i = 0; | ||
1165 | while ((irq = platform_get_irq(pdev, i++)) != -ENXIO) { | ||
1166 | if (irq < 0) | ||
1167 | return irq; | ||
1168 | |||
1169 | err = devm_request_irq(iommu->dev, irq, rk_iommu_irq, | ||
1170 | IRQF_SHARED, dev_name(dev), iommu); | ||
1171 | if (err) | ||
1172 | return err; | ||
1173 | } | ||
1174 | |||
1175 | iommu->reset_disabled = device_property_read_bool(dev, | 1164 | iommu->reset_disabled = device_property_read_bool(dev, |
1176 | "rockchip,disable-mmu-reset"); | 1165 | "rockchip,disable-mmu-reset"); |
1177 | 1166 | ||
@@ -1228,6 +1217,19 @@ static int rk_iommu_probe(struct platform_device *pdev) | |||
1228 | 1217 | ||
1229 | pm_runtime_enable(dev); | 1218 | pm_runtime_enable(dev); |
1230 | 1219 | ||
1220 | i = 0; | ||
1221 | while ((irq = platform_get_irq(pdev, i++)) != -ENXIO) { | ||
1222 | if (irq < 0) | ||
1223 | return irq; | ||
1224 | |||
1225 | err = devm_request_irq(iommu->dev, irq, rk_iommu_irq, | ||
1226 | IRQF_SHARED, dev_name(dev), iommu); | ||
1227 | if (err) { | ||
1228 | pm_runtime_disable(dev); | ||
1229 | goto err_remove_sysfs; | ||
1230 | } | ||
1231 | } | ||
1232 | |||
1231 | return 0; | 1233 | return 0; |
1232 | err_remove_sysfs: | 1234 | err_remove_sysfs: |
1233 | iommu_device_sysfs_remove(&iommu->iommu); | 1235 | iommu_device_sysfs_remove(&iommu->iommu); |