diff options
author | Jordan Crouse <jcrouse@codeaurora.org> | 2018-11-07 15:35:51 -0700 |
---|---|---|
committer | Rob Clark <robdclark@gmail.com> | 2018-12-11 13:05:32 -0500 |
commit | 7ad0e8cf6317825d2b7fc52a9000fb16461c2857 (patch) | |
tree | e57b5891e2092e5fd4aa1650c8aecac5a4caff9b /drivers/gpu/drm/msm/msm_gem.c | |
parent | 9fe041f6fdfedd92e15dd81d96475ff04bdf879e (diff) |
drm/msm: Count how many times iova memory is pinned
Add a reference count to track how many times a particular
chunk of iova memory is pinned (mapped) in the iomu and
add msm_gem_unpin_iova to give up references.
It is important to note that msm_gem_unpin_iova replaces
msm_gem_put_iova because the new implicit behavior
that an assigned iova in a given vma is now valid for the
life of the buffer and what we are really focusing on is
the use of that iova.
For now the unmappings are lazy; once the reference counts
go to zero they *COULD* be unmapped dynamically but that
will require an outside force such as a shrinker or
mm_notifiers. For now, we're just focusing on getting
the counting right and setting ourselves up to be ready
for the future.
Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
Diffstat (limited to 'drivers/gpu/drm/msm/msm_gem.c')
-rw-r--r-- | drivers/gpu/drm/msm/msm_gem.c | 43 |
1 files changed, 28 insertions, 15 deletions
diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index 75a1f50f8f57..3d46d931ba67 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -352,7 +352,8 @@ put_iova(struct drm_gem_object *obj) WARN_ON(!mutex_is_locked(&msm_obj->lock)); list_for_each_entry_safe(vma, tmp, &msm_obj->vmas, list) { - msm_gem_unmap_vma(vma->aspace, vma); + msm_gem_purge_vma(vma->aspace, vma); + msm_gem_close_vma(vma->aspace, vma); del_vma(vma); } } @@ -430,7 +431,10 @@ int msm_gem_get_and_pin_iova(struct drm_gem_object *obj, return ret; } -/* Get an iova but don't pin the memory behind it */ +/* + * Get an iova but don't pin it. Doesn't need a put because iovas are currently + * valid for the life of the object + */ int msm_gem_get_iova(struct drm_gem_object *obj, struct msm_gem_address_space *aspace, uint64_t *iova) { @@ -444,7 +448,6 @@ int msm_gem_get_iova(struct drm_gem_object *obj, return ret; } - /* get iova without taking a reference, used in places where you have * already done a 'msm_gem_get_and_pin_iova' or 'msm_gem_get_iova' */ @@ -462,15 +465,24 @@ uint64_t msm_gem_iova(struct drm_gem_object *obj, return vma ? vma->iova : 0; } -void msm_gem_put_iova(struct drm_gem_object *obj, +/* + * Unpin a iova by updating the reference counts. The memory isn't actually + * purged until something else (shrinker, mm_notifier, destroy, etc) decides + * to get rid of it + */ +void msm_gem_unpin_iova(struct drm_gem_object *obj, struct msm_gem_address_space *aspace) { - // XXX TODO .. - // NOTE: probably don't need a _locked() version.. we wouldn't - // normally unmap here, but instead just mark that it could be - // unmapped (if the iova refcnt drops to zero), but then later - // if another _get_iova_locked() fails we can start unmapping - // things that are no longer needed.. + struct msm_gem_object *msm_obj = to_msm_bo(obj); + struct msm_gem_vma *vma; + + mutex_lock(&msm_obj->lock); + vma = lookup_vma(obj, aspace); + + if (!WARN_ON(!vma)) + msm_gem_unmap_vma(aspace, vma); + + mutex_unlock(&msm_obj->lock); } int msm_gem_dumb_create(struct drm_file *file, struct drm_device *dev, @@ -786,11 +798,12 @@ void msm_gem_describe(struct drm_gem_object *obj, struct seq_file *m) if (!list_empty(&msm_obj->vmas)) { - seq_puts(m, " vmas:"); + seq_puts(m, " vmas:"); list_for_each_entry(vma, &msm_obj->vmas, list) - seq_printf(m, " [%s: %08llx,%s]", vma->aspace->name, - vma->iova, vma->mapped ? "mapped" : "unmapped"); + seq_printf(m, " [%s: %08llx,%s,inuse=%d]", vma->aspace->name, + vma->iova, vma->mapped ? "mapped" : "unmapped", + vma->inuse); seq_puts(m, "\n"); } @@ -1093,7 +1106,7 @@ static void *_msm_gem_kernel_new(struct drm_device *dev, uint32_t size, vaddr = msm_gem_get_vaddr(obj); if (IS_ERR(vaddr)) { - msm_gem_put_iova(obj, aspace); + msm_gem_unpin_iova(obj, aspace); ret = PTR_ERR(vaddr); goto err; } @@ -1133,7 +1146,7 @@ void msm_gem_kernel_put(struct drm_gem_object *bo, return; msm_gem_put_vaddr(bo); - msm_gem_put_iova(bo, aspace); + msm_gem_unpin_iova(bo, aspace); if (locked) drm_gem_object_put(bo); |