Message ID | 20180108195809.GA30493@xps13.dannf |
---|---|
State | New |
Headers | show |
Series | [Bionic] iommu/arm-smmu-v3: Cope with duplicated Stream IDs | expand |
On Mon, Jan 08, 2018 at 12:58:09PM -0700, dann frazier wrote: > From: Robin Murphy <robin.murphy@arm.com> > > BugLink: https://bugs.launchpad.net/bugs/1741975 > > For PCI devices behind an aliasing PCIe-to-PCI/X bridge, the bridge > alias to DevFn 0.0 on the subordinate bus may match the original RID of > the device, resulting in the same SID being present in the device's > fwspec twice. This causes trouble later in arm_smmu_write_strtab_ent() > when we wind up visiting the STE a second time and find it already live. > > Avoid the issue by giving arm_smmu_install_ste_for_dev() the cleverness > to skip over duplicates. It seems mildly counterintuitive compared to > preventing the duplicates from existing in the first place, but since > the DT and ACPI probe paths build their fwspecs differently, this is > actually the cleanest and most self-contained way to deal with it. > > Cc: <stable@vger.kernel.org> > Fixes: 8f78515425da ("iommu/arm-smmu: Implement of_xlate() for SMMUv3") > Reported-by: Tomasz Nowicki <tomasz.nowicki@caviumnetworks.com> > Tested-by: Tomasz Nowicki <Tomasz.Nowicki@cavium.com> > Tested-by: Jayachandran C. <jnair@caviumnetworks.com> > Signed-off-by: Robin Murphy <robin.murphy@arm.com> > Signed-off-by: Will Deacon <will.deacon@arm.com> > (cherry picked from commit 563b5cbe334e9503ab2b234e279d500fc4f76018) > Signed-off-by: dann frazier <dann.frazier@canonical.com> Not a nak on the merits of the patch, however bionic already got this patch from upstream stable so this patch is not needed.
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index e67ba6c40faf..d2e17d3396a2 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -1644,7 +1644,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; @@ -1652,6 +1652,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); } }