diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 172 |
1 files changed, 91 insertions, 81 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index ab83dfcabb41..f7fceb63413c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | |||
@@ -90,12 +90,14 @@ static int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data) | |||
90 | goto free_chunk; | 90 | goto free_chunk; |
91 | } | 91 | } |
92 | 92 | ||
93 | mutex_lock(&p->ctx->lock); | ||
94 | |||
93 | /* get chunks */ | 95 | /* get chunks */ |
94 | chunk_array_user = u64_to_user_ptr(cs->in.chunks); | 96 | chunk_array_user = u64_to_user_ptr(cs->in.chunks); |
95 | if (copy_from_user(chunk_array, chunk_array_user, | 97 | if (copy_from_user(chunk_array, chunk_array_user, |
96 | sizeof(uint64_t)*cs->in.num_chunks)) { | 98 | sizeof(uint64_t)*cs->in.num_chunks)) { |
97 | ret = -EFAULT; | 99 | ret = -EFAULT; |
98 | goto put_ctx; | 100 | goto free_chunk; |
99 | } | 101 | } |
100 | 102 | ||
101 | p->nchunks = cs->in.num_chunks; | 103 | p->nchunks = cs->in.num_chunks; |
@@ -103,7 +105,7 @@ static int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data) | |||
103 | GFP_KERNEL); | 105 | GFP_KERNEL); |
104 | if (!p->chunks) { | 106 | if (!p->chunks) { |
105 | ret = -ENOMEM; | 107 | ret = -ENOMEM; |
106 | goto put_ctx; | 108 | goto free_chunk; |
107 | } | 109 | } |
108 | 110 | ||
109 | for (i = 0; i < p->nchunks; i++) { | 111 | for (i = 0; i < p->nchunks; i++) { |
@@ -170,6 +172,11 @@ static int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data) | |||
170 | if (ret) | 172 | if (ret) |
171 | goto free_all_kdata; | 173 | goto free_all_kdata; |
172 | 174 | ||
175 | if (p->ctx->vram_lost_counter != p->job->vram_lost_counter) { | ||
176 | ret = -ECANCELED; | ||
177 | goto free_all_kdata; | ||
178 | } | ||
179 | |||
173 | if (p->uf_entry.robj) | 180 | if (p->uf_entry.robj) |
174 | p->job->uf_addr = uf_offset; | 181 | p->job->uf_addr = uf_offset; |
175 | kfree(chunk_array); | 182 | kfree(chunk_array); |
@@ -183,8 +190,6 @@ free_partial_kdata: | |||
183 | kfree(p->chunks); | 190 | kfree(p->chunks); |
184 | p->chunks = NULL; | 191 | p->chunks = NULL; |
185 | p->nchunks = 0; | 192 | p->nchunks = 0; |
186 | put_ctx: | ||
187 | amdgpu_ctx_put(p->ctx); | ||
188 | free_chunk: | 193 | free_chunk: |
189 | kfree(chunk_array); | 194 | kfree(chunk_array); |
190 | 195 | ||
@@ -705,7 +710,8 @@ static int amdgpu_cs_sync_rings(struct amdgpu_cs_parser *p) | |||
705 | 710 | ||
706 | list_for_each_entry(e, &p->validated, tv.head) { | 711 | list_for_each_entry(e, &p->validated, tv.head) { |
707 | struct reservation_object *resv = e->robj->tbo.resv; | 712 | struct reservation_object *resv = e->robj->tbo.resv; |
708 | r = amdgpu_sync_resv(p->adev, &p->job->sync, resv, p->filp); | 713 | r = amdgpu_sync_resv(p->adev, &p->job->sync, resv, p->filp, |
714 | amdgpu_bo_explicit_sync(e->robj)); | ||
709 | 715 | ||
710 | if (r) | 716 | if (r) |
711 | return r; | 717 | return r; |
@@ -736,8 +742,10 @@ static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, | |||
736 | 742 | ||
737 | dma_fence_put(parser->fence); | 743 | dma_fence_put(parser->fence); |
738 | 744 | ||
739 | if (parser->ctx) | 745 | if (parser->ctx) { |
746 | mutex_unlock(&parser->ctx->lock); | ||
740 | amdgpu_ctx_put(parser->ctx); | 747 | amdgpu_ctx_put(parser->ctx); |
748 | } | ||
741 | if (parser->bo_list) | 749 | if (parser->bo_list) |
742 | amdgpu_bo_list_put(parser->bo_list); | 750 | amdgpu_bo_list_put(parser->bo_list); |
743 | 751 | ||
@@ -844,14 +852,58 @@ static int amdgpu_cs_ib_vm_chunk(struct amdgpu_device *adev, | |||
844 | struct amdgpu_fpriv *fpriv = p->filp->driver_priv; | 852 | struct amdgpu_fpriv *fpriv = p->filp->driver_priv; |
845 | struct amdgpu_vm *vm = &fpriv->vm; | 853 | struct amdgpu_vm *vm = &fpriv->vm; |
846 | struct amdgpu_ring *ring = p->job->ring; | 854 | struct amdgpu_ring *ring = p->job->ring; |
847 | int i, r; | 855 | int r; |
848 | 856 | ||
849 | /* Only for UVD/VCE VM emulation */ | 857 | /* Only for UVD/VCE VM emulation */ |
850 | if (ring->funcs->parse_cs) { | 858 | if (p->job->ring->funcs->parse_cs) { |
851 | for (i = 0; i < p->job->num_ibs; i++) { | 859 | unsigned i, j; |
852 | r = amdgpu_ring_parse_cs(ring, p, i); | 860 | |
861 | for (i = 0, j = 0; i < p->nchunks && j < p->job->num_ibs; i++) { | ||
862 | struct drm_amdgpu_cs_chunk_ib *chunk_ib; | ||
863 | struct amdgpu_bo_va_mapping *m; | ||
864 | struct amdgpu_bo *aobj = NULL; | ||
865 | struct amdgpu_cs_chunk *chunk; | ||
866 | struct amdgpu_ib *ib; | ||
867 | uint64_t offset; | ||
868 | uint8_t *kptr; | ||
869 | |||
870 | chunk = &p->chunks[i]; | ||
871 | ib = &p->job->ibs[j]; | ||
872 | chunk_ib = chunk->kdata; | ||
873 | |||
874 | if (chunk->chunk_id != AMDGPU_CHUNK_ID_IB) | ||
875 | continue; | ||
876 | |||
877 | r = amdgpu_cs_find_mapping(p, chunk_ib->va_start, | ||
878 | &aobj, &m); | ||
879 | if (r) { | ||
880 | DRM_ERROR("IB va_start is invalid\n"); | ||
881 | return r; | ||
882 | } | ||
883 | |||
884 | if ((chunk_ib->va_start + chunk_ib->ib_bytes) > | ||
885 | (m->last + 1) * AMDGPU_GPU_PAGE_SIZE) { | ||
886 | DRM_ERROR("IB va_start+ib_bytes is invalid\n"); | ||
887 | return -EINVAL; | ||
888 | } | ||
889 | |||
890 | /* the IB should be reserved at this point */ | ||
891 | r = amdgpu_bo_kmap(aobj, (void **)&kptr); | ||
892 | if (r) { | ||
893 | return r; | ||
894 | } | ||
895 | |||
896 | offset = m->start * AMDGPU_GPU_PAGE_SIZE; | ||
897 | kptr += chunk_ib->va_start - offset; | ||
898 | |||
899 | memcpy(ib->ptr, kptr, chunk_ib->ib_bytes); | ||
900 | amdgpu_bo_kunmap(aobj); | ||
901 | |||
902 | r = amdgpu_ring_parse_cs(ring, p, j); | ||
853 | if (r) | 903 | if (r) |
854 | return r; | 904 | return r; |
905 | |||
906 | j++; | ||
855 | } | 907 | } |
856 | } | 908 | } |
857 | 909 | ||
@@ -918,54 +970,18 @@ static int amdgpu_cs_ib_fill(struct amdgpu_device *adev, | |||
918 | 970 | ||
919 | parser->job->ring = ring; | 971 | parser->job->ring = ring; |
920 | 972 | ||
921 | if (ring->funcs->parse_cs) { | 973 | r = amdgpu_ib_get(adev, vm, |
922 | struct amdgpu_bo_va_mapping *m; | 974 | ring->funcs->parse_cs ? chunk_ib->ib_bytes : 0, |
923 | struct amdgpu_bo *aobj = NULL; | 975 | ib); |
924 | uint64_t offset; | 976 | if (r) { |
925 | uint8_t *kptr; | 977 | DRM_ERROR("Failed to get ib !\n"); |
926 | 978 | return r; | |
927 | r = amdgpu_cs_find_mapping(parser, chunk_ib->va_start, | ||
928 | &aobj, &m); | ||
929 | if (r) { | ||
930 | DRM_ERROR("IB va_start is invalid\n"); | ||
931 | return r; | ||
932 | } | ||
933 | |||
934 | if ((chunk_ib->va_start + chunk_ib->ib_bytes) > | ||
935 | (m->last + 1) * AMDGPU_GPU_PAGE_SIZE) { | ||
936 | DRM_ERROR("IB va_start+ib_bytes is invalid\n"); | ||
937 | return -EINVAL; | ||
938 | } | ||
939 | |||
940 | /* the IB should be reserved at this point */ | ||
941 | r = amdgpu_bo_kmap(aobj, (void **)&kptr); | ||
942 | if (r) { | ||
943 | return r; | ||
944 | } | ||
945 | |||
946 | offset = m->start * AMDGPU_GPU_PAGE_SIZE; | ||
947 | kptr += chunk_ib->va_start - offset; | ||
948 | |||
949 | r = amdgpu_ib_get(adev, vm, chunk_ib->ib_bytes, ib); | ||
950 | if (r) { | ||
951 | DRM_ERROR("Failed to get ib !\n"); | ||
952 | return r; | ||
953 | } | ||
954 | |||
955 | memcpy(ib->ptr, kptr, chunk_ib->ib_bytes); | ||
956 | amdgpu_bo_kunmap(aobj); | ||
957 | } else { | ||
958 | r = amdgpu_ib_get(adev, vm, 0, ib); | ||
959 | if (r) { | ||
960 | DRM_ERROR("Failed to get ib !\n"); | ||
961 | return r; | ||
962 | } | ||
963 | |||
964 | } | 979 | } |
965 | 980 | ||
966 | ib->gpu_addr = chunk_ib->va_start; | 981 | ib->gpu_addr = chunk_ib->va_start; |
967 | ib->length_dw = chunk_ib->ib_bytes / 4; | 982 | ib->length_dw = chunk_ib->ib_bytes / 4; |
968 | ib->flags = chunk_ib->flags; | 983 | ib->flags = chunk_ib->flags; |
984 | |||
969 | j++; | 985 | j++; |
970 | } | 986 | } |
971 | 987 | ||
@@ -975,7 +991,7 @@ static int amdgpu_cs_ib_fill(struct amdgpu_device *adev, | |||
975 | parser->job->ring->funcs->type == AMDGPU_RING_TYPE_VCE)) | 991 | parser->job->ring->funcs->type == AMDGPU_RING_TYPE_VCE)) |
976 | return -EINVAL; | 992 | return -EINVAL; |
977 | 993 | ||
978 | return 0; | 994 | return amdgpu_ctx_wait_prev_fence(parser->ctx, parser->job->ring->idx); |
979 | } | 995 | } |
980 | 996 | ||
981 | static int amdgpu_cs_process_fence_dep(struct amdgpu_cs_parser *p, | 997 | static int amdgpu_cs_process_fence_dep(struct amdgpu_cs_parser *p, |
@@ -1176,6 +1192,8 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p, | |||
1176 | job->uf_sequence = seq; | 1192 | job->uf_sequence = seq; |
1177 | 1193 | ||
1178 | amdgpu_job_free_resources(job); | 1194 | amdgpu_job_free_resources(job); |
1195 | amdgpu_ring_priority_get(job->ring, | ||
1196 | amd_sched_get_job_priority(&job->base)); | ||
1179 | 1197 | ||
1180 | trace_amdgpu_cs_ioctl(job); | 1198 | trace_amdgpu_cs_ioctl(job); |
1181 | amd_sched_entity_push_job(&job->base); | 1199 | amd_sched_entity_push_job(&job->base); |
@@ -1189,7 +1207,6 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p, | |||
1189 | int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) | 1207 | int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) |
1190 | { | 1208 | { |
1191 | struct amdgpu_device *adev = dev->dev_private; | 1209 | struct amdgpu_device *adev = dev->dev_private; |
1192 | struct amdgpu_fpriv *fpriv = filp->driver_priv; | ||
1193 | union drm_amdgpu_cs *cs = data; | 1210 | union drm_amdgpu_cs *cs = data; |
1194 | struct amdgpu_cs_parser parser = {}; | 1211 | struct amdgpu_cs_parser parser = {}; |
1195 | bool reserved_buffers = false; | 1212 | bool reserved_buffers = false; |
@@ -1197,8 +1214,6 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) | |||
1197 | 1214 | ||
1198 | if (!adev->accel_working) | 1215 | if (!adev->accel_working) |
1199 | return -EBUSY; | 1216 | return -EBUSY; |
1200 | if (amdgpu_kms_vram_lost(adev, fpriv)) | ||
1201 | return -ENODEV; | ||
1202 | 1217 | ||
1203 | parser.adev = adev; | 1218 | parser.adev = adev; |
1204 | parser.filp = filp; | 1219 | parser.filp = filp; |
@@ -1209,6 +1224,10 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) | |||
1209 | goto out; | 1224 | goto out; |
1210 | } | 1225 | } |
1211 | 1226 | ||
1227 | r = amdgpu_cs_ib_fill(adev, &parser); | ||
1228 | if (r) | ||
1229 | goto out; | ||
1230 | |||
1212 | r = amdgpu_cs_parser_bos(&parser, data); | 1231 | r = amdgpu_cs_parser_bos(&parser, data); |
1213 | if (r) { | 1232 | if (r) { |
1214 | if (r == -ENOMEM) | 1233 | if (r == -ENOMEM) |
@@ -1219,9 +1238,6 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) | |||
1219 | } | 1238 | } |
1220 | 1239 | ||
1221 | reserved_buffers = true; | 1240 | reserved_buffers = true; |
1222 | r = amdgpu_cs_ib_fill(adev, &parser); | ||
1223 | if (r) | ||
1224 | goto out; | ||
1225 | 1241 | ||
1226 | r = amdgpu_cs_dependencies(adev, &parser); | 1242 | r = amdgpu_cs_dependencies(adev, &parser); |
1227 | if (r) { | 1243 | if (r) { |
@@ -1257,16 +1273,12 @@ int amdgpu_cs_wait_ioctl(struct drm_device *dev, void *data, | |||
1257 | { | 1273 | { |
1258 | union drm_amdgpu_wait_cs *wait = data; | 1274 | union drm_amdgpu_wait_cs *wait = data; |
1259 | struct amdgpu_device *adev = dev->dev_private; | 1275 | struct amdgpu_device *adev = dev->dev_private; |
1260 | struct amdgpu_fpriv *fpriv = filp->driver_priv; | ||
1261 | unsigned long timeout = amdgpu_gem_timeout(wait->in.timeout); | 1276 | unsigned long timeout = amdgpu_gem_timeout(wait->in.timeout); |
1262 | struct amdgpu_ring *ring = NULL; | 1277 | struct amdgpu_ring *ring = NULL; |
1263 | struct amdgpu_ctx *ctx; | 1278 | struct amdgpu_ctx *ctx; |
1264 | struct dma_fence *fence; | 1279 | struct dma_fence *fence; |
1265 | long r; | 1280 | long r; |
1266 | 1281 | ||
1267 | if (amdgpu_kms_vram_lost(adev, fpriv)) | ||
1268 | return -ENODEV; | ||
1269 | |||
1270 | ctx = amdgpu_ctx_get(filp->driver_priv, wait->in.ctx_id); | 1282 | ctx = amdgpu_ctx_get(filp->driver_priv, wait->in.ctx_id); |
1271 | if (ctx == NULL) | 1283 | if (ctx == NULL) |
1272 | return -EINVAL; | 1284 | return -EINVAL; |
@@ -1284,6 +1296,8 @@ int amdgpu_cs_wait_ioctl(struct drm_device *dev, void *data, | |||
1284 | r = PTR_ERR(fence); | 1296 | r = PTR_ERR(fence); |
1285 | else if (fence) { | 1297 | else if (fence) { |
1286 | r = dma_fence_wait_timeout(fence, true, timeout); | 1298 | r = dma_fence_wait_timeout(fence, true, timeout); |
1299 | if (r > 0 && fence->error) | ||
1300 | r = fence->error; | ||
1287 | dma_fence_put(fence); | 1301 | dma_fence_put(fence); |
1288 | } else | 1302 | } else |
1289 | r = 1; | 1303 | r = 1; |
@@ -1335,16 +1349,12 @@ int amdgpu_cs_fence_to_handle_ioctl(struct drm_device *dev, void *data, | |||
1335 | struct drm_file *filp) | 1349 | struct drm_file *filp) |
1336 | { | 1350 | { |
1337 | struct amdgpu_device *adev = dev->dev_private; | 1351 | struct amdgpu_device *adev = dev->dev_private; |
1338 | struct amdgpu_fpriv *fpriv = filp->driver_priv; | ||
1339 | union drm_amdgpu_fence_to_handle *info = data; | 1352 | union drm_amdgpu_fence_to_handle *info = data; |
1340 | struct dma_fence *fence; | 1353 | struct dma_fence *fence; |
1341 | struct drm_syncobj *syncobj; | 1354 | struct drm_syncobj *syncobj; |
1342 | struct sync_file *sync_file; | 1355 | struct sync_file *sync_file; |
1343 | int fd, r; | 1356 | int fd, r; |
1344 | 1357 | ||
1345 | if (amdgpu_kms_vram_lost(adev, fpriv)) | ||
1346 | return -ENODEV; | ||
1347 | |||
1348 | fence = amdgpu_cs_get_fence(adev, filp, &info->in.fence); | 1358 | fence = amdgpu_cs_get_fence(adev, filp, &info->in.fence); |
1349 | if (IS_ERR(fence)) | 1359 | if (IS_ERR(fence)) |
1350 | return PTR_ERR(fence); | 1360 | return PTR_ERR(fence); |
@@ -1425,6 +1435,9 @@ static int amdgpu_cs_wait_all_fences(struct amdgpu_device *adev, | |||
1425 | 1435 | ||
1426 | if (r == 0) | 1436 | if (r == 0) |
1427 | break; | 1437 | break; |
1438 | |||
1439 | if (fence->error) | ||
1440 | return fence->error; | ||
1428 | } | 1441 | } |
1429 | 1442 | ||
1430 | memset(wait, 0, sizeof(*wait)); | 1443 | memset(wait, 0, sizeof(*wait)); |
@@ -1485,7 +1498,7 @@ out: | |||
1485 | wait->out.status = (r > 0); | 1498 | wait->out.status = (r > 0); |
1486 | wait->out.first_signaled = first; | 1499 | wait->out.first_signaled = first; |
1487 | /* set return value 0 to indicate success */ | 1500 | /* set return value 0 to indicate success */ |
1488 | r = 0; | 1501 | r = array[first]->error; |
1489 | 1502 | ||
1490 | err_free_fence_array: | 1503 | err_free_fence_array: |
1491 | for (i = 0; i < fence_count; i++) | 1504 | for (i = 0; i < fence_count; i++) |
@@ -1506,15 +1519,12 @@ int amdgpu_cs_wait_fences_ioctl(struct drm_device *dev, void *data, | |||
1506 | struct drm_file *filp) | 1519 | struct drm_file *filp) |
1507 | { | 1520 | { |
1508 | struct amdgpu_device *adev = dev->dev_private; | 1521 | struct amdgpu_device *adev = dev->dev_private; |
1509 | struct amdgpu_fpriv *fpriv = filp->driver_priv; | ||
1510 | union drm_amdgpu_wait_fences *wait = data; | 1522 | union drm_amdgpu_wait_fences *wait = data; |
1511 | uint32_t fence_count = wait->in.fence_count; | 1523 | uint32_t fence_count = wait->in.fence_count; |
1512 | struct drm_amdgpu_fence *fences_user; | 1524 | struct drm_amdgpu_fence *fences_user; |
1513 | struct drm_amdgpu_fence *fences; | 1525 | struct drm_amdgpu_fence *fences; |
1514 | int r; | 1526 | int r; |
1515 | 1527 | ||
1516 | if (amdgpu_kms_vram_lost(adev, fpriv)) | ||
1517 | return -ENODEV; | ||
1518 | /* Get the fences from userspace */ | 1528 | /* Get the fences from userspace */ |
1519 | fences = kmalloc_array(fence_count, sizeof(struct drm_amdgpu_fence), | 1529 | fences = kmalloc_array(fence_count, sizeof(struct drm_amdgpu_fence), |
1520 | GFP_KERNEL); | 1530 | GFP_KERNEL); |
@@ -1572,14 +1582,14 @@ int amdgpu_cs_find_mapping(struct amdgpu_cs_parser *parser, | |||
1572 | if (READ_ONCE((*bo)->tbo.resv->lock.ctx) != &parser->ticket) | 1582 | if (READ_ONCE((*bo)->tbo.resv->lock.ctx) != &parser->ticket) |
1573 | return -EINVAL; | 1583 | return -EINVAL; |
1574 | 1584 | ||
1575 | r = amdgpu_ttm_bind(&(*bo)->tbo, &(*bo)->tbo.mem); | 1585 | if (!((*bo)->flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS)) { |
1576 | if (unlikely(r)) | 1586 | (*bo)->flags |= AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS; |
1577 | return r; | 1587 | amdgpu_ttm_placement_from_domain(*bo, (*bo)->allowed_domains); |
1578 | 1588 | r = ttm_bo_validate(&(*bo)->tbo, &(*bo)->placement, false, | |
1579 | if ((*bo)->flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS) | 1589 | false); |
1580 | return 0; | 1590 | if (r) |
1591 | return r; | ||
1592 | } | ||
1581 | 1593 | ||
1582 | (*bo)->flags |= AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS; | 1594 | return amdgpu_ttm_bind(&(*bo)->tbo, &(*bo)->tbo.mem); |
1583 | amdgpu_ttm_placement_from_domain(*bo, (*bo)->allowed_domains); | ||
1584 | return ttm_bo_validate(&(*bo)->tbo, &(*bo)->placement, false, false); | ||
1585 | } | 1595 | } |