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 {
struct arm_smmu_master {
struct arm_smmu_device *smmu;
struct arm_smmu_strtab_ent ste;
u32 *sids;
unsigned int num_sids;
};
/* 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)
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;
struct arm_smmu_master *master = fwspec->iommu_priv;
struct arm_smmu_device *smmu = master->smmu;
for (i = 0; i < fwspec->num_ids; ++i) {
u32 sid = fwspec->ids[i];
for (i = 0; i < master->num_sids; ++i) {
u32 sid = master->sids[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)
if (master->sids[j] == sid)
break;
if (j < i)
continue;
......@@ -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;
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)
......@@ -1736,7 +1734,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
/* Already attached to a different domain? */
if (ste->assigned)
arm_smmu_detach_dev(dev);
arm_smmu_detach_dev(master);
mutex_lock(&smmu_domain->init_mutex);
......@@ -1770,7 +1768,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
ste->s2_cfg = &smmu_domain->s2_cfg;
}
arm_smmu_install_ste_for_dev(fwspec);
arm_smmu_install_ste_for_dev(master);
out_unlock:
mutex_unlock(&smmu_domain->init_mutex);
return ret;
......@@ -1883,12 +1881,14 @@ static int arm_smmu_add_device(struct device *dev)
return -ENOMEM;
master->smmu = smmu;
master->sids = fwspec->ids;
master->num_sids = fwspec->num_ids;
fwspec->iommu_priv = master;
}
/* Check the SIDs are in range of the SMMU and our stream table */
for (i = 0; i < fwspec->num_ids; i++) {
u32 sid = fwspec->ids[i];
for (i = 0; i < master->num_sids; i++) {
u32 sid = master->sids[i];
if (!arm_smmu_sid_in_range(smmu, sid))
return -ERANGE;
......@@ -1922,7 +1922,7 @@ static void arm_smmu_remove_device(struct device *dev)
master = fwspec->iommu_priv;
smmu = master->smmu;
if (master && master->ste.assigned)
arm_smmu_detach_dev(dev);
arm_smmu_detach_dev(master);
iommu_group_remove_device(dev);
iommu_device_unlink(&smmu->iommu, dev);
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