From 75bc0cc55c2c563a0585846e5e8fe244de186580 Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Mon, 13 Feb 2017 10:14:30 -0700 Subject: drm/msm: Reference count address spaces 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. Change-Id: Ic0dedbad3769801b62152d81b37f2f43f962d308 Signed-off-by: Jordan Crouse --- drivers/gpu/drm/msm/adreno/adreno_gpu.c | 2 +- drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c | 2 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | 2 +- drivers/gpu/drm/msm/msm_drv.c | 2 +- drivers/gpu/drm/msm/msm_drv.h | 2 +- drivers/gpu/drm/msm/msm_gem.h | 2 ++ drivers/gpu/drm/msm/msm_gem_vma.c | 41 +++++++++++++++++++++++++-------- drivers/gpu/drm/msm/sde/sde_kms.c | 4 ++-- 8 files changed, 41 insertions(+), 16 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index 6600c62288d5..337ed53b7bc8 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -626,6 +626,6 @@ void adreno_gpu_cleanup(struct adreno_gpu *gpu) if (aspace) { aspace->mmu->funcs->detach(aspace->mmu); - msm_gem_address_space_destroy(aspace); + msm_gem_address_space_put(aspace); } } diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c index da9d58eccc3a..b6cddee0cf34 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c @@ -204,7 +204,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); } kfree(mdp4_kms); diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c index 2e5754bd8280..e4e69ebd116e 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c @@ -137,7 +137,7 @@ static void mdp5_destroy(struct msm_kms *kms) if (aspace) { aspace->mmu->funcs->detach(aspace->mmu); - msm_gem_address_space_destroy(aspace); + msm_gem_address_space_put(aspace); } if (mdp5_kms->ctlm) diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index bc014c547908..4d39eb439793 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -637,7 +637,7 @@ static void msm_postclose(struct drm_device *dev, struct drm_file *file) mutex_lock(&dev->struct_mutex); if (ctx && ctx->aspace && ctx->aspace != priv->gpu->aspace) { ctx->aspace->mmu->funcs->detach(ctx->aspace->mmu); - msm_gem_address_space_destroy(ctx->aspace); + msm_gem_address_space_put(ctx->aspace); } mutex_unlock(&dev->struct_mutex); diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index fe32ea1d4e00..0a06c1cb27a4 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -405,7 +405,7 @@ int msm_gem_map_vma(struct msm_gem_address_space *aspace, struct msm_gem_vma *vma, struct sg_table *sgt, void *priv, unsigned int flags); -void msm_gem_address_space_destroy(struct msm_gem_address_space *aspace); +void msm_gem_address_space_put(struct msm_gem_address_space *aspace); /* For GPU and legacy display */ struct msm_gem_address_space * diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h index e70e8833b30c..ac46c473791f 100644 --- a/drivers/gpu/drm/msm/msm_gem.h +++ b/drivers/gpu/drm/msm/msm_gem.h @@ -18,6 +18,7 @@ #ifndef __MSM_GEM_H__ #define __MSM_GEM_H__ +#include #include #include "msm_drv.h" @@ -38,6 +39,7 @@ struct msm_gem_address_space { const char *name; struct msm_mmu *mmu; const struct msm_gem_aspace_ops *ops; + struct kref kref; }; struct msm_gem_vma { diff --git a/drivers/gpu/drm/msm/msm_gem_vma.c b/drivers/gpu/drm/msm/msm_gem_vma.c index 2baa5a3e6ce4..7ca96831a9b3 100644 --- a/drivers/gpu/drm/msm/msm_gem_vma.c +++ b/drivers/gpu/drm/msm/msm_gem_vma.c @@ -19,6 +19,24 @@ #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); + + if (aspace->ops->destroy) + aspace->ops->destroy(aspace); + + 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); +} + /* SDE address space operations */ static void smmu_aspace_unmap_vma(struct msm_gem_address_space *aspace, struct msm_gem_vma *vma, struct sg_table *sgt, @@ -34,6 +52,8 @@ static void smmu_aspace_unmap_vma(struct msm_gem_address_space *aspace, DMA_BIDIRECTIONAL); vma->iova = 0; + + msm_gem_address_space_put(aspace); } @@ -54,6 +74,9 @@ static int smmu_aspace_map_vma(struct msm_gem_address_space *aspace, if (!ret) vma->iova = sg_dma_address(sgt->sgl); + /* Get a reference to the aspace to keep it around */ + kref_get(&aspace->kref); + return ret; } @@ -79,6 +102,8 @@ msm_gem_smmu_address_space_create(struct device *dev, struct msm_mmu *mmu, aspace->mmu = mmu; aspace->ops = &smmu_aspace_ops; + kref_init(&aspace->kref); + return aspace; } @@ -104,6 +129,8 @@ static void iommu_aspace_unmap_vma(struct msm_gem_address_space *aspace, drm_mm_remove_node(&vma->node); vma->iova = 0; + + msm_gem_address_space_put(aspace); } static int iommu_aspace_map_vma(struct msm_gem_address_space *aspace, @@ -139,6 +166,9 @@ static int iommu_aspace_map_vma(struct msm_gem_address_space *aspace, ret = aspace->mmu->funcs->map(aspace->mmu, vma->iova, sgt, iommu_flags); + /* Get a reference to the aspace to keep it around */ + kref_get(&aspace->kref); + return ret; } @@ -176,6 +206,8 @@ msm_gem_address_space_new(struct msm_mmu *mmu, const char *name, local->base.mmu = mmu; local->base.ops = &msm_iommu_aspace_ops; + kref_init(&local->base.kref); + return &local->base; } @@ -210,15 +242,6 @@ msm_gem_address_space_create(struct device *dev, struct iommu_domain *domain, domain->geometry.aperture_end); } -void -msm_gem_address_space_destroy(struct msm_gem_address_space *aspace) -{ - if (aspace && aspace->ops->destroy) - aspace->ops->destroy(aspace); - - kfree(aspace); -} - /* Create a new dynamic instance */ struct msm_gem_address_space * msm_gem_address_space_create_instance(struct msm_mmu *parent, const char *name, diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c index 4907b3233894..576e7d1e7189 100644 --- a/drivers/gpu/drm/msm/sde/sde_kms.c +++ b/drivers/gpu/drm/msm/sde/sde_kms.c @@ -947,7 +947,7 @@ static int _sde_kms_mmu_destroy(struct sde_kms *sde_kms) mmu = sde_kms->aspace[i]->mmu; mmu->funcs->detach(mmu); - msm_gem_address_space_destroy(sde_kms->aspace[i]); + msm_gem_address_space_put(sde_kms->aspace[i]); sde_kms->aspace[i] = NULL; } @@ -986,7 +986,7 @@ static int _sde_kms_mmu_init(struct sde_kms *sde_kms) ARRAY_SIZE(iommu_ports)); if (ret) { SDE_ERROR("failed to attach iommu %d: %d\n", i, ret); - msm_gem_address_space_destroy(aspace); + msm_gem_address_space_put(aspace); goto fail; } -- cgit v1.2.3