aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c')
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c137
1 files changed, 80 insertions, 57 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
index 3b355aeb62fd..749420f1ea6f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
@@ -154,42 +154,41 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data)
154{ 154{
155 union drm_amdgpu_cs *cs = data; 155 union drm_amdgpu_cs *cs = data;
156 uint64_t *chunk_array_user; 156 uint64_t *chunk_array_user;
157 uint64_t *chunk_array = NULL; 157 uint64_t *chunk_array;
158 struct amdgpu_fpriv *fpriv = p->filp->driver_priv; 158 struct amdgpu_fpriv *fpriv = p->filp->driver_priv;
159 unsigned size, i; 159 unsigned size, i;
160 int r = 0; 160 int ret;
161 161
162 if (!cs->in.num_chunks) 162 if (cs->in.num_chunks == 0)
163 goto out; 163 return 0;
164
165 chunk_array = kmalloc_array(cs->in.num_chunks, sizeof(uint64_t), GFP_KERNEL);
166 if (!chunk_array)
167 return -ENOMEM;
164 168
165 p->ctx = amdgpu_ctx_get(fpriv, cs->in.ctx_id); 169 p->ctx = amdgpu_ctx_get(fpriv, cs->in.ctx_id);
166 if (!p->ctx) { 170 if (!p->ctx) {
167 r = -EINVAL; 171 ret = -EINVAL;
168 goto out; 172 goto free_chunk;
169 } 173 }
174
170 p->bo_list = amdgpu_bo_list_get(fpriv, cs->in.bo_list_handle); 175 p->bo_list = amdgpu_bo_list_get(fpriv, cs->in.bo_list_handle);
171 176
172 /* get chunks */ 177 /* get chunks */
173 INIT_LIST_HEAD(&p->validated); 178 INIT_LIST_HEAD(&p->validated);
174 chunk_array = kmalloc_array(cs->in.num_chunks, sizeof(uint64_t), GFP_KERNEL);
175 if (chunk_array == NULL) {
176 r = -ENOMEM;
177 goto out;
178 }
179
180 chunk_array_user = (uint64_t __user *)(cs->in.chunks); 179 chunk_array_user = (uint64_t __user *)(cs->in.chunks);
181 if (copy_from_user(chunk_array, chunk_array_user, 180 if (copy_from_user(chunk_array, chunk_array_user,
182 sizeof(uint64_t)*cs->in.num_chunks)) { 181 sizeof(uint64_t)*cs->in.num_chunks)) {
183 r = -EFAULT; 182 ret = -EFAULT;
184 goto out; 183 goto put_bo_list;
185 } 184 }
186 185
187 p->nchunks = cs->in.num_chunks; 186 p->nchunks = cs->in.num_chunks;
188 p->chunks = kmalloc_array(p->nchunks, sizeof(struct amdgpu_cs_chunk), 187 p->chunks = kmalloc_array(p->nchunks, sizeof(struct amdgpu_cs_chunk),
189 GFP_KERNEL); 188 GFP_KERNEL);
190 if (p->chunks == NULL) { 189 if (!p->chunks) {
191 r = -ENOMEM; 190 ret = -ENOMEM;
192 goto out; 191 goto put_bo_list;
193 } 192 }
194 193
195 for (i = 0; i < p->nchunks; i++) { 194 for (i = 0; i < p->nchunks; i++) {
@@ -200,8 +199,9 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data)
200 chunk_ptr = (void __user *)chunk_array[i]; 199 chunk_ptr = (void __user *)chunk_array[i];
201 if (copy_from_user(&user_chunk, chunk_ptr, 200 if (copy_from_user(&user_chunk, chunk_ptr,
202 sizeof(struct drm_amdgpu_cs_chunk))) { 201 sizeof(struct drm_amdgpu_cs_chunk))) {
203 r = -EFAULT; 202 ret = -EFAULT;
204 goto out; 203 i--;
204 goto free_partial_kdata;
205 } 205 }
206 p->chunks[i].chunk_id = user_chunk.chunk_id; 206 p->chunks[i].chunk_id = user_chunk.chunk_id;
207 p->chunks[i].length_dw = user_chunk.length_dw; 207 p->chunks[i].length_dw = user_chunk.length_dw;
@@ -212,13 +212,14 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data)
212 212
213 p->chunks[i].kdata = drm_malloc_ab(size, sizeof(uint32_t)); 213 p->chunks[i].kdata = drm_malloc_ab(size, sizeof(uint32_t));
214 if (p->chunks[i].kdata == NULL) { 214 if (p->chunks[i].kdata == NULL) {
215 r = -ENOMEM; 215 ret = -ENOMEM;
216 goto out; 216 i--;
217 goto free_partial_kdata;
217 } 218 }
218 size *= sizeof(uint32_t); 219 size *= sizeof(uint32_t);
219 if (copy_from_user(p->chunks[i].kdata, cdata, size)) { 220 if (copy_from_user(p->chunks[i].kdata, cdata, size)) {
220 r = -EFAULT; 221 ret = -EFAULT;
221 goto out; 222 goto free_partial_kdata;
222 } 223 }
223 224
224 switch (p->chunks[i].chunk_id) { 225 switch (p->chunks[i].chunk_id) {
@@ -238,15 +239,15 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data)
238 gobj = drm_gem_object_lookup(p->adev->ddev, 239 gobj = drm_gem_object_lookup(p->adev->ddev,
239 p->filp, handle); 240 p->filp, handle);
240 if (gobj == NULL) { 241 if (gobj == NULL) {
241 r = -EINVAL; 242 ret = -EINVAL;
242 goto out; 243 goto free_partial_kdata;
243 } 244 }
244 245
245 p->uf.bo = gem_to_amdgpu_bo(gobj); 246 p->uf.bo = gem_to_amdgpu_bo(gobj);
246 p->uf.offset = fence_data->offset; 247 p->uf.offset = fence_data->offset;
247 } else { 248 } else {
248 r = -EINVAL; 249 ret = -EINVAL;
249 goto out; 250 goto free_partial_kdata;
250 } 251 }
251 break; 252 break;
252 253
@@ -254,19 +255,35 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data)
254 break; 255 break;
255 256
256 default: 257 default:
257 r = -EINVAL; 258 ret = -EINVAL;
258 goto out; 259 goto free_partial_kdata;
259 } 260 }
260 } 261 }
261 262
262 263
263 p->ibs = kcalloc(p->num_ibs, sizeof(struct amdgpu_ib), GFP_KERNEL); 264 p->ibs = kcalloc(p->num_ibs, sizeof(struct amdgpu_ib), GFP_KERNEL);
264 if (!p->ibs) 265 if (!p->ibs) {
265 r = -ENOMEM; 266 ret = -ENOMEM;
267 goto free_all_kdata;
268 }
266 269
267out:
268 kfree(chunk_array); 270 kfree(chunk_array);
269 return r; 271 return 0;
272
273free_all_kdata:
274 i = p->nchunks - 1;
275free_partial_kdata:
276 for (; i >= 0; i--)
277 drm_free_large(p->chunks[i].kdata);
278 kfree(p->chunks);
279put_bo_list:
280 if (p->bo_list)
281 amdgpu_bo_list_put(p->bo_list);
282 amdgpu_ctx_put(p->ctx);
283free_chunk:
284 kfree(chunk_array);
285
286 return ret;
270} 287}
271 288
272/* Returns how many bytes TTM can move per IB. 289/* Returns how many bytes TTM can move per IB.
@@ -321,25 +338,17 @@ static u64 amdgpu_cs_get_threshold_for_moves(struct amdgpu_device *adev)
321 return max(bytes_moved_threshold, 1024*1024ull); 338 return max(bytes_moved_threshold, 1024*1024ull);
322} 339}
323 340
324int amdgpu_cs_list_validate(struct amdgpu_cs_parser *p) 341int amdgpu_cs_list_validate(struct amdgpu_device *adev,
342 struct amdgpu_vm *vm,
343 struct list_head *validated)
325{ 344{
326 struct amdgpu_fpriv *fpriv = p->filp->driver_priv;
327 struct amdgpu_vm *vm = &fpriv->vm;
328 struct amdgpu_device *adev = p->adev;
329 struct amdgpu_bo_list_entry *lobj; 345 struct amdgpu_bo_list_entry *lobj;
330 struct list_head duplicates;
331 struct amdgpu_bo *bo; 346 struct amdgpu_bo *bo;
332 u64 bytes_moved = 0, initial_bytes_moved; 347 u64 bytes_moved = 0, initial_bytes_moved;
333 u64 bytes_moved_threshold = amdgpu_cs_get_threshold_for_moves(adev); 348 u64 bytes_moved_threshold = amdgpu_cs_get_threshold_for_moves(adev);
334 int r; 349 int r;
335 350
336 INIT_LIST_HEAD(&duplicates); 351 list_for_each_entry(lobj, validated, tv.head) {
337 r = ttm_eu_reserve_buffers(&p->ticket, &p->validated, true, &duplicates);
338 if (unlikely(r != 0)) {
339 return r;
340 }
341
342 list_for_each_entry(lobj, &p->validated, tv.head) {
343 bo = lobj->robj; 352 bo = lobj->robj;
344 if (!bo->pin_count) { 353 if (!bo->pin_count) {
345 u32 domain = lobj->prefered_domains; 354 u32 domain = lobj->prefered_domains;
@@ -373,7 +382,6 @@ int amdgpu_cs_list_validate(struct amdgpu_cs_parser *p)
373 domain = lobj->allowed_domains; 382 domain = lobj->allowed_domains;
374 goto retry; 383 goto retry;
375 } 384 }
376 ttm_eu_backoff_reservation(&p->ticket, &p->validated);
377 return r; 385 return r;
378 } 386 }
379 } 387 }
@@ -386,6 +394,7 @@ static int amdgpu_cs_parser_relocs(struct amdgpu_cs_parser *p)
386{ 394{
387 struct amdgpu_fpriv *fpriv = p->filp->driver_priv; 395 struct amdgpu_fpriv *fpriv = p->filp->driver_priv;
388 struct amdgpu_cs_buckets buckets; 396 struct amdgpu_cs_buckets buckets;
397 struct list_head duplicates;
389 bool need_mmap_lock = false; 398 bool need_mmap_lock = false;
390 int i, r; 399 int i, r;
391 400
@@ -405,8 +414,22 @@ static int amdgpu_cs_parser_relocs(struct amdgpu_cs_parser *p)
405 if (need_mmap_lock) 414 if (need_mmap_lock)
406 down_read(&current->mm->mmap_sem); 415 down_read(&current->mm->mmap_sem);
407 416
408 r = amdgpu_cs_list_validate(p); 417 INIT_LIST_HEAD(&duplicates);
418 r = ttm_eu_reserve_buffers(&p->ticket, &p->validated, true, &duplicates);
419 if (unlikely(r != 0))
420 goto error_reserve;
421
422 r = amdgpu_cs_list_validate(p->adev, &fpriv->vm, &p->validated);
423 if (r)
424 goto error_validate;
425
426 r = amdgpu_cs_list_validate(p->adev, &fpriv->vm, &duplicates);
427
428error_validate:
429 if (r)
430 ttm_eu_backoff_reservation(&p->ticket, &p->validated);
409 431
432error_reserve:
410 if (need_mmap_lock) 433 if (need_mmap_lock)
411 up_read(&current->mm->mmap_sem); 434 up_read(&current->mm->mmap_sem);
412 435
@@ -772,15 +795,15 @@ static int amdgpu_cs_dependencies(struct amdgpu_device *adev,
772 return 0; 795 return 0;
773} 796}
774 797
775static int amdgpu_cs_free_job(struct amdgpu_job *sched_job) 798static int amdgpu_cs_free_job(struct amdgpu_job *job)
776{ 799{
777 int i; 800 int i;
778 if (sched_job->ibs) 801 if (job->ibs)
779 for (i = 0; i < sched_job->num_ibs; i++) 802 for (i = 0; i < job->num_ibs; i++)
780 amdgpu_ib_free(sched_job->adev, &sched_job->ibs[i]); 803 amdgpu_ib_free(job->adev, &job->ibs[i]);
781 kfree(sched_job->ibs); 804 kfree(job->ibs);
782 if (sched_job->uf.bo) 805 if (job->uf.bo)
783 drm_gem_object_unreference_unlocked(&sched_job->uf.bo->gem_base); 806 drm_gem_object_unreference_unlocked(&job->uf.bo->gem_base);
784 return 0; 807 return 0;
785} 808}
786 809
@@ -804,7 +827,7 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
804 r = amdgpu_cs_parser_init(parser, data); 827 r = amdgpu_cs_parser_init(parser, data);
805 if (r) { 828 if (r) {
806 DRM_ERROR("Failed to initialize parser !\n"); 829 DRM_ERROR("Failed to initialize parser !\n");
807 amdgpu_cs_parser_fini(parser, r, false); 830 kfree(parser);
808 up_read(&adev->exclusive_lock); 831 up_read(&adev->exclusive_lock);
809 r = amdgpu_cs_handle_lockup(adev, r); 832 r = amdgpu_cs_handle_lockup(adev, r);
810 return r; 833 return r;
@@ -842,7 +865,7 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
842 job = kzalloc(sizeof(struct amdgpu_job), GFP_KERNEL); 865 job = kzalloc(sizeof(struct amdgpu_job), GFP_KERNEL);
843 if (!job) 866 if (!job)
844 return -ENOMEM; 867 return -ENOMEM;
845 job->base.sched = ring->scheduler; 868 job->base.sched = &ring->sched;
846 job->base.s_entity = &parser->ctx->rings[ring->idx].entity; 869 job->base.s_entity = &parser->ctx->rings[ring->idx].entity;
847 job->adev = parser->adev; 870 job->adev = parser->adev;
848 job->ibs = parser->ibs; 871 job->ibs = parser->ibs;
@@ -857,7 +880,7 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
857 880
858 job->free_job = amdgpu_cs_free_job; 881 job->free_job = amdgpu_cs_free_job;
859 mutex_lock(&job->job_lock); 882 mutex_lock(&job->job_lock);
860 r = amd_sched_entity_push_job((struct amd_sched_job *)job); 883 r = amd_sched_entity_push_job(&job->base);
861 if (r) { 884 if (r) {
862 mutex_unlock(&job->job_lock); 885 mutex_unlock(&job->job_lock);
863 amdgpu_cs_free_job(job); 886 amdgpu_cs_free_job(job);