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. Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org> Signed-off-by: Rob Clark <robdclark@gmail.com>
This commit is contained in:
parent
9873ef0743
commit
ee546cd34a
|
@ -438,6 +438,6 @@ void adreno_gpu_cleanup(struct adreno_gpu *adreno_gpu)
|
||||||
if (gpu->aspace) {
|
if (gpu->aspace) {
|
||||||
gpu->aspace->mmu->funcs->detach(gpu->aspace->mmu,
|
gpu->aspace->mmu->funcs->detach(gpu->aspace->mmu,
|
||||||
iommu_ports, ARRAY_SIZE(iommu_ports));
|
iommu_ports, ARRAY_SIZE(iommu_ports));
|
||||||
msm_gem_address_space_destroy(gpu->aspace);
|
msm_gem_address_space_put(gpu->aspace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -169,7 +169,7 @@ static void mdp4_destroy(struct msm_kms *kms)
|
||||||
if (aspace) {
|
if (aspace) {
|
||||||
aspace->mmu->funcs->detach(aspace->mmu,
|
aspace->mmu->funcs->detach(aspace->mmu,
|
||||||
iommu_ports, ARRAY_SIZE(iommu_ports));
|
iommu_ports, ARRAY_SIZE(iommu_ports));
|
||||||
msm_gem_address_space_destroy(aspace);
|
msm_gem_address_space_put(aspace);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mdp4_kms->rpm_enabled)
|
if (mdp4_kms->rpm_enabled)
|
||||||
|
|
|
@ -175,7 +175,7 @@ static void mdp5_kms_destroy(struct msm_kms *kms)
|
||||||
if (aspace) {
|
if (aspace) {
|
||||||
aspace->mmu->funcs->detach(aspace->mmu,
|
aspace->mmu->funcs->detach(aspace->mmu,
|
||||||
iommu_ports, ARRAY_SIZE(iommu_ports));
|
iommu_ports, ARRAY_SIZE(iommu_ports));
|
||||||
msm_gem_address_space_destroy(aspace);
|
msm_gem_address_space_put(aspace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
int msm_gem_map_vma(struct msm_gem_address_space *aspace,
|
||||||
struct msm_gem_vma *vma, struct sg_table *sgt, int npages);
|
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 *
|
struct msm_gem_address_space *
|
||||||
msm_gem_address_space_create(struct device *dev, struct iommu_domain *domain,
|
msm_gem_address_space_create(struct device *dev, struct iommu_domain *domain,
|
||||||
const char *name);
|
const char *name);
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#ifndef __MSM_GEM_H__
|
#ifndef __MSM_GEM_H__
|
||||||
#define __MSM_GEM_H__
|
#define __MSM_GEM_H__
|
||||||
|
|
||||||
|
#include <linux/kref.h>
|
||||||
#include <linux/reservation.h>
|
#include <linux/reservation.h>
|
||||||
#include "msm_drv.h"
|
#include "msm_drv.h"
|
||||||
|
|
||||||
|
@ -31,6 +32,7 @@ struct msm_gem_address_space {
|
||||||
*/
|
*/
|
||||||
struct drm_mm mm;
|
struct drm_mm mm;
|
||||||
struct msm_mmu *mmu;
|
struct msm_mmu *mmu;
|
||||||
|
struct kref kref;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct msm_gem_vma {
|
struct msm_gem_vma {
|
||||||
|
|
|
@ -19,6 +19,25 @@
|
||||||
#include "msm_gem.h"
|
#include "msm_gem.h"
|
||||||
#include "msm_mmu.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
|
void
|
||||||
msm_gem_unmap_vma(struct msm_gem_address_space *aspace,
|
msm_gem_unmap_vma(struct msm_gem_address_space *aspace,
|
||||||
struct msm_gem_vma *vma, struct sg_table *sgt)
|
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);
|
drm_mm_remove_node(&vma->node);
|
||||||
|
|
||||||
vma->iova = 0;
|
vma->iova = 0;
|
||||||
|
|
||||||
|
msm_gem_address_space_put(aspace);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -57,16 +78,10 @@ msm_gem_map_vma(struct msm_gem_address_space *aspace,
|
||||||
size, IOMMU_READ | IOMMU_WRITE);
|
size, IOMMU_READ | IOMMU_WRITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
/* Get a reference to the aspace to keep it around */
|
||||||
}
|
kref_get(&aspace->kref);
|
||||||
|
|
||||||
void
|
return ret;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct msm_gem_address_space *
|
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),
|
drm_mm_init(&aspace->mm, (domain->geometry.aperture_start >> PAGE_SHIFT),
|
||||||
(domain->geometry.aperture_end >> PAGE_SHIFT) - 1);
|
(domain->geometry.aperture_end >> PAGE_SHIFT) - 1);
|
||||||
|
|
||||||
|
kref_init(&aspace->kref);
|
||||||
|
|
||||||
return aspace;
|
return aspace;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue