diff options
Diffstat (limited to 'drivers/iommu/arm-smmu-v3.c')
| -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);  	}  } |