summaryrefslogtreecommitdiffstats
path: root/drivers/iommu/sprd-iommu.c
diff options
context:
space:
mode:
authorChunyan Zhang <chunyan.zhang@unisoc.com>2023-03-31 11:31:23 +0800
committerJoerg Roedel <jroedel@suse.de>2023-03-31 10:12:51 +0200
commit9afea57384d4ae7b2034593eac7fa76c7122762a (patch)
tree5bd711826f720f3086f673599e47c7b690767d74 /drivers/iommu/sprd-iommu.c
parente8d018dd0257f744ca50a729e3d042cf2ec9da65 (diff)
downloadlinux-9afea57384d4ae7b2034593eac7fa76c7122762a.tar.gz
linux-9afea57384d4ae7b2034593eac7fa76c7122762a.tar.bz2
linux-9afea57384d4ae7b2034593eac7fa76c7122762a.zip
iommu/sprd: Release dma buffer to avoid memory leak
When attaching to a domain, the driver would alloc a DMA buffer which is used to store address mapping table, and it need to be released when the IOMMU domain is freed. Signed-off-by: Chunyan Zhang <chunyan.zhang@unisoc.com> Link: https://lore.kernel.org/r/20230331033124.864691-2-zhang.lyra@gmail.com Signed-off-by: Joerg Roedel <jroedel@suse.de>
Diffstat (limited to 'drivers/iommu/sprd-iommu.c')
-rw-r--r--drivers/iommu/sprd-iommu.c29
1 files changed, 22 insertions, 7 deletions
diff --git a/drivers/iommu/sprd-iommu.c b/drivers/iommu/sprd-iommu.c
index ae94d74b73f4..7df1f730c778 100644
--- a/drivers/iommu/sprd-iommu.c
+++ b/drivers/iommu/sprd-iommu.c
@@ -151,13 +151,6 @@ static struct iommu_domain *sprd_iommu_domain_alloc(unsigned int domain_type)
return &dom->domain;
}
-static void sprd_iommu_domain_free(struct iommu_domain *domain)
-{
- struct sprd_iommu_domain *dom = to_sprd_domain(domain);
-
- kfree(dom);
-}
-
static void sprd_iommu_first_vpn(struct sprd_iommu_domain *dom)
{
struct sprd_iommu_device *sdev = dom->sdev;
@@ -230,6 +223,28 @@ static void sprd_iommu_hw_en(struct sprd_iommu_device *sdev, bool en)
sprd_iommu_update_bits(sdev, reg_cfg, mask, 0, val);
}
+static void sprd_iommu_cleanup(struct sprd_iommu_domain *dom)
+{
+ size_t pgt_size;
+
+ /* Nothing need to do if the domain hasn't been attached */
+ if (!dom->sdev)
+ return;
+
+ pgt_size = sprd_iommu_pgt_size(&dom->domain);
+ dma_free_coherent(dom->sdev->dev, pgt_size, dom->pgt_va, dom->pgt_pa);
+ dom->sdev = NULL;
+ sprd_iommu_hw_en(dom->sdev, false);
+}
+
+static void sprd_iommu_domain_free(struct iommu_domain *domain)
+{
+ struct sprd_iommu_domain *dom = to_sprd_domain(domain);
+
+ sprd_iommu_cleanup(dom);
+ kfree(dom);
+}
+
static int sprd_iommu_attach_device(struct iommu_domain *domain,
struct device *dev)
{