drm/amdgpu: move PT validation back into VM code v2
authorChristian König <christian.koenig@amd.com>
Wed, 28 Sep 2016 10:03:04 +0000 (12:03 +0200)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 25 Oct 2016 18:38:27 +0000 (14:38 -0400)
Saves a bunch of CPU cycles when swapping things back in and
allows us to split the VM headers into a separate file.

v2: rename parameters

Signed-off-by: Christian König <christian.koenig@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/amdgpu.h
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c

index 1c874fd525a094f3805b422d06242955c4e7cbf1..848e4ed7e32aeef2929fa0da60e8e8275f6af7b0 100644 (file)
@@ -915,8 +915,9 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm);
 void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm,
                         struct list_head *validated,
                         struct amdgpu_bo_list_entry *entry);
-void amdgpu_vm_get_pt_bos(struct amdgpu_device *adev, struct amdgpu_vm *vm,
-                         struct list_head *duplicates);
+int amdgpu_vm_validate_pt_bos(struct amdgpu_device *adev, struct amdgpu_vm *vm,
+                             int (*callback)(void *p, struct amdgpu_bo *bo),
+                             void *param);
 void amdgpu_vm_move_pt_bos_in_lru(struct amdgpu_device *adev,
                                  struct amdgpu_vm *vm);
 int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
index 504ae09d3991dcd9306ceba3c614b26f281695c5..a13e551e67cf6f459e013ff55327423922a30139 100644 (file)
@@ -388,9 +388,9 @@ retry:
 
 /* Last resort, try to evict something from the current working set */
 static bool amdgpu_cs_try_evict(struct amdgpu_cs_parser *p,
-                               struct amdgpu_bo_list_entry *lobj)
+                               struct amdgpu_bo *validated)
 {
-       uint32_t domain = lobj->robj->allowed_domains;
+       uint32_t domain = validated->allowed_domains;
        int r;
 
        if (!p->evictable)
@@ -406,7 +406,7 @@ static bool amdgpu_cs_try_evict(struct amdgpu_cs_parser *p,
                uint32_t other;
 
                /* If we reached our current BO we can forget it */
-               if (candidate == lobj)
+               if (candidate->robj == validated)
                        break;
 
                other = amdgpu_mem_type_to_domain(bo->tbo.mem.mem_type);
@@ -439,6 +439,23 @@ static bool amdgpu_cs_try_evict(struct amdgpu_cs_parser *p,
        return false;
 }
 
+static int amdgpu_cs_validate(void *param, struct amdgpu_bo *bo)
+{
+       struct amdgpu_cs_parser *p = param;
+       int r;
+
+       do {
+               r = amdgpu_cs_bo_validate(p, bo);
+       } while (r == -ENOMEM && amdgpu_cs_try_evict(p, bo));
+       if (r)
+               return r;
+
+       if (bo->shadow)
+               r = amdgpu_cs_bo_validate(p, bo);
+
+       return r;
+}
+
 static int amdgpu_cs_list_validate(struct amdgpu_cs_parser *p,
                            struct list_head *validated)
 {
@@ -466,18 +483,10 @@ static int amdgpu_cs_list_validate(struct amdgpu_cs_parser *p,
                if (p->evictable == lobj)
                        p->evictable = NULL;
 
-               do {
-                       r = amdgpu_cs_bo_validate(p, bo);
-               } while (r == -ENOMEM && amdgpu_cs_try_evict(p, lobj));
+               r = amdgpu_cs_validate(p, bo);
                if (r)
                        return r;
 
-               if (bo->shadow) {
-                       r = amdgpu_cs_bo_validate(p, bo);
-                       if (r)
-                               return r;
-               }
-
                if (binding_userptr) {
                        drm_free_large(lobj->user_pages);
                        lobj->user_pages = NULL;
@@ -595,14 +604,19 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p,
                list_splice(&need_pages, &p->validated);
        }
 
-       amdgpu_vm_get_pt_bos(p->adev, &fpriv->vm, &duplicates);
-
        p->bytes_moved_threshold = amdgpu_cs_get_threshold_for_moves(p->adev);
        p->bytes_moved = 0;
        p->evictable = list_last_entry(&p->validated,
                                       struct amdgpu_bo_list_entry,
                                       tv.head);
 
+       r = amdgpu_vm_validate_pt_bos(p->adev, &fpriv->vm,
+                                     amdgpu_cs_validate, p);
+       if (r) {
+               DRM_ERROR("amdgpu_vm_validate_pt_bos() failed.\n");
+               goto error_validate;
+       }
+
        r = amdgpu_cs_list_validate(p, &duplicates);
        if (r) {
                DRM_ERROR("amdgpu_cs_list_validate(duplicates) failed.\n");
index d4fce326502bc4ed1e6f2b841bee9590cb8aba53..5dc0158b12db3a975e9e596566ad11635c31b0d4 100644 (file)
@@ -469,6 +469,16 @@ out:
        return r;
 }
 
+static int amdgpu_gem_va_check(void *param, struct amdgpu_bo *bo)
+{
+       unsigned domain = amdgpu_mem_type_to_domain(bo->tbo.mem.mem_type);
+
+       /* if anything is swapped out don't swap it in here,
+          just abort and wait for the next CS */
+
+       return domain == AMDGPU_GEM_DOMAIN_CPU ? -ERESTARTSYS : 0;
+}
+
 /**
  * amdgpu_gem_va_update_vm -update the bo_va in its VM
  *
@@ -479,7 +489,8 @@ out:
  * vital here, so they are not reported back to userspace.
  */
 static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev,
-                                   struct amdgpu_bo_va *bo_va, uint32_t operation)
+                                   struct amdgpu_bo_va *bo_va,
+                                   uint32_t operation)
 {
        struct ttm_validate_buffer tv, *entry;
        struct amdgpu_bo_list_entry vm_pd;
@@ -502,7 +513,6 @@ static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev,
        if (r)
                goto error_print;
 
-       amdgpu_vm_get_pt_bos(adev, bo_va->vm, &duplicates);
        list_for_each_entry(entry, &list, head) {
                domain = amdgpu_mem_type_to_domain(entry->bo->mem.mem_type);
                /* if anything is swapped out don't swap it in here,
@@ -510,13 +520,10 @@ static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev,
                if (domain == AMDGPU_GEM_DOMAIN_CPU)
                        goto error_unreserve;
        }
-       list_for_each_entry(entry, &duplicates, head) {
-               domain = amdgpu_mem_type_to_domain(entry->bo->mem.mem_type);
-               /* if anything is swapped out don't swap it in here,
-                  just abort and wait for the next CS */
-               if (domain == AMDGPU_GEM_DOMAIN_CPU)
-                       goto error_unreserve;
-       }
+       r = amdgpu_vm_validate_pt_bos(adev, bo_va->vm, amdgpu_gem_va_check,
+                                     NULL);
+       if (r)
+               goto error_unreserve;
 
        r = amdgpu_vm_update_page_directory(adev, bo_va->vm);
        if (r)
@@ -537,8 +544,6 @@ error_print:
                DRM_ERROR("Couldn't update BO_VA (%d)\n", r);
 }
 
-
-
 int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
                          struct drm_file *filp)
 {
index f4b78b66444d97e4c60a25354d78b0bec2fcd0b2..c171b16cf0f11409567b3103eab7b6e5db35ab39 100644 (file)
@@ -116,27 +116,29 @@ void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm,
 }
 
 /**
- * amdgpu_vm_get_bos - add the vm BOs to a duplicates list
+ * amdgpu_vm_validate_pt_bos - validate the page table BOs
  *
  * @adev: amdgpu device pointer
  * @vm: vm providing the BOs
- * @duplicates: head of duplicates list
+ * @validate: callback to do the validation
+ * @param: parameter for the validation callback
  *
- * Add the page directory to the BO duplicates list
- * for command submission.
+ * Validate the page table BOs on command submission if neccessary.
  */
-void amdgpu_vm_get_pt_bos(struct amdgpu_device *adev, struct amdgpu_vm *vm,
-                         struct list_head *duplicates)
+int amdgpu_vm_validate_pt_bos(struct amdgpu_device *adev, struct amdgpu_vm *vm,
+                             int (*validate)(void *p, struct amdgpu_bo *bo),
+                             void *param)
 {
        uint64_t num_evictions;
        unsigned i;
+       int r;
 
        /* We only need to validate the page tables
         * if they aren't already valid.
         */
        num_evictions = atomic64_read(&adev->num_evictions);
        if (num_evictions == vm->last_eviction_counter)
-               return;
+               return 0;
 
        /* add the vm page table to the list */
        for (i = 0; i <= vm->max_pde_used; ++i) {
@@ -145,9 +147,12 @@ void amdgpu_vm_get_pt_bos(struct amdgpu_device *adev, struct amdgpu_vm *vm,
                if (!entry->robj)
                        continue;
 
-               list_add(&entry->tv.head, duplicates);
+               r = validate(param, entry->robj);
+               if (r)
+                       return r;
        }
 
+       return 0;
 }
 
 /**