diff options
author | Christian König <deathsimple@vodafone.de> | 2012-09-11 16:10:04 +0200 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2012-09-20 19:10:42 +0200 |
commit | e971bd5e45764ff76df0ff110a19bf6b924f84d6 (patch) | |
tree | ddbb71c68d5cd1d3d525ba815b5357ef73194c02 /drivers/gpu/drm/radeon/radeon_gem.c | |
parent | drm/radeon: fix gem_close_object handling (diff) | |
download | linux-e971bd5e45764ff76df0ff110a19bf6b924f84d6.tar.xz linux-e971bd5e45764ff76df0ff110a19bf6b924f84d6.zip |
drm/radeon: rework the VM code a bit more (v2)
Roughly based on how nouveau is handling it. Instead of
adding the bo_va when the address is set add the bo_va
when the handle is opened, but set the address to zero
until userspace tells us where to place it.
This fixes another bunch of problems with glamor.
v2: agd5f: fix build after dropping patch 7/8.
Signed-off-by: Christian König <deathsimple@vodafone.de>
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_gem.c')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_gem.c | 47 |
1 files changed, 41 insertions, 6 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index cfad667ce785..6579befa5101 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c @@ -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,6 +158,7 @@ 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; int r; if (rdev->family < CHIP_CAYMAN) { @@ -146,7 +171,12 @@ void radeon_gem_object_close(struct drm_gem_object *obj, "we fail to reserve bo (%d)\n", r); return; } - radeon_vm_bo_rmv(rdev, vm, rbo); + 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); } @@ -462,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_vm_bo_find(&fpriv->vm, rbo); - 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; |