diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 333 |
1 files changed, 246 insertions, 87 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 1f040d85ac47..e4424b4db5d3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | |||
@@ -126,12 +126,54 @@ int amdgpu_cs_get_ring(struct amdgpu_device *adev, u32 ip_type, | |||
126 | return 0; | 126 | return 0; |
127 | } | 127 | } |
128 | 128 | ||
129 | static void amdgpu_job_work_func(struct work_struct *work) | ||
130 | { | ||
131 | struct amdgpu_cs_parser *sched_job = | ||
132 | container_of(work, struct amdgpu_cs_parser, | ||
133 | job_work); | ||
134 | mutex_lock(&sched_job->job_lock); | ||
135 | if (sched_job->free_job) | ||
136 | sched_job->free_job(sched_job); | ||
137 | mutex_unlock(&sched_job->job_lock); | ||
138 | /* after processing job, free memory */ | ||
139 | fence_put(&sched_job->s_fence->base); | ||
140 | kfree(sched_job); | ||
141 | } | ||
142 | struct amdgpu_cs_parser *amdgpu_cs_parser_create(struct amdgpu_device *adev, | ||
143 | struct drm_file *filp, | ||
144 | struct amdgpu_ctx *ctx, | ||
145 | struct amdgpu_ib *ibs, | ||
146 | uint32_t num_ibs) | ||
147 | { | ||
148 | struct amdgpu_cs_parser *parser; | ||
149 | int i; | ||
150 | |||
151 | parser = kzalloc(sizeof(struct amdgpu_cs_parser), GFP_KERNEL); | ||
152 | if (!parser) | ||
153 | return NULL; | ||
154 | |||
155 | parser->adev = adev; | ||
156 | parser->filp = filp; | ||
157 | parser->ctx = ctx; | ||
158 | parser->ibs = ibs; | ||
159 | parser->num_ibs = num_ibs; | ||
160 | if (amdgpu_enable_scheduler) { | ||
161 | mutex_init(&parser->job_lock); | ||
162 | INIT_WORK(&parser->job_work, amdgpu_job_work_func); | ||
163 | } | ||
164 | for (i = 0; i < num_ibs; i++) | ||
165 | ibs[i].ctx = ctx; | ||
166 | |||
167 | return parser; | ||
168 | } | ||
169 | |||
129 | int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data) | 170 | int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data) |
130 | { | 171 | { |
131 | union drm_amdgpu_cs *cs = data; | 172 | union drm_amdgpu_cs *cs = data; |
132 | uint64_t *chunk_array_user; | 173 | uint64_t *chunk_array_user; |
133 | uint64_t *chunk_array = NULL; | 174 | uint64_t *chunk_array = NULL; |
134 | struct amdgpu_fpriv *fpriv = p->filp->driver_priv; | 175 | struct amdgpu_fpriv *fpriv = p->filp->driver_priv; |
176 | struct amdgpu_bo_list *bo_list = NULL; | ||
135 | unsigned size, i; | 177 | unsigned size, i; |
136 | int r = 0; | 178 | int r = 0; |
137 | 179 | ||
@@ -143,17 +185,30 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data) | |||
143 | r = -EINVAL; | 185 | r = -EINVAL; |
144 | goto out; | 186 | goto out; |
145 | } | 187 | } |
146 | p->bo_list = amdgpu_bo_list_get(fpriv, cs->in.bo_list_handle); | 188 | bo_list = amdgpu_bo_list_get(fpriv, cs->in.bo_list_handle); |
189 | if (!amdgpu_enable_scheduler) | ||
190 | p->bo_list = bo_list; | ||
191 | else { | ||
192 | if (bo_list && !bo_list->has_userptr) { | ||
193 | p->bo_list = amdgpu_bo_list_clone(bo_list); | ||
194 | amdgpu_bo_list_put(bo_list); | ||
195 | if (!p->bo_list) | ||
196 | return -ENOMEM; | ||
197 | } else if (bo_list && bo_list->has_userptr) | ||
198 | p->bo_list = bo_list; | ||
199 | else | ||
200 | p->bo_list = NULL; | ||
201 | } | ||
147 | 202 | ||
148 | /* get chunks */ | 203 | /* get chunks */ |
149 | INIT_LIST_HEAD(&p->validated); | 204 | INIT_LIST_HEAD(&p->validated); |
150 | chunk_array = kcalloc(cs->in.num_chunks, sizeof(uint64_t), GFP_KERNEL); | 205 | chunk_array = kmalloc_array(cs->in.num_chunks, sizeof(uint64_t), GFP_KERNEL); |
151 | if (chunk_array == NULL) { | 206 | if (chunk_array == NULL) { |
152 | r = -ENOMEM; | 207 | r = -ENOMEM; |
153 | goto out; | 208 | goto out; |
154 | } | 209 | } |
155 | 210 | ||
156 | chunk_array_user = (uint64_t *)(unsigned long)(cs->in.chunks); | 211 | chunk_array_user = (uint64_t __user *)(cs->in.chunks); |
157 | if (copy_from_user(chunk_array, chunk_array_user, | 212 | if (copy_from_user(chunk_array, chunk_array_user, |
158 | sizeof(uint64_t)*cs->in.num_chunks)) { | 213 | sizeof(uint64_t)*cs->in.num_chunks)) { |
159 | r = -EFAULT; | 214 | r = -EFAULT; |
@@ -161,7 +216,7 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data) | |||
161 | } | 216 | } |
162 | 217 | ||
163 | p->nchunks = cs->in.num_chunks; | 218 | p->nchunks = cs->in.num_chunks; |
164 | p->chunks = kcalloc(p->nchunks, sizeof(struct amdgpu_cs_chunk), | 219 | p->chunks = kmalloc_array(p->nchunks, sizeof(struct amdgpu_cs_chunk), |
165 | GFP_KERNEL); | 220 | GFP_KERNEL); |
166 | if (p->chunks == NULL) { | 221 | if (p->chunks == NULL) { |
167 | r = -ENOMEM; | 222 | r = -ENOMEM; |
@@ -173,7 +228,7 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data) | |||
173 | struct drm_amdgpu_cs_chunk user_chunk; | 228 | struct drm_amdgpu_cs_chunk user_chunk; |
174 | uint32_t __user *cdata; | 229 | uint32_t __user *cdata; |
175 | 230 | ||
176 | chunk_ptr = (void __user *)(unsigned long)chunk_array[i]; | 231 | chunk_ptr = (void __user *)chunk_array[i]; |
177 | if (copy_from_user(&user_chunk, chunk_ptr, | 232 | if (copy_from_user(&user_chunk, chunk_ptr, |
178 | sizeof(struct drm_amdgpu_cs_chunk))) { | 233 | sizeof(struct drm_amdgpu_cs_chunk))) { |
179 | r = -EFAULT; | 234 | r = -EFAULT; |
@@ -183,7 +238,7 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data) | |||
183 | p->chunks[i].length_dw = user_chunk.length_dw; | 238 | p->chunks[i].length_dw = user_chunk.length_dw; |
184 | 239 | ||
185 | size = p->chunks[i].length_dw; | 240 | size = p->chunks[i].length_dw; |
186 | cdata = (void __user *)(unsigned long)user_chunk.chunk_data; | 241 | cdata = (void __user *)user_chunk.chunk_data; |
187 | p->chunks[i].user_ptr = cdata; | 242 | p->chunks[i].user_ptr = cdata; |
188 | 243 | ||
189 | p->chunks[i].kdata = drm_malloc_ab(size, sizeof(uint32_t)); | 244 | p->chunks[i].kdata = drm_malloc_ab(size, sizeof(uint32_t)); |
@@ -235,11 +290,10 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data) | |||
235 | } | 290 | } |
236 | } | 291 | } |
237 | 292 | ||
238 | p->ibs = kcalloc(p->num_ibs, sizeof(struct amdgpu_ib), GFP_KERNEL); | 293 | |
239 | if (!p->ibs) { | 294 | p->ibs = kmalloc_array(p->num_ibs, sizeof(struct amdgpu_ib), GFP_KERNEL); |
295 | if (!p->ibs) | ||
240 | r = -ENOMEM; | 296 | r = -ENOMEM; |
241 | goto out; | ||
242 | } | ||
243 | 297 | ||
244 | out: | 298 | out: |
245 | kfree(chunk_array); | 299 | kfree(chunk_array); |
@@ -415,18 +469,8 @@ static int cmp_size_smaller_first(void *priv, struct list_head *a, | |||
415 | return (int)la->robj->tbo.num_pages - (int)lb->robj->tbo.num_pages; | 469 | return (int)la->robj->tbo.num_pages - (int)lb->robj->tbo.num_pages; |
416 | } | 470 | } |
417 | 471 | ||
418 | /** | 472 | static void amdgpu_cs_parser_fini_early(struct amdgpu_cs_parser *parser, int error, bool backoff) |
419 | * cs_parser_fini() - clean parser states | ||
420 | * @parser: parser structure holding parsing context. | ||
421 | * @error: error number | ||
422 | * | ||
423 | * If error is set than unvalidate buffer, otherwise just free memory | ||
424 | * used by parsing context. | ||
425 | **/ | ||
426 | static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, bool backoff) | ||
427 | { | 473 | { |
428 | unsigned i; | ||
429 | |||
430 | if (!error) { | 474 | if (!error) { |
431 | /* Sort the buffer list from the smallest to largest buffer, | 475 | /* Sort the buffer list from the smallest to largest buffer, |
432 | * which affects the order of buffers in the LRU list. | 476 | * which affects the order of buffers in the LRU list. |
@@ -447,11 +491,19 @@ static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, bo | |||
447 | ttm_eu_backoff_reservation(&parser->ticket, | 491 | ttm_eu_backoff_reservation(&parser->ticket, |
448 | &parser->validated); | 492 | &parser->validated); |
449 | } | 493 | } |
494 | } | ||
450 | 495 | ||
496 | static void amdgpu_cs_parser_fini_late(struct amdgpu_cs_parser *parser) | ||
497 | { | ||
498 | unsigned i; | ||
451 | if (parser->ctx) | 499 | if (parser->ctx) |
452 | amdgpu_ctx_put(parser->ctx); | 500 | amdgpu_ctx_put(parser->ctx); |
453 | if (parser->bo_list) | 501 | if (parser->bo_list) { |
454 | amdgpu_bo_list_put(parser->bo_list); | 502 | if (amdgpu_enable_scheduler && !parser->bo_list->has_userptr) |
503 | amdgpu_bo_list_free(parser->bo_list); | ||
504 | else | ||
505 | amdgpu_bo_list_put(parser->bo_list); | ||
506 | } | ||
455 | drm_free_large(parser->vm_bos); | 507 | drm_free_large(parser->vm_bos); |
456 | for (i = 0; i < parser->nchunks; i++) | 508 | for (i = 0; i < parser->nchunks; i++) |
457 | drm_free_large(parser->chunks[i].kdata); | 509 | drm_free_large(parser->chunks[i].kdata); |
@@ -462,6 +514,29 @@ static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, bo | |||
462 | kfree(parser->ibs); | 514 | kfree(parser->ibs); |
463 | if (parser->uf.bo) | 515 | if (parser->uf.bo) |
464 | drm_gem_object_unreference_unlocked(&parser->uf.bo->gem_base); | 516 | drm_gem_object_unreference_unlocked(&parser->uf.bo->gem_base); |
517 | |||
518 | if (!amdgpu_enable_scheduler) | ||
519 | kfree(parser); | ||
520 | } | ||
521 | |||
522 | /** | ||
523 | * cs_parser_fini() - clean parser states | ||
524 | * @parser: parser structure holding parsing context. | ||
525 | * @error: error number | ||
526 | * | ||
527 | * If error is set than unvalidate buffer, otherwise just free memory | ||
528 | * used by parsing context. | ||
529 | **/ | ||
530 | static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, bool backoff) | ||
531 | { | ||
532 | amdgpu_cs_parser_fini_early(parser, error, backoff); | ||
533 | amdgpu_cs_parser_fini_late(parser); | ||
534 | } | ||
535 | |||
536 | static int amdgpu_cs_parser_free_job(struct amdgpu_cs_parser *sched_job) | ||
537 | { | ||
538 | amdgpu_cs_parser_fini_late(sched_job); | ||
539 | return 0; | ||
465 | } | 540 | } |
466 | 541 | ||
467 | static int amdgpu_bo_vm_update_pte(struct amdgpu_cs_parser *p, | 542 | static int amdgpu_bo_vm_update_pte(struct amdgpu_cs_parser *p, |
@@ -476,12 +551,18 @@ static int amdgpu_bo_vm_update_pte(struct amdgpu_cs_parser *p, | |||
476 | if (r) | 551 | if (r) |
477 | return r; | 552 | return r; |
478 | 553 | ||
554 | r = amdgpu_sync_fence(adev, &p->ibs[0].sync, vm->page_directory_fence); | ||
555 | if (r) | ||
556 | return r; | ||
557 | |||
479 | r = amdgpu_vm_clear_freed(adev, vm); | 558 | r = amdgpu_vm_clear_freed(adev, vm); |
480 | if (r) | 559 | if (r) |
481 | return r; | 560 | return r; |
482 | 561 | ||
483 | if (p->bo_list) { | 562 | if (p->bo_list) { |
484 | for (i = 0; i < p->bo_list->num_entries; i++) { | 563 | for (i = 0; i < p->bo_list->num_entries; i++) { |
564 | struct fence *f; | ||
565 | |||
485 | /* ignore duplicates */ | 566 | /* ignore duplicates */ |
486 | bo = p->bo_list->array[i].robj; | 567 | bo = p->bo_list->array[i].robj; |
487 | if (!bo) | 568 | if (!bo) |
@@ -495,7 +576,10 @@ static int amdgpu_bo_vm_update_pte(struct amdgpu_cs_parser *p, | |||
495 | if (r) | 576 | if (r) |
496 | return r; | 577 | return r; |
497 | 578 | ||
498 | amdgpu_sync_fence(&p->ibs[0].sync, bo_va->last_pt_update); | 579 | f = bo_va->last_pt_update; |
580 | r = amdgpu_sync_fence(adev, &p->ibs[0].sync, f); | ||
581 | if (r) | ||
582 | return r; | ||
499 | } | 583 | } |
500 | } | 584 | } |
501 | 585 | ||
@@ -529,9 +613,9 @@ static int amdgpu_cs_ib_vm_chunk(struct amdgpu_device *adev, | |||
529 | goto out; | 613 | goto out; |
530 | } | 614 | } |
531 | amdgpu_cs_sync_rings(parser); | 615 | amdgpu_cs_sync_rings(parser); |
532 | 616 | if (!amdgpu_enable_scheduler) | |
533 | r = amdgpu_ib_schedule(adev, parser->num_ibs, parser->ibs, | 617 | r = amdgpu_ib_schedule(adev, parser->num_ibs, parser->ibs, |
534 | parser->filp); | 618 | parser->filp); |
535 | 619 | ||
536 | out: | 620 | out: |
537 | mutex_unlock(&vm->mutex); | 621 | mutex_unlock(&vm->mutex); |
@@ -650,7 +734,6 @@ static int amdgpu_cs_ib_fill(struct amdgpu_device *adev, | |||
650 | ib->oa_size = amdgpu_bo_size(oa); | 734 | ib->oa_size = amdgpu_bo_size(oa); |
651 | } | 735 | } |
652 | } | 736 | } |
653 | |||
654 | /* wrap the last IB with user fence */ | 737 | /* wrap the last IB with user fence */ |
655 | if (parser->uf.bo) { | 738 | if (parser->uf.bo) { |
656 | struct amdgpu_ib *ib = &parser->ibs[parser->num_ibs - 1]; | 739 | struct amdgpu_ib *ib = &parser->ibs[parser->num_ibs - 1]; |
@@ -693,9 +776,9 @@ static int amdgpu_cs_dependencies(struct amdgpu_device *adev, | |||
693 | sizeof(struct drm_amdgpu_cs_chunk_dep); | 776 | sizeof(struct drm_amdgpu_cs_chunk_dep); |
694 | 777 | ||
695 | for (j = 0; j < num_deps; ++j) { | 778 | for (j = 0; j < num_deps; ++j) { |
696 | struct amdgpu_fence *fence; | ||
697 | struct amdgpu_ring *ring; | 779 | struct amdgpu_ring *ring; |
698 | struct amdgpu_ctx *ctx; | 780 | struct amdgpu_ctx *ctx; |
781 | struct fence *fence; | ||
699 | 782 | ||
700 | r = amdgpu_cs_get_ring(adev, deps[j].ip_type, | 783 | r = amdgpu_cs_get_ring(adev, deps[j].ip_type, |
701 | deps[j].ip_instance, | 784 | deps[j].ip_instance, |
@@ -707,50 +790,34 @@ static int amdgpu_cs_dependencies(struct amdgpu_device *adev, | |||
707 | if (ctx == NULL) | 790 | if (ctx == NULL) |
708 | return -EINVAL; | 791 | return -EINVAL; |
709 | 792 | ||
710 | r = amdgpu_fence_recreate(ring, p->filp, | 793 | fence = amdgpu_ctx_get_fence(ctx, ring, |
711 | deps[j].handle, | 794 | deps[j].handle); |
712 | &fence); | 795 | if (IS_ERR(fence)) { |
713 | if (r) { | 796 | r = PTR_ERR(fence); |
714 | amdgpu_ctx_put(ctx); | 797 | amdgpu_ctx_put(ctx); |
715 | return r; | 798 | return r; |
716 | } | ||
717 | 799 | ||
718 | amdgpu_sync_fence(&ib->sync, fence); | 800 | } else if (fence) { |
719 | amdgpu_fence_unref(&fence); | 801 | r = amdgpu_sync_fence(adev, &ib->sync, fence); |
720 | amdgpu_ctx_put(ctx); | 802 | fence_put(fence); |
803 | amdgpu_ctx_put(ctx); | ||
804 | if (r) | ||
805 | return r; | ||
806 | } | ||
721 | } | 807 | } |
722 | } | 808 | } |
723 | 809 | ||
724 | return 0; | 810 | return 0; |
725 | } | 811 | } |
726 | 812 | ||
727 | int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) | 813 | static int amdgpu_cs_parser_prepare_job(struct amdgpu_cs_parser *sched_job) |
728 | { | 814 | { |
729 | struct amdgpu_device *adev = dev->dev_private; | ||
730 | union drm_amdgpu_cs *cs = data; | ||
731 | struct amdgpu_cs_parser parser; | ||
732 | int r, i; | 815 | int r, i; |
816 | struct amdgpu_cs_parser *parser = sched_job; | ||
817 | struct amdgpu_device *adev = sched_job->adev; | ||
733 | bool reserved_buffers = false; | 818 | bool reserved_buffers = false; |
734 | 819 | ||
735 | down_read(&adev->exclusive_lock); | 820 | r = amdgpu_cs_parser_relocs(parser); |
736 | if (!adev->accel_working) { | ||
737 | up_read(&adev->exclusive_lock); | ||
738 | return -EBUSY; | ||
739 | } | ||
740 | /* initialize parser */ | ||
741 | memset(&parser, 0, sizeof(struct amdgpu_cs_parser)); | ||
742 | parser.filp = filp; | ||
743 | parser.adev = adev; | ||
744 | r = amdgpu_cs_parser_init(&parser, data); | ||
745 | if (r) { | ||
746 | DRM_ERROR("Failed to initialize parser !\n"); | ||
747 | amdgpu_cs_parser_fini(&parser, r, false); | ||
748 | up_read(&adev->exclusive_lock); | ||
749 | r = amdgpu_cs_handle_lockup(adev, r); | ||
750 | return r; | ||
751 | } | ||
752 | |||
753 | r = amdgpu_cs_parser_relocs(&parser); | ||
754 | if (r) { | 821 | if (r) { |
755 | if (r != -ERESTARTSYS) { | 822 | if (r != -ERESTARTSYS) { |
756 | if (r == -ENOMEM) | 823 | if (r == -ENOMEM) |
@@ -762,30 +829,114 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) | |||
762 | 829 | ||
763 | if (!r) { | 830 | if (!r) { |
764 | reserved_buffers = true; | 831 | reserved_buffers = true; |
765 | r = amdgpu_cs_ib_fill(adev, &parser); | 832 | r = amdgpu_cs_ib_fill(adev, parser); |
833 | } | ||
834 | if (!r) { | ||
835 | r = amdgpu_cs_dependencies(adev, parser); | ||
836 | if (r) | ||
837 | DRM_ERROR("Failed in the dependencies handling %d!\n", r); | ||
766 | } | 838 | } |
839 | if (r) { | ||
840 | amdgpu_cs_parser_fini(parser, r, reserved_buffers); | ||
841 | return r; | ||
842 | } | ||
843 | |||
844 | for (i = 0; i < parser->num_ibs; i++) | ||
845 | trace_amdgpu_cs(parser, i); | ||
846 | |||
847 | r = amdgpu_cs_ib_vm_chunk(adev, parser); | ||
848 | return r; | ||
849 | } | ||
850 | |||
851 | static struct amdgpu_ring *amdgpu_cs_parser_get_ring( | ||
852 | struct amdgpu_device *adev, | ||
853 | struct amdgpu_cs_parser *parser) | ||
854 | { | ||
855 | int i, r; | ||
856 | |||
857 | struct amdgpu_cs_chunk *chunk; | ||
858 | struct drm_amdgpu_cs_chunk_ib *chunk_ib; | ||
859 | struct amdgpu_ring *ring; | ||
860 | for (i = 0; i < parser->nchunks; i++) { | ||
861 | chunk = &parser->chunks[i]; | ||
862 | chunk_ib = (struct drm_amdgpu_cs_chunk_ib *)chunk->kdata; | ||
863 | |||
864 | if (chunk->chunk_id != AMDGPU_CHUNK_ID_IB) | ||
865 | continue; | ||
866 | |||
867 | r = amdgpu_cs_get_ring(adev, chunk_ib->ip_type, | ||
868 | chunk_ib->ip_instance, chunk_ib->ring, | ||
869 | &ring); | ||
870 | if (r) | ||
871 | return NULL; | ||
872 | break; | ||
873 | } | ||
874 | return ring; | ||
875 | } | ||
876 | |||
877 | int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) | ||
878 | { | ||
879 | struct amdgpu_device *adev = dev->dev_private; | ||
880 | union drm_amdgpu_cs *cs = data; | ||
881 | struct amdgpu_cs_parser *parser; | ||
882 | int r; | ||
767 | 883 | ||
768 | if (!r) | 884 | down_read(&adev->exclusive_lock); |
769 | r = amdgpu_cs_dependencies(adev, &parser); | 885 | if (!adev->accel_working) { |
886 | up_read(&adev->exclusive_lock); | ||
887 | return -EBUSY; | ||
888 | } | ||
770 | 889 | ||
890 | parser = amdgpu_cs_parser_create(adev, filp, NULL, NULL, 0); | ||
891 | if (!parser) | ||
892 | return -ENOMEM; | ||
893 | r = amdgpu_cs_parser_init(parser, data); | ||
771 | if (r) { | 894 | if (r) { |
772 | amdgpu_cs_parser_fini(&parser, r, reserved_buffers); | 895 | DRM_ERROR("Failed to initialize parser !\n"); |
896 | amdgpu_cs_parser_fini(parser, r, false); | ||
773 | up_read(&adev->exclusive_lock); | 897 | up_read(&adev->exclusive_lock); |
774 | r = amdgpu_cs_handle_lockup(adev, r); | 898 | r = amdgpu_cs_handle_lockup(adev, r); |
775 | return r; | 899 | return r; |
776 | } | 900 | } |
777 | 901 | ||
778 | for (i = 0; i < parser.num_ibs; i++) | 902 | if (amdgpu_enable_scheduler && parser->num_ibs) { |
779 | trace_amdgpu_cs(&parser, i); | 903 | struct amdgpu_ring * ring = |
904 | amdgpu_cs_parser_get_ring(adev, parser); | ||
905 | r = amdgpu_cs_parser_prepare_job(parser); | ||
906 | if (r) | ||
907 | goto out; | ||
908 | parser->ring = ring; | ||
909 | parser->free_job = amdgpu_cs_parser_free_job; | ||
910 | mutex_lock(&parser->job_lock); | ||
911 | r = amd_sched_push_job(ring->scheduler, | ||
912 | &parser->ctx->rings[ring->idx].entity, | ||
913 | parser, | ||
914 | &parser->s_fence); | ||
915 | if (r) { | ||
916 | mutex_unlock(&parser->job_lock); | ||
917 | goto out; | ||
918 | } | ||
919 | parser->ibs[parser->num_ibs - 1].sequence = | ||
920 | amdgpu_ctx_add_fence(parser->ctx, ring, | ||
921 | &parser->s_fence->base, | ||
922 | parser->s_fence->v_seq); | ||
923 | cs->out.handle = parser->s_fence->v_seq; | ||
924 | list_sort(NULL, &parser->validated, cmp_size_smaller_first); | ||
925 | ttm_eu_fence_buffer_objects(&parser->ticket, | ||
926 | &parser->validated, | ||
927 | &parser->s_fence->base); | ||
780 | 928 | ||
781 | r = amdgpu_cs_ib_vm_chunk(adev, &parser); | 929 | mutex_unlock(&parser->job_lock); |
782 | if (r) { | 930 | up_read(&adev->exclusive_lock); |
783 | goto out; | 931 | return 0; |
784 | } | 932 | } |
933 | r = amdgpu_cs_parser_prepare_job(parser); | ||
934 | if (r) | ||
935 | goto out; | ||
785 | 936 | ||
786 | cs->out.handle = parser.ibs[parser.num_ibs - 1].fence->seq; | 937 | cs->out.handle = parser->ibs[parser->num_ibs - 1].sequence; |
787 | out: | 938 | out: |
788 | amdgpu_cs_parser_fini(&parser, r, true); | 939 | amdgpu_cs_parser_fini(parser, r, true); |
789 | up_read(&adev->exclusive_lock); | 940 | up_read(&adev->exclusive_lock); |
790 | r = amdgpu_cs_handle_lockup(adev, r); | 941 | r = amdgpu_cs_handle_lockup(adev, r); |
791 | return r; | 942 | return r; |
@@ -806,30 +957,29 @@ int amdgpu_cs_wait_ioctl(struct drm_device *dev, void *data, | |||
806 | union drm_amdgpu_wait_cs *wait = data; | 957 | union drm_amdgpu_wait_cs *wait = data; |
807 | struct amdgpu_device *adev = dev->dev_private; | 958 | struct amdgpu_device *adev = dev->dev_private; |
808 | unsigned long timeout = amdgpu_gem_timeout(wait->in.timeout); | 959 | unsigned long timeout = amdgpu_gem_timeout(wait->in.timeout); |
809 | struct amdgpu_fence *fence = NULL; | ||
810 | struct amdgpu_ring *ring = NULL; | 960 | struct amdgpu_ring *ring = NULL; |
811 | struct amdgpu_ctx *ctx; | 961 | struct amdgpu_ctx *ctx; |
962 | struct fence *fence; | ||
812 | long r; | 963 | long r; |
813 | 964 | ||
814 | ctx = amdgpu_ctx_get(filp->driver_priv, wait->in.ctx_id); | ||
815 | if (ctx == NULL) | ||
816 | return -EINVAL; | ||
817 | |||
818 | r = amdgpu_cs_get_ring(adev, wait->in.ip_type, wait->in.ip_instance, | 965 | r = amdgpu_cs_get_ring(adev, wait->in.ip_type, wait->in.ip_instance, |
819 | wait->in.ring, &ring); | 966 | wait->in.ring, &ring); |
820 | if (r) { | 967 | if (r) |
821 | amdgpu_ctx_put(ctx); | ||
822 | return r; | 968 | return r; |
823 | } | ||
824 | 969 | ||
825 | r = amdgpu_fence_recreate(ring, filp, wait->in.handle, &fence); | 970 | ctx = amdgpu_ctx_get(filp->driver_priv, wait->in.ctx_id); |
826 | if (r) { | 971 | if (ctx == NULL) |
827 | amdgpu_ctx_put(ctx); | 972 | return -EINVAL; |
828 | return r; | 973 | |
829 | } | 974 | fence = amdgpu_ctx_get_fence(ctx, ring, wait->in.handle); |
975 | if (IS_ERR(fence)) | ||
976 | r = PTR_ERR(fence); | ||
977 | else if (fence) { | ||
978 | r = fence_wait_timeout(fence, true, timeout); | ||
979 | fence_put(fence); | ||
980 | } else | ||
981 | r = 1; | ||
830 | 982 | ||
831 | r = fence_wait_timeout(&fence->base, true, timeout); | ||
832 | amdgpu_fence_unref(&fence); | ||
833 | amdgpu_ctx_put(ctx); | 983 | amdgpu_ctx_put(ctx); |
834 | if (r < 0) | 984 | if (r < 0) |
835 | return r; | 985 | return r; |
@@ -864,7 +1014,16 @@ amdgpu_cs_find_mapping(struct amdgpu_cs_parser *parser, | |||
864 | if (!reloc->bo_va) | 1014 | if (!reloc->bo_va) |
865 | continue; | 1015 | continue; |
866 | 1016 | ||
867 | list_for_each_entry(mapping, &reloc->bo_va->mappings, list) { | 1017 | list_for_each_entry(mapping, &reloc->bo_va->valids, list) { |
1018 | if (mapping->it.start > addr || | ||
1019 | addr > mapping->it.last) | ||
1020 | continue; | ||
1021 | |||
1022 | *bo = reloc->bo_va->bo; | ||
1023 | return mapping; | ||
1024 | } | ||
1025 | |||
1026 | list_for_each_entry(mapping, &reloc->bo_va->invalids, list) { | ||
868 | if (mapping->it.start > addr || | 1027 | if (mapping->it.start > addr || |
869 | addr > mapping->it.last) | 1028 | addr > mapping->it.last) |
870 | continue; | 1029 | continue; |