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 a0487bdfd6a8..251fe0fac80c 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c @@ -4740,6 +4740,8 @@ static void arm_smmu_disable_action(void *data) { struct arm_smmu_device *smmu = data; + if (smmu->impl_ops && smmu->impl_ops->device_disable) + smmu->impl_ops->device_disable(smmu); arm_smmu_device_disable(smmu); } diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h index c909c9a88538..1c4877ada1ee 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h @@ -871,6 +871,7 @@ struct arm_smmu_strtab_cfg { struct arm_smmu_impl_ops { int (*device_reset)(struct arm_smmu_device *smmu); + void (*device_disable)(struct arm_smmu_device *smmu); void (*device_remove)(struct arm_smmu_device *smmu); int (*init_structures)(struct arm_smmu_device *smmu); struct arm_smmu_cmdq *(*get_secondary_cmdq)( diff --git a/drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c b/drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c index 67be62a6e764..aaf9ce38bd93 100644 --- a/drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c +++ b/drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c @@ -761,8 +761,6 @@ static void tegra241_cmdqv_remove_vintf(struct tegra241_cmdqv *cmdqv, u16 idx) struct tegra241_vintf *vintf = cmdqv->vintfs[idx]; u16 lidx; - tegra241_vintf_hw_deinit(vintf); - /* Remove LVCMDQ resources */ for (lidx = 0; lidx < vintf->cmdqv->num_lvcmdqs_per_vintf; lidx++) if (vintf->lvcmdqs[lidx]) @@ -779,6 +777,17 @@ static void tegra241_cmdqv_remove_vintf(struct tegra241_cmdqv *cmdqv, u16 idx) } } +static void tegra241_cmdqv_hw_disable(struct arm_smmu_device *smmu) +{ + struct tegra241_cmdqv *cmdqv = + container_of(smmu, struct tegra241_cmdqv, smmu); + u16 idx; + + for (idx = 0; idx < cmdqv->num_vintfs; idx++) + if (cmdqv->vintfs[idx]) + tegra241_vintf_hw_deinit(cmdqv->vintfs[idx]); +} + static void tegra241_cmdqv_remove(struct arm_smmu_device *smmu) { struct tegra241_cmdqv *cmdqv = @@ -844,6 +853,7 @@ static struct arm_smmu_impl_ops tegra241_cmdqv_impl_ops = { /* For in-kernel use */ .get_secondary_cmdq = tegra241_cmdqv_get_cmdq, .device_reset = tegra241_cmdqv_hw_reset, + .device_disable = tegra241_cmdqv_hw_disable, .device_remove = tegra241_cmdqv_remove, /* For user-space use */ .hw_info = tegra241_cmdqv_hw_info, @@ -1152,6 +1162,7 @@ static void tegra241_cmdqv_destroy_vintf_user(struct iommufd_viommu *viommu) if (vintf->mmap_offset) iommufd_viommu_destroy_mmap(&vintf->vsmmu.core, vintf->mmap_offset); + tegra241_vintf_hw_deinit(vintf); tegra241_cmdqv_remove_vintf(vintf->cmdqv, vintf->idx); }