aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
diff options
context:
space:
mode:
authorChristian König <christian.koenig@amd.com>2017-08-25 03:14:43 -0400
committerAlex Deucher <alexander.deucher@amd.com>2017-08-31 13:46:35 -0400
commite1eb899b45781b9bb77e6d7772d6e67bb0bc1a18 (patch)
treea9ae3cb189187feffa80d868d5caa31bb2a78795 /drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
parent73fb16e7ebee12953de32a7a2552e0cf2bf74ebf (diff)
drm/amdgpu: add IOCTL interface for per VM BOs v3
Add the IOCTL interface so that applications can allocate per VM BOs. Still WIP since not all corner cases are tested yet, but this reduces average CS overhead for 10K BOs from 21ms down to 48us. v2: add some extra checks, remove the WIP tag v3: rename new flag to AMDGPU_GEM_CREATE_VM_ALWAYS_VALID Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c')
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c63
1 files changed, 46 insertions, 17 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
index e32a2b55b54f..f1e61b3df640 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
@@ -44,11 +44,12 @@ void amdgpu_gem_object_free(struct drm_gem_object *gobj)
44} 44}
45 45
46int amdgpu_gem_object_create(struct amdgpu_device *adev, unsigned long size, 46int amdgpu_gem_object_create(struct amdgpu_device *adev, unsigned long size,
47 int alignment, u32 initial_domain, 47 int alignment, u32 initial_domain,
48 u64 flags, bool kernel, 48 u64 flags, bool kernel,
49 struct drm_gem_object **obj) 49 struct reservation_object *resv,
50 struct drm_gem_object **obj)
50{ 51{
51 struct amdgpu_bo *robj; 52 struct amdgpu_bo *bo;
52 int r; 53 int r;
53 54
54 *obj = NULL; 55 *obj = NULL;
@@ -59,7 +60,7 @@ int amdgpu_gem_object_create(struct amdgpu_device *adev, unsigned long size,
59 60
60retry: 61retry:
61 r = amdgpu_bo_create(adev, size, alignment, kernel, initial_domain, 62 r = amdgpu_bo_create(adev, size, alignment, kernel, initial_domain,
62 flags, NULL, NULL, 0, &robj); 63 flags, NULL, resv, 0, &bo);
63 if (r) { 64 if (r) {
64 if (r != -ERESTARTSYS) { 65 if (r != -ERESTARTSYS) {
65 if (initial_domain == AMDGPU_GEM_DOMAIN_VRAM) { 66 if (initial_domain == AMDGPU_GEM_DOMAIN_VRAM) {
@@ -71,7 +72,7 @@ retry:
71 } 72 }
72 return r; 73 return r;
73 } 74 }
74 *obj = &robj->gem_base; 75 *obj = &bo->gem_base;
75 76
76 return 0; 77 return 0;
77} 78}
@@ -119,6 +120,10 @@ int amdgpu_gem_object_open(struct drm_gem_object *obj,
119 if (mm && mm != current->mm) 120 if (mm && mm != current->mm)
120 return -EPERM; 121 return -EPERM;
121 122
123 if (abo->flags & AMDGPU_GEM_CREATE_VM_ALWAYS_VALID &&
124 abo->tbo.resv != vm->root.base.bo->tbo.resv)
125 return -EPERM;
126
122 r = amdgpu_bo_reserve(abo, false); 127 r = amdgpu_bo_reserve(abo, false);
123 if (r) 128 if (r)
124 return r; 129 return r;
@@ -142,13 +147,14 @@ void amdgpu_gem_object_close(struct drm_gem_object *obj,
142 struct amdgpu_vm *vm = &fpriv->vm; 147 struct amdgpu_vm *vm = &fpriv->vm;
143 148
144 struct amdgpu_bo_list_entry vm_pd; 149 struct amdgpu_bo_list_entry vm_pd;
145 struct list_head list; 150 struct list_head list, duplicates;
146 struct ttm_validate_buffer tv; 151 struct ttm_validate_buffer tv;
147 struct ww_acquire_ctx ticket; 152 struct ww_acquire_ctx ticket;
148 struct amdgpu_bo_va *bo_va; 153 struct amdgpu_bo_va *bo_va;
149 int r; 154 int r;
150 155
151 INIT_LIST_HEAD(&list); 156 INIT_LIST_HEAD(&list);
157 INIT_LIST_HEAD(&duplicates);
152 158
153 tv.bo = &bo->tbo; 159 tv.bo = &bo->tbo;
154 tv.shared = true; 160 tv.shared = true;
@@ -156,7 +162,7 @@ void amdgpu_gem_object_close(struct drm_gem_object *obj,
156 162
157 amdgpu_vm_get_pd_bo(vm, &list, &vm_pd); 163 amdgpu_vm_get_pd_bo(vm, &list, &vm_pd);
158 164
159 r = ttm_eu_reserve_buffers(&ticket, &list, false, NULL); 165 r = ttm_eu_reserve_buffers(&ticket, &list, false, &duplicates);
160 if (r) { 166 if (r) {
161 dev_err(adev->dev, "leaking bo va because " 167 dev_err(adev->dev, "leaking bo va because "
162 "we fail to reserve bo (%d)\n", r); 168 "we fail to reserve bo (%d)\n", r);
@@ -191,9 +197,12 @@ int amdgpu_gem_create_ioctl(struct drm_device *dev, void *data,
191 struct drm_file *filp) 197 struct drm_file *filp)
192{ 198{
193 struct amdgpu_device *adev = dev->dev_private; 199 struct amdgpu_device *adev = dev->dev_private;
200 struct amdgpu_fpriv *fpriv = filp->driver_priv;
201 struct amdgpu_vm *vm = &fpriv->vm;
194 union drm_amdgpu_gem_create *args = data; 202 union drm_amdgpu_gem_create *args = data;
195 uint64_t flags = args->in.domain_flags; 203 uint64_t flags = args->in.domain_flags;
196 uint64_t size = args->in.bo_size; 204 uint64_t size = args->in.bo_size;
205 struct reservation_object *resv = NULL;
197 struct drm_gem_object *gobj; 206 struct drm_gem_object *gobj;
198 uint32_t handle; 207 uint32_t handle;
199 int r; 208 int r;
@@ -202,7 +211,8 @@ int amdgpu_gem_create_ioctl(struct drm_device *dev, void *data,
202 if (flags & ~(AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED | 211 if (flags & ~(AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED |
203 AMDGPU_GEM_CREATE_NO_CPU_ACCESS | 212 AMDGPU_GEM_CREATE_NO_CPU_ACCESS |
204 AMDGPU_GEM_CREATE_CPU_GTT_USWC | 213 AMDGPU_GEM_CREATE_CPU_GTT_USWC |
205 AMDGPU_GEM_CREATE_VRAM_CLEARED)) 214 AMDGPU_GEM_CREATE_VRAM_CLEARED |
215 AMDGPU_GEM_CREATE_VM_ALWAYS_VALID))
206 return -EINVAL; 216 return -EINVAL;
207 217
208 /* reject invalid gem domains */ 218 /* reject invalid gem domains */
@@ -229,9 +239,25 @@ int amdgpu_gem_create_ioctl(struct drm_device *dev, void *data,
229 } 239 }
230 size = roundup(size, PAGE_SIZE); 240 size = roundup(size, PAGE_SIZE);
231 241
242 if (flags & AMDGPU_GEM_CREATE_VM_ALWAYS_VALID) {
243 r = amdgpu_bo_reserve(vm->root.base.bo, false);
244 if (r)
245 return r;
246
247 resv = vm->root.base.bo->tbo.resv;
248 }
249
232 r = amdgpu_gem_object_create(adev, size, args->in.alignment, 250 r = amdgpu_gem_object_create(adev, size, args->in.alignment,
233 (u32)(0xffffffff & args->in.domains), 251 (u32)(0xffffffff & args->in.domains),
234 flags, false, &gobj); 252 flags, false, resv, &gobj);
253 if (flags & AMDGPU_GEM_CREATE_VM_ALWAYS_VALID) {
254 if (!r) {
255 struct amdgpu_bo *abo = gem_to_amdgpu_bo(gobj);
256
257 abo->parent = amdgpu_bo_ref(vm->root.base.bo);
258 }
259 amdgpu_bo_unreserve(vm->root.base.bo);
260 }
235 if (r) 261 if (r)
236 return r; 262 return r;
237 263
@@ -273,9 +299,8 @@ int amdgpu_gem_userptr_ioctl(struct drm_device *dev, void *data,
273 } 299 }
274 300
275 /* create a gem object to contain this object in */ 301 /* create a gem object to contain this object in */
276 r = amdgpu_gem_object_create(adev, args->size, 0, 302 r = amdgpu_gem_object_create(adev, args->size, 0, AMDGPU_GEM_DOMAIN_CPU,
277 AMDGPU_GEM_DOMAIN_CPU, 0, 303 0, 0, NULL, &gobj);
278 0, &gobj);
279 if (r) 304 if (r)
280 return r; 305 return r;
281 306
@@ -527,7 +552,7 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
527 struct amdgpu_bo_list_entry vm_pd; 552 struct amdgpu_bo_list_entry vm_pd;
528 struct ttm_validate_buffer tv; 553 struct ttm_validate_buffer tv;
529 struct ww_acquire_ctx ticket; 554 struct ww_acquire_ctx ticket;
530 struct list_head list; 555 struct list_head list, duplicates;
531 uint64_t va_flags; 556 uint64_t va_flags;
532 int r = 0; 557 int r = 0;
533 558
@@ -563,6 +588,7 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
563 } 588 }
564 589
565 INIT_LIST_HEAD(&list); 590 INIT_LIST_HEAD(&list);
591 INIT_LIST_HEAD(&duplicates);
566 if ((args->operation != AMDGPU_VA_OP_CLEAR) && 592 if ((args->operation != AMDGPU_VA_OP_CLEAR) &&
567 !(args->flags & AMDGPU_VM_PAGE_PRT)) { 593 !(args->flags & AMDGPU_VM_PAGE_PRT)) {
568 gobj = drm_gem_object_lookup(filp, args->handle); 594 gobj = drm_gem_object_lookup(filp, args->handle);
@@ -579,7 +605,7 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
579 605
580 amdgpu_vm_get_pd_bo(&fpriv->vm, &list, &vm_pd); 606 amdgpu_vm_get_pd_bo(&fpriv->vm, &list, &vm_pd);
581 607
582 r = ttm_eu_reserve_buffers(&ticket, &list, true, NULL); 608 r = ttm_eu_reserve_buffers(&ticket, &list, true, &duplicates);
583 if (r) 609 if (r)
584 goto error_unref; 610 goto error_unref;
585 611
@@ -645,6 +671,7 @@ error_unref:
645int amdgpu_gem_op_ioctl(struct drm_device *dev, void *data, 671int amdgpu_gem_op_ioctl(struct drm_device *dev, void *data,
646 struct drm_file *filp) 672 struct drm_file *filp)
647{ 673{
674 struct amdgpu_device *adev = dev->dev_private;
648 struct drm_amdgpu_gem_op *args = data; 675 struct drm_amdgpu_gem_op *args = data;
649 struct drm_gem_object *gobj; 676 struct drm_gem_object *gobj;
650 struct amdgpu_bo *robj; 677 struct amdgpu_bo *robj;
@@ -692,6 +719,9 @@ int amdgpu_gem_op_ioctl(struct drm_device *dev, void *data,
692 if (robj->allowed_domains == AMDGPU_GEM_DOMAIN_VRAM) 719 if (robj->allowed_domains == AMDGPU_GEM_DOMAIN_VRAM)
693 robj->allowed_domains |= AMDGPU_GEM_DOMAIN_GTT; 720 robj->allowed_domains |= AMDGPU_GEM_DOMAIN_GTT;
694 721
722 if (robj->flags & AMDGPU_GEM_CREATE_VM_ALWAYS_VALID)
723 amdgpu_vm_bo_invalidate(adev, robj, true);
724
695 amdgpu_bo_unreserve(robj); 725 amdgpu_bo_unreserve(robj);
696 break; 726 break;
697 default: 727 default:
@@ -721,8 +751,7 @@ int amdgpu_mode_dumb_create(struct drm_file *file_priv,
721 r = amdgpu_gem_object_create(adev, args->size, 0, 751 r = amdgpu_gem_object_create(adev, args->size, 0,
722 AMDGPU_GEM_DOMAIN_VRAM, 752 AMDGPU_GEM_DOMAIN_VRAM,
723 AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED, 753 AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
724 ttm_bo_type_device, 754 false, NULL, &gobj);
725 &gobj);
726 if (r) 755 if (r)
727 return -ENOMEM; 756 return -ENOMEM;
728 757