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 <[email protected]>
---
 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(&current->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(&current->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, &gtt->guptasks);
                spin_unlock(&gtt->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(&gtt->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(&current->mm->mmap_sem);
+       up_read(&mm->mmap_sem);
        return 0;
 
 release_pages:
        release_pages(pages, pinned);
-       up_read(&current->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(&gtt->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(&gtt->guptasklock);
        INIT_LIST_HEAD(&gtt->guptasks);
        atomic_set(&gtt->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

_______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

Reply via email to