| .. | .. |
|---|
| 27 | 27 | |
|---|
| 28 | 28 | #include <linux/firmware.h> |
|---|
| 29 | 29 | #include <linux/module.h> |
|---|
| 30 | | -#include <drm/drmP.h> |
|---|
| 30 | + |
|---|
| 31 | 31 | #include <drm/drm.h> |
|---|
| 32 | 32 | |
|---|
| 33 | 33 | #include "amdgpu.h" |
|---|
| .. | .. |
|---|
| 80 | 80 | MODULE_FIRMWARE(FIRMWARE_VEGA20); |
|---|
| 81 | 81 | |
|---|
| 82 | 82 | static void amdgpu_vce_idle_work_handler(struct work_struct *work); |
|---|
| 83 | +static int amdgpu_vce_get_create_msg(struct amdgpu_ring *ring, uint32_t handle, |
|---|
| 84 | + struct amdgpu_bo *bo, |
|---|
| 85 | + struct dma_fence **fence); |
|---|
| 86 | +static int amdgpu_vce_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle, |
|---|
| 87 | + bool direct, struct dma_fence **fence); |
|---|
| 83 | 88 | |
|---|
| 84 | 89 | /** |
|---|
| 85 | 90 | * amdgpu_vce_init - allocate memory, load vce firmware |
|---|
| .. | .. |
|---|
| 211 | 216 | if (adev->vce.vcpu_bo == NULL) |
|---|
| 212 | 217 | return 0; |
|---|
| 213 | 218 | |
|---|
| 219 | + cancel_delayed_work_sync(&adev->vce.idle_work); |
|---|
| 214 | 220 | drm_sched_entity_destroy(&adev->vce.entity); |
|---|
| 215 | 221 | |
|---|
| 216 | 222 | amdgpu_bo_free_kernel(&adev->vce.vcpu_bo, &adev->vce.gpu_addr, |
|---|
| .. | .. |
|---|
| 234 | 240 | int amdgpu_vce_entity_init(struct amdgpu_device *adev) |
|---|
| 235 | 241 | { |
|---|
| 236 | 242 | struct amdgpu_ring *ring; |
|---|
| 237 | | - struct drm_sched_rq *rq; |
|---|
| 243 | + struct drm_gpu_scheduler *sched; |
|---|
| 238 | 244 | int r; |
|---|
| 239 | 245 | |
|---|
| 240 | 246 | ring = &adev->vce.ring[0]; |
|---|
| 241 | | - rq = &ring->sched.sched_rq[DRM_SCHED_PRIORITY_NORMAL]; |
|---|
| 242 | | - r = drm_sched_entity_init(&adev->vce.entity, &rq, 1, NULL); |
|---|
| 247 | + sched = &ring->sched; |
|---|
| 248 | + r = drm_sched_entity_init(&adev->vce.entity, DRM_SCHED_PRIORITY_NORMAL, |
|---|
| 249 | + &sched, 1, NULL); |
|---|
| 243 | 250 | if (r != 0) { |
|---|
| 244 | 251 | DRM_ERROR("Failed setting up VCE run queue.\n"); |
|---|
| 245 | 252 | return r; |
|---|
| .. | .. |
|---|
| 428 | 435 | * |
|---|
| 429 | 436 | * Open up a stream for HW test |
|---|
| 430 | 437 | */ |
|---|
| 431 | | -int amdgpu_vce_get_create_msg(struct amdgpu_ring *ring, uint32_t handle, |
|---|
| 432 | | - struct dma_fence **fence) |
|---|
| 438 | +static int amdgpu_vce_get_create_msg(struct amdgpu_ring *ring, uint32_t handle, |
|---|
| 439 | + struct amdgpu_bo *bo, |
|---|
| 440 | + struct dma_fence **fence) |
|---|
| 433 | 441 | { |
|---|
| 434 | 442 | const unsigned ib_size_dw = 1024; |
|---|
| 435 | 443 | struct amdgpu_job *job; |
|---|
| 436 | 444 | struct amdgpu_ib *ib; |
|---|
| 437 | 445 | struct dma_fence *f = NULL; |
|---|
| 438 | | - uint64_t dummy; |
|---|
| 446 | + uint64_t addr; |
|---|
| 439 | 447 | int i, r; |
|---|
| 440 | 448 | |
|---|
| 441 | | - r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4, &job); |
|---|
| 449 | + r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4, |
|---|
| 450 | + AMDGPU_IB_POOL_DIRECT, &job); |
|---|
| 442 | 451 | if (r) |
|---|
| 443 | 452 | return r; |
|---|
| 444 | 453 | |
|---|
| 445 | 454 | ib = &job->ibs[0]; |
|---|
| 446 | 455 | |
|---|
| 447 | | - dummy = ib->gpu_addr + 1024; |
|---|
| 456 | + addr = amdgpu_bo_gpu_offset(bo); |
|---|
| 448 | 457 | |
|---|
| 449 | 458 | /* stitch together an VCE create msg */ |
|---|
| 450 | 459 | ib->length_dw = 0; |
|---|
| .. | .. |
|---|
| 476 | 485 | |
|---|
| 477 | 486 | ib->ptr[ib->length_dw++] = 0x00000014; /* len */ |
|---|
| 478 | 487 | ib->ptr[ib->length_dw++] = 0x05000005; /* feedback buffer */ |
|---|
| 479 | | - ib->ptr[ib->length_dw++] = upper_32_bits(dummy); |
|---|
| 480 | | - ib->ptr[ib->length_dw++] = dummy; |
|---|
| 488 | + ib->ptr[ib->length_dw++] = upper_32_bits(addr); |
|---|
| 489 | + ib->ptr[ib->length_dw++] = addr; |
|---|
| 481 | 490 | ib->ptr[ib->length_dw++] = 0x00000001; |
|---|
| 482 | 491 | |
|---|
| 483 | 492 | for (i = ib->length_dw; i < ib_size_dw; ++i) |
|---|
| .. | .. |
|---|
| 507 | 516 | * |
|---|
| 508 | 517 | * Close up a stream for HW test or if userspace failed to do so |
|---|
| 509 | 518 | */ |
|---|
| 510 | | -int amdgpu_vce_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle, |
|---|
| 511 | | - bool direct, struct dma_fence **fence) |
|---|
| 519 | +static int amdgpu_vce_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle, |
|---|
| 520 | + bool direct, struct dma_fence **fence) |
|---|
| 512 | 521 | { |
|---|
| 513 | 522 | const unsigned ib_size_dw = 1024; |
|---|
| 514 | 523 | struct amdgpu_job *job; |
|---|
| .. | .. |
|---|
| 516 | 525 | struct dma_fence *f = NULL; |
|---|
| 517 | 526 | int i, r; |
|---|
| 518 | 527 | |
|---|
| 519 | | - r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4, &job); |
|---|
| 528 | + r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4, |
|---|
| 529 | + direct ? AMDGPU_IB_POOL_DIRECT : |
|---|
| 530 | + AMDGPU_IB_POOL_DELAYED, &job); |
|---|
| 520 | 531 | if (r) |
|---|
| 521 | 532 | return r; |
|---|
| 522 | 533 | |
|---|
| .. | .. |
|---|
| 644 | 655 | |
|---|
| 645 | 656 | if ((addr + (uint64_t)size) > |
|---|
| 646 | 657 | (mapping->last + 1) * AMDGPU_GPU_PAGE_SIZE) { |
|---|
| 647 | | - DRM_ERROR("BO to small for addr 0x%010Lx %d %d\n", |
|---|
| 658 | + DRM_ERROR("BO too small for addr 0x%010Lx %d %d\n", |
|---|
| 648 | 659 | addr, lo, hi); |
|---|
| 649 | 660 | return -EINVAL; |
|---|
| 650 | 661 | } |
|---|
| .. | .. |
|---|
| 1032 | 1043 | * @ib: the IB to execute |
|---|
| 1033 | 1044 | * |
|---|
| 1034 | 1045 | */ |
|---|
| 1035 | | -void amdgpu_vce_ring_emit_ib(struct amdgpu_ring *ring, struct amdgpu_ib *ib, |
|---|
| 1036 | | - unsigned vmid, bool ctx_switch) |
|---|
| 1046 | +void amdgpu_vce_ring_emit_ib(struct amdgpu_ring *ring, |
|---|
| 1047 | + struct amdgpu_job *job, |
|---|
| 1048 | + struct amdgpu_ib *ib, |
|---|
| 1049 | + uint32_t flags) |
|---|
| 1037 | 1050 | { |
|---|
| 1038 | 1051 | amdgpu_ring_write(ring, VCE_CMD_IB); |
|---|
| 1039 | 1052 | amdgpu_ring_write(ring, lower_32_bits(ib->gpu_addr)); |
|---|
| .. | .. |
|---|
| 1079 | 1092 | return 0; |
|---|
| 1080 | 1093 | |
|---|
| 1081 | 1094 | r = amdgpu_ring_alloc(ring, 16); |
|---|
| 1082 | | - if (r) { |
|---|
| 1083 | | - DRM_ERROR("amdgpu: vce failed to lock ring %d (%d).\n", |
|---|
| 1084 | | - ring->idx, r); |
|---|
| 1095 | + if (r) |
|---|
| 1085 | 1096 | return r; |
|---|
| 1086 | | - } |
|---|
| 1087 | 1097 | |
|---|
| 1088 | 1098 | rptr = amdgpu_ring_get_rptr(ring); |
|---|
| 1089 | 1099 | |
|---|
| .. | .. |
|---|
| 1093 | 1103 | for (i = 0; i < timeout; i++) { |
|---|
| 1094 | 1104 | if (amdgpu_ring_get_rptr(ring) != rptr) |
|---|
| 1095 | 1105 | break; |
|---|
| 1096 | | - DRM_UDELAY(1); |
|---|
| 1106 | + udelay(1); |
|---|
| 1097 | 1107 | } |
|---|
| 1098 | 1108 | |
|---|
| 1099 | | - if (i < timeout) { |
|---|
| 1100 | | - DRM_DEBUG("ring test on %d succeeded in %d usecs\n", |
|---|
| 1101 | | - ring->idx, i); |
|---|
| 1102 | | - } else { |
|---|
| 1103 | | - DRM_ERROR("amdgpu: ring %d test failed\n", |
|---|
| 1104 | | - ring->idx); |
|---|
| 1109 | + if (i >= timeout) |
|---|
| 1105 | 1110 | r = -ETIMEDOUT; |
|---|
| 1106 | | - } |
|---|
| 1107 | 1111 | |
|---|
| 1108 | 1112 | return r; |
|---|
| 1109 | 1113 | } |
|---|
| .. | .. |
|---|
| 1117 | 1121 | int amdgpu_vce_ring_test_ib(struct amdgpu_ring *ring, long timeout) |
|---|
| 1118 | 1122 | { |
|---|
| 1119 | 1123 | struct dma_fence *fence = NULL; |
|---|
| 1124 | + struct amdgpu_bo *bo = NULL; |
|---|
| 1120 | 1125 | long r; |
|---|
| 1121 | 1126 | |
|---|
| 1122 | 1127 | /* skip vce ring1/2 ib test for now, since it's not reliable */ |
|---|
| 1123 | 1128 | if (ring != &ring->adev->vce.ring[0]) |
|---|
| 1124 | 1129 | return 0; |
|---|
| 1125 | 1130 | |
|---|
| 1126 | | - r = amdgpu_vce_get_create_msg(ring, 1, NULL); |
|---|
| 1127 | | - if (r) { |
|---|
| 1128 | | - DRM_ERROR("amdgpu: failed to get create msg (%ld).\n", r); |
|---|
| 1131 | + r = amdgpu_bo_create_reserved(ring->adev, 512, PAGE_SIZE, |
|---|
| 1132 | + AMDGPU_GEM_DOMAIN_VRAM, |
|---|
| 1133 | + &bo, NULL, NULL); |
|---|
| 1134 | + if (r) |
|---|
| 1135 | + return r; |
|---|
| 1136 | + |
|---|
| 1137 | + r = amdgpu_vce_get_create_msg(ring, 1, bo, NULL); |
|---|
| 1138 | + if (r) |
|---|
| 1129 | 1139 | goto error; |
|---|
| 1130 | | - } |
|---|
| 1131 | 1140 | |
|---|
| 1132 | 1141 | r = amdgpu_vce_get_destroy_msg(ring, 1, true, &fence); |
|---|
| 1133 | | - if (r) { |
|---|
| 1134 | | - DRM_ERROR("amdgpu: failed to get destroy ib (%ld).\n", r); |
|---|
| 1142 | + if (r) |
|---|
| 1135 | 1143 | goto error; |
|---|
| 1136 | | - } |
|---|
| 1137 | 1144 | |
|---|
| 1138 | 1145 | r = dma_fence_wait_timeout(fence, false, timeout); |
|---|
| 1139 | | - if (r == 0) { |
|---|
| 1140 | | - DRM_ERROR("amdgpu: IB test timed out.\n"); |
|---|
| 1146 | + if (r == 0) |
|---|
| 1141 | 1147 | r = -ETIMEDOUT; |
|---|
| 1142 | | - } else if (r < 0) { |
|---|
| 1143 | | - DRM_ERROR("amdgpu: fence wait failed (%ld).\n", r); |
|---|
| 1144 | | - } else { |
|---|
| 1145 | | - DRM_DEBUG("ib test on ring %d succeeded\n", ring->idx); |
|---|
| 1148 | + else if (r > 0) |
|---|
| 1146 | 1149 | r = 0; |
|---|
| 1147 | | - } |
|---|
| 1150 | + |
|---|
| 1148 | 1151 | error: |
|---|
| 1149 | 1152 | dma_fence_put(fence); |
|---|
| 1153 | + amdgpu_bo_unreserve(bo); |
|---|
| 1154 | + amdgpu_bo_unref(&bo); |
|---|
| 1150 | 1155 | return r; |
|---|
| 1151 | 1156 | } |
|---|