From bca5ee8dfa87c954a9e36dfd94fb0d92d8944a1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 14 Jul 2014 18:28:42 +0200 Subject: [PATCH 1/2] drm/radeon: fix handling of radeon_vm_bo_rmv v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We must reserve the PD and PTs as well when we invalidate the BOs locations. Bug: https://bugs.freedesktop.org/show_bug.cgi?id=79980 Signed-off-by: Christian König Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/radeon.h | 3 +- drivers/gpu/drm/radeon/radeon_gem.c | 10 +----- drivers/gpu/drm/radeon/radeon_kms.c | 13 +++---- drivers/gpu/drm/radeon/radeon_object.c | 2 +- drivers/gpu/drm/radeon/radeon_vm.c | 62 ++++++++++++++++++++++++++++------ 5 files changed, 60 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index b720450..079eac7 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -2848,7 +2848,8 @@ int radeon_vm_bo_set_addr(struct radeon_device *rdev, uint64_t offset, uint32_t flags); int radeon_vm_bo_rmv(struct radeon_device *rdev, - struct radeon_bo_va *bo_va); + struct radeon_vm *vm, + struct radeon_bo *bo); /* audio */ void r600_audio_update_hdmi(struct work_struct *work); diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index d09650c..7b9463f 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c @@ -167,26 +167,18 @@ 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) { return; } - r = radeon_bo_reserve(rbo, true); + r = radeon_vm_bo_rmv(rdev, vm, rbo); if (r) { dev_err(rdev->dev, "leaking bo va because " "we fail to reserve bo (%d)\n", r); return; } - 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); } static int radeon_gem_handle_lockup(struct radeon_device *rdev, int r) diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index 35d9318..d4b6b60 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -640,18 +640,13 @@ void radeon_driver_postclose_kms(struct drm_device *dev, /* new gpu have virtual address space support */ if (rdev->family >= CHIP_CAYMAN && file_priv->driver_priv) { struct radeon_fpriv *fpriv = file_priv->driver_priv; - struct radeon_bo_va *bo_va; int r; if (rdev->accel_working) { - r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false); - if (!r) { - bo_va = radeon_vm_bo_find(&fpriv->vm, - rdev->ring_tmp_bo.bo); - if (bo_va) - radeon_vm_bo_rmv(rdev, bo_va); - radeon_bo_unreserve(rdev->ring_tmp_bo.bo); - } + r = radeon_vm_bo_rmv(rdev, &fpriv->vm, + rdev->ring_tmp_bo.bo); + if (r) + DRM_ERROR("tmp_bo removal failed (%d)!\n", r); } radeon_vm_fini(rdev, &fpriv->vm); diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 6c717b2..3309d47 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -52,7 +52,7 @@ static void radeon_bo_clear_va(struct radeon_bo *bo) list_for_each_entry_safe(bo_va, tmp, &bo->va, bo_list) { /* remove from all vm address space */ - radeon_vm_bo_rmv(bo->rdev, bo_va); + radeon_vm_bo_rmv(bo->rdev, bo_va->vm, bo_va->bo); } } diff --git a/drivers/gpu/drm/radeon/radeon_vm.c b/drivers/gpu/drm/radeon/radeon_vm.c index eecff6b..537fed6 100644 --- a/drivers/gpu/drm/radeon/radeon_vm.c +++ b/drivers/gpu/drm/radeon/radeon_vm.c @@ -914,29 +914,71 @@ int radeon_vm_bo_update(struct radeon_device *rdev, * radeon_vm_bo_rmv - remove a bo to a specific vm * * @rdev: radeon_device pointer - * @bo_va: requested bo_va + * @vm: requested vm + * @bo: requested bo * - * Remove @bo_va->bo from the requested vm (cayman+). - * Remove @bo_va->bo from the list of bos associated with the bo_va->vm and - * remove the ptes for @bo_va in the page table. + * Remove @bo from the list of bos associated with the @vm and + * remove the ptes for @bo in the page table. * Returns 0 for success. - * - * Object have to be reserved! */ int radeon_vm_bo_rmv(struct radeon_device *rdev, - struct radeon_bo_va *bo_va) + struct radeon_vm *vm, + struct radeon_bo *bo) { - int r = 0; + struct radeon_cs_reloc *vm_relocs, bo_reloc; + struct radeon_bo_va *bo_va; + struct ww_acquire_ctx ticket; + struct list_head head; + int r; + + memset(&bo_reloc, 0, sizeof(bo_reloc)); + bo_reloc.robj = bo; + bo_reloc.tv.bo = &bo->tbo; + bo_reloc.prefered_domains = RADEON_GEM_DOMAIN_VRAM | + RADEON_GEM_DOMAIN_GTT; + bo_reloc.allowed_domains = bo_reloc.prefered_domains; + + INIT_LIST_HEAD(&head); + list_add(&bo_reloc.tv.head, &head); + + vm_relocs = radeon_vm_get_bos(rdev, vm, &head); + r = radeon_bo_list_validate(rdev, &ticket, &head, + RADEON_RING_TYPE_GFX_INDEX); + if (r) + goto release_vm_relocs; + + bo_va = radeon_vm_bo_find(vm, bo); + if (!bo_va || --bo_va->ref_count > 0) { + r = 0; /* It's not an error to have more references */ + ttm_eu_backoff_reservation(&ticket, &head); + goto release_vm_relocs; + } mutex_lock(&bo_va->vm->mutex); - if (bo_va->soffset) + if (bo_va->soffset) { r = radeon_vm_bo_update(rdev, bo_va->vm, bo_va->bo, NULL); + if (r) { + ttm_eu_backoff_reservation(&ticket, &head); + mutex_unlock(&bo_va->vm->mutex); + goto release_vm_relocs; + } + } list_del(&bo_va->vm_list); - mutex_unlock(&bo_va->vm->mutex); list_del(&bo_va->bo_list); + if (bo_va->soffset && vm->fence) + ttm_eu_fence_buffer_objects(&ticket, &head, vm->fence); + else + ttm_eu_backoff_reservation(&ticket, &head); + + mutex_unlock(&bo_va->vm->mutex); kfree(bo_va); + + r = 0; + +release_vm_relocs: + kfree(vm_relocs); return r; } -- 1.9.1