iommu/sprd: Release dma buffer to avoid memory leak
authorChunyan Zhang <chunyan.zhang@unisoc.com>
Fri, 31 Mar 2023 03:31:23 +0000 (11:31 +0800)
committerJoerg Roedel <jroedel@suse.de>
Fri, 31 Mar 2023 08:12:51 +0000 (10:12 +0200)
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>
drivers/iommu/sprd-iommu.c

index ae94d74b73f46f369b54a15c053305d4aa1f781b..7df1f730c778e7541958642915e65bbc1637057d 100644 (file)
@@ -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)
 {