1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27#include <linux/firmware.h>
28#include <linux/module.h>
29#include <linux/pci.h>
30
31#include "amdgpu.h"
32#include "amdgpu_pm.h"
33#include "amdgpu_vcn.h"
34#include "soc15d.h"
35
36
37#define FIRMWARE_RAVEN "amdgpu/raven_vcn.bin"
38#define FIRMWARE_PICASSO "amdgpu/picasso_vcn.bin"
39#define FIRMWARE_RAVEN2 "amdgpu/raven2_vcn.bin"
40#define FIRMWARE_ARCTURUS "amdgpu/arcturus_vcn.bin"
41#define FIRMWARE_RENOIR "amdgpu/renoir_vcn.bin"
42#define FIRMWARE_NAVI10 "amdgpu/navi10_vcn.bin"
43#define FIRMWARE_NAVI14 "amdgpu/navi14_vcn.bin"
44#define FIRMWARE_NAVI12 "amdgpu/navi12_vcn.bin"
45#define FIRMWARE_SIENNA_CICHLID "amdgpu/sienna_cichlid_vcn.bin"
46#define FIRMWARE_NAVY_FLOUNDER "amdgpu/navy_flounder_vcn.bin"
47
48MODULE_FIRMWARE(FIRMWARE_RAVEN);
49MODULE_FIRMWARE(FIRMWARE_PICASSO);
50MODULE_FIRMWARE(FIRMWARE_RAVEN2);
51MODULE_FIRMWARE(FIRMWARE_ARCTURUS);
52MODULE_FIRMWARE(FIRMWARE_RENOIR);
53MODULE_FIRMWARE(FIRMWARE_NAVI10);
54MODULE_FIRMWARE(FIRMWARE_NAVI14);
55MODULE_FIRMWARE(FIRMWARE_NAVI12);
56MODULE_FIRMWARE(FIRMWARE_SIENNA_CICHLID);
57MODULE_FIRMWARE(FIRMWARE_NAVY_FLOUNDER);
58
59static void amdgpu_vcn_idle_work_handler(struct work_struct *work);
60
61int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
62{
63 unsigned long bo_size;
64 const char *fw_name;
65 const struct common_firmware_header *hdr;
66 unsigned char fw_check;
67 int i, r;
68
69 INIT_DELAYED_WORK(&adev->vcn.idle_work, amdgpu_vcn_idle_work_handler);
70 mutex_init(&adev->vcn.vcn_pg_lock);
71 mutex_init(&adev->vcn.vcn1_jpeg1_workaround);
72 atomic_set(&adev->vcn.total_submission_cnt, 0);
73 for (i = 0; i < adev->vcn.num_vcn_inst; i++)
74 atomic_set(&adev->vcn.inst[i].dpg_enc_submission_cnt, 0);
75
76 switch (adev->asic_type) {
77 case CHIP_RAVEN:
78 if (adev->apu_flags & AMD_APU_IS_RAVEN2)
79 fw_name = FIRMWARE_RAVEN2;
80 else if (adev->apu_flags & AMD_APU_IS_PICASSO)
81 fw_name = FIRMWARE_PICASSO;
82 else
83 fw_name = FIRMWARE_RAVEN;
84 break;
85 case CHIP_ARCTURUS:
86 fw_name = FIRMWARE_ARCTURUS;
87 if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
88 (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
89 adev->vcn.indirect_sram = true;
90 break;
91 case CHIP_RENOIR:
92 fw_name = FIRMWARE_RENOIR;
93 if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
94 (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
95 adev->vcn.indirect_sram = true;
96 break;
97 case CHIP_NAVI10:
98 fw_name = FIRMWARE_NAVI10;
99 if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
100 (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
101 adev->vcn.indirect_sram = true;
102 break;
103 case CHIP_NAVI14:
104 fw_name = FIRMWARE_NAVI14;
105 if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
106 (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
107 adev->vcn.indirect_sram = true;
108 break;
109 case CHIP_NAVI12:
110 fw_name = FIRMWARE_NAVI12;
111 if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
112 (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
113 adev->vcn.indirect_sram = true;
114 break;
115 case CHIP_SIENNA_CICHLID:
116 fw_name = FIRMWARE_SIENNA_CICHLID;
117 if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
118 (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
119 adev->vcn.indirect_sram = true;
120 break;
121 case CHIP_NAVY_FLOUNDER:
122 fw_name = FIRMWARE_NAVY_FLOUNDER;
123 if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
124 (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
125 adev->vcn.indirect_sram = true;
126 break;
127 default:
128 return -EINVAL;
129 }
130
131 r = request_firmware(&adev->vcn.fw, fw_name, adev->dev);
132 if (r) {
133 dev_err(adev->dev, "amdgpu_vcn: Can't load firmware \"%s\"\n",
134 fw_name);
135 return r;
136 }
137
138 r = amdgpu_ucode_validate(adev->vcn.fw);
139 if (r) {
140 dev_err(adev->dev, "amdgpu_vcn: Can't validate firmware \"%s\"\n",
141 fw_name);
142 release_firmware(adev->vcn.fw);
143 adev->vcn.fw = NULL;
144 return r;
145 }
146
147 hdr = (const struct common_firmware_header *)adev->vcn.fw->data;
148 adev->vcn.fw_version = le32_to_cpu(hdr->ucode_version);
149
150
151
152
153
154
155
156 fw_check = (le32_to_cpu(hdr->ucode_version) >> 20) & 0xf;
157 if (fw_check) {
158 unsigned int dec_ver, enc_major, enc_minor, vep, fw_rev;
159
160 fw_rev = le32_to_cpu(hdr->ucode_version) & 0xfff;
161 enc_minor = (le32_to_cpu(hdr->ucode_version) >> 12) & 0xff;
162 enc_major = fw_check;
163 dec_ver = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xf;
164 vep = (le32_to_cpu(hdr->ucode_version) >> 28) & 0xf;
165 DRM_INFO("Found VCN firmware Version ENC: %hu.%hu DEC: %hu VEP: %hu Revision: %hu\n",
166 enc_major, enc_minor, dec_ver, vep, fw_rev);
167 } else {
168 unsigned int version_major, version_minor, family_id;
169
170 family_id = le32_to_cpu(hdr->ucode_version) & 0xff;
171 version_major = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xff;
172 version_minor = (le32_to_cpu(hdr->ucode_version) >> 8) & 0xff;
173 DRM_INFO("Found VCN firmware Version: %hu.%hu Family ID: %hu\n",
174 version_major, version_minor, family_id);
175 }
176
177 bo_size = AMDGPU_VCN_STACK_SIZE + AMDGPU_VCN_CONTEXT_SIZE;
178 if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
179 bo_size += AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8);
180 bo_size += AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_fw_shared));
181
182 for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
183 if (adev->vcn.harvest_config & (1 << i))
184 continue;
185
186 r = amdgpu_bo_create_kernel(adev, bo_size, PAGE_SIZE,
187 AMDGPU_GEM_DOMAIN_VRAM, &adev->vcn.inst[i].vcpu_bo,
188 &adev->vcn.inst[i].gpu_addr, &adev->vcn.inst[i].cpu_addr);
189 if (r) {
190 dev_err(adev->dev, "(%d) failed to allocate vcn bo\n", r);
191 return r;
192 }
193
194 adev->vcn.inst[i].fw_shared_cpu_addr = adev->vcn.inst[i].cpu_addr +
195 bo_size - AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_fw_shared));
196 adev->vcn.inst[i].fw_shared_gpu_addr = adev->vcn.inst[i].gpu_addr +
197 bo_size - AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_fw_shared));
198
199 if (adev->vcn.indirect_sram) {
200 r = amdgpu_bo_create_kernel(adev, 64 * 2 * 4, PAGE_SIZE,
201 AMDGPU_GEM_DOMAIN_VRAM, &adev->vcn.inst[i].dpg_sram_bo,
202 &adev->vcn.inst[i].dpg_sram_gpu_addr, &adev->vcn.inst[i].dpg_sram_cpu_addr);
203 if (r) {
204 dev_err(adev->dev, "VCN %d (%d) failed to allocate DPG bo\n", i, r);
205 return r;
206 }
207 }
208 }
209
210 return 0;
211}
212
213int amdgpu_vcn_sw_fini(struct amdgpu_device *adev)
214{
215 int i, j;
216
217 cancel_delayed_work_sync(&adev->vcn.idle_work);
218
219 for (j = 0; j < adev->vcn.num_vcn_inst; ++j) {
220 if (adev->vcn.harvest_config & (1 << j))
221 continue;
222
223 if (adev->vcn.indirect_sram) {
224 amdgpu_bo_free_kernel(&adev->vcn.inst[j].dpg_sram_bo,
225 &adev->vcn.inst[j].dpg_sram_gpu_addr,
226 (void **)&adev->vcn.inst[j].dpg_sram_cpu_addr);
227 }
228 kvfree(adev->vcn.inst[j].saved_bo);
229
230 amdgpu_bo_free_kernel(&adev->vcn.inst[j].vcpu_bo,
231 &adev->vcn.inst[j].gpu_addr,
232 (void **)&adev->vcn.inst[j].cpu_addr);
233
234 amdgpu_ring_fini(&adev->vcn.inst[j].ring_dec);
235
236 for (i = 0; i < adev->vcn.num_enc_rings; ++i)
237 amdgpu_ring_fini(&adev->vcn.inst[j].ring_enc[i]);
238 }
239
240 release_firmware(adev->vcn.fw);
241 mutex_destroy(&adev->vcn.vcn1_jpeg1_workaround);
242 mutex_destroy(&adev->vcn.vcn_pg_lock);
243
244 return 0;
245}
246
247int amdgpu_vcn_suspend(struct amdgpu_device *adev)
248{
249 unsigned size;
250 void *ptr;
251 int i;
252
253 cancel_delayed_work_sync(&adev->vcn.idle_work);
254
255 for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
256 if (adev->vcn.harvest_config & (1 << i))
257 continue;
258 if (adev->vcn.inst[i].vcpu_bo == NULL)
259 return 0;
260
261 size = amdgpu_bo_size(adev->vcn.inst[i].vcpu_bo);
262 ptr = adev->vcn.inst[i].cpu_addr;
263
264 adev->vcn.inst[i].saved_bo = kvmalloc(size, GFP_KERNEL);
265 if (!adev->vcn.inst[i].saved_bo)
266 return -ENOMEM;
267
268 memcpy_fromio(adev->vcn.inst[i].saved_bo, ptr, size);
269 }
270 return 0;
271}
272
273int amdgpu_vcn_resume(struct amdgpu_device *adev)
274{
275 unsigned size;
276 void *ptr;
277 int i;
278
279 for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
280 if (adev->vcn.harvest_config & (1 << i))
281 continue;
282 if (adev->vcn.inst[i].vcpu_bo == NULL)
283 return -EINVAL;
284
285 size = amdgpu_bo_size(adev->vcn.inst[i].vcpu_bo);
286 ptr = adev->vcn.inst[i].cpu_addr;
287
288 if (adev->vcn.inst[i].saved_bo != NULL) {
289 memcpy_toio(ptr, adev->vcn.inst[i].saved_bo, size);
290 kvfree(adev->vcn.inst[i].saved_bo);
291 adev->vcn.inst[i].saved_bo = NULL;
292 } else {
293 const struct common_firmware_header *hdr;
294 unsigned offset;
295
296 hdr = (const struct common_firmware_header *)adev->vcn.fw->data;
297 if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) {
298 offset = le32_to_cpu(hdr->ucode_array_offset_bytes);
299 memcpy_toio(adev->vcn.inst[i].cpu_addr, adev->vcn.fw->data + offset,
300 le32_to_cpu(hdr->ucode_size_bytes));
301 size -= le32_to_cpu(hdr->ucode_size_bytes);
302 ptr += le32_to_cpu(hdr->ucode_size_bytes);
303 }
304 memset_io(ptr, 0, size);
305 }
306 }
307 return 0;
308}
309
310static void amdgpu_vcn_idle_work_handler(struct work_struct *work)
311{
312 struct amdgpu_device *adev =
313 container_of(work, struct amdgpu_device, vcn.idle_work.work);
314 unsigned int fences = 0, fence[AMDGPU_MAX_VCN_INSTANCES] = {0};
315 unsigned int i, j;
316
317 for (j = 0; j < adev->vcn.num_vcn_inst; ++j) {
318 if (adev->vcn.harvest_config & (1 << j))
319 continue;
320
321 for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
322 fence[j] += amdgpu_fence_count_emitted(&adev->vcn.inst[j].ring_enc[i]);
323 }
324
325 if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
326 struct dpg_pause_state new_state;
327
328 if (fence[j] ||
329 unlikely(atomic_read(&adev->vcn.inst[j].dpg_enc_submission_cnt)))
330 new_state.fw_based = VCN_DPG_STATE__PAUSE;
331 else
332 new_state.fw_based = VCN_DPG_STATE__UNPAUSE;
333
334 adev->vcn.pause_dpg_mode(adev, j, &new_state);
335 }
336
337 fence[j] += amdgpu_fence_count_emitted(&adev->vcn.inst[j].ring_dec);
338 fences += fence[j];
339 }
340
341 if (!fences && !atomic_read(&adev->vcn.total_submission_cnt)) {
342 amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCN,
343 AMD_PG_STATE_GATE);
344 } else {
345 schedule_delayed_work(&adev->vcn.idle_work, VCN_IDLE_TIMEOUT);
346 }
347}
348
349void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring)
350{
351 struct amdgpu_device *adev = ring->adev;
352
353 atomic_inc(&adev->vcn.total_submission_cnt);
354 cancel_delayed_work_sync(&adev->vcn.idle_work);
355
356 mutex_lock(&adev->vcn.vcn_pg_lock);
357 amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCN,
358 AMD_PG_STATE_UNGATE);
359
360 if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
361 struct dpg_pause_state new_state;
362
363 if (ring->funcs->type == AMDGPU_RING_TYPE_VCN_ENC) {
364 atomic_inc(&adev->vcn.inst[ring->me].dpg_enc_submission_cnt);
365 new_state.fw_based = VCN_DPG_STATE__PAUSE;
366 } else {
367 unsigned int fences = 0;
368 unsigned int i;
369
370 for (i = 0; i < adev->vcn.num_enc_rings; ++i)
371 fences += amdgpu_fence_count_emitted(&adev->vcn.inst[ring->me].ring_enc[i]);
372
373 if (fences || atomic_read(&adev->vcn.inst[ring->me].dpg_enc_submission_cnt))
374 new_state.fw_based = VCN_DPG_STATE__PAUSE;
375 else
376 new_state.fw_based = VCN_DPG_STATE__UNPAUSE;
377 }
378
379 adev->vcn.pause_dpg_mode(adev, ring->me, &new_state);
380 }
381 mutex_unlock(&adev->vcn.vcn_pg_lock);
382}
383
384void amdgpu_vcn_ring_end_use(struct amdgpu_ring *ring)
385{
386 if (ring->adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG &&
387 ring->funcs->type == AMDGPU_RING_TYPE_VCN_ENC)
388 atomic_dec(&ring->adev->vcn.inst[ring->me].dpg_enc_submission_cnt);
389
390 atomic_dec(&ring->adev->vcn.total_submission_cnt);
391
392 schedule_delayed_work(&ring->adev->vcn.idle_work, VCN_IDLE_TIMEOUT);
393}
394
395int amdgpu_vcn_dec_ring_test_ring(struct amdgpu_ring *ring)
396{
397 struct amdgpu_device *adev = ring->adev;
398 uint32_t tmp = 0;
399 unsigned i;
400 int r;
401
402
403 if (amdgpu_sriov_vf(adev))
404 return 0;
405
406 WREG32(adev->vcn.inst[ring->me].external.scratch9, 0xCAFEDEAD);
407 r = amdgpu_ring_alloc(ring, 3);
408 if (r)
409 return r;
410 amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.scratch9, 0));
411 amdgpu_ring_write(ring, 0xDEADBEEF);
412 amdgpu_ring_commit(ring);
413 for (i = 0; i < adev->usec_timeout; i++) {
414 tmp = RREG32(adev->vcn.inst[ring->me].external.scratch9);
415 if (tmp == 0xDEADBEEF)
416 break;
417 udelay(1);
418 }
419
420 if (i >= adev->usec_timeout)
421 r = -ETIMEDOUT;
422
423 return r;
424}
425
426static int amdgpu_vcn_dec_send_msg(struct amdgpu_ring *ring,
427 struct amdgpu_bo *bo,
428 struct dma_fence **fence)
429{
430 struct amdgpu_device *adev = ring->adev;
431 struct dma_fence *f = NULL;
432 struct amdgpu_job *job;
433 struct amdgpu_ib *ib;
434 uint64_t addr;
435 int i, r;
436
437 r = amdgpu_job_alloc_with_ib(adev, 64,
438 AMDGPU_IB_POOL_DIRECT, &job);
439 if (r)
440 goto err;
441
442 ib = &job->ibs[0];
443 addr = amdgpu_bo_gpu_offset(bo);
444 ib->ptr[0] = PACKET0(adev->vcn.internal.data0, 0);
445 ib->ptr[1] = addr;
446 ib->ptr[2] = PACKET0(adev->vcn.internal.data1, 0);
447 ib->ptr[3] = addr >> 32;
448 ib->ptr[4] = PACKET0(adev->vcn.internal.cmd, 0);
449 ib->ptr[5] = 0;
450 for (i = 6; i < 16; i += 2) {
451 ib->ptr[i] = PACKET0(adev->vcn.internal.nop, 0);
452 ib->ptr[i+1] = 0;
453 }
454 ib->length_dw = 16;
455
456 r = amdgpu_job_submit_direct(job, ring, &f);
457 if (r)
458 goto err_free;
459
460 amdgpu_bo_fence(bo, f, false);
461 amdgpu_bo_unreserve(bo);
462 amdgpu_bo_unref(&bo);
463
464 if (fence)
465 *fence = dma_fence_get(f);
466 dma_fence_put(f);
467
468 return 0;
469
470err_free:
471 amdgpu_job_free(job);
472
473err:
474 amdgpu_bo_unreserve(bo);
475 amdgpu_bo_unref(&bo);
476 return r;
477}
478
479static int amdgpu_vcn_dec_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
480 struct dma_fence **fence)
481{
482 struct amdgpu_device *adev = ring->adev;
483 struct amdgpu_bo *bo = NULL;
484 uint32_t *msg;
485 int r, i;
486
487 r = amdgpu_bo_create_reserved(adev, 1024, PAGE_SIZE,
488 AMDGPU_GEM_DOMAIN_VRAM,
489 &bo, NULL, (void **)&msg);
490 if (r)
491 return r;
492
493 msg[0] = cpu_to_le32(0x00000028);
494 msg[1] = cpu_to_le32(0x00000038);
495 msg[2] = cpu_to_le32(0x00000001);
496 msg[3] = cpu_to_le32(0x00000000);
497 msg[4] = cpu_to_le32(handle);
498 msg[5] = cpu_to_le32(0x00000000);
499 msg[6] = cpu_to_le32(0x00000001);
500 msg[7] = cpu_to_le32(0x00000028);
501 msg[8] = cpu_to_le32(0x00000010);
502 msg[9] = cpu_to_le32(0x00000000);
503 msg[10] = cpu_to_le32(0x00000007);
504 msg[11] = cpu_to_le32(0x00000000);
505 msg[12] = cpu_to_le32(0x00000780);
506 msg[13] = cpu_to_le32(0x00000440);
507 for (i = 14; i < 1024; ++i)
508 msg[i] = cpu_to_le32(0x0);
509
510 return amdgpu_vcn_dec_send_msg(ring, bo, fence);
511}
512
513static int amdgpu_vcn_dec_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
514 struct dma_fence **fence)
515{
516 struct amdgpu_device *adev = ring->adev;
517 struct amdgpu_bo *bo = NULL;
518 uint32_t *msg;
519 int r, i;
520
521 r = amdgpu_bo_create_reserved(adev, 1024, PAGE_SIZE,
522 AMDGPU_GEM_DOMAIN_VRAM,
523 &bo, NULL, (void **)&msg);
524 if (r)
525 return r;
526
527 msg[0] = cpu_to_le32(0x00000028);
528 msg[1] = cpu_to_le32(0x00000018);
529 msg[2] = cpu_to_le32(0x00000000);
530 msg[3] = cpu_to_le32(0x00000002);
531 msg[4] = cpu_to_le32(handle);
532 msg[5] = cpu_to_le32(0x00000000);
533 for (i = 6; i < 1024; ++i)
534 msg[i] = cpu_to_le32(0x0);
535
536 return amdgpu_vcn_dec_send_msg(ring, bo, fence);
537}
538
539int amdgpu_vcn_dec_ring_test_ib(struct amdgpu_ring *ring, long timeout)
540{
541 struct dma_fence *fence;
542 long r;
543
544 r = amdgpu_vcn_dec_get_create_msg(ring, 1, NULL);
545 if (r)
546 goto error;
547
548 r = amdgpu_vcn_dec_get_destroy_msg(ring, 1, &fence);
549 if (r)
550 goto error;
551
552 r = dma_fence_wait_timeout(fence, false, timeout);
553 if (r == 0)
554 r = -ETIMEDOUT;
555 else if (r > 0)
556 r = 0;
557
558 dma_fence_put(fence);
559error:
560 return r;
561}
562
563int amdgpu_vcn_enc_ring_test_ring(struct amdgpu_ring *ring)
564{
565 struct amdgpu_device *adev = ring->adev;
566 uint32_t rptr;
567 unsigned i;
568 int r;
569
570 if (amdgpu_sriov_vf(adev))
571 return 0;
572
573 r = amdgpu_ring_alloc(ring, 16);
574 if (r)
575 return r;
576
577 rptr = amdgpu_ring_get_rptr(ring);
578
579 amdgpu_ring_write(ring, VCN_ENC_CMD_END);
580 amdgpu_ring_commit(ring);
581
582 for (i = 0; i < adev->usec_timeout; i++) {
583 if (amdgpu_ring_get_rptr(ring) != rptr)
584 break;
585 udelay(1);
586 }
587
588 if (i >= adev->usec_timeout)
589 r = -ETIMEDOUT;
590
591 return r;
592}
593
594static int amdgpu_vcn_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
595 struct amdgpu_bo *bo,
596 struct dma_fence **fence)
597{
598 const unsigned ib_size_dw = 16;
599 struct amdgpu_job *job;
600 struct amdgpu_ib *ib;
601 struct dma_fence *f = NULL;
602 uint64_t addr;
603 int i, r;
604
605 r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4,
606 AMDGPU_IB_POOL_DIRECT, &job);
607 if (r)
608 return r;
609
610 ib = &job->ibs[0];
611 addr = amdgpu_bo_gpu_offset(bo);
612
613 ib->length_dw = 0;
614 ib->ptr[ib->length_dw++] = 0x00000018;
615 ib->ptr[ib->length_dw++] = 0x00000001;
616 ib->ptr[ib->length_dw++] = handle;
617 ib->ptr[ib->length_dw++] = upper_32_bits(addr);
618 ib->ptr[ib->length_dw++] = addr;
619 ib->ptr[ib->length_dw++] = 0x0000000b;
620
621 ib->ptr[ib->length_dw++] = 0x00000014;
622 ib->ptr[ib->length_dw++] = 0x00000002;
623 ib->ptr[ib->length_dw++] = 0x0000001c;
624 ib->ptr[ib->length_dw++] = 0x00000000;
625 ib->ptr[ib->length_dw++] = 0x00000000;
626
627 ib->ptr[ib->length_dw++] = 0x00000008;
628 ib->ptr[ib->length_dw++] = 0x08000001;
629
630 for (i = ib->length_dw; i < ib_size_dw; ++i)
631 ib->ptr[i] = 0x0;
632
633 r = amdgpu_job_submit_direct(job, ring, &f);
634 if (r)
635 goto err;
636
637 if (fence)
638 *fence = dma_fence_get(f);
639 dma_fence_put(f);
640
641 return 0;
642
643err:
644 amdgpu_job_free(job);
645 return r;
646}
647
648static int amdgpu_vcn_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
649 struct amdgpu_bo *bo,
650 struct dma_fence **fence)
651{
652 const unsigned ib_size_dw = 16;
653 struct amdgpu_job *job;
654 struct amdgpu_ib *ib;
655 struct dma_fence *f = NULL;
656 uint64_t addr;
657 int i, r;
658
659 r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4,
660 AMDGPU_IB_POOL_DIRECT, &job);
661 if (r)
662 return r;
663
664 ib = &job->ibs[0];
665 addr = amdgpu_bo_gpu_offset(bo);
666
667 ib->length_dw = 0;
668 ib->ptr[ib->length_dw++] = 0x00000018;
669 ib->ptr[ib->length_dw++] = 0x00000001;
670 ib->ptr[ib->length_dw++] = handle;
671 ib->ptr[ib->length_dw++] = upper_32_bits(addr);
672 ib->ptr[ib->length_dw++] = addr;
673 ib->ptr[ib->length_dw++] = 0x0000000b;
674
675 ib->ptr[ib->length_dw++] = 0x00000014;
676 ib->ptr[ib->length_dw++] = 0x00000002;
677 ib->ptr[ib->length_dw++] = 0x0000001c;
678 ib->ptr[ib->length_dw++] = 0x00000000;
679 ib->ptr[ib->length_dw++] = 0x00000000;
680
681 ib->ptr[ib->length_dw++] = 0x00000008;
682 ib->ptr[ib->length_dw++] = 0x08000002;
683
684 for (i = ib->length_dw; i < ib_size_dw; ++i)
685 ib->ptr[i] = 0x0;
686
687 r = amdgpu_job_submit_direct(job, ring, &f);
688 if (r)
689 goto err;
690
691 if (fence)
692 *fence = dma_fence_get(f);
693 dma_fence_put(f);
694
695 return 0;
696
697err:
698 amdgpu_job_free(job);
699 return r;
700}
701
702int amdgpu_vcn_enc_ring_test_ib(struct amdgpu_ring *ring, long timeout)
703{
704 struct dma_fence *fence = NULL;
705 struct amdgpu_bo *bo = NULL;
706 long r;
707
708 r = amdgpu_bo_create_reserved(ring->adev, 128 * 1024, PAGE_SIZE,
709 AMDGPU_GEM_DOMAIN_VRAM,
710 &bo, NULL, NULL);
711 if (r)
712 return r;
713
714 r = amdgpu_vcn_enc_get_create_msg(ring, 1, bo, NULL);
715 if (r)
716 goto error;
717
718 r = amdgpu_vcn_enc_get_destroy_msg(ring, 1, bo, &fence);
719 if (r)
720 goto error;
721
722 r = dma_fence_wait_timeout(fence, false, timeout);
723 if (r == 0)
724 r = -ETIMEDOUT;
725 else if (r > 0)
726 r = 0;
727
728error:
729 dma_fence_put(fence);
730 amdgpu_bo_unreserve(bo);
731 amdgpu_bo_unref(&bo);
732 return r;
733}
734