summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bo.c10
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drv.h1
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_gem.c42
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_vm.h1
4 files changed, 43 insertions, 11 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
index 49af4072c0f6..890d50e4d682 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -49,7 +49,6 @@ nouveau_bo_del_ttm(struct ttm_buffer_object *bo)
DRM_ERROR("bo %p still attached to GEM object\n", bo);
nv10_mem_put_tile_region(dev, nvbo->tile, NULL);
- nouveau_bo_vma_del(nvbo, &nvbo->vma);
kfree(nvbo);
}
@@ -115,14 +114,6 @@ nouveau_bo_new(struct drm_device *dev, int size, int align,
nvbo->bo.mem.num_pages = size >> PAGE_SHIFT;
nouveau_bo_placement_set(nvbo, flags, 0);
- if (dev_priv->chan_vm) {
- ret = nouveau_bo_vma_add(nvbo, dev_priv->chan_vm, &nvbo->vma);
- if (ret) {
- kfree(nvbo);
- return ret;
- }
- }
-
ret = ttm_bo_init(&dev_priv->ttm.bdev, &nvbo->bo, size,
ttm_bo_type_device, &nvbo->placement,
align >> PAGE_SHIFT, 0, false, NULL, size,
@@ -1103,6 +1094,7 @@ nouveau_bo_vma_add(struct nouveau_bo *nvbo, struct nouveau_vm *vm,
nouveau_vm_map_sg(vma, 0, size, node, node->pages);
list_add_tail(&vma->head, &nvbo->vma_list);
+ vma->refcount = 1;
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
index bdb682d613d3..bbea0452dca7 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -115,7 +115,6 @@ struct nouveau_bo {
struct nouveau_channel *channel;
- struct nouveau_vma vma;
struct list_head vma_list;
unsigned page_shift;
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c
index 3e1c7010e076..022393777805 100644
--- a/drivers/gpu/drm/nouveau/nouveau_gem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
@@ -63,20 +63,60 @@ int
nouveau_gem_object_open(struct drm_gem_object *gem, struct drm_file *file_priv)
{
struct nouveau_fpriv *fpriv = nouveau_fpriv(file_priv);
+ struct nouveau_bo *nvbo = nouveau_gem_object(gem);
+ struct nouveau_vma *vma;
+ int ret;
if (!fpriv->vm)
return 0;
- return 0;
+ ret = ttm_bo_reserve(&nvbo->bo, false, false, false, 0);
+ if (ret)
+ return ret;
+
+ vma = nouveau_bo_vma_find(nvbo, fpriv->vm);
+ if (!vma) {
+ vma = kzalloc(sizeof(*vma), GFP_KERNEL);
+ if (!vma) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ret = nouveau_bo_vma_add(nvbo, fpriv->vm, vma);
+ if (ret) {
+ kfree(vma);
+ goto out;
+ }
+ } else {
+ vma->refcount++;
+ }
+
+out:
+ ttm_bo_unreserve(&nvbo->bo);
+ return ret;
}
void
nouveau_gem_object_close(struct drm_gem_object *gem, struct drm_file *file_priv)
{
struct nouveau_fpriv *fpriv = nouveau_fpriv(file_priv);
+ struct nouveau_bo *nvbo = nouveau_gem_object(gem);
+ struct nouveau_vma *vma;
+ int ret;
if (!fpriv->vm)
return;
+
+ ret = ttm_bo_reserve(&nvbo->bo, false, false, false, 0);
+ if (ret)
+ return;
+
+ vma = nouveau_bo_vma_find(nvbo, fpriv->vm);
+ if (vma) {
+ if (--vma->refcount == 0)
+ nouveau_bo_vma_del(nvbo, vma);
+ }
+ ttm_bo_unreserve(&nvbo->bo);
}
int
diff --git a/drivers/gpu/drm/nouveau/nouveau_vm.h b/drivers/gpu/drm/nouveau/nouveau_vm.h
index 07d07ff9e28b..579ca8cc223c 100644
--- a/drivers/gpu/drm/nouveau/nouveau_vm.h
+++ b/drivers/gpu/drm/nouveau/nouveau_vm.h
@@ -42,6 +42,7 @@ struct nouveau_vm_pgd {
struct nouveau_vma {
struct list_head head;
+ int refcount;
struct nouveau_vm *vm;
struct nouveau_mm_node *node;
u64 offset;
OpenPOWER on IntegriCloud