Commit 1ea5440e authored by Thierry Reding's avatar Thierry Reding Committed by Joerg Roedel
Browse files

iommu/tegra-smmu: Prune IOMMU group when it is released



In order to share groups between multiple devices we keep track of them
in a per-SMMU list. When an IOMMU group is released, a dangling pointer
to it stays around in that list. Fix this by implementing an IOMMU data
release callback for groups where the dangling pointer can be removed.

Signed-off-by: default avatarThierry Reding <treding@nvidia.com>
Link: https://lore.kernel.org/r/20200806155404.3936074-4-thierry.reding@gmail.com


Signed-off-by: default avatarJoerg Roedel <jroedel@suse.de>
parent 5b30fbfa
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@

struct tegra_smmu_group {
	struct list_head list;
	struct tegra_smmu *smmu;
	const struct tegra_smmu_group_soc *soc;
	struct iommu_group *group;
};
@@ -813,6 +814,16 @@ tegra_smmu_find_group(struct tegra_smmu *smmu, unsigned int swgroup)
	return NULL;
}

static void tegra_smmu_group_release(void *iommu_data)
{
	struct tegra_smmu_group *group = iommu_data;
	struct tegra_smmu *smmu = group->smmu;

	mutex_lock(&smmu->lock);
	list_del(&group->list);
	mutex_unlock(&smmu->lock);
}

static struct iommu_group *tegra_smmu_group_get(struct tegra_smmu *smmu,
						unsigned int swgroup)
{
@@ -840,6 +851,7 @@ static struct iommu_group *tegra_smmu_group_get(struct tegra_smmu *smmu,
	}

	INIT_LIST_HEAD(&group->list);
	group->smmu = smmu;
	group->soc = soc;

	group->group = iommu_group_alloc();
@@ -849,6 +861,7 @@ static struct iommu_group *tegra_smmu_group_get(struct tegra_smmu *smmu,
		return NULL;
	}

	iommu_group_set_iommudata(group->group, group, tegra_smmu_group_release);
	iommu_group_set_name(group->group, soc->name);
	list_add_tail(&group->list, &smmu->groups);
	mutex_unlock(&smmu->lock);