drm/msm: Reference count address spaces
authorJordan Crouse <jcrouse@codeaurora.org>
Tue, 7 Mar 2017 17:02:52 +0000 (10:02 -0700)
committerRob Clark <robdclark@gmail.com>
Sat, 8 Apr 2017 10:59:36 +0000 (06:59 -0400)
There are reasons for a memory object to outlive the file descriptor
that created it and so the address space that a buffer object is
attached to must also outlive the file descriptor. Reference count
the address space so that it can remain viable until all the objects
have released their addresses.

Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
drivers/gpu/drm/msm/adreno/adreno_gpu.c
drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
drivers/gpu/drm/msm/msm_drv.h
drivers/gpu/drm/msm/msm_gem.h
drivers/gpu/drm/msm/msm_gem_vma.c

index a50f9ba3bafa831b767e7b7418a21be349a73ac8..9a92bcf982b85e6c81b51e5a1c4988ab7ce4e396 100644 (file)
@@ -438,6 +438,6 @@ void adreno_gpu_cleanup(struct adreno_gpu *adreno_gpu)
        if (gpu->aspace) {
                gpu->aspace->mmu->funcs->detach(gpu->aspace->mmu,
                        iommu_ports, ARRAY_SIZE(iommu_ports));
-               msm_gem_address_space_destroy(gpu->aspace);
+               msm_gem_address_space_put(gpu->aspace);
        }
 }
index a4e1206a66a8dfa676661822801fbdd08cbfe431..6295204cabe99d1581581e646ed8b87b62282810 100644 (file)
@@ -169,7 +169,7 @@ static void mdp4_destroy(struct msm_kms *kms)
        if (aspace) {
                aspace->mmu->funcs->detach(aspace->mmu,
                                iommu_ports, ARRAY_SIZE(iommu_ports));
-               msm_gem_address_space_destroy(aspace);
+               msm_gem_address_space_put(aspace);
        }
 
        if (mdp4_kms->rpm_enabled)
index 24f76f48d56c18674cbbe64aca68ef36166fd883..d3d6b4cae1e6c86f1fa461b16dda05d649c1c0e8 100644 (file)
@@ -175,7 +175,7 @@ static void mdp5_kms_destroy(struct msm_kms *kms)
        if (aspace) {
                aspace->mmu->funcs->detach(aspace->mmu,
                                iommu_ports, ARRAY_SIZE(iommu_ports));
-               msm_gem_address_space_destroy(aspace);
+               msm_gem_address_space_put(aspace);
        }
 }
 
index b885c3d5ae4dfb8759ae4a928c32f41f78a91475..28b6f9ba50664509bb44fa2b5704d3bcc86a67af 100644 (file)
@@ -191,7 +191,8 @@ void msm_gem_unmap_vma(struct msm_gem_address_space *aspace,
 int msm_gem_map_vma(struct msm_gem_address_space *aspace,
                struct msm_gem_vma *vma, struct sg_table *sgt, int npages);
 
-void msm_gem_address_space_destroy(struct msm_gem_address_space *aspace);
+void msm_gem_address_space_put(struct msm_gem_address_space *aspace);
+
 struct msm_gem_address_space *
 msm_gem_address_space_create(struct device *dev, struct iommu_domain *domain,
                const char *name);
index 7d529516b3327bc3c77517b2f95e4c42e3b6420b..1b4cf20043ea3367c02a7b711534fbadaa78409f 100644 (file)
@@ -18,6 +18,7 @@
 #ifndef __MSM_GEM_H__
 #define __MSM_GEM_H__
 
+#include <linux/kref.h>
 #include <linux/reservation.h>
 #include "msm_drv.h"
 
@@ -31,6 +32,7 @@ struct msm_gem_address_space {
         */
        struct drm_mm mm;
        struct msm_mmu *mmu;
+       struct kref kref;
 };
 
 struct msm_gem_vma {
index b654eca7636aa0a56eb1f0a1a32f21da9fd1d1c2..f285d7e210db40c62f9858e7b16c4f439f621a00 100644 (file)
 #include "msm_gem.h"
 #include "msm_mmu.h"
 
+static void
+msm_gem_address_space_destroy(struct kref *kref)
+{
+       struct msm_gem_address_space *aspace = container_of(kref,
+                       struct msm_gem_address_space, kref);
+
+       drm_mm_takedown(&aspace->mm);
+       if (aspace->mmu)
+               aspace->mmu->funcs->destroy(aspace->mmu);
+       kfree(aspace);
+}
+
+
+void msm_gem_address_space_put(struct msm_gem_address_space *aspace)
+{
+       if (aspace)
+               kref_put(&aspace->kref, msm_gem_address_space_destroy);
+}
+
 void
 msm_gem_unmap_vma(struct msm_gem_address_space *aspace,
                struct msm_gem_vma *vma, struct sg_table *sgt)
@@ -34,6 +53,8 @@ msm_gem_unmap_vma(struct msm_gem_address_space *aspace,
        drm_mm_remove_node(&vma->node);
 
        vma->iova = 0;
+
+       msm_gem_address_space_put(aspace);
 }
 
 int
@@ -57,16 +78,10 @@ msm_gem_map_vma(struct msm_gem_address_space *aspace,
                                size, IOMMU_READ | IOMMU_WRITE);
        }
 
-       return ret;
-}
+       /* Get a reference to the aspace to keep it around */
+       kref_get(&aspace->kref);
 
-void
-msm_gem_address_space_destroy(struct msm_gem_address_space *aspace)
-{
-       drm_mm_takedown(&aspace->mm);
-       if (aspace->mmu)
-               aspace->mmu->funcs->destroy(aspace->mmu);
-       kfree(aspace);
+       return ret;
 }
 
 struct msm_gem_address_space *
@@ -85,5 +100,7 @@ msm_gem_address_space_create(struct device *dev, struct iommu_domain *domain,
        drm_mm_init(&aspace->mm, (domain->geometry.aperture_start >> PAGE_SHIFT),
                        (domain->geometry.aperture_end >> PAGE_SHIFT) - 1);
 
+       kref_init(&aspace->kref);
+
        return aspace;
 }