diff options
Diffstat (limited to 'common/recipes-kernel/linux/linux-yocto-4.19.8/1285-drm-amdgpu-replace-get_user_pages-with-HMM-mirror-he.patch')
-rw-r--r-- | common/recipes-kernel/linux/linux-yocto-4.19.8/1285-drm-amdgpu-replace-get_user_pages-with-HMM-mirror-he.patch | 672 |
1 files changed, 672 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/linux-yocto-4.19.8/1285-drm-amdgpu-replace-get_user_pages-with-HMM-mirror-he.patch b/common/recipes-kernel/linux/linux-yocto-4.19.8/1285-drm-amdgpu-replace-get_user_pages-with-HMM-mirror-he.patch new file mode 100644 index 00000000..a1510ff1 --- /dev/null +++ b/common/recipes-kernel/linux/linux-yocto-4.19.8/1285-drm-amdgpu-replace-get_user_pages-with-HMM-mirror-he.patch @@ -0,0 +1,672 @@ +From 3bf8b153e39c41e2e9d9398075fcdbc608b85d69 Mon Sep 17 00:00:00 2001 +From: Philip Yang <Philip.Yang@amd.com> +Date: Thu, 13 Dec 2018 15:35:28 -0500 +Subject: [PATCH 1285/2940] drm/amdgpu: replace get_user_pages with HMM mirror + helpers +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Use HMM helper function hmm_vma_fault() to get physical pages backing +userptr and start CPU page table update track of those pages. Then use +hmm_vma_range_done() to check if those pages are updated before +amdgpu_cs_submit for gfx or before user queues are resumed for kfd. + +If userptr pages are updated, for gfx, amdgpu_cs_ioctl will restart +from scratch, for kfd, restore worker is rescheduled to retry. + +HMM simplify the CPU page table concurrent update check, so remove +guptasklock, mmu_invalidations, last_set_pages fields from +amdgpu_ttm_tt struct. + +HMM does not pin the page (increase page ref count), so remove related +operations like release_pages(), put_page(), mark_page_dirty(). + +Change-Id: Ibec614d6aed9f8c414e9bab11cee29b849511c4d +Signed-off-by: Philip Yang <Philip.Yang@amd.com> +Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> +Reviewed-by: Christian König <christian.koenig@amd.com> +Signed-off-by: Chaudhary Amit Kumar <Chaudharyamit.Kumar@amd.com> +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h | 2 +- + drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 140 ++++++--------- + drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 14 +- + drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c | 25 ++- + drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h | 4 +- + drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 178 ++++++++------------ + drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h | 3 +- + 7 files changed, 157 insertions(+), 209 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h +index 7c5f5d1601e6..a130e766cbdb 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h +@@ -36,7 +36,7 @@ struct amdgpu_bo_list_entry { + struct amdgpu_bo_va *bo_va; + uint32_t priority; + struct page **user_pages; +- int user_invalidated; ++ bool user_invalidated; + }; + + struct amdgpu_bo_list { +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +index 7a4508f1ab81..adfebc79124b 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +@@ -53,7 +53,6 @@ static int amdgpu_cs_user_fence_chunk(struct amdgpu_cs_parser *p, + p->uf_entry.tv.bo = &bo->tbo; + /* One for TTM and one for the CS job */ + p->uf_entry.tv.num_shared = 2; +- p->uf_entry.user_pages = NULL; + + drm_gem_object_put_unlocked(gobj); + +@@ -541,14 +540,14 @@ static 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 (amdgpu_ttm_tt_userptr_needs_pages(bo->tbo.ttm) && +- lobj->user_pages) { ++ if (amdgpu_ttm_tt_is_userptr(bo->tbo.ttm) && ++ lobj->user_invalidated && lobj->user_pages) { + amdgpu_bo_placement_from_domain(bo, + AMDGPU_GEM_DOMAIN_CPU); + r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx); + if (r) + return r; ++ + amdgpu_ttm_tt_set_user_pages(bo->tbo.ttm, + lobj->user_pages); + binding_userptr = true; +@@ -579,7 +578,6 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p, + struct amdgpu_bo *gds; + struct amdgpu_bo *gws; + struct amdgpu_bo *oa; +- unsigned tries = 10; + int r; + + INIT_LIST_HEAD(&p->validated); +@@ -615,79 +613,45 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p, + if (p->uf_entry.tv.bo && !ttm_to_amdgpu_bo(p->uf_entry.tv.bo)->parent) + list_add(&p->uf_entry.tv.head, &p->validated); + +- while (1) { +- struct list_head need_pages; +- +- r = ttm_eu_reserve_buffers(&p->ticket, &p->validated, true, +- &duplicates); +- if (unlikely(r != 0)) { +- if (r != -ERESTARTSYS) +- DRM_ERROR("ttm_eu_reserve_buffers failed.\n"); +- goto error_free_pages; +- } +- +- INIT_LIST_HEAD(&need_pages); +- amdgpu_bo_list_for_each_userptr_entry(e, p->bo_list) { +- struct amdgpu_bo *bo = ttm_to_amdgpu_bo(e->tv.bo); +- +- if (amdgpu_ttm_tt_userptr_invalidated(bo->tbo.ttm, +- &e->user_invalidated) && e->user_pages) { +- +- /* We acquired a page array, but somebody +- * invalidated it. Free it and try again +- */ +- release_pages(e->user_pages, +- bo->tbo.ttm->num_pages); +- kvfree(e->user_pages); +- e->user_pages = NULL; +- } +- +- if (amdgpu_ttm_tt_userptr_needs_pages(bo->tbo.ttm) && +- !e->user_pages) { +- list_del(&e->tv.head); +- list_add(&e->tv.head, &need_pages); +- +- amdgpu_bo_unreserve(bo); +- } ++ /* Get userptr backing pages. If pages are updated after registered ++ * in amdgpu_gem_userptr_ioctl(), amdgpu_cs_list_validate() will do ++ * amdgpu_ttm_backend_bind() to flush and invalidate new pages ++ */ ++ amdgpu_bo_list_for_each_userptr_entry(e, p->bo_list) { ++ struct amdgpu_bo *bo = ttm_to_amdgpu_bo(e->tv.bo); ++ bool userpage_invalidated = false; ++ int i; ++ ++ e->user_pages = kvmalloc_array(bo->tbo.ttm->num_pages, ++ sizeof(struct page *), ++ GFP_KERNEL | __GFP_ZERO); ++ if (!e->user_pages) { ++ DRM_ERROR("calloc failure\n"); ++ return -ENOMEM; + } + +- if (list_empty(&need_pages)) +- break; +- +- /* Unreserve everything again. */ +- ttm_eu_backoff_reservation(&p->ticket, &p->validated); +- +- /* We tried too many times, just abort */ +- if (!--tries) { +- r = -EDEADLK; +- DRM_ERROR("deadlock in %s\n", __func__); +- goto error_free_pages; ++ r = amdgpu_ttm_tt_get_user_pages(bo->tbo.ttm, e->user_pages); ++ if (r) { ++ kvfree(e->user_pages); ++ e->user_pages = NULL; ++ return r; + } + +- /* Fill the page arrays for all userptrs. */ +- list_for_each_entry(e, &need_pages, tv.head) { +- struct ttm_tt *ttm = e->tv.bo->ttm; +- +- e->user_pages = kvmalloc_array(ttm->num_pages, +- sizeof(struct page*), +- GFP_KERNEL | __GFP_ZERO); +- if (!e->user_pages) { +- r = -ENOMEM; +- DRM_ERROR("calloc failure in %s\n", __func__); +- goto error_free_pages; +- } +- +- r = amdgpu_ttm_tt_get_user_pages(ttm, e->user_pages); +- if (r) { +- DRM_ERROR("amdgpu_ttm_tt_get_user_pages failed.\n"); +- kvfree(e->user_pages); +- e->user_pages = NULL; +- goto error_free_pages; ++ for (i = 0; i < bo->tbo.ttm->num_pages; i++) { ++ if (bo->tbo.ttm->pages[i] != e->user_pages[i]) { ++ userpage_invalidated = true; ++ break; + } + } ++ e->user_invalidated = userpage_invalidated; ++ } + +- /* And try again. */ +- list_splice(&need_pages, &p->validated); ++ r = ttm_eu_reserve_buffers(&p->ticket, &p->validated, true, ++ &duplicates); ++ if (unlikely(r != 0)) { ++ if (r != -ERESTARTSYS) ++ DRM_ERROR("ttm_eu_reserve_buffers failed.\n"); ++ goto out; + } + + amdgpu_cs_get_threshold_for_moves(p->adev, &p->bytes_moved_threshold, +@@ -756,19 +720,7 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p, + error_validate: + if (r) + ttm_eu_backoff_reservation(&p->ticket, &p->validated); +- +-error_free_pages: +- +- amdgpu_bo_list_for_each_userptr_entry(e, p->bo_list) { +- struct amdgpu_bo *bo = ttm_to_amdgpu_bo(e->tv.bo); +- if (!e->user_pages) +- continue; +- +- release_pages(e->user_pages, +- bo->tbo.ttm->num_pages); +- kvfree(e->user_pages); +- } +- ++out: + return r; + } + +@@ -1227,7 +1179,6 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p, + struct amdgpu_bo_list_entry *e; + struct amdgpu_job *job; + uint64_t seq; +- + int r; + + job = p->job; +@@ -1237,15 +1188,23 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p, + if (r) + goto error_unlock; + +- /* No memory allocation is allowed while holding the mn lock */ ++ /* No memory allocation is allowed while holding the mn lock. ++ * p->mn is hold until amdgpu_cs_submit is finished and fence is added ++ * to BOs. ++ */ + amdgpu_mn_lock(p->mn); ++ ++ /* If userptr are invalidated after amdgpu_cs_parser_bos(), return ++ * -EAGAIN, drmIoctl in libdrm will restart the amdgpu_cs_ioctl. ++ */ + amdgpu_bo_list_for_each_userptr_entry(e, p->bo_list) { + struct amdgpu_bo *bo = ttm_to_amdgpu_bo(e->tv.bo); + +- if (amdgpu_ttm_tt_userptr_needs_pages(bo->tbo.ttm)) { +- r = -ERESTARTSYS; +- goto error_abort; +- } ++ r |= !amdgpu_ttm_tt_get_user_pages_done(bo->tbo.ttm); ++ } ++ if (r) { ++ r = -EAGAIN; ++ goto error_abort; + } + + job->owner = p->filp; +@@ -1342,6 +1301,7 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) + + out: + amdgpu_cs_parser_fini(&parser, r, reserved_buffers); ++ + return r; + } + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +index 254a7c6c5724..48b0ca33ac06 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +@@ -360,26 +360,24 @@ int amdgpu_gem_userptr_ioctl(struct drm_device *dev, void *data, + + r = amdgpu_bo_reserve(bo, true); + if (r) +- goto free_pages; ++ goto user_pages_done; + + amdgpu_bo_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_GTT); + r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx); + amdgpu_bo_unreserve(bo); + if (r) +- goto free_pages; ++ goto user_pages_done; + } + + r = drm_gem_handle_create(filp, gobj, &handle); +- /* drop reference from allocate - handle holds it now */ +- drm_gem_object_put_unlocked(gobj); + if (r) +- return r; ++ goto user_pages_done; + + args->handle = handle; +- return 0; + +-free_pages: +- release_pages(bo->tbo.ttm->pages, bo->tbo.ttm->num_pages); ++user_pages_done: ++ if (args->flags & AMDGPU_GEM_USERPTR_VALIDATE) ++ amdgpu_ttm_tt_get_user_pages_done(bo->tbo.ttm); + + release_object: + drm_gem_object_put_unlocked(gobj); +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c +index 090b5793daef..4ac567dc4646 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c +@@ -220,8 +220,6 @@ static void amdgpu_mn_invalidate_node(struct amdgpu_mn_node *node, + true, false, MAX_SCHEDULE_TIMEOUT); + if (r <= 0) + DRM_ERROR("(%ld) failed to wait for user bo\n", r); +- +- amdgpu_ttm_tt_mark_user_pages(bo->tbo.ttm); + } + } + +@@ -533,3 +531,26 @@ void amdgpu_mn_unregister(struct amdgpu_bo *bo) + mutex_unlock(&adev->mn_lock); + } + ++/* flags used by HMM internal, not related to CPU/GPU PTE flags */ ++static const uint64_t hmm_range_flags[HMM_PFN_FLAG_MAX] = { ++ (1 << 0), /* HMM_PFN_VALID */ ++ (1 << 1), /* HMM_PFN_WRITE */ ++ 0 /* HMM_PFN_DEVICE_PRIVATE */ ++}; ++ ++static const uint64_t hmm_range_values[HMM_PFN_VALUE_MAX] = { ++ 0xfffffffffffffffeUL, /* HMM_PFN_ERROR */ ++ 0, /* HMM_PFN_NONE */ ++ 0xfffffffffffffffcUL /* HMM_PFN_SPECIAL */ ++}; ++ ++void amdgpu_hmm_init_range(struct hmm_range *range) ++{ ++ if (range) { ++ range->flags = hmm_range_flags; ++ range->values = hmm_range_values; ++ range->pfn_shift = PAGE_SHIFT; ++ range->pfns = NULL; ++ INIT_LIST_HEAD(&range->list); ++ } ++} +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h +index 0a51fd00021c..4803e216e174 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h +@@ -25,9 +25,10 @@ + #define __AMDGPU_MN_H__ + + /* +- * MMU Notifier ++ * HMM mirror + */ + struct amdgpu_mn; ++struct hmm_range; + + enum amdgpu_mn_type { + AMDGPU_MN_TYPE_GFX, +@@ -41,6 +42,7 @@ struct amdgpu_mn *amdgpu_mn_get(struct amdgpu_device *adev, + enum amdgpu_mn_type type); + int amdgpu_mn_register(struct amdgpu_bo *bo, unsigned long addr); + void amdgpu_mn_unregister(struct amdgpu_bo *bo); ++void amdgpu_hmm_init_range(struct hmm_range *range); + #else + static inline void amdgpu_mn_lock(struct amdgpu_mn *mn) {} + static inline void amdgpu_mn_unlock(struct amdgpu_mn *mn) {} +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +index fe853624e293..d587b374665e 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +@@ -43,6 +43,7 @@ + #include <linux/pagemap.h> + #include <linux/debugfs.h> + #include <linux/iommu.h> ++#include <linux/hmm.h> + #include "amdgpu.h" + #include "amdgpu_object.h" + #include "amdgpu_trace.h" +@@ -838,98 +839,102 @@ static unsigned long amdgpu_ttm_io_mem_pfn(struct ttm_buffer_object *bo, + /* + * TTM backend functions. + */ +-struct amdgpu_ttm_gup_task_list { +- struct list_head list; +- struct task_struct *task; +-}; +- + struct amdgpu_ttm_tt { + struct ttm_dma_tt ttm; + u64 offset; + uint64_t userptr; + struct task_struct *usertask; + uint32_t userflags; +- spinlock_t guptasklock; +- struct list_head guptasks; +- atomic_t mmu_invalidations; +- uint32_t last_set_pages; ++ struct hmm_range range; + }; + + /** +- * amdgpu_ttm_tt_get_user_pages - Pin pages of memory pointed to by a USERPTR +- * pointer to memory ++ * amdgpu_ttm_tt_get_user_pages - get device accessible pages that back user ++ * memory and start HMM tracking CPU page table update + * +- * Called by amdgpu_gem_userptr_ioctl() and amdgpu_cs_parser_bos(). +- * This provides a wrapper around the get_user_pages() call to provide +- * device accessible pages that back user memory. ++ * Calling function must call amdgpu_ttm_tt_userptr_range_done() once and only ++ * once afterwards to stop HMM tracking + */ + int amdgpu_ttm_tt_get_user_pages(struct ttm_tt *ttm, struct page **pages) + { + struct amdgpu_ttm_tt *gtt = (void *)ttm; + struct mm_struct *mm = gtt->usertask->mm; +- unsigned int flags = 0; +- unsigned pinned = 0; +- int r; ++ unsigned long end = gtt->userptr + ttm->num_pages * PAGE_SIZE; ++ struct hmm_range *range = >t->range; ++ int r = 0, i; + + if (!mm) /* Happens during process shutdown */ + return -ESRCH; + +- if (!(gtt->userflags & AMDGPU_GEM_USERPTR_READONLY)) +- flags |= FOLL_WRITE; ++ amdgpu_hmm_init_range(range); + + down_read(&mm->mmap_sem); + +- if (gtt->userflags & AMDGPU_GEM_USERPTR_ANONONLY) { +- /* +- * 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; ++ range->vma = find_vma(mm, gtt->userptr); ++ if (!range_in_vma(range->vma, gtt->userptr, end)) ++ r = -EFAULT; ++ else if ((gtt->userflags & AMDGPU_GEM_USERPTR_ANONONLY) && ++ range->vma->vm_file) ++ r = -EPERM; ++ if (r) ++ goto out; + +- vma = find_vma(mm, gtt->userptr); +- if (!vma || vma->vm_file || vma->vm_end < end) { +- up_read(&mm->mmap_sem); +- return -EPERM; +- } ++ range->pfns = kvmalloc_array(ttm->num_pages, sizeof(uint64_t), ++ GFP_KERNEL); ++ if (range->pfns == NULL) { ++ r = -ENOMEM; ++ goto out; + } ++ range->start = gtt->userptr; ++ range->end = end; + +- /* loop enough times using contiguous pages of memory */ +- do { +- unsigned num_pages = ttm->num_pages - pinned; +- uint64_t userptr = gtt->userptr + pinned * PAGE_SIZE; +- struct page **p = pages + pinned; +- struct amdgpu_ttm_gup_task_list guptask; ++ range->pfns[0] = range->flags[HMM_PFN_VALID]; ++ range->pfns[0] |= amdgpu_ttm_tt_is_readonly(ttm) ? ++ 0 : range->flags[HMM_PFN_WRITE]; ++ for (i = 1; i < ttm->num_pages; i++) ++ range->pfns[i] = range->pfns[0]; + +- guptask.task = current; +- spin_lock(>t->guptasklock); +- list_add(&guptask.list, >t->guptasks); +- spin_unlock(>t->guptasklock); ++ /* This may trigger page table update */ ++ r = hmm_vma_fault(range, true); ++ if (r) ++ goto out_free_pfns; + +- if (mm == current->mm) +- r = get_user_pages(userptr, num_pages, flags, p, NULL); +- else +- r = get_user_pages_remote(gtt->usertask, +- mm, userptr, num_pages, +- flags, p, NULL, NULL); ++ up_read(&mm->mmap_sem); + +- spin_lock(>t->guptasklock); +- list_del(&guptask.list); +- spin_unlock(>t->guptasklock); ++ for (i = 0; i < ttm->num_pages; i++) ++ pages[i] = hmm_pfn_to_page(range, range->pfns[i]); + +- if (r < 0) +- goto release_pages; ++ return 0; + +- pinned += r; ++out_free_pfns: ++ kvfree(range->pfns); ++ range->pfns = NULL; ++out: ++ up_read(&mm->mmap_sem); ++ return r; ++} + +- } while (pinned < ttm->num_pages); ++/** ++ * amdgpu_ttm_tt_userptr_range_done - stop HMM track the CPU page table change ++ * Check if the pages backing this ttm range have been invalidated ++ * ++ * Returns: true if pages are still valid ++ */ ++bool amdgpu_ttm_tt_get_user_pages_done(struct ttm_tt *ttm) ++{ ++ struct amdgpu_ttm_tt *gtt = (void *)ttm; ++ bool r = false; + +- up_read(&mm->mmap_sem); +- return 0; ++ if (!gtt || !gtt->userptr) ++ return false; ++ ++ WARN_ONCE(!gtt->range.pfns, "No user pages to check\n"); ++ if (gtt->range.pfns) { ++ r = hmm_vma_range_done(>t->range); ++ kvfree(gtt->range.pfns); ++ gtt->range.pfns = NULL; ++ } + +-release_pages: +- release_pages(pages, pinned); +- up_read(&mm->mmap_sem); + return r; + } + +@@ -942,16 +947,10 @@ int amdgpu_ttm_tt_get_user_pages(struct ttm_tt *ttm, struct page **pages) + */ + void amdgpu_ttm_tt_set_user_pages(struct ttm_tt *ttm, struct page **pages) + { +- struct amdgpu_ttm_tt *gtt = (void *)ttm; + unsigned i; + +- gtt->last_set_pages = atomic_read(>t->mmu_invalidations); +- for (i = 0; i < ttm->num_pages; ++i) { +- if (ttm->pages[i]) +- put_page(ttm->pages[i]); +- ++ for (i = 0; i < ttm->num_pages; ++i) + ttm->pages[i] = pages ? pages[i] : NULL; +- } + } + + /** +@@ -1036,10 +1035,11 @@ static void amdgpu_ttm_tt_unpin_userptr(struct ttm_tt *ttm) + /* unmap the pages mapped to the device */ + dma_unmap_sg(adev->dev, ttm->sg->sgl, ttm->sg->nents, direction); + +- /* mark the pages as dirty */ +- amdgpu_ttm_tt_mark_user_pages(ttm); +- + sg_free_table(ttm->sg); ++ ++ if (gtt->range.pfns && ++ ttm->pages[0] == hmm_pfn_to_page(>t->range, gtt->range.pfns[0])) ++ WARN_ONCE(1, "Missing get_user_page_done\n"); + } + + int amdgpu_ttm_gart_bind(struct amdgpu_device *adev, +@@ -1390,11 +1390,6 @@ int amdgpu_ttm_tt_set_userptr(struct ttm_tt *ttm, uint64_t addr, + gtt->usertask = current->group_leader; + get_task_struct(gtt->usertask); + +- spin_lock_init(>t->guptasklock); +- INIT_LIST_HEAD(>t->guptasks); +- atomic_set(>t->mmu_invalidations, 0); +- gtt->last_set_pages = 0; +- + return 0; + } + +@@ -1423,7 +1418,6 @@ bool amdgpu_ttm_tt_affect_userptr(struct ttm_tt *ttm, unsigned long start, + unsigned long end) + { + struct amdgpu_ttm_tt *gtt = (void *)ttm; +- struct amdgpu_ttm_gup_task_list *entry; + unsigned long size; + + if (gtt == NULL || !gtt->userptr) +@@ -1436,48 +1430,20 @@ bool amdgpu_ttm_tt_affect_userptr(struct ttm_tt *ttm, unsigned long start, + if (gtt->userptr > end || gtt->userptr + size <= start) + return false; + +- /* Search the lists of tasks that hold this mapping and see +- * if current is one of them. If it is return false. +- */ +- spin_lock(>t->guptasklock); +- list_for_each_entry(entry, >t->guptasks, list) { +- if (entry->task == current) { +- spin_unlock(>t->guptasklock); +- return false; +- } +- } +- spin_unlock(>t->guptasklock); +- +- atomic_inc(>t->mmu_invalidations); +- + return true; + } + + /** +- * amdgpu_ttm_tt_userptr_invalidated - Has the ttm_tt object been invalidated? ++ * amdgpu_ttm_tt_is_userptr - Have the pages backing by userptr? + */ +-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; +-} +- +-/** +- * amdgpu_ttm_tt_userptr_needs_pages - Have the pages backing this ttm_tt object +- * been invalidated since the last time they've been set? +- */ +-bool amdgpu_ttm_tt_userptr_needs_pages(struct ttm_tt *ttm) ++bool amdgpu_ttm_tt_is_userptr(struct ttm_tt *ttm) + { + struct amdgpu_ttm_tt *gtt = (void *)ttm; + + if (gtt == NULL || !gtt->userptr) + return false; + +- return atomic_read(>t->mmu_invalidations) != gtt->last_set_pages; ++ return true; + } + + /** +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h +index ef0f86f688a9..9afdf06717f7 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h +@@ -108,6 +108,7 @@ int amdgpu_ttm_alloc_gart(struct ttm_buffer_object *bo); + int amdgpu_ttm_recover_gart(struct ttm_buffer_object *tbo); + + int amdgpu_ttm_tt_get_user_pages(struct ttm_tt *ttm, struct page **pages); ++bool amdgpu_ttm_tt_get_user_pages_done(struct ttm_tt *ttm); + void amdgpu_ttm_tt_set_user_pages(struct ttm_tt *ttm, struct page **pages); + void amdgpu_ttm_tt_mark_user_pages(struct ttm_tt *ttm); + int amdgpu_ttm_tt_set_userptr(struct ttm_tt *ttm, uint64_t addr, +@@ -118,7 +119,7 @@ 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_userptr_needs_pages(struct ttm_tt *ttm); ++bool amdgpu_ttm_tt_is_userptr(struct ttm_tt *ttm); + bool amdgpu_ttm_tt_is_readonly(struct ttm_tt *ttm); + uint64_t amdgpu_ttm_tt_pde_flags(struct ttm_tt *ttm, struct ttm_mem_reg *mem); + uint64_t amdgpu_ttm_tt_pte_flags(struct amdgpu_device *adev, struct ttm_tt *ttm, +-- +2.17.1 + |