diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-01-05 19:17:16 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-01-05 19:17:16 -0500 |
commit | 313243aa1a8c6e5ac8749338139d11ede860ae81 (patch) | |
tree | ddfa7df97639353c60a11655ad012a9dc45b01bc | |
parent | f84d595a5b6e11620a56db6c1cf0988834e6eb5b (diff) | |
parent | 563b5cbe334e9503ab2b234e279d500fc4f76018 (diff) |
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
-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) | |||
1698 | domain->pgsize_bitmap = pgtbl_cfg.pgsize_bitmap; | 1698 | domain->pgsize_bitmap = pgtbl_cfg.pgsize_bitmap; |
1699 | domain->geometry.aperture_end = (1UL << ias) - 1; | 1699 | domain->geometry.aperture_end = (1UL << ias) - 1; |
1700 | domain->geometry.force_aperture = true; | 1700 | domain->geometry.force_aperture = true; |
1701 | smmu_domain->pgtbl_ops = pgtbl_ops; | ||
1702 | 1701 | ||
1703 | ret = finalise_stage_fn(smmu_domain, &pgtbl_cfg); | 1702 | ret = finalise_stage_fn(smmu_domain, &pgtbl_cfg); |
1704 | if (ret < 0) | 1703 | if (ret < 0) { |
1705 | free_io_pgtable_ops(pgtbl_ops); | 1704 | free_io_pgtable_ops(pgtbl_ops); |
1705 | return ret; | ||
1706 | } | ||
1706 | 1707 | ||
1707 | return ret; | 1708 | smmu_domain->pgtbl_ops = pgtbl_ops; |
1709 | return 0; | ||
1708 | } | 1710 | } |
1709 | 1711 | ||
1710 | static __le64 *arm_smmu_get_step_for_sid(struct arm_smmu_device *smmu, u32 sid) | 1712 | 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) | |||
1731 | 1733 | ||
1732 | static void arm_smmu_install_ste_for_dev(struct iommu_fwspec *fwspec) | 1734 | static void arm_smmu_install_ste_for_dev(struct iommu_fwspec *fwspec) |
1733 | { | 1735 | { |
1734 | int i; | 1736 | int i, j; |
1735 | struct arm_smmu_master_data *master = fwspec->iommu_priv; | 1737 | struct arm_smmu_master_data *master = fwspec->iommu_priv; |
1736 | struct arm_smmu_device *smmu = master->smmu; | 1738 | struct arm_smmu_device *smmu = master->smmu; |
1737 | 1739 | ||
@@ -1739,6 +1741,13 @@ static void arm_smmu_install_ste_for_dev(struct iommu_fwspec *fwspec) | |||
1739 | u32 sid = fwspec->ids[i]; | 1741 | u32 sid = fwspec->ids[i]; |
1740 | __le64 *step = arm_smmu_get_step_for_sid(smmu, sid); | 1742 | __le64 *step = arm_smmu_get_step_for_sid(smmu, sid); |
1741 | 1743 | ||
1744 | /* Bridged PCI devices may end up with duplicated IDs */ | ||
1745 | for (j = 0; j < i; j++) | ||
1746 | if (fwspec->ids[j] == sid) | ||
1747 | break; | ||
1748 | if (j < i) | ||
1749 | continue; | ||
1750 | |||
1742 | arm_smmu_write_strtab_ent(smmu, sid, step, &master->ste); | 1751 | arm_smmu_write_strtab_ent(smmu, sid, step, &master->ste); |
1743 | } | 1752 | } |
1744 | } | 1753 | } |