Commit bcecaee4 authored by Jean-Philippe Brucker's avatar Jean-Philippe Brucker Committed by Will Deacon

iommu/arm-smmu-v3: Store SteamIDs in master

Simplify the attach/detach code a bit by keeping a pointer to the stream
IDs in the master structure. Although not completely obvious here, it does
make the subsequent support for ATS, PRI and PASID a bit simpler.
Signed-off-by: default avatarJean-Philippe Brucker <jean-philippe.brucker@arm.com>
Signed-off-by: default avatarWill Deacon <will.deacon@arm.com>
parent b54f4260
...@@ -594,6 +594,8 @@ struct arm_smmu_device { ...@@ -594,6 +594,8 @@ struct arm_smmu_device {
struct arm_smmu_master { struct arm_smmu_master {
struct arm_smmu_device *smmu; struct arm_smmu_device *smmu;
struct arm_smmu_strtab_ent ste; struct arm_smmu_strtab_ent ste;
u32 *sids;
unsigned int num_sids;
}; };
/* SMMU private data for an IOMMU domain */ /* SMMU private data for an IOMMU domain */
...@@ -1688,19 +1690,18 @@ static __le64 *arm_smmu_get_step_for_sid(struct arm_smmu_device *smmu, u32 sid) ...@@ -1688,19 +1690,18 @@ static __le64 *arm_smmu_get_step_for_sid(struct arm_smmu_device *smmu, u32 sid)
return step; return step;
} }
static void arm_smmu_install_ste_for_dev(struct iommu_fwspec *fwspec) static void arm_smmu_install_ste_for_dev(struct arm_smmu_master *master)
{ {
int i, j; int i, j;
struct arm_smmu_master *master = fwspec->iommu_priv;
struct arm_smmu_device *smmu = master->smmu; struct arm_smmu_device *smmu = master->smmu;
for (i = 0; i < fwspec->num_ids; ++i) { for (i = 0; i < master->num_sids; ++i) {
u32 sid = fwspec->ids[i]; u32 sid = master->sids[i];
__le64 *step = arm_smmu_get_step_for_sid(smmu, sid); __le64 *step = arm_smmu_get_step_for_sid(smmu, sid);
/* Bridged PCI devices may end up with duplicated IDs */ /* Bridged PCI devices may end up with duplicated IDs */
for (j = 0; j < i; j++) for (j = 0; j < i; j++)
if (fwspec->ids[j] == sid) if (master->sids[j] == sid)
break; break;
if (j < i) if (j < i)
continue; continue;
...@@ -1709,13 +1710,10 @@ static void arm_smmu_install_ste_for_dev(struct iommu_fwspec *fwspec) ...@@ -1709,13 +1710,10 @@ static void arm_smmu_install_ste_for_dev(struct iommu_fwspec *fwspec)
} }
} }
static void arm_smmu_detach_dev(struct device *dev) static void arm_smmu_detach_dev(struct arm_smmu_master *master)
{ {
struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
struct arm_smmu_master *master = fwspec->iommu_priv;
master->ste.assigned = false; master->ste.assigned = false;
arm_smmu_install_ste_for_dev(fwspec); arm_smmu_install_ste_for_dev(master);
} }
static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
...@@ -1736,7 +1734,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) ...@@ -1736,7 +1734,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
/* Already attached to a different domain? */ /* Already attached to a different domain? */
if (ste->assigned) if (ste->assigned)
arm_smmu_detach_dev(dev); arm_smmu_detach_dev(master);
mutex_lock(&smmu_domain->init_mutex); mutex_lock(&smmu_domain->init_mutex);
...@@ -1770,7 +1768,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) ...@@ -1770,7 +1768,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
ste->s2_cfg = &smmu_domain->s2_cfg; ste->s2_cfg = &smmu_domain->s2_cfg;
} }
arm_smmu_install_ste_for_dev(fwspec); arm_smmu_install_ste_for_dev(master);
out_unlock: out_unlock:
mutex_unlock(&smmu_domain->init_mutex); mutex_unlock(&smmu_domain->init_mutex);
return ret; return ret;
...@@ -1883,12 +1881,14 @@ static int arm_smmu_add_device(struct device *dev) ...@@ -1883,12 +1881,14 @@ static int arm_smmu_add_device(struct device *dev)
return -ENOMEM; return -ENOMEM;
master->smmu = smmu; master->smmu = smmu;
master->sids = fwspec->ids;
master->num_sids = fwspec->num_ids;
fwspec->iommu_priv = master; fwspec->iommu_priv = master;
} }
/* Check the SIDs are in range of the SMMU and our stream table */ /* Check the SIDs are in range of the SMMU and our stream table */
for (i = 0; i < fwspec->num_ids; i++) { for (i = 0; i < master->num_sids; i++) {
u32 sid = fwspec->ids[i]; u32 sid = master->sids[i];
if (!arm_smmu_sid_in_range(smmu, sid)) if (!arm_smmu_sid_in_range(smmu, sid))
return -ERANGE; return -ERANGE;
...@@ -1922,7 +1922,7 @@ static void arm_smmu_remove_device(struct device *dev) ...@@ -1922,7 +1922,7 @@ static void arm_smmu_remove_device(struct device *dev)
master = fwspec->iommu_priv; master = fwspec->iommu_priv;
smmu = master->smmu; smmu = master->smmu;
if (master && master->ste.assigned) if (master && master->ste.assigned)
arm_smmu_detach_dev(dev); arm_smmu_detach_dev(master);
iommu_group_remove_device(dev); iommu_group_remove_device(dev);
iommu_device_unlink(&smmu->iommu, dev); iommu_device_unlink(&smmu->iommu, dev);
kfree(master); kfree(master);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment