diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-01-05 16:17:16 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-01-05 16:17:16 -0800 |
commit | 313243aa1a8c6e5ac8749338139d11ede860ae81 (patch) | |
tree | ddfa7df97639353c60a11655ad012a9dc45b01bc /drivers | |
parent | f84d595a5b6e11620a56db6c1cf0988834e6eb5b (diff) | |
parent | 563b5cbe334e9503ab2b234e279d500fc4f76018 (diff) | |
download | linux-stable-313243aa1a8c6e5ac8749338139d11ede860ae81.tar.gz linux-stable-313243aa1a8c6e5ac8749338139d11ede860ae81.tar.bz2 linux-stable-313243aa1a8c6e5ac8749338139d11ede860ae81.zip |
Merge tag 'iommu-v4.15-rc7' of git://github.com/awilliam/linux-vfio
Pull IOMMU fixes from Alex Williamson:
"Fixes via Will Deacon for arm-smmu-v3.
- Fix duplicate Stream ID handling in arm-smmu-v3
- Fix arm-smmu-v3 page table ops double free"
* tag 'iommu-v4.15-rc7' of git://github.com/awilliam/linux-vfio:
iommu/arm-smmu-v3: Cope with duplicated Stream IDs
iommu/arm-smmu-v3: Don't free page table ops twice
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/iommu/arm-smmu-v3.c | 17 |
1 files changed, 13 insertions, 4 deletions
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index f122071688fd..744592d330ca 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -1698,13 +1698,15 @@ static int arm_smmu_domain_finalise(struct iommu_domain *domain) domain->pgsize_bitmap = pgtbl_cfg.pgsize_bitmap; domain->geometry.aperture_end = (1UL << ias) - 1; domain->geometry.force_aperture = true; - smmu_domain->pgtbl_ops = pgtbl_ops; ret = finalise_stage_fn(smmu_domain, &pgtbl_cfg); - if (ret < 0) + if (ret < 0) { free_io_pgtable_ops(pgtbl_ops); + return ret; + } - return ret; + smmu_domain->pgtbl_ops = pgtbl_ops; + return 0; } static __le64 *arm_smmu_get_step_for_sid(struct arm_smmu_device *smmu, u32 sid) @@ -1731,7 +1733,7 @@ static __le64 *arm_smmu_get_step_for_sid(struct arm_smmu_device *smmu, u32 sid) static void arm_smmu_install_ste_for_dev(struct iommu_fwspec *fwspec) { - int i; + int i, j; struct arm_smmu_master_data *master = fwspec->iommu_priv; struct arm_smmu_device *smmu = master->smmu; @@ -1739,6 +1741,13 @@ static void arm_smmu_install_ste_for_dev(struct iommu_fwspec *fwspec) u32 sid = fwspec->ids[i]; __le64 *step = arm_smmu_get_step_for_sid(smmu, sid); + /* Bridged PCI devices may end up with duplicated IDs */ + for (j = 0; j < i; j++) + if (fwspec->ids[j] == sid) + break; + if (j < i) + continue; + arm_smmu_write_strtab_ent(smmu, sid, step, &master->ste); } } |