diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 63 |
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 | ||
46 | int amdgpu_gem_object_create(struct amdgpu_device *adev, unsigned long size, | 46 | int 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 | ||
60 | retry: | 61 | retry: |
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: | |||
645 | int amdgpu_gem_op_ioctl(struct drm_device *dev, void *data, | 671 | int 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 | ||