diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 160 |
1 files changed, 74 insertions, 86 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 313ac971eaaf..5b70a30967ec 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | |||
@@ -804,8 +804,9 @@ static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, | |||
804 | amdgpu_bo_unref(&parser->uf_entry.robj); | 804 | amdgpu_bo_unref(&parser->uf_entry.robj); |
805 | } | 805 | } |
806 | 806 | ||
807 | static int amdgpu_bo_vm_update_pte(struct amdgpu_cs_parser *p) | 807 | static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p) |
808 | { | 808 | { |
809 | struct amdgpu_ring *ring = to_amdgpu_ring(p->entity->rq->sched); | ||
809 | struct amdgpu_fpriv *fpriv = p->filp->driver_priv; | 810 | struct amdgpu_fpriv *fpriv = p->filp->driver_priv; |
810 | struct amdgpu_device *adev = p->adev; | 811 | struct amdgpu_device *adev = p->adev; |
811 | struct amdgpu_vm *vm = &fpriv->vm; | 812 | struct amdgpu_vm *vm = &fpriv->vm; |
@@ -814,6 +815,71 @@ static int amdgpu_bo_vm_update_pte(struct amdgpu_cs_parser *p) | |||
814 | struct amdgpu_bo *bo; | 815 | struct amdgpu_bo *bo; |
815 | int r; | 816 | int r; |
816 | 817 | ||
818 | /* Only for UVD/VCE VM emulation */ | ||
819 | if (ring->funcs->parse_cs || ring->funcs->patch_cs_in_place) { | ||
820 | unsigned i, j; | ||
821 | |||
822 | for (i = 0, j = 0; i < p->nchunks && j < p->job->num_ibs; i++) { | ||
823 | struct drm_amdgpu_cs_chunk_ib *chunk_ib; | ||
824 | struct amdgpu_bo_va_mapping *m; | ||
825 | struct amdgpu_bo *aobj = NULL; | ||
826 | struct amdgpu_cs_chunk *chunk; | ||
827 | uint64_t offset, va_start; | ||
828 | struct amdgpu_ib *ib; | ||
829 | uint8_t *kptr; | ||
830 | |||
831 | chunk = &p->chunks[i]; | ||
832 | ib = &p->job->ibs[j]; | ||
833 | chunk_ib = chunk->kdata; | ||
834 | |||
835 | if (chunk->chunk_id != AMDGPU_CHUNK_ID_IB) | ||
836 | continue; | ||
837 | |||
838 | va_start = chunk_ib->va_start & AMDGPU_VA_HOLE_MASK; | ||
839 | r = amdgpu_cs_find_mapping(p, va_start, &aobj, &m); | ||
840 | if (r) { | ||
841 | DRM_ERROR("IB va_start is invalid\n"); | ||
842 | return r; | ||
843 | } | ||
844 | |||
845 | if ((va_start + chunk_ib->ib_bytes) > | ||
846 | (m->last + 1) * AMDGPU_GPU_PAGE_SIZE) { | ||
847 | DRM_ERROR("IB va_start+ib_bytes is invalid\n"); | ||
848 | return -EINVAL; | ||
849 | } | ||
850 | |||
851 | /* the IB should be reserved at this point */ | ||
852 | r = amdgpu_bo_kmap(aobj, (void **)&kptr); | ||
853 | if (r) { | ||
854 | return r; | ||
855 | } | ||
856 | |||
857 | offset = m->start * AMDGPU_GPU_PAGE_SIZE; | ||
858 | kptr += va_start - offset; | ||
859 | |||
860 | if (ring->funcs->parse_cs) { | ||
861 | memcpy(ib->ptr, kptr, chunk_ib->ib_bytes); | ||
862 | amdgpu_bo_kunmap(aobj); | ||
863 | |||
864 | r = amdgpu_ring_parse_cs(ring, p, j); | ||
865 | if (r) | ||
866 | return r; | ||
867 | } else { | ||
868 | ib->ptr = (uint32_t *)kptr; | ||
869 | r = amdgpu_ring_patch_cs_in_place(ring, p, j); | ||
870 | amdgpu_bo_kunmap(aobj); | ||
871 | if (r) | ||
872 | return r; | ||
873 | } | ||
874 | |||
875 | j++; | ||
876 | } | ||
877 | } | ||
878 | |||
879 | if (!p->job->vm) | ||
880 | return amdgpu_cs_sync_rings(p); | ||
881 | |||
882 | |||
817 | r = amdgpu_vm_clear_freed(adev, vm, NULL); | 883 | r = amdgpu_vm_clear_freed(adev, vm, NULL); |
818 | if (r) | 884 | if (r) |
819 | return r; | 885 | return r; |
@@ -876,6 +942,12 @@ static int amdgpu_bo_vm_update_pte(struct amdgpu_cs_parser *p) | |||
876 | if (r) | 942 | if (r) |
877 | return r; | 943 | return r; |
878 | 944 | ||
945 | r = reservation_object_reserve_shared(vm->root.base.bo->tbo.resv); | ||
946 | if (r) | ||
947 | return r; | ||
948 | |||
949 | p->job->vm_pd_addr = amdgpu_bo_gpu_offset(vm->root.base.bo); | ||
950 | |||
879 | if (amdgpu_vm_debug) { | 951 | if (amdgpu_vm_debug) { |
880 | /* Invalidate all BOs to test for userspace bugs */ | 952 | /* Invalidate all BOs to test for userspace bugs */ |
881 | amdgpu_bo_list_for_each_entry(e, p->bo_list) { | 953 | amdgpu_bo_list_for_each_entry(e, p->bo_list) { |
@@ -887,90 +959,6 @@ static int amdgpu_bo_vm_update_pte(struct amdgpu_cs_parser *p) | |||
887 | } | 959 | } |
888 | } | 960 | } |
889 | 961 | ||
890 | return r; | ||
891 | } | ||
892 | |||
893 | static int amdgpu_cs_ib_vm_chunk(struct amdgpu_device *adev, | ||
894 | struct amdgpu_cs_parser *p) | ||
895 | { | ||
896 | struct amdgpu_ring *ring = to_amdgpu_ring(p->entity->rq->sched); | ||
897 | struct amdgpu_fpriv *fpriv = p->filp->driver_priv; | ||
898 | struct amdgpu_vm *vm = &fpriv->vm; | ||
899 | int r; | ||
900 | |||
901 | /* Only for UVD/VCE VM emulation */ | ||
902 | if (ring->funcs->parse_cs || ring->funcs->patch_cs_in_place) { | ||
903 | unsigned i, j; | ||
904 | |||
905 | for (i = 0, j = 0; i < p->nchunks && j < p->job->num_ibs; i++) { | ||
906 | struct drm_amdgpu_cs_chunk_ib *chunk_ib; | ||
907 | struct amdgpu_bo_va_mapping *m; | ||
908 | struct amdgpu_bo *aobj = NULL; | ||
909 | struct amdgpu_cs_chunk *chunk; | ||
910 | uint64_t offset, va_start; | ||
911 | struct amdgpu_ib *ib; | ||
912 | uint8_t *kptr; | ||
913 | |||
914 | chunk = &p->chunks[i]; | ||
915 | ib = &p->job->ibs[j]; | ||
916 | chunk_ib = chunk->kdata; | ||
917 | |||
918 | if (chunk->chunk_id != AMDGPU_CHUNK_ID_IB) | ||
919 | continue; | ||
920 | |||
921 | va_start = chunk_ib->va_start & AMDGPU_VA_HOLE_MASK; | ||
922 | r = amdgpu_cs_find_mapping(p, va_start, &aobj, &m); | ||
923 | if (r) { | ||
924 | DRM_ERROR("IB va_start is invalid\n"); | ||
925 | return r; | ||
926 | } | ||
927 | |||
928 | if ((va_start + chunk_ib->ib_bytes) > | ||
929 | (m->last + 1) * AMDGPU_GPU_PAGE_SIZE) { | ||
930 | DRM_ERROR("IB va_start+ib_bytes is invalid\n"); | ||
931 | return -EINVAL; | ||
932 | } | ||
933 | |||
934 | /* the IB should be reserved at this point */ | ||
935 | r = amdgpu_bo_kmap(aobj, (void **)&kptr); | ||
936 | if (r) { | ||
937 | return r; | ||
938 | } | ||
939 | |||
940 | offset = m->start * AMDGPU_GPU_PAGE_SIZE; | ||
941 | kptr += va_start - offset; | ||
942 | |||
943 | if (ring->funcs->parse_cs) { | ||
944 | memcpy(ib->ptr, kptr, chunk_ib->ib_bytes); | ||
945 | amdgpu_bo_kunmap(aobj); | ||
946 | |||
947 | r = amdgpu_ring_parse_cs(ring, p, j); | ||
948 | if (r) | ||
949 | return r; | ||
950 | } else { | ||
951 | ib->ptr = (uint32_t *)kptr; | ||
952 | r = amdgpu_ring_patch_cs_in_place(ring, p, j); | ||
953 | amdgpu_bo_kunmap(aobj); | ||
954 | if (r) | ||
955 | return r; | ||
956 | } | ||
957 | |||
958 | j++; | ||
959 | } | ||
960 | } | ||
961 | |||
962 | if (p->job->vm) { | ||
963 | p->job->vm_pd_addr = amdgpu_bo_gpu_offset(vm->root.base.bo); | ||
964 | |||
965 | r = amdgpu_bo_vm_update_pte(p); | ||
966 | if (r) | ||
967 | return r; | ||
968 | |||
969 | r = reservation_object_reserve_shared(vm->root.base.bo->tbo.resv); | ||
970 | if (r) | ||
971 | return r; | ||
972 | } | ||
973 | |||
974 | return amdgpu_cs_sync_rings(p); | 962 | return amdgpu_cs_sync_rings(p); |
975 | } | 963 | } |
976 | 964 | ||
@@ -1309,7 +1297,7 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) | |||
1309 | for (i = 0; i < parser.job->num_ibs; i++) | 1297 | for (i = 0; i < parser.job->num_ibs; i++) |
1310 | trace_amdgpu_cs(&parser, i); | 1298 | trace_amdgpu_cs(&parser, i); |
1311 | 1299 | ||
1312 | r = amdgpu_cs_ib_vm_chunk(adev, &parser); | 1300 | r = amdgpu_cs_vm_handling(&parser); |
1313 | if (r) | 1301 | if (r) |
1314 | goto out; | 1302 | goto out; |
1315 | 1303 | ||