Skip to content

Commit

Permalink
iommu/arm-smmu-v3: Unregister IOMMU and bus ops on device removal
Browse files Browse the repository at this point in the history
When removing the SMMUv3 driver, we need to clear any state that we
registered during probe. This includes our bus ops, sysfs entries and
the IOMMU device registered for early firmware probing of masters.

Signed-off-by: Will Deacon <will@kernel.org>
Tested-by: John Garry <john.garry@huawei.com> # smmu v3
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Joerg Roedel <jroedel@suse.de>
  • Loading branch information
Will Deacon authored and Joerg Roedel committed Dec 23, 2019
1 parent 34debdc commit ab24677
Showing 1 changed file with 43 additions and 21 deletions.
64 changes: 43 additions & 21 deletions drivers/iommu/arm-smmu-v3.c
Original file line number Diff line number Diff line change
Expand Up @@ -3565,6 +3565,45 @@ static unsigned long arm_smmu_resource_size(struct arm_smmu_device *smmu)
return SZ_128K;
}

static int arm_smmu_set_bus_ops(struct iommu_ops *ops)
{
int err;

#ifdef CONFIG_PCI
if (pci_bus_type.iommu_ops != ops) {
if (ops)
pci_request_acs();
err = bus_set_iommu(&pci_bus_type, ops);
if (err)
return err;
}
#endif
#ifdef CONFIG_ARM_AMBA
if (amba_bustype.iommu_ops != ops) {
err = bus_set_iommu(&amba_bustype, ops);
if (err)
goto err_reset_pci_ops;
}
#endif
if (platform_bus_type.iommu_ops != ops) {
err = bus_set_iommu(&platform_bus_type, ops);
if (err)
goto err_reset_amba_ops;
}

return 0;

err_reset_amba_ops:
#ifdef CONFIG_ARM_AMBA
bus_set_iommu(&amba_bustype, NULL);
#endif
err_reset_pci_ops: __maybe_unused;
#ifdef CONFIG_PCI
bus_set_iommu(&pci_bus_type, NULL);
#endif
return err;
}

static int arm_smmu_device_probe(struct platform_device *pdev)
{
int irq, ret;
Expand Down Expand Up @@ -3655,33 +3694,16 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
return ret;
}

#ifdef CONFIG_PCI
if (pci_bus_type.iommu_ops != &arm_smmu_ops) {
pci_request_acs();
ret = bus_set_iommu(&pci_bus_type, &arm_smmu_ops);
if (ret)
return ret;
}
#endif
#ifdef CONFIG_ARM_AMBA
if (amba_bustype.iommu_ops != &arm_smmu_ops) {
ret = bus_set_iommu(&amba_bustype, &arm_smmu_ops);
if (ret)
return ret;
}
#endif
if (platform_bus_type.iommu_ops != &arm_smmu_ops) {
ret = bus_set_iommu(&platform_bus_type, &arm_smmu_ops);
if (ret)
return ret;
}
return 0;
return arm_smmu_set_bus_ops(&arm_smmu_ops);
}

static int arm_smmu_device_remove(struct platform_device *pdev)
{
struct arm_smmu_device *smmu = platform_get_drvdata(pdev);

arm_smmu_set_bus_ops(NULL);
iommu_device_unregister(&smmu->iommu);
iommu_device_sysfs_remove(&smmu->iommu);
arm_smmu_device_disable(smmu);

return 0;
Expand Down

0 comments on commit ab24677

Please sign in to comment.