Hi Felix, The patch looks fine to me and I can ACK it, but I would prefer that Alex or Christian will review it as well before pushing it. Thanks, Oded On Fri, Mar 23, 2018 at 10:32 PM, Felix Kuehling <Felix.Kuehling at amd.com> wrote: > This commit allows amdgpu_ttm_tt_get_user_pages to work in a worker > thread rather than regular process context. This will be used when > KFD userptr BOs are restored after an MMU-notifier eviction. > > v2: Manage task reference with get_task_struct/put_task_struct > > Signed-off-by: Felix Kuehling <Felix.Kuehling at amd.com> > --- > drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 38 +++++++++++++++++++++++++-------- > 1 file changed, 29 insertions(+), 9 deletions(-) > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c > index c2fae04..25490fe 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c > @@ -689,7 +689,7 @@ struct amdgpu_ttm_tt { > struct ttm_dma_tt ttm; > u64 offset; > uint64_t userptr; > - struct mm_struct *usermm; > + struct task_struct *usertask; > uint32_t userflags; > spinlock_t guptasklock; > struct list_head guptasks; > @@ -700,14 +700,18 @@ struct amdgpu_ttm_tt { > 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; > > + if (!mm) /* Happens during process shutdown */ > + return -ESRCH; > + > if (!(gtt->userflags & AMDGPU_GEM_USERPTR_READONLY)) > flags |= FOLL_WRITE; > > - down_read(¤t->mm->mmap_sem); > + down_read(&mm->mmap_sem); > > if (gtt->userflags & AMDGPU_GEM_USERPTR_ANONONLY) { > /* check that we only use anonymous memory > @@ -715,9 +719,9 @@ int amdgpu_ttm_tt_get_user_pages(struct ttm_tt *ttm, struct page **pages) > unsigned long end = gtt->userptr + ttm->num_pages * PAGE_SIZE; > struct vm_area_struct *vma; > > - vma = find_vma(gtt->usermm, gtt->userptr); > + vma = find_vma(mm, gtt->userptr); > if (!vma || vma->vm_file || vma->vm_end < end) { > - up_read(¤t->mm->mmap_sem); > + up_read(&mm->mmap_sem); > return -EPERM; > } > } > @@ -733,7 +737,12 @@ int amdgpu_ttm_tt_get_user_pages(struct ttm_tt *ttm, struct page **pages) > list_add(&guptask.list, >t->guptasks); > spin_unlock(>t->guptasklock); > > - r = get_user_pages(userptr, num_pages, flags, p, NULL); > + 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); > > spin_lock(>t->guptasklock); > list_del(&guptask.list); > @@ -746,12 +755,12 @@ int amdgpu_ttm_tt_get_user_pages(struct ttm_tt *ttm, struct page **pages) > > } while (pinned < ttm->num_pages); > > - up_read(¤t->mm->mmap_sem); > + up_read(&mm->mmap_sem); > return 0; > > release_pages: > release_pages(pages, pinned); > - up_read(¤t->mm->mmap_sem); > + up_read(&mm->mmap_sem); > return r; > } > > @@ -972,6 +981,9 @@ static void amdgpu_ttm_backend_destroy(struct ttm_tt *ttm) > { > struct amdgpu_ttm_tt *gtt = (void *)ttm; > > + if (gtt->usertask) > + put_task_struct(gtt->usertask); > + > ttm_dma_tt_fini(>t->ttm); > kfree(gtt); > } > @@ -1072,8 +1084,13 @@ int amdgpu_ttm_tt_set_userptr(struct ttm_tt *ttm, uint64_t addr, > return -EINVAL; > > gtt->userptr = addr; > - gtt->usermm = current->mm; > gtt->userflags = flags; > + > + if (gtt->usertask) > + put_task_struct(gtt->usertask); > + 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); > @@ -1089,7 +1106,10 @@ struct mm_struct *amdgpu_ttm_tt_get_usermm(struct ttm_tt *ttm) > if (gtt == NULL) > return NULL; > > - return gtt->usermm; > + if (gtt->usertask == NULL) > + return NULL; > + > + return gtt->usertask->mm; > } > > bool amdgpu_ttm_tt_affect_userptr(struct ttm_tt *ttm, unsigned long start, > -- > 2.7.4 >