diff options
Diffstat (limited to 'common/recipes-kernel/linux/files/0363-drm-amdgpu-move-get_user_pages-out-of-amdgpu_ttm_tt_.patch')
-rw-r--r-- | common/recipes-kernel/linux/files/0363-drm-amdgpu-move-get_user_pages-out-of-amdgpu_ttm_tt_.patch | 447 |
1 files changed, 0 insertions, 447 deletions
diff --git a/common/recipes-kernel/linux/files/0363-drm-amdgpu-move-get_user_pages-out-of-amdgpu_ttm_tt_.patch b/common/recipes-kernel/linux/files/0363-drm-amdgpu-move-get_user_pages-out-of-amdgpu_ttm_tt_.patch deleted file mode 100644 index 7e2976f9..00000000 --- a/common/recipes-kernel/linux/files/0363-drm-amdgpu-move-get_user_pages-out-of-amdgpu_ttm_tt_.patch +++ /dev/null @@ -1,447 +0,0 @@ -From 20b395a08bdc56f0bb9e34d3840718583159352b Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com> -Date: Tue, 23 Feb 2016 12:36:59 +0100 -Subject: [PATCH 0363/1110] drm/amdgpu: move get_user_pages out of - amdgpu_ttm_tt_pin_userptr v6 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -That avoids lock inversion between the BO reservation lock -and the anon_vma lock. - -v2: -* Changed amdgpu_bo_list_entry.user_pages to an array of pointers -* Lock mmap_sem only for get_user_pages -* Added invalidation of unbound userpointer BOs -* Fixed memory leak and page reference leak - -v3 (chk): -* Revert locking mmap_sem only for_get user_pages -* Revert adding invalidation of unbound userpointer BOs -* Sanitize and fix error handling - -v4 (chk): -* Init userpages pointer everywhere. -* Fix error handling when get_user_pages() fails. -* Add invalidation of unbound userpointer BOs again. - -v5 (chk): -* Add maximum number of tries. - -v6 (chk): -* Fix error handling when we run out of tries. - -Signed-off-by: Christian König <christian.koenig@amd.com> -Signed-off-by: Felix Kuehling <Felix.Kuehling@amd.com> -Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> (v4) -Acked-by: Alex Deucher <alexander.deucher@amd.com> -Signed-off-by: Kalyan Alle <kalyan.alle@amd.com> ---- - drivers/gpu/drm/amd/amdgpu/amdgpu.h | 5 ++ - drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c | 1 + - drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 118 ++++++++++++++++++++++++++-- - drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 23 ++++-- - drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 53 +++++++++---- - drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 2 + - 6 files changed, 176 insertions(+), 26 deletions(-) - -diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h -index 0bc033e..66aef04 100644 ---- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h -+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h -@@ -432,6 +432,8 @@ struct amdgpu_bo_list_entry { - struct ttm_validate_buffer tv; - struct amdgpu_bo_va *bo_va; - uint32_t priority; -+ struct page **user_pages; -+ int user_invalidated; - }; - - struct amdgpu_bo_va_mapping { -@@ -2329,11 +2331,14 @@ int amdgpu_cs_get_ring(struct amdgpu_device *adev, u32 ip_type, - struct amdgpu_ring **out_ring); - void amdgpu_ttm_placement_from_domain(struct amdgpu_bo *rbo, u32 domain); - bool amdgpu_ttm_bo_is_amdgpu_bo(struct ttm_buffer_object *bo); -+int amdgpu_ttm_tt_get_user_pages(struct ttm_tt *ttm, struct page **pages); - int amdgpu_ttm_tt_set_userptr(struct ttm_tt *ttm, uint64_t addr, - uint32_t flags); - struct mm_struct *amdgpu_ttm_tt_get_usermm(struct ttm_tt *ttm); - bool amdgpu_ttm_tt_affect_userptr(struct ttm_tt *ttm, unsigned long start, - unsigned long end); -+bool amdgpu_ttm_tt_userptr_invalidated(struct ttm_tt *ttm, -+ int *last_invalidated); - bool amdgpu_ttm_tt_is_readonly(struct ttm_tt *ttm); - uint32_t amdgpu_ttm_tt_pte_flags(struct amdgpu_device *adev, struct ttm_tt *ttm, - struct ttm_mem_reg *mem); -diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c -index 82f8caf..17a2f83 100644 ---- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c -+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c -@@ -201,6 +201,7 @@ void amdgpu_bo_list_get_list(struct amdgpu_bo_list *list, - - list_add_tail(&list->array[i].tv.head, - &bucket[priority]); -+ list->array[i].user_pages = NULL; - } - - /* Connect the sorted buckets in the output list. */ -diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c -index a92a30a..62027c6 100644 ---- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c -+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c -@@ -152,6 +152,7 @@ static int amdgpu_cs_user_fence_chunk(struct amdgpu_cs_parser *p, - p->uf_entry.priority = 0; - p->uf_entry.tv.bo = &p->uf_entry.robj->tbo; - p->uf_entry.tv.shared = true; -+ p->uf_entry.user_pages = NULL; - - drm_gem_object_unreference_unlocked(gobj); - return 0; -@@ -344,6 +345,7 @@ int amdgpu_cs_list_validate(struct amdgpu_cs_parser *p, - - list_for_each_entry(lobj, validated, tv.head) { - struct amdgpu_bo *bo = lobj->robj; -+ bool binding_userptr = false; - struct mm_struct *usermm; - uint32_t domain; - -@@ -351,6 +353,15 @@ int amdgpu_cs_list_validate(struct amdgpu_cs_parser *p, - if (usermm && usermm != current->mm) - return -EPERM; - -+ /* Check if we have user pages and nobody bound the BO already */ -+ if (lobj->user_pages && bo->tbo.ttm->state != tt_bound) { -+ size_t size = sizeof(struct page *); -+ -+ size *= bo->tbo.ttm->num_pages; -+ memcpy(bo->tbo.ttm->pages, lobj->user_pages, size); -+ binding_userptr = true; -+ } -+ - if (bo->pin_count) - continue; - -@@ -382,6 +393,11 @@ int amdgpu_cs_list_validate(struct amdgpu_cs_parser *p, - } - return r; - } -+ -+ if (binding_userptr) { -+ drm_free_large(lobj->user_pages); -+ lobj->user_pages = NULL; -+ } - } - return 0; - } -@@ -389,8 +405,10 @@ int amdgpu_cs_list_validate(struct amdgpu_cs_parser *p, - static int amdgpu_cs_parser_relocs(struct amdgpu_cs_parser *p) - { - struct amdgpu_cs_buckets buckets; -+ struct amdgpu_bo_list_entry *e; - struct list_head duplicates; - bool need_mmap_lock = false; -+ unsigned i, tries = 10; - - int i, r; - -@@ -413,9 +431,81 @@ static int amdgpu_cs_parser_relocs(struct amdgpu_cs_parser *p) - if (need_mmap_lock) - down_read(¤t->mm->mmap_sem); - -- r = ttm_eu_reserve_buffers(&p->ticket, &p->validated, true, &duplicates); -- if (unlikely(r != 0)) -- goto error_reserve; -+ while (1) { -+ struct list_head need_pages; -+ unsigned i; -+ -+ r = ttm_eu_reserve_buffers(&p->ticket, &p->validated, true, -+ &duplicates); -+ if (unlikely(r != 0)) -+ goto error_free_pages; -+ -+ /* Without a BO list we don't have userptr BOs */ -+ if (!p->bo_list) -+ break; -+ -+ INIT_LIST_HEAD(&need_pages); -+ for (i = p->bo_list->first_userptr; -+ i < p->bo_list->num_entries; ++i) { -+ -+ e = &p->bo_list->array[i]; -+ -+ if (amdgpu_ttm_tt_userptr_invalidated(e->robj->tbo.ttm, -+ &e->user_invalidated) && e->user_pages) { -+ -+ /* We acquired a page array, but somebody -+ * invalidated it. Free it an try again -+ */ -+ release_pages(e->user_pages, -+ e->robj->tbo.ttm->num_pages, -+ false); -+ drm_free_large(e->user_pages); -+ e->user_pages = NULL; -+ } -+ -+ if (e->robj->tbo.ttm->state != tt_bound && -+ !e->user_pages) { -+ list_del(&e->tv.head); -+ list_add(&e->tv.head, &need_pages); -+ -+ amdgpu_bo_unreserve(e->robj); -+ } -+ } -+ -+ if (list_empty(&need_pages)) -+ break; -+ -+ /* Unreserve everything again. */ -+ ttm_eu_backoff_reservation(&p->ticket, &p->validated); -+ -+ /* We tried to often, just abort */ -+ if (!--tries) { -+ r = -EDEADLK; -+ goto error_free_pages; -+ } -+ -+ /* Fill the page arrays for all useptrs. */ -+ list_for_each_entry(e, &need_pages, tv.head) { -+ struct ttm_tt *ttm = e->robj->tbo.ttm; -+ -+ e->user_pages = drm_calloc_large(ttm->num_pages, -+ sizeof(struct page*)); -+ if (!e->user_pages) { -+ r = -ENOMEM; -+ goto error_free_pages; -+ } -+ -+ r = amdgpu_ttm_tt_get_user_pages(ttm, e->user_pages); -+ if (r) { -+ drm_free_large(e->user_pages); -+ e->user_pages = NULL; -+ goto error_free_pages; -+ } -+ } -+ -+ /* And try again. */ -+ list_splice(&need_pages, &p->validated); -+ } - - amdgpu_vm_get_pt_bos(&fpriv->vm, &duplicates); - -@@ -445,9 +535,25 @@ error_validate: - if (r) - ttm_eu_backoff_reservation(&p->ticket, &p->validated); - --error_reserve: -- if (need_mmap_lock) -- up_read(¤t->mm->mmap_sem); -+error_free_pages: -+ -+ if (need_mmap_lock) -+ up_read(¤t->mm->mmap_sem); -+ -+ if (p->bo_list) { -+ for (i = p->bo_list->first_userptr; -+ i < p->bo_list->num_entries; ++i) { -+ e = &p->bo_list->array[i]; -+ -+ if (!e->user_pages) -+ continue; -+ -+ release_pages(e->user_pages, -+ e->robj->tbo.ttm->num_pages, -+ false); -+ drm_free_large(e->user_pages); -+ } -+ } - - return r; - } -diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c -index 6270a20..cbacf72 100644 ---- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c -+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c -@@ -274,18 +274,23 @@ int amdgpu_gem_userptr_ioctl(struct drm_device *dev, void *data, - - if (args->flags & AMDGPU_GEM_USERPTR_VALIDATE) { - down_read(¤t->mm->mmap_sem); -+ -+ r = amdgpu_ttm_tt_get_user_pages(bo->tbo.ttm, -+ bo->tbo.ttm->pages); -+ if (r) -+ goto unlock_mmap_sem; -+ - r = amdgpu_bo_reserve(bo, true); -- if (r) { -- up_read(¤t->mm->mmap_sem); -- goto release_object; -- } -+ if (r) -+ goto free_pages; - - amdgpu_ttm_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_GTT); - r = ttm_bo_validate(&bo->tbo, &bo->placement, true, false); - amdgpu_bo_unreserve(bo); -- up_read(¤t->mm->mmap_sem); - if (r) -- goto release_object; -+ goto free_pages; -+ -+ up_read(¤t->mm->mmap_sem); - } - - r = drm_gem_handle_create(filp, gobj, &handle); -@@ -297,6 +302,12 @@ int amdgpu_gem_userptr_ioctl(struct drm_device *dev, void *data, - args->handle = handle; - return 0; - -+free_pages: -+ release_pages(bo->tbo.ttm->pages, bo->tbo.ttm->num_pages, false); -+ -+unlock_mmap_sem: -+ up_read(¤t->mm->mmap_sem); -+ - release_object: - drm_gem_object_unreference_unlocked(gobj); - -diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c -index 051cd39..6bbd395 100644 ---- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c -+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c -@@ -508,22 +508,18 @@ struct amdgpu_ttm_tt { - uint32_t userflags; - spinlock_t guptasklock; - struct list_head guptasks; -+ atomic_t mmu_invalidations; - }; - --/* prepare the sg table with the user pages */ --static int amdgpu_ttm_tt_pin_userptr(struct ttm_tt *ttm) -+int amdgpu_ttm_tt_get_user_pages(struct ttm_tt *ttm, struct page **pages) - { -- struct amdgpu_device *adev = amdgpu_get_adev(ttm->bdev); - struct amdgpu_ttm_tt *gtt = (void *)ttm; -- unsigned pinned = 0, nents; -- int r; -- - int write = !(gtt->userflags & AMDGPU_GEM_USERPTR_READONLY); -- enum dma_data_direction direction = write ? -- DMA_BIDIRECTIONAL : DMA_TO_DEVICE; -+ unsigned pinned = 0; -+ int r; - - if (gtt->userflags & AMDGPU_GEM_USERPTR_ANONONLY) { -- /* check that we only pin down anonymous memory -+ /* check that we only use anonymous memory - to prevent problems with writeback */ - unsigned long end = gtt->userptr + ttm->num_pages * PAGE_SIZE; - struct vm_area_struct *vma; -@@ -536,7 +532,7 @@ static int amdgpu_ttm_tt_pin_userptr(struct ttm_tt *ttm) - do { - unsigned num_pages = ttm->num_pages - pinned; - uint64_t userptr = gtt->userptr + pinned * PAGE_SIZE; -- struct page **pages = ttm->pages + pinned; -+ struct page **p = pages + pinned; - struct amdgpu_ttm_gup_task_list guptask; - - guptask.task = current; -@@ -545,7 +541,7 @@ static int amdgpu_ttm_tt_pin_userptr(struct ttm_tt *ttm) - spin_unlock(>t->guptasklock); - - r = get_user_pages(current, current->mm, userptr, num_pages, -- write, 0, pages, NULL); -+ write, 0, p, NULL); - - spin_lock(>t->guptasklock); - list_del(&guptask.list); -@@ -558,6 +554,25 @@ static int amdgpu_ttm_tt_pin_userptr(struct ttm_tt *ttm) - - } while (pinned < ttm->num_pages); - -+ return 0; -+ -+release_pages: -+ release_pages(pages, pinned, 0); -+ return r; -+} -+ -+/* prepare the sg table with the user pages */ -+static int amdgpu_ttm_tt_pin_userptr(struct ttm_tt *ttm) -+{ -+ struct amdgpu_device *adev = amdgpu_get_adev(ttm->bdev); -+ struct amdgpu_ttm_tt *gtt = (void *)ttm; -+ unsigned nents; -+ int r; -+ -+ int write = !(gtt->userflags & AMDGPU_GEM_USERPTR_READONLY); -+ enum dma_data_direction direction = write ? -+ DMA_BIDIRECTIONAL : DMA_TO_DEVICE; -+ - r = sg_alloc_table_from_pages(ttm->sg, ttm->pages, ttm->num_pages, 0, - ttm->num_pages << PAGE_SHIFT, - GFP_KERNEL); -@@ -576,9 +591,6 @@ static int amdgpu_ttm_tt_pin_userptr(struct ttm_tt *ttm) - - release_sg: - kfree(ttm->sg); -- --release_pages: -- release_pages(ttm->pages, pinned, 0); - return r; - } - -@@ -803,6 +815,7 @@ int amdgpu_ttm_tt_set_userptr(struct ttm_tt *ttm, uint64_t addr, - gtt->userflags = flags; - spin_lock_init(>t->guptasklock); - INIT_LIST_HEAD(>t->guptasks); -+ atomic_set(>t->mmu_invalidations, 0); - - return 0; - } -@@ -840,9 +853,21 @@ bool amdgpu_ttm_tt_affect_userptr(struct ttm_tt *ttm, unsigned long start, - } - spin_unlock(>t->guptasklock); - -+ atomic_inc(>t->mmu_invalidations); -+ - return true; - } - -+bool amdgpu_ttm_tt_userptr_invalidated(struct ttm_tt *ttm, -+ int *last_invalidated) -+{ -+ struct amdgpu_ttm_tt *gtt = (void *)ttm; -+ int prev_invalidated = *last_invalidated; -+ -+ *last_invalidated = atomic_read(>t->mmu_invalidations); -+ return prev_invalidated != *last_invalidated; -+} -+ - bool amdgpu_ttm_tt_is_readonly(struct ttm_tt *ttm) - { - struct amdgpu_ttm_tt *gtt = (void *)ttm; -diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c -index f139cea..99afc64 100644 ---- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c -+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c -@@ -94,6 +94,7 @@ void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm, - entry->priority = 0; - entry->tv.bo = &vm->page_directory->tbo; - entry->tv.shared = true; -+ entry->user_pages = NULL; - list_add(&entry->tv.head, validated); - } - -@@ -1191,6 +1192,7 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev, - entry->priority = 0; - entry->tv.bo = &entry->robj->tbo; - entry->tv.shared = true; -+ entry->user_pages = NULL; - vm->page_tables[pt_idx].addr = 0; - } - --- -2.7.4 - |