]> rtime.felk.cvut.cz Git - linux-imx.git/blobdiff - drivers/gpu/drm/radeon/radeon_gem.c
drm/radeon: rework the VM code a bit more (v2)
[linux-imx.git] / drivers / gpu / drm / radeon / radeon_gem.c
index 84d045245739eb3b049e78f88693d6dc1dd229da..6579befa51014bee0b3848f7e55b36ba8e425d94 100644 (file)
@@ -124,6 +124,30 @@ void radeon_gem_fini(struct radeon_device *rdev)
  */
 int radeon_gem_object_open(struct drm_gem_object *obj, struct drm_file *file_priv)
 {
+       struct radeon_bo *rbo = gem_to_radeon_bo(obj);
+       struct radeon_device *rdev = rbo->rdev;
+       struct radeon_fpriv *fpriv = file_priv->driver_priv;
+       struct radeon_vm *vm = &fpriv->vm;
+       struct radeon_bo_va *bo_va;
+       int r;
+
+       if (rdev->family < CHIP_CAYMAN) {
+               return 0;
+       }
+
+       r = radeon_bo_reserve(rbo, false);
+       if (r) {
+               return r;
+       }
+
+       bo_va = radeon_vm_bo_find(vm, rbo);
+       if (!bo_va) {
+               bo_va = radeon_vm_bo_add(rdev, vm, rbo);
+       } else {
+               ++bo_va->ref_count;
+       }
+       radeon_bo_unreserve(rbo);
+
        return 0;
 }
 
@@ -134,23 +158,23 @@ void radeon_gem_object_close(struct drm_gem_object *obj,
        struct radeon_device *rdev = rbo->rdev;
        struct radeon_fpriv *fpriv = file_priv->driver_priv;
        struct radeon_vm *vm = &fpriv->vm;
-       struct radeon_bo_va *bo_va, *tmp;
+       struct radeon_bo_va *bo_va;
+       int r;
 
        if (rdev->family < CHIP_CAYMAN) {
                return;
        }
 
-       if (radeon_bo_reserve(rbo, false)) {
+       r = radeon_bo_reserve(rbo, true);
+       if (r) {
+               dev_err(rdev->dev, "leaking bo va because "
+                       "we fail to reserve bo (%d)\n", r);
                return;
        }
-       list_for_each_entry_safe(bo_va, tmp, &rbo->va, bo_list) {
-               if (bo_va->vm == vm) {
-                       /* remove from this vm address space */
-                       mutex_lock(&vm->mutex);
-                       list_del(&bo_va->vm_list);
-                       mutex_unlock(&vm->mutex);
-                       list_del(&bo_va->bo_list);
-                       kfree(bo_va);
+       bo_va = radeon_vm_bo_find(vm, rbo);
+       if (bo_va) {
+               if (--bo_va->ref_count == 0) {
+                       radeon_vm_bo_rmv(rdev, bo_va);
                }
        }
        radeon_bo_unreserve(rbo);
@@ -468,19 +492,24 @@ int radeon_gem_va_ioctl(struct drm_device *dev, void *data,
                drm_gem_object_unreference_unlocked(gobj);
                return r;
        }
+       bo_va = radeon_vm_bo_find(&fpriv->vm, rbo);
+       if (!bo_va) {
+               args->operation = RADEON_VA_RESULT_ERROR;
+               drm_gem_object_unreference_unlocked(gobj);
+               return -ENOENT;
+       }
+
        switch (args->operation) {
        case RADEON_VA_MAP:
-               bo_va = radeon_bo_va(rbo, &fpriv->vm);
-               if (bo_va) {
+               if (bo_va->soffset) {
                        args->operation = RADEON_VA_RESULT_VA_EXIST;
                        args->offset = bo_va->soffset;
                        goto out;
                }
-               r = radeon_vm_bo_add(rdev, &fpriv->vm, rbo,
-                                    args->offset, args->flags);
+               r = radeon_vm_bo_set_addr(rdev, bo_va, args->offset, args->flags);
                break;
        case RADEON_VA_UNMAP:
-               r = radeon_vm_bo_rmv(rdev, &fpriv->vm, rbo);
+               r = radeon_vm_bo_set_addr(rdev, bo_va, 0, 0);
                break;
        default:
                break;