From 91acbeb68ab10c0c0f65f30b5b7fddbde4c97dd2 Mon Sep 17 00:00:00 2001 From: Christian König Date: Mon, 14 Dec 2015 16:42:31 +0100 Subject: drm/amdgpu: fix user fence handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes a random corruption under memory pressure. We need to fence the BO for the user fence as well, otherwise it might be swapped out and the GPU could write the fence value to an undesired location. Signed-off-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 63 ++++++++++++++++++++++------------ 1 file changed, 42 insertions(+), 21 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 4f352ec9dec4..25a3e2485cc2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -127,6 +127,37 @@ int amdgpu_cs_get_ring(struct amdgpu_device *adev, u32 ip_type, return 0; } +static int amdgpu_cs_user_fence_chunk(struct amdgpu_cs_parser *p, + struct drm_amdgpu_cs_chunk_fence *fence_data) +{ + struct drm_gem_object *gobj; + uint32_t handle; + + handle = fence_data->handle; + gobj = drm_gem_object_lookup(p->adev->ddev, p->filp, + fence_data->handle); + if (gobj == NULL) + return -EINVAL; + + p->uf.bo = amdgpu_bo_ref(gem_to_amdgpu_bo(gobj)); + p->uf.offset = fence_data->offset; + + if (amdgpu_ttm_tt_has_userptr(p->uf.bo->tbo.ttm)) { + drm_gem_object_unreference_unlocked(gobj); + return -EINVAL; + } + + p->uf_entry.robj = amdgpu_bo_ref(p->uf.bo); + p->uf_entry.prefered_domains = AMDGPU_GEM_DOMAIN_GTT; + p->uf_entry.allowed_domains = AMDGPU_GEM_DOMAIN_GTT; + p->uf_entry.priority = 0; + p->uf_entry.tv.bo = &p->uf_entry.robj->tbo; + p->uf_entry.tv.shared = true; + + drm_gem_object_unreference_unlocked(gobj); + return 0; +} + int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data) { union drm_amdgpu_cs *cs = data; @@ -207,28 +238,15 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data) case AMDGPU_CHUNK_ID_FENCE: size = sizeof(struct drm_amdgpu_cs_chunk_fence); - if (p->chunks[i].length_dw * sizeof(uint32_t) >= size) { - uint32_t handle; - struct drm_gem_object *gobj; - struct drm_amdgpu_cs_chunk_fence *fence_data; - - fence_data = (void *)p->chunks[i].kdata; - handle = fence_data->handle; - gobj = drm_gem_object_lookup(p->adev->ddev, - p->filp, handle); - if (gobj == NULL) { - ret = -EINVAL; - goto free_partial_kdata; - } - - p->uf.bo = gem_to_amdgpu_bo(gobj); - amdgpu_bo_ref(p->uf.bo); - drm_gem_object_unreference_unlocked(gobj); - p->uf.offset = fence_data->offset; - } else { + if (p->chunks[i].length_dw * sizeof(uint32_t) < size) { ret = -EINVAL; goto free_partial_kdata; } + + ret = amdgpu_cs_user_fence_chunk(p, (void *)p->chunks[i].kdata); + if (ret) + goto free_partial_kdata; + break; case AMDGPU_CHUNK_ID_DEPENDENCIES: @@ -391,6 +409,9 @@ static int amdgpu_cs_parser_relocs(struct amdgpu_cs_parser *p) p->vm_bos = amdgpu_vm_get_bos(p->adev, &fpriv->vm, &p->validated); + if (p->uf.bo) + list_add(&p->uf_entry.tv.head, &p->validated); + if (need_mmap_lock) down_read(¤t->mm->mmap_sem); @@ -488,8 +509,8 @@ static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, bo for (i = 0; i < parser->num_ibs; i++) amdgpu_ib_free(parser->adev, &parser->ibs[i]); kfree(parser->ibs); - if (parser->uf.bo) - amdgpu_bo_unref(&parser->uf.bo); + amdgpu_bo_unref(&parser->uf.bo); + amdgpu_bo_unref(&parser->uf_entry.robj); } static int amdgpu_bo_vm_update_pte(struct amdgpu_cs_parser *p, -- cgit v1.2.3 From 3c0eea6c35d932c4d25070868067dc9cd9ceab91 Mon Sep 17 00:00:00 2001 From: Christian König Date: Fri, 11 Dec 2015 14:39:05 +0100 Subject: drm/amdgpu: put VM page tables directly into duplicates list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit They share the reservation object with the page directory anyway. Signed-off-by: Christian König Reviewed-by: Alex Deucher Reviewed-by: Chunming Zhou --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 3 ++- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 12 +++++++----- 4 files changed, 12 insertions(+), 9 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index c3996e0e2e7e..dc3dab539e4c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -982,7 +982,8 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm); void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm); struct amdgpu_bo_list_entry *amdgpu_vm_get_bos(struct amdgpu_device *adev, struct amdgpu_vm *vm, - struct list_head *head); + struct list_head *validated, + struct list_head *duplicates); int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring, struct amdgpu_sync *sync); void amdgpu_vm_flush(struct amdgpu_ring *ring, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 1d44d508d4d4..9591c13781bd 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -386,13 +386,13 @@ static int amdgpu_cs_parser_relocs(struct amdgpu_cs_parser *p) amdgpu_cs_buckets_get_list(&buckets, &p->validated); } + INIT_LIST_HEAD(&duplicates); p->vm_bos = amdgpu_vm_get_bos(p->adev, &fpriv->vm, - &p->validated); + &p->validated, &duplicates); if (need_mmap_lock) down_read(¤t->mm->mmap_sem); - INIT_LIST_HEAD(&duplicates); r = ttm_eu_reserve_buffers(&p->ticket, &p->validated, true, &duplicates); if (unlikely(r != 0)) goto error_reserve; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index fc32fc01a64b..7fe7f8afa5ff 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -460,7 +460,7 @@ static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev, tv.shared = true; list_add(&tv.head, &list); - vm_bos = amdgpu_vm_get_bos(adev, bo_va->vm, &list); + vm_bos = amdgpu_vm_get_bos(adev, bo_va->vm, &list, &duplicates); if (!vm_bos) return; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index fce4c6d952c8..f6c1d6f0bf37 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -78,14 +78,16 @@ static unsigned amdgpu_vm_directory_size(struct amdgpu_device *adev) * amdgpu_vm_get_bos - add the vm BOs to a validation list * * @vm: vm providing the BOs - * @head: head of validation list + * @validated: head of validation list + * @duplicates: head of duplicates list * * Add the page directory to the list of BOs to * validate for command submission (cayman+). */ struct amdgpu_bo_list_entry *amdgpu_vm_get_bos(struct amdgpu_device *adev, - struct amdgpu_vm *vm, - struct list_head *head) + struct amdgpu_vm *vm, + struct list_head *validated, + struct list_head *duplicates) { struct amdgpu_bo_list_entry *list; unsigned i, idx; @@ -103,7 +105,7 @@ struct amdgpu_bo_list_entry *amdgpu_vm_get_bos(struct amdgpu_device *adev, list[0].priority = 0; list[0].tv.bo = &vm->page_directory->tbo; list[0].tv.shared = true; - list_add(&list[0].tv.head, head); + list_add(&list[0].tv.head, validated); for (i = 0, idx = 1; i <= vm->max_pde_used; i++) { if (!vm->page_tables[i].bo) @@ -115,7 +117,7 @@ struct amdgpu_bo_list_entry *amdgpu_vm_get_bos(struct amdgpu_device *adev, list[idx].priority = 0; list[idx].tv.bo = &list[idx].robj->tbo; list[idx].tv.shared = true; - list_add(&list[idx++].tv.head, head); + list_add(&list[idx++].tv.head, duplicates); } return list; -- cgit v1.2.3 From 56467ebfb254836dc30eb45d4ac8a46a400bfad6 Mon Sep 17 00:00:00 2001 From: Christian König Date: Fri, 11 Dec 2015 15:16:32 +0100 Subject: drm/amdgpu: split VM PD and PT handling during CS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This way we avoid the extra allocation for the page directory entry. Signed-off-by: Christian König Reviewed-by: Alex Deucher Reviewed-by: Chunming Zhou --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 10 +++++--- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 9 +++++-- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 16 +++++++----- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 45 ++++++++++++++++++++------------- 4 files changed, 51 insertions(+), 29 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index dc3dab539e4c..40850afa763f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -980,10 +980,11 @@ struct amdgpu_vm_manager { void amdgpu_vm_manager_fini(struct amdgpu_device *adev); int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm); void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm); -struct amdgpu_bo_list_entry *amdgpu_vm_get_bos(struct amdgpu_device *adev, - struct amdgpu_vm *vm, - struct list_head *validated, - struct list_head *duplicates); +void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm, + struct list_head *validated, + struct amdgpu_bo_list_entry *entry); +struct amdgpu_bo_list_entry *amdgpu_vm_get_pt_bos(struct amdgpu_vm *vm, + struct list_head *duplicates); int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring, struct amdgpu_sync *sync); void amdgpu_vm_flush(struct amdgpu_ring *ring, @@ -1253,6 +1254,7 @@ struct amdgpu_cs_parser { unsigned nchunks; struct amdgpu_cs_chunk *chunks; /* relocations */ + struct amdgpu_bo_list_entry vm_pd; struct amdgpu_bo_list_entry *vm_bos; struct list_head validated; struct fence *fence; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 9591c13781bd..3fb21ecd29e0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -387,8 +387,7 @@ static int amdgpu_cs_parser_relocs(struct amdgpu_cs_parser *p) } INIT_LIST_HEAD(&duplicates); - p->vm_bos = amdgpu_vm_get_bos(p->adev, &fpriv->vm, - &p->validated, &duplicates); + amdgpu_vm_get_pd_bo(&fpriv->vm, &p->validated, &p->vm_pd); if (need_mmap_lock) down_read(¤t->mm->mmap_sem); @@ -397,6 +396,12 @@ static int amdgpu_cs_parser_relocs(struct amdgpu_cs_parser *p) if (unlikely(r != 0)) goto error_reserve; + p->vm_bos = amdgpu_vm_get_pt_bos(&fpriv->vm, &duplicates); + if (!p->vm_bos) { + r = -ENOMEM; + goto error_validate; + } + r = amdgpu_cs_list_validate(p->adev, &fpriv->vm, &p->validated); if (r) goto error_validate; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index 7fe7f8afa5ff..ea0fe94e4b54 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -448,6 +448,7 @@ static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev, { struct ttm_validate_buffer tv, *entry; struct amdgpu_bo_list_entry *vm_bos; + struct amdgpu_bo_list_entry vm_pd; struct ww_acquire_ctx ticket; struct list_head list, duplicates; unsigned domain; @@ -460,14 +461,18 @@ static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev, tv.shared = true; list_add(&tv.head, &list); - vm_bos = amdgpu_vm_get_bos(adev, bo_va->vm, &list, &duplicates); - if (!vm_bos) - return; + amdgpu_vm_get_pd_bo(bo_va->vm, &list, &vm_pd); /* Provide duplicates to avoid -EALREADY */ r = ttm_eu_reserve_buffers(&ticket, &list, true, &duplicates); if (r) - goto error_free; + goto error_print; + + vm_bos = amdgpu_vm_get_pt_bos(bo_va->vm, &duplicates); + if (!vm_bos) { + r = -ENOMEM; + goto error_unreserve; + } list_for_each_entry(entry, &list, head) { domain = amdgpu_mem_type_to_domain(entry->bo->mem.mem_type); @@ -489,10 +494,9 @@ static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev, error_unreserve: ttm_eu_backoff_reservation(&ticket, &list); - -error_free: drm_free_large(vm_bos); +error_print: if (r && r != -ERESTARTSYS) DRM_ERROR("Couldn't update BO_VA (%d)\n", r); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index f6c1d6f0bf37..592be6438a6c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -75,39 +75,50 @@ static unsigned amdgpu_vm_directory_size(struct amdgpu_device *adev) } /** - * amdgpu_vm_get_bos - add the vm BOs to a validation list + * amdgpu_vm_get_pd_bo - add the VM PD to a validation list * * @vm: vm providing the BOs * @validated: head of validation list + * @entry: entry to add + * + * Add the page directory to the list of BOs to + * validate for command submission. + */ +void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm, + struct list_head *validated, + struct amdgpu_bo_list_entry *entry) +{ + entry->robj = vm->page_directory; + entry->prefered_domains = AMDGPU_GEM_DOMAIN_VRAM; + entry->allowed_domains = AMDGPU_GEM_DOMAIN_VRAM; + entry->priority = 0; + entry->tv.bo = &vm->page_directory->tbo; + entry->tv.shared = true; + list_add(&entry->tv.head, validated); +} + +/** + * amdgpu_vm_get_bos - add the vm BOs to a validation list + * + * @vm: vm providing the BOs * @duplicates: head of duplicates list * * Add the page directory to the list of BOs to * validate for command submission (cayman+). */ -struct amdgpu_bo_list_entry *amdgpu_vm_get_bos(struct amdgpu_device *adev, - struct amdgpu_vm *vm, - struct list_head *validated, - struct list_head *duplicates) +struct amdgpu_bo_list_entry *amdgpu_vm_get_pt_bos(struct amdgpu_vm *vm, + struct list_head *duplicates) { struct amdgpu_bo_list_entry *list; unsigned i, idx; - list = drm_malloc_ab(vm->max_pde_used + 2, + list = drm_malloc_ab(vm->max_pde_used + 1, sizeof(struct amdgpu_bo_list_entry)); - if (!list) { + if (!list) return NULL; - } /* add the vm page table to the list */ - list[0].robj = vm->page_directory; - list[0].prefered_domains = AMDGPU_GEM_DOMAIN_VRAM; - list[0].allowed_domains = AMDGPU_GEM_DOMAIN_VRAM; - list[0].priority = 0; - list[0].tv.bo = &vm->page_directory->tbo; - list[0].tv.shared = true; - list_add(&list[0].tv.head, validated); - - for (i = 0, idx = 1; i <= vm->max_pde_used; i++) { + for (i = 0, idx = 0; i <= vm->max_pde_used; i++) { if (!vm->page_tables[i].bo) continue; -- cgit v1.2.3 From ee1782c3f27fec5462363af48f27811b049155ab Mon Sep 17 00:00:00 2001 From: Christian König Date: Fri, 11 Dec 2015 21:01:23 +0100 Subject: drm/amdgpu: keep the PTs validation list in the VM v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This avoids allocating it on the fly. v2: fix grammar in comment Signed-off-by: Christian König Reviewed-by: Alex Deucher Reviewed-by: Chunming Zhou --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 8 ++---- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 7 +---- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 9 +----- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 50 +++++++++++++++------------------ 4 files changed, 27 insertions(+), 47 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 40850afa763f..d4e9272b60e8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -917,8 +917,8 @@ struct amdgpu_ring { #define AMDGPU_VM_FAULT_STOP_ALWAYS 2 struct amdgpu_vm_pt { - struct amdgpu_bo *bo; - uint64_t addr; + struct amdgpu_bo_list_entry entry; + uint64_t addr; }; struct amdgpu_vm_id { @@ -983,8 +983,7 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm); void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm, struct list_head *validated, struct amdgpu_bo_list_entry *entry); -struct amdgpu_bo_list_entry *amdgpu_vm_get_pt_bos(struct amdgpu_vm *vm, - struct list_head *duplicates); +void amdgpu_vm_get_pt_bos(struct amdgpu_vm *vm, struct list_head *duplicates); int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring, struct amdgpu_sync *sync); void amdgpu_vm_flush(struct amdgpu_ring *ring, @@ -1255,7 +1254,6 @@ struct amdgpu_cs_parser { struct amdgpu_cs_chunk *chunks; /* relocations */ struct amdgpu_bo_list_entry vm_pd; - struct amdgpu_bo_list_entry *vm_bos; struct list_head validated; struct fence *fence; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 3fb21ecd29e0..6ce595ff1aff 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -396,11 +396,7 @@ static int amdgpu_cs_parser_relocs(struct amdgpu_cs_parser *p) if (unlikely(r != 0)) goto error_reserve; - p->vm_bos = amdgpu_vm_get_pt_bos(&fpriv->vm, &duplicates); - if (!p->vm_bos) { - r = -ENOMEM; - goto error_validate; - } + amdgpu_vm_get_pt_bos(&fpriv->vm, &duplicates); r = amdgpu_cs_list_validate(p->adev, &fpriv->vm, &p->validated); if (r) @@ -483,7 +479,6 @@ static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, bo if (parser->bo_list) amdgpu_bo_list_put(parser->bo_list); - drm_free_large(parser->vm_bos); for (i = 0; i < parser->nchunks; i++) drm_free_large(parser->chunks[i].kdata); kfree(parser->chunks); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index ea0fe94e4b54..8c5687e4a6d1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -447,7 +447,6 @@ static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev, struct amdgpu_bo_va *bo_va, uint32_t operation) { struct ttm_validate_buffer tv, *entry; - struct amdgpu_bo_list_entry *vm_bos; struct amdgpu_bo_list_entry vm_pd; struct ww_acquire_ctx ticket; struct list_head list, duplicates; @@ -468,12 +467,7 @@ static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev, if (r) goto error_print; - vm_bos = amdgpu_vm_get_pt_bos(bo_va->vm, &duplicates); - if (!vm_bos) { - r = -ENOMEM; - goto error_unreserve; - } - + amdgpu_vm_get_pt_bos(bo_va->vm, &duplicates); list_for_each_entry(entry, &list, head) { domain = amdgpu_mem_type_to_domain(entry->bo->mem.mem_type); /* if anything is swapped out don't swap it in here, @@ -494,7 +488,6 @@ static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev, error_unreserve: ttm_eu_backoff_reservation(&ticket, &list); - drm_free_large(vm_bos); error_print: if (r && r != -ERESTARTSYS) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 592be6438a6c..e0fa9d9ff5c2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -98,40 +98,27 @@ void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm, } /** - * amdgpu_vm_get_bos - add the vm BOs to a validation list + * amdgpu_vm_get_bos - add the vm BOs to a duplicates list * * @vm: vm providing the BOs * @duplicates: head of duplicates list * - * Add the page directory to the list of BOs to - * validate for command submission (cayman+). + * Add the page directory to the BO duplicates list + * for command submission. */ -struct amdgpu_bo_list_entry *amdgpu_vm_get_pt_bos(struct amdgpu_vm *vm, - struct list_head *duplicates) +void amdgpu_vm_get_pt_bos(struct amdgpu_vm *vm, struct list_head *duplicates) { - struct amdgpu_bo_list_entry *list; - unsigned i, idx; - - list = drm_malloc_ab(vm->max_pde_used + 1, - sizeof(struct amdgpu_bo_list_entry)); - if (!list) - return NULL; + unsigned i; /* add the vm page table to the list */ - for (i = 0, idx = 0; i <= vm->max_pde_used; i++) { - if (!vm->page_tables[i].bo) + for (i = 0; i <= vm->max_pde_used; ++i) { + struct amdgpu_bo_list_entry *entry = &vm->page_tables[i].entry; + + if (!entry->robj) continue; - list[idx].robj = vm->page_tables[i].bo; - list[idx].prefered_domains = AMDGPU_GEM_DOMAIN_VRAM; - list[idx].allowed_domains = AMDGPU_GEM_DOMAIN_VRAM; - list[idx].priority = 0; - list[idx].tv.bo = &list[idx].robj->tbo; - list[idx].tv.shared = true; - list_add(&list[idx++].tv.head, duplicates); + list_add(&entry->tv.head, duplicates); } - - return list; } /** @@ -474,7 +461,7 @@ int amdgpu_vm_update_page_directory(struct amdgpu_device *adev, /* walk over the address space and update the page directory */ for (pt_idx = 0; pt_idx <= vm->max_pde_used; ++pt_idx) { - struct amdgpu_bo *bo = vm->page_tables[pt_idx].bo; + struct amdgpu_bo *bo = vm->page_tables[pt_idx].entry.robj; uint64_t pde, pt; if (bo == NULL) @@ -651,7 +638,7 @@ static int amdgpu_vm_update_ptes(struct amdgpu_device *adev, /* walk over the address space and update the page tables */ for (addr = start; addr < end; ) { uint64_t pt_idx = addr >> amdgpu_vm_block_size; - struct amdgpu_bo *pt = vm->page_tables[pt_idx].bo; + struct amdgpu_bo *pt = vm->page_tables[pt_idx].entry.robj; unsigned nptes; uint64_t pte; int r; @@ -1083,9 +1070,11 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev, /* walk over the address space and allocate the page tables */ for (pt_idx = saddr; pt_idx <= eaddr; ++pt_idx) { struct reservation_object *resv = vm->page_directory->tbo.resv; + struct amdgpu_bo_list_entry *entry; struct amdgpu_bo *pt; - if (vm->page_tables[pt_idx].bo) + entry = &vm->page_tables[pt_idx].entry; + if (entry->robj) continue; r = amdgpu_bo_create(adev, AMDGPU_VM_PTE_COUNT * 8, @@ -1102,8 +1091,13 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev, goto error_free; } + entry->robj = pt; + entry->prefered_domains = AMDGPU_GEM_DOMAIN_VRAM; + entry->allowed_domains = AMDGPU_GEM_DOMAIN_VRAM; + entry->priority = 0; + entry->tv.bo = &entry->robj->tbo; + entry->tv.shared = true; vm->page_tables[pt_idx].addr = 0; - vm->page_tables[pt_idx].bo = pt; } return 0; @@ -1334,7 +1328,7 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm) } for (i = 0; i < amdgpu_vm_num_pdes(adev); i++) - amdgpu_bo_unref(&vm->page_tables[i].bo); + amdgpu_bo_unref(&vm->page_tables[i].entry.robj); kfree(vm->page_tables); amdgpu_bo_unref(&vm->page_directory); -- cgit v1.2.3 From eceb8a1562db6fc3e1c21cd54a4be0189aa1d0e3 Mon Sep 17 00:00:00 2001 From: Christian König Date: Mon, 11 Jan 2016 15:35:21 +0100 Subject: drm/amdgpu: move VM page tables to the LRU end on CS v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This makes it less likely to run into an ENOMEM because VM page tables are evicted last. v2: move the BOs in the LRU tail after validation Signed-off-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 7 ++++++- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 27 +++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 003959f99251..313b0cc8d676 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -987,6 +987,8 @@ void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm, struct list_head *validated, struct amdgpu_bo_list_entry *entry); void amdgpu_vm_get_pt_bos(struct amdgpu_vm *vm, struct list_head *duplicates); +void amdgpu_vm_move_pt_bos_in_lru(struct amdgpu_device *adev, + struct amdgpu_vm *vm); int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring, struct amdgpu_sync *sync); void amdgpu_vm_flush(struct amdgpu_ring *ring, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index ce0254d4dcd7..1fffc338f69d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -428,8 +428,10 @@ static int amdgpu_cs_parser_relocs(struct amdgpu_cs_parser *p) r = amdgpu_cs_list_validate(p->adev, &fpriv->vm, &duplicates); error_validate: - if (r) + if (r) { + amdgpu_vm_move_pt_bos_in_lru(p->adev, &fpriv->vm); ttm_eu_backoff_reservation(&p->ticket, &p->validated); + } error_reserve: if (need_mmap_lock) @@ -473,8 +475,11 @@ static int cmp_size_smaller_first(void *priv, struct list_head *a, **/ static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, bool backoff) { + struct amdgpu_fpriv *fpriv = parser->filp->driver_priv; unsigned i; + amdgpu_vm_move_pt_bos_in_lru(parser->adev, &fpriv->vm); + if (!error) { /* Sort the buffer list from the smallest to largest buffer, * which affects the order of buffers in the LRU list. diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 8f7688e598a1..aefc668e6b5d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -119,6 +119,33 @@ void amdgpu_vm_get_pt_bos(struct amdgpu_vm *vm, struct list_head *duplicates) list_add(&entry->tv.head, duplicates); } + +} + +/** + * amdgpu_vm_move_pt_bos_in_lru - move the PT BOs to the LRU tail + * + * @adev: amdgpu device instance + * @vm: vm providing the BOs + * + * Move the PT BOs to the tail of the LRU. + */ +void amdgpu_vm_move_pt_bos_in_lru(struct amdgpu_device *adev, + struct amdgpu_vm *vm) +{ + struct ttm_bo_global *glob = adev->mman.bdev.glob; + unsigned i; + + spin_lock(&glob->lru_lock); + for (i = 0; i <= vm->max_pde_used; ++i) { + struct amdgpu_bo_list_entry *entry = &vm->page_tables[i].entry; + + if (!entry->robj) + continue; + + ttm_bo_move_to_lru_tail(&entry->robj->tbo); + } + spin_unlock(&glob->lru_lock); } /** -- cgit v1.2.3 From d8e0cae645504a787b05abfb91afee8cd7fa1701 Mon Sep 17 00:00:00 2001 From: Christian König Date: Mon, 11 Jan 2016 15:35:22 +0100 Subject: drm/amdgpu: validate duplicates first MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Most VM BOs end up in the duplicates list, validate it first make -ENOMEM less likely. Signed-off-by: Christian König Reviewed-by: Chunming Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 1fffc338f69d..6f89f8e034d0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -421,11 +421,11 @@ static int amdgpu_cs_parser_relocs(struct amdgpu_cs_parser *p) amdgpu_vm_get_pt_bos(&fpriv->vm, &duplicates); - r = amdgpu_cs_list_validate(p->adev, &fpriv->vm, &p->validated); + r = amdgpu_cs_list_validate(p->adev, &fpriv->vm, &duplicates); if (r) goto error_validate; - r = amdgpu_cs_list_validate(p->adev, &fpriv->vm, &duplicates); + r = amdgpu_cs_list_validate(p->adev, &fpriv->vm, &p->validated); error_validate: if (r) { -- cgit v1.2.3