Merge branch 'drm-next-4.18' of git://people.freedesktop.org/~agd5f/linux into drm...
[linux-2.6-microblaze.git] / drivers / gpu / drm / amd / amdgpu / amdgpu_ttm.c
index 5e9fd25..69a2b25 100644 (file)
@@ -682,7 +682,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;
@@ -693,14 +693,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
@@ -708,9 +712,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;
                }
        }
@@ -726,7 +730,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);
@@ -739,12 +748,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;
 }
 
@@ -999,6 +1008,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);
 }
@@ -1100,8 +1112,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);
@@ -1117,7 +1134,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,