Commit fd714986 authored by Nicolin Chen's avatar Nicolin Chen Committed by Joerg Roedel
Browse files

iommu: Pass in old domain to attach_dev callback functions



The IOMMU core attaches each device to a default domain on probe(). Then,
every new "attach" operation has a fundamental meaning of two-fold:
 - detach from its currently attached (old) domain
 - attach to a given new domain

Modern IOMMU drivers following this pattern usually want to clean up the
things related to the old domain, so they call iommu_get_domain_for_dev()
to fetch the old domain.

Pass in the old domain pointer from the core to drivers, aligning with the
set_dev_pasid op that does so already.

Ensure all low-level attach fcuntions in the core can forward the correct
old domain pointer. Thus, rework those functions as well.

Suggested-by: default avatarJason Gunthorpe <jgg@nvidia.com>
Reviewed-by: default avatarKevin Tian <kevin.tian@intel.com>
Reviewed-by: default avatarJason Gunthorpe <jgg@nvidia.com>
Signed-off-by: default avatarNicolin Chen <nicolinc@nvidia.com>
Reviewed-by: default avatarLu Baolu <baolu.lu@linux.intel.com>
Signed-off-by: default avatarJoerg Roedel <joerg.roedel@amd.com>
parent 2b33598e
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -1156,7 +1156,8 @@ EXPORT_SYMBOL_GPL(iommu_add_device);
 */
static int
spapr_tce_platform_iommu_attach_dev(struct iommu_domain *platform_domain,
				    struct device *dev)
				    struct device *dev,
				    struct iommu_domain *old)
{
	struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
	struct iommu_table_group *table_group;
@@ -1189,7 +1190,7 @@ static struct iommu_domain spapr_tce_platform_domain = {

static int
spapr_tce_blocked_iommu_attach_dev(struct iommu_domain *platform_domain,
				     struct device *dev)
				   struct device *dev, struct iommu_domain *old)
{
	struct iommu_group *grp = iommu_group_get(dev);
	struct iommu_table_group *table_group;
+6 −5
Original line number Diff line number Diff line
@@ -70,8 +70,8 @@ int amd_iommu_max_glx_val = -1;
 */
DEFINE_IDA(pdom_ids);

static int amd_iommu_attach_device(struct iommu_domain *dom,
				   struct device *dev);
static int amd_iommu_attach_device(struct iommu_domain *dom, struct device *dev,
				   struct iommu_domain *old);

static void set_dte_entry(struct amd_iommu *iommu,
			  struct iommu_dev_data *dev_data);
@@ -2635,7 +2635,8 @@ void amd_iommu_domain_free(struct iommu_domain *dom)
}

static int blocked_domain_attach_device(struct iommu_domain *domain,
					struct device *dev)
					struct device *dev,
					struct iommu_domain *old)
{
	struct iommu_dev_data *dev_data = dev_iommu_priv_get(dev);

@@ -2685,8 +2686,8 @@ void amd_iommu_init_identity_domain(void)
	protection_domain_init(&identity_domain);
}

static int amd_iommu_attach_device(struct iommu_domain *dom,
				   struct device *dev)
static int amd_iommu_attach_device(struct iommu_domain *dom, struct device *dev,
				   struct iommu_domain *old)
{
	struct iommu_dev_data *dev_data = dev_iommu_priv_get(dev);
	struct protection_domain *domain = to_pdomain(dom);
+6 −3
Original line number Diff line number Diff line
@@ -672,7 +672,8 @@ static int apple_dart_domain_add_streams(struct apple_dart_domain *domain,
}

static int apple_dart_attach_dev_paging(struct iommu_domain *domain,
					struct device *dev)
					struct device *dev,
					struct iommu_domain *old)
{
	int ret, i;
	struct apple_dart_stream_map *stream_map;
@@ -693,7 +694,8 @@ static int apple_dart_attach_dev_paging(struct iommu_domain *domain,
}

static int apple_dart_attach_dev_identity(struct iommu_domain *domain,
					  struct device *dev)
					  struct device *dev,
					  struct iommu_domain *old)
{
	struct apple_dart_master_cfg *cfg = dev_iommu_priv_get(dev);
	struct apple_dart_stream_map *stream_map;
@@ -717,7 +719,8 @@ static struct iommu_domain apple_dart_identity_domain = {
};

static int apple_dart_attach_dev_blocked(struct iommu_domain *domain,
					 struct device *dev)
					 struct device *dev,
					 struct iommu_domain *old)
{
	struct apple_dart_master_cfg *cfg = dev_iommu_priv_get(dev);
	struct apple_dart_stream_map *stream_map;
+3 −2
Original line number Diff line number Diff line
@@ -138,14 +138,15 @@ void arm_smmu_master_clear_vmaster(struct arm_smmu_master *master)
}

static int arm_smmu_attach_dev_nested(struct iommu_domain *domain,
				      struct device *dev)
				      struct device *dev,
				      struct iommu_domain *old_domain)
{
	struct arm_smmu_nested_domain *nested_domain =
		to_smmu_nested_domain(domain);
	struct arm_smmu_master *master = dev_iommu_priv_get(dev);
	struct arm_smmu_attach_state state = {
		.master = master,
		.old_domain = iommu_get_domain_for_dev(dev),
		.old_domain = old_domain,
		.ssid = IOMMU_NO_PASID,
	};
	struct arm_smmu_ste ste;
+15 −9
Original line number Diff line number Diff line
@@ -3002,7 +3002,8 @@ void arm_smmu_attach_commit(struct arm_smmu_attach_state *state)
	master->ats_enabled = state->ats_enabled;
}

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,
			       struct iommu_domain *old_domain)
{
	int ret = 0;
	struct arm_smmu_ste target;
@@ -3010,7 +3011,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
	struct arm_smmu_device *smmu;
	struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
	struct arm_smmu_attach_state state = {
		.old_domain = iommu_get_domain_for_dev(dev),
		.old_domain = old_domain,
		.ssid = IOMMU_NO_PASID,
	};
	struct arm_smmu_master *master;
@@ -3186,7 +3187,7 @@ static int arm_smmu_blocking_set_dev_pasid(struct iommu_domain *new_domain,

	/*
	 * When the last user of the CD table goes away downgrade the STE back
	 * to a non-cd_table one.
	 * to a non-cd_table one, by re-attaching its sid_domain.
	 */
	if (!arm_smmu_ssids_in_use(&master->cd_table)) {
		struct iommu_domain *sid_domain =
@@ -3194,12 +3195,14 @@ static int arm_smmu_blocking_set_dev_pasid(struct iommu_domain *new_domain,

		if (sid_domain->type == IOMMU_DOMAIN_IDENTITY ||
		    sid_domain->type == IOMMU_DOMAIN_BLOCKED)
			sid_domain->ops->attach_dev(sid_domain, dev);
			sid_domain->ops->attach_dev(sid_domain, dev,
						    sid_domain);
	}
	return 0;
}

static void arm_smmu_attach_dev_ste(struct iommu_domain *domain,
				    struct iommu_domain *old_domain,
				    struct device *dev,
				    struct arm_smmu_ste *ste,
				    unsigned int s1dss)
@@ -3207,7 +3210,7 @@ static void arm_smmu_attach_dev_ste(struct iommu_domain *domain,
	struct arm_smmu_master *master = dev_iommu_priv_get(dev);
	struct arm_smmu_attach_state state = {
		.master = master,
		.old_domain = iommu_get_domain_for_dev(dev),
		.old_domain = old_domain,
		.ssid = IOMMU_NO_PASID,
	};

@@ -3248,14 +3251,16 @@ static void arm_smmu_attach_dev_ste(struct iommu_domain *domain,
}

static int arm_smmu_attach_dev_identity(struct iommu_domain *domain,
					struct device *dev)
					struct device *dev,
					struct iommu_domain *old_domain)
{
	struct arm_smmu_ste ste;
	struct arm_smmu_master *master = dev_iommu_priv_get(dev);

	arm_smmu_master_clear_vmaster(master);
	arm_smmu_make_bypass_ste(master->smmu, &ste);
	arm_smmu_attach_dev_ste(domain, dev, &ste, STRTAB_STE_1_S1DSS_BYPASS);
	arm_smmu_attach_dev_ste(domain, old_domain, dev, &ste,
				STRTAB_STE_1_S1DSS_BYPASS);
	return 0;
}

@@ -3269,14 +3274,15 @@ static struct iommu_domain arm_smmu_identity_domain = {
};

static int arm_smmu_attach_dev_blocked(struct iommu_domain *domain,
					struct device *dev)
				       struct device *dev,
				       struct iommu_domain *old_domain)
{
	struct arm_smmu_ste ste;
	struct arm_smmu_master *master = dev_iommu_priv_get(dev);

	arm_smmu_master_clear_vmaster(master);
	arm_smmu_make_abort_ste(&ste);
	arm_smmu_attach_dev_ste(domain, dev, &ste,
	arm_smmu_attach_dev_ste(domain, old_domain, dev, &ste,
				STRTAB_STE_1_S1DSS_TERMINATE);
	return 0;
}
Loading