From: Thierry Reding Date: Thu, 6 Aug 2020 15:54:04 +0000 (+0200) Subject: iommu/tegra-smmu: Prune IOMMU group when it is released X-Git-Url: http://git.maquefel.me/?a=commitdiff_plain;h=1ea5440e36a792d01aae0b22159e0a13b33589fe;p=linux.git 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: Thierry Reding Link: https://lore.kernel.org/r/20200806155404.3936074-4-thierry.reding@gmail.com Signed-off-by: Joerg Roedel --- diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index c439c0929ef8a..2574e716086bc 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -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);