diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2013-05-07 09:48:30 +1000 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2013-07-01 13:50:31 +1000 |
commit | c4c7044ffc1ba973e2ec0f0dc94980b49101d877 (patch) | |
tree | 936ddc8e8ae3b940079e5577a4ad947a90d58343 /drivers/gpu/drm/nouveau/nouveau_gem.c | |
parent | 780194b1b9f5fdbaa06dd71e60b31ceaaedafbe4 (diff) | |
download | op-kernel-dev-c4c7044ffc1ba973e2ec0f0dc94980b49101d877.zip op-kernel-dev-c4c7044ffc1ba973e2ec0f0dc94980b49101d877.tar.gz |
drm/nouveau: delay busy bo vma removal until fence signals
As opposed to an explicit wait. Allows userspace to not stall waiting
on buffer deletion.
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_gem.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_gem.c | 41 |
1 files changed, 37 insertions, 4 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index b4b4d0c..c0e324b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -101,6 +101,41 @@ out: return ret; } +static void +nouveau_gem_object_delete(void *data) +{ + struct nouveau_vma *vma = data; + nouveau_vm_unmap(vma); + nouveau_vm_put(vma); + kfree(vma); +} + +static void +nouveau_gem_object_unmap(struct nouveau_bo *nvbo, struct nouveau_vma *vma) +{ + const bool mapped = nvbo->bo.mem.mem_type != TTM_PL_SYSTEM; + struct nouveau_fence *fence = NULL; + + list_del(&vma->head); + + if (mapped) { + spin_lock(&nvbo->bo.bdev->fence_lock); + if (nvbo->bo.sync_obj) + fence = nouveau_fence_ref(nvbo->bo.sync_obj); + spin_unlock(&nvbo->bo.bdev->fence_lock); + } + + if (fence) { + nouveau_fence_work(fence, nouveau_gem_object_delete, vma); + } else { + if (mapped) + nouveau_vm_unmap(vma); + nouveau_vm_put(vma); + kfree(vma); + } + nouveau_fence_unref(&fence); +} + void nouveau_gem_object_close(struct drm_gem_object *gem, struct drm_file *file_priv) { @@ -118,10 +153,8 @@ nouveau_gem_object_close(struct drm_gem_object *gem, struct drm_file *file_priv) vma = nouveau_bo_vma_find(nvbo, cli->base.vm); if (vma) { - if (--vma->refcount == 0) { - nouveau_bo_vma_del(nvbo, vma); - kfree(vma); - } + if (--vma->refcount == 0) + nouveau_gem_object_unmap(nvbo, vma); } ttm_bo_unreserve(&nvbo->bo); } |