diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 128 |
1 files changed, 63 insertions, 65 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index 0bda8f2a188a..a418df1b9422 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 | } |
| @@ -112,7 +113,17 @@ int amdgpu_gem_object_open(struct drm_gem_object *obj, | |||
| 112 | struct amdgpu_fpriv *fpriv = file_priv->driver_priv; | 113 | struct amdgpu_fpriv *fpriv = file_priv->driver_priv; |
| 113 | struct amdgpu_vm *vm = &fpriv->vm; | 114 | struct amdgpu_vm *vm = &fpriv->vm; |
| 114 | struct amdgpu_bo_va *bo_va; | 115 | struct amdgpu_bo_va *bo_va; |
| 116 | struct mm_struct *mm; | ||
| 115 | int r; | 117 | int r; |
| 118 | |||
| 119 | mm = amdgpu_ttm_tt_get_usermm(abo->tbo.ttm); | ||
| 120 | if (mm && mm != current->mm) | ||
| 121 | return -EPERM; | ||
| 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 | |||
| 116 | r = amdgpu_bo_reserve(abo, false); | 127 | r = amdgpu_bo_reserve(abo, false); |
| 117 | if (r) | 128 | if (r) |
| 118 | return r; | 129 | return r; |
| @@ -127,35 +138,6 @@ int amdgpu_gem_object_open(struct drm_gem_object *obj, | |||
| 127 | return 0; | 138 | return 0; |
| 128 | } | 139 | } |
| 129 | 140 | ||
| 130 | static int amdgpu_gem_vm_check(void *param, struct amdgpu_bo *bo) | ||
| 131 | { | ||
| 132 | /* if anything is swapped out don't swap it in here, | ||
| 133 | just abort and wait for the next CS */ | ||
| 134 | if (!amdgpu_bo_gpu_accessible(bo)) | ||
| 135 | return -ERESTARTSYS; | ||
| 136 | |||
| 137 | if (bo->shadow && !amdgpu_bo_gpu_accessible(bo->shadow)) | ||
| 138 | return -ERESTARTSYS; | ||
| 139 | |||
| 140 | return 0; | ||
| 141 | } | ||
| 142 | |||
| 143 | static bool amdgpu_gem_vm_ready(struct amdgpu_device *adev, | ||
| 144 | struct amdgpu_vm *vm, | ||
| 145 | struct list_head *list) | ||
| 146 | { | ||
| 147 | struct ttm_validate_buffer *entry; | ||
| 148 | |||
| 149 | list_for_each_entry(entry, list, head) { | ||
| 150 | struct amdgpu_bo *bo = | ||
| 151 | container_of(entry->bo, struct amdgpu_bo, tbo); | ||
| 152 | if (amdgpu_gem_vm_check(NULL, bo)) | ||
| 153 | return false; | ||
| 154 | } | ||
| 155 | |||
| 156 | return !amdgpu_vm_validate_pt_bos(adev, vm, amdgpu_gem_vm_check, NULL); | ||
| 157 | } | ||
| 158 | |||
| 159 | void amdgpu_gem_object_close(struct drm_gem_object *obj, | 141 | void amdgpu_gem_object_close(struct drm_gem_object *obj, |
| 160 | struct drm_file *file_priv) | 142 | struct drm_file *file_priv) |
| 161 | { | 143 | { |
| @@ -165,13 +147,14 @@ void amdgpu_gem_object_close(struct drm_gem_object *obj, | |||
| 165 | struct amdgpu_vm *vm = &fpriv->vm; | 147 | struct amdgpu_vm *vm = &fpriv->vm; |
| 166 | 148 | ||
| 167 | struct amdgpu_bo_list_entry vm_pd; | 149 | struct amdgpu_bo_list_entry vm_pd; |
| 168 | struct list_head list; | 150 | struct list_head list, duplicates; |
| 169 | struct ttm_validate_buffer tv; | 151 | struct ttm_validate_buffer tv; |
| 170 | struct ww_acquire_ctx ticket; | 152 | struct ww_acquire_ctx ticket; |
| 171 | struct amdgpu_bo_va *bo_va; | 153 | struct amdgpu_bo_va *bo_va; |
| 172 | int r; | 154 | int r; |
| 173 | 155 | ||
| 174 | INIT_LIST_HEAD(&list); | 156 | INIT_LIST_HEAD(&list); |
| 157 | INIT_LIST_HEAD(&duplicates); | ||
| 175 | 158 | ||
| 176 | tv.bo = &bo->tbo; | 159 | tv.bo = &bo->tbo; |
| 177 | tv.shared = true; | 160 | tv.shared = true; |
| @@ -179,7 +162,7 @@ void amdgpu_gem_object_close(struct drm_gem_object *obj, | |||
| 179 | 162 | ||
| 180 | amdgpu_vm_get_pd_bo(vm, &list, &vm_pd); | 163 | amdgpu_vm_get_pd_bo(vm, &list, &vm_pd); |
| 181 | 164 | ||
| 182 | r = ttm_eu_reserve_buffers(&ticket, &list, false, NULL); | 165 | r = ttm_eu_reserve_buffers(&ticket, &list, false, &duplicates); |
| 183 | if (r) { | 166 | if (r) { |
| 184 | dev_err(adev->dev, "leaking bo va because " | 167 | dev_err(adev->dev, "leaking bo va because " |
| 185 | "we fail to reserve bo (%d)\n", r); | 168 | "we fail to reserve bo (%d)\n", r); |
| @@ -189,7 +172,7 @@ void amdgpu_gem_object_close(struct drm_gem_object *obj, | |||
| 189 | if (bo_va && --bo_va->ref_count == 0) { | 172 | if (bo_va && --bo_va->ref_count == 0) { |
| 190 | amdgpu_vm_bo_rmv(adev, bo_va); | 173 | amdgpu_vm_bo_rmv(adev, bo_va); |
| 191 | 174 | ||
| 192 | if (amdgpu_gem_vm_ready(adev, vm, &list)) { | 175 | if (amdgpu_vm_ready(vm)) { |
| 193 | struct dma_fence *fence = NULL; | 176 | struct dma_fence *fence = NULL; |
| 194 | 177 | ||
| 195 | r = amdgpu_vm_clear_freed(adev, vm, &fence); | 178 | r = amdgpu_vm_clear_freed(adev, vm, &fence); |
| @@ -214,18 +197,24 @@ int amdgpu_gem_create_ioctl(struct drm_device *dev, void *data, | |||
| 214 | struct drm_file *filp) | 197 | struct drm_file *filp) |
| 215 | { | 198 | { |
| 216 | 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; | ||
| 217 | union drm_amdgpu_gem_create *args = data; | 202 | union drm_amdgpu_gem_create *args = data; |
| 203 | uint64_t flags = args->in.domain_flags; | ||
| 218 | uint64_t size = args->in.bo_size; | 204 | uint64_t size = args->in.bo_size; |
| 205 | struct reservation_object *resv = NULL; | ||
| 219 | struct drm_gem_object *gobj; | 206 | struct drm_gem_object *gobj; |
| 220 | uint32_t handle; | 207 | uint32_t handle; |
| 221 | bool kernel = false; | ||
| 222 | int r; | 208 | int r; |
| 223 | 209 | ||
| 224 | /* reject invalid gem flags */ | 210 | /* reject invalid gem flags */ |
| 225 | if (args->in.domain_flags & ~(AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED | | 211 | if (flags & ~(AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED | |
| 226 | AMDGPU_GEM_CREATE_NO_CPU_ACCESS | | 212 | AMDGPU_GEM_CREATE_NO_CPU_ACCESS | |
| 227 | AMDGPU_GEM_CREATE_CPU_GTT_USWC | | 213 | AMDGPU_GEM_CREATE_CPU_GTT_USWC | |
| 228 | AMDGPU_GEM_CREATE_VRAM_CLEARED)) | 214 | AMDGPU_GEM_CREATE_VRAM_CLEARED | |
| 215 | AMDGPU_GEM_CREATE_VM_ALWAYS_VALID | | ||
| 216 | AMDGPU_GEM_CREATE_EXPLICIT_SYNC)) | ||
| 217 | |||
| 229 | return -EINVAL; | 218 | return -EINVAL; |
| 230 | 219 | ||
| 231 | /* reject invalid gem domains */ | 220 | /* reject invalid gem domains */ |
| @@ -240,7 +229,7 @@ int amdgpu_gem_create_ioctl(struct drm_device *dev, void *data, | |||
| 240 | /* create a gem object to contain this object in */ | 229 | /* create a gem object to contain this object in */ |
| 241 | if (args->in.domains & (AMDGPU_GEM_DOMAIN_GDS | | 230 | if (args->in.domains & (AMDGPU_GEM_DOMAIN_GDS | |
| 242 | AMDGPU_GEM_DOMAIN_GWS | AMDGPU_GEM_DOMAIN_OA)) { | 231 | AMDGPU_GEM_DOMAIN_GWS | AMDGPU_GEM_DOMAIN_OA)) { |
| 243 | kernel = true; | 232 | flags |= AMDGPU_GEM_CREATE_NO_CPU_ACCESS; |
| 244 | if (args->in.domains == AMDGPU_GEM_DOMAIN_GDS) | 233 | if (args->in.domains == AMDGPU_GEM_DOMAIN_GDS) |
| 245 | size = size << AMDGPU_GDS_SHIFT; | 234 | size = size << AMDGPU_GDS_SHIFT; |
| 246 | else if (args->in.domains == AMDGPU_GEM_DOMAIN_GWS) | 235 | else if (args->in.domains == AMDGPU_GEM_DOMAIN_GWS) |
| @@ -252,10 +241,25 @@ int amdgpu_gem_create_ioctl(struct drm_device *dev, void *data, | |||
| 252 | } | 241 | } |
| 253 | size = roundup(size, PAGE_SIZE); | ||
