diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c | 170 |
1 files changed, 91 insertions, 79 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c index 875626a2eccb..05865ce35351 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c | |||
@@ -36,7 +36,7 @@ | |||
36 | #include "cikd.h" | 36 | #include "cikd.h" |
37 | 37 | ||
38 | /* 1 second timeout */ | 38 | /* 1 second timeout */ |
39 | #define VCE_IDLE_TIMEOUT_MS 1000 | 39 | #define VCE_IDLE_TIMEOUT msecs_to_jiffies(1000) |
40 | 40 | ||
41 | /* Firmware Names */ | 41 | /* Firmware Names */ |
42 | #ifdef CONFIG_DRM_AMDGPU_CIK | 42 | #ifdef CONFIG_DRM_AMDGPU_CIK |
@@ -85,8 +85,6 @@ int amdgpu_vce_sw_init(struct amdgpu_device *adev, unsigned long size) | |||
85 | unsigned ucode_version, version_major, version_minor, binary_id; | 85 | unsigned ucode_version, version_major, version_minor, binary_id; |
86 | int i, r; | 86 | int i, r; |
87 | 87 | ||
88 | INIT_DELAYED_WORK(&adev->vce.idle_work, amdgpu_vce_idle_work_handler); | ||
89 | |||
90 | switch (adev->asic_type) { | 88 | switch (adev->asic_type) { |
91 | #ifdef CONFIG_DRM_AMDGPU_CIK | 89 | #ifdef CONFIG_DRM_AMDGPU_CIK |
92 | case CHIP_BONAIRE: | 90 | case CHIP_BONAIRE: |
@@ -197,6 +195,9 @@ int amdgpu_vce_sw_init(struct amdgpu_device *adev, unsigned long size) | |||
197 | adev->vce.filp[i] = NULL; | 195 | adev->vce.filp[i] = NULL; |
198 | } | 196 | } |
199 | 197 | ||
198 | INIT_DELAYED_WORK(&adev->vce.idle_work, amdgpu_vce_idle_work_handler); | ||
199 | mutex_init(&adev->vce.idle_mutex); | ||
200 | |||
200 | return 0; | 201 | return 0; |
201 | } | 202 | } |
202 | 203 | ||
@@ -220,6 +221,7 @@ int amdgpu_vce_sw_fini(struct amdgpu_device *adev) | |||
220 | amdgpu_ring_fini(&adev->vce.ring[1]); | 221 | amdgpu_ring_fini(&adev->vce.ring[1]); |
221 | 222 | ||
222 | release_firmware(adev->vce.fw); | 223 | release_firmware(adev->vce.fw); |
224 | mutex_destroy(&adev->vce.idle_mutex); | ||
223 | 225 | ||
224 | return 0; | 226 | return 0; |
225 | } | 227 | } |
@@ -310,37 +312,44 @@ static void amdgpu_vce_idle_work_handler(struct work_struct *work) | |||
310 | amdgpu_asic_set_vce_clocks(adev, 0, 0); | 312 | amdgpu_asic_set_vce_clocks(adev, 0, 0); |
311 | } | 313 | } |
312 | } else { | 314 | } else { |
313 | schedule_delayed_work(&adev->vce.idle_work, | 315 | schedule_delayed_work(&adev->vce.idle_work, VCE_IDLE_TIMEOUT); |
314 | msecs_to_jiffies(VCE_IDLE_TIMEOUT_MS)); | ||
315 | } | 316 | } |
316 | } | 317 | } |
317 | 318 | ||
318 | /** | 319 | /** |
319 | * amdgpu_vce_note_usage - power up VCE | 320 | * amdgpu_vce_ring_begin_use - power up VCE |
320 | * | 321 | * |
321 | * @adev: amdgpu_device pointer | 322 | * @ring: amdgpu ring |
322 | * | 323 | * |
323 | * Make sure VCE is powerd up when we want to use it | 324 | * Make sure VCE is powerd up when we want to use it |
324 | */ | 325 | */ |
325 | static void amdgpu_vce_note_usage(struct amdgpu_device *adev) | 326 | void amdgpu_vce_ring_begin_use(struct amdgpu_ring *ring) |
326 | { | 327 | { |
327 | bool streams_changed = false; | 328 | struct amdgpu_device *adev = ring->adev; |
328 | bool set_clocks = !cancel_delayed_work_sync(&adev->vce.idle_work); | 329 | bool set_clocks; |
329 | set_clocks &= schedule_delayed_work(&adev->vce.idle_work, | ||
330 | msecs_to_jiffies(VCE_IDLE_TIMEOUT_MS)); | ||
331 | |||
332 | if (adev->pm.dpm_enabled) { | ||
333 | /* XXX figure out if the streams changed */ | ||
334 | streams_changed = false; | ||
335 | } | ||
336 | 330 | ||
337 | if (set_clocks || streams_changed) { | 331 | mutex_lock(&adev->vce.idle_mutex); |
332 | set_clocks = !cancel_delayed_work_sync(&adev->vce.idle_work); | ||
333 | if (set_clocks) { | ||
338 | if (adev->pm.dpm_enabled) { | 334 | if (adev->pm.dpm_enabled) { |
339 | amdgpu_dpm_enable_vce(adev, true); | 335 | amdgpu_dpm_enable_vce(adev, true); |
340 | } else { | 336 | } else { |
341 | amdgpu_asic_set_vce_clocks(adev, 53300, 40000); | 337 | amdgpu_asic_set_vce_clocks(adev, 53300, 40000); |
342 | } | 338 | } |
343 | } | 339 | } |
340 | mutex_unlock(&adev->vce.idle_mutex); | ||
341 | } | ||
342 | |||
343 | /** | ||
344 | * amdgpu_vce_ring_end_use - power VCE down | ||
345 | * | ||
346 | * @ring: amdgpu ring | ||
347 | * | ||
348 | * Schedule work to power VCE down again | ||
349 | */ | ||
350 | void amdgpu_vce_ring_end_use(struct amdgpu_ring *ring) | ||
351 | { | ||
352 | schedule_delayed_work(&ring->adev->vce.idle_work, VCE_IDLE_TIMEOUT); | ||
344 | } | 353 | } |
345 | 354 | ||
346 | /** | 355 | /** |
@@ -357,11 +366,10 @@ void amdgpu_vce_free_handles(struct amdgpu_device *adev, struct drm_file *filp) | |||
357 | int i, r; | 366 | int i, r; |
358 | for (i = 0; i < AMDGPU_MAX_VCE_HANDLES; ++i) { | 367 | for (i = 0; i < AMDGPU_MAX_VCE_HANDLES; ++i) { |
359 | uint32_t handle = atomic_read(&adev->vce.handles[i]); | 368 | uint32_t handle = atomic_read(&adev->vce.handles[i]); |
369 | |||
360 | if (!handle || adev->vce.filp[i] != filp) | 370 | if (!handle || adev->vce.filp[i] != filp) |
361 | continue; | 371 | continue; |
362 | 372 | ||
363 | amdgpu_vce_note_usage(adev); | ||
364 | |||
365 | r = amdgpu_vce_get_destroy_msg(ring, handle, false, NULL); | 373 | r = amdgpu_vce_get_destroy_msg(ring, handle, false, NULL); |
366 | if (r) | 374 | if (r) |
367 | DRM_ERROR("Error destroying VCE handle (%d)!\n", r); | 375 | DRM_ERROR("Error destroying VCE handle (%d)!\n", r); |
@@ -437,7 +445,7 @@ int amdgpu_vce_get_create_msg(struct amdgpu_ring *ring, uint32_t handle, | |||
437 | ib->ptr[i] = 0x0; | 445 | ib->ptr[i] = 0x0; |
438 | 446 | ||
439 | r = amdgpu_ib_schedule(ring, 1, ib, NULL, NULL, &f); | 447 | r = amdgpu_ib_schedule(ring, 1, ib, NULL, NULL, &f); |
440 | job->fence = f; | 448 | job->fence = fence_get(f); |
441 | if (r) | 449 | if (r) |
442 | goto err; | 450 | goto err; |
443 | 451 | ||
@@ -469,7 +477,6 @@ int amdgpu_vce_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle, | |||
469 | struct amdgpu_job *job; | 477 | struct amdgpu_job *job; |
470 | struct amdgpu_ib *ib; | 478 | struct amdgpu_ib *ib; |
471 | struct fence *f = NULL; | 479 | struct fence *f = NULL; |
472 | uint64_t dummy; | ||
473 | int i, r; | 480 | int i, r; |
474 | 481 | ||
475 | r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4, &job); | 482 | r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4, &job); |
@@ -477,7 +484,6 @@ int amdgpu_vce_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle, | |||
477 | return r; | 484 | return r; |
478 | 485 | ||
479 | ib = &job->ibs[0]; | 486 | ib = &job->ibs[0]; |
480 | dummy = ib->gpu_addr + 1024; | ||
481 | 487 | ||
482 | /* stitch together an VCE destroy msg */ | 488 | /* stitch together an VCE destroy msg */ |
483 | ib->length_dw = 0; | 489 | ib->length_dw = 0; |
@@ -485,11 +491,14 @@ int amdgpu_vce_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle, | |||
485 | ib->ptr[ib->length_dw++] = 0x00000001; /* session cmd */ | 491 | ib->ptr[ib->length_dw++] = 0x00000001; /* session cmd */ |
486 | ib->ptr[ib->length_dw++] = handle; | 492 | ib->ptr[ib->length_dw++] = handle; |
487 | 493 | ||
488 | ib->ptr[ib->length_dw++] = 0x00000014; /* len */ | 494 | ib->ptr[ib->length_dw++] = 0x00000020; /* len */ |
489 | ib->ptr[ib->length_dw++] = 0x05000005; /* feedback buffer */ | 495 | ib->ptr[ib->length_dw++] = 0x00000002; /* task info */ |
490 | ib->ptr[ib->length_dw++] = upper_32_bits(dummy); | 496 | ib->ptr[ib->length_dw++] = 0xffffffff; /* next task info, set to 0xffffffff if no */ |
491 | ib->ptr[ib->length_dw++] = dummy; | 497 | ib->ptr[ib->length_dw++] = 0x00000001; /* destroy session */ |
492 | ib->ptr[ib->length_dw++] = 0x00000001; | 498 | ib->ptr[ib->length_dw++] = 0x00000000; |
499 | ib->ptr[ib->length_dw++] = 0x00000000; | ||
500 | ib->ptr[ib->length_dw++] = 0xffffffff; /* feedback is not needed, set to 0xffffffff and firmware will not output feedback */ | ||
501 | ib->ptr[ib->length_dw++] = 0x00000000; | ||
493 | 502 | ||
494 | ib->ptr[ib->length_dw++] = 0x00000008; /* len */ | 503 | ib->ptr[ib->length_dw++] = 0x00000008; /* len */ |
495 | ib->ptr[ib->length_dw++] = 0x02000001; /* destroy cmd */ | 504 | ib->ptr[ib->length_dw++] = 0x02000001; /* destroy cmd */ |
@@ -499,7 +508,7 @@ int amdgpu_vce_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle, | |||
499 | 508 | ||
500 | if (direct) { | 509 | if (direct) { |
501 | r = amdgpu_ib_schedule(ring, 1, ib, NULL, NULL, &f); | 510 | r = amdgpu_ib_schedule(ring, 1, ib, NULL, NULL, &f); |
502 | job->fence = f; | 511 | job->fence = fence_get(f); |
503 | if (r) | 512 | if (r) |
504 | goto err; | 513 | goto err; |
505 | 514 | ||
@@ -580,12 +589,10 @@ static int amdgpu_vce_cs_reloc(struct amdgpu_cs_parser *p, uint32_t ib_idx, | |||
580 | * we we don't have another free session index. | 589 | * we we don't have another free session index. |
581 | */ | 590 | */ |
582 | static int amdgpu_vce_validate_handle(struct amdgpu_cs_parser *p, | 591 | static int amdgpu_vce_validate_handle(struct amdgpu_cs_parser *p, |
583 | uint32_t handle, bool *allocated) | 592 | uint32_t handle, uint32_t *allocated) |
584 | { | 593 | { |
585 | unsigned i; | 594 | unsigned i; |
586 | 595 | ||
587 | *allocated = false; | ||
588 | |||
589 | /* validate the handle */ | 596 | /* validate the handle */ |
590 | for (i = 0; i < AMDGPU_MAX_VCE_HANDLES; ++i) { | 597 | for (i = 0; i < AMDGPU_MAX_VCE_HANDLES; ++i) { |
591 | if (atomic_read(&p->adev->vce.handles[i]) == handle) { | 598 | if (atomic_read(&p->adev->vce.handles[i]) == handle) { |
@@ -602,7 +609,7 @@ static int amdgpu_vce_validate_handle(struct amdgpu_cs_parser *p, | |||
602 | if (!atomic_cmpxchg(&p->adev->vce.handles[i], 0, handle)) { | 609 | if (!atomic_cmpxchg(&p->adev->vce.handles[i], 0, handle)) { |
603 | p->adev->vce.filp[i] = p->filp; | 610 | p->adev->vce.filp[i] = p->filp; |
604 | p->adev->vce.img_size[i] = 0; | 611 | p->adev->vce.img_size[i] = 0; |
605 | *allocated = true; | 612 | *allocated |= 1 << i; |
606 | return i; | 613 | return i; |
607 | } | 614 | } |
608 | } | 615 | } |
@@ -622,15 +629,13 @@ int amdgpu_vce_ring_parse_cs(struct amdgpu_cs_parser *p, uint32_t ib_idx) | |||
622 | struct amdgpu_ib *ib = &p->job->ibs[ib_idx]; | 629 | struct amdgpu_ib *ib = &p->job->ibs[ib_idx]; |
623 | unsigned fb_idx = 0, bs_idx = 0; | 630 | unsigned fb_idx = 0, bs_idx = 0; |
624 | int session_idx = -1; | 631 | int session_idx = -1; |
625 | bool destroyed = false; | 632 | uint32_t destroyed = 0; |
626 | bool created = false; | 633 | uint32_t created = 0; |
627 | bool allocated = false; | 634 | uint32_t allocated = 0; |
628 | uint32_t tmp, handle = 0; | 635 | uint32_t tmp, handle = 0; |
629 | uint32_t *size = &tmp; | 636 | uint32_t *size = &tmp; |
630 | int i, r = 0, idx = 0; | 637 | int i, r = 0, idx = 0; |
631 | 638 | ||
632 | amdgpu_vce_note_usage(p->adev); | ||
633 | |||
634 | while (idx < ib->length_dw) { | 639 | while (idx < ib->length_dw) { |
635 | uint32_t len = amdgpu_get_ib_value(p, ib_idx, idx); | 640 | uint32_t len = amdgpu_get_ib_value(p, ib_idx, idx); |
636 | uint32_t cmd = amdgpu_get_ib_value(p, ib_idx, idx + 1); | 641 | uint32_t cmd = amdgpu_get_ib_value(p, ib_idx, idx + 1); |
@@ -641,30 +646,30 @@ int amdgpu_vce_ring_parse_cs(struct amdgpu_cs_parser *p, uint32_t ib_idx) | |||
641 | goto out; | 646 | goto out; |
642 | } | 647 | } |
643 | 648 | ||
644 | if (destroyed) { | ||
645 | DRM_ERROR("No other command allowed after destroy!\n"); | ||
646 | r = -EINVAL; | ||
647 | goto out; | ||
648 | } | ||
649 | |||
650 | switch (cmd) { | 649 | switch (cmd) { |
651 | case 0x00000001: // session | 650 | case 0x00000001: /* session */ |
652 | handle = amdgpu_get_ib_value(p, ib_idx, idx + 2); | 651 | handle = amdgpu_get_ib_value(p, ib_idx, idx + 2); |
653 | session_idx = amdgpu_vce_validate_handle(p, handle, | 652 | session_idx = amdgpu_vce_validate_handle(p, handle, |
654 | &allocated); | 653 | &allocated); |
655 | if (session_idx < 0) | 654 | if (session_idx < 0) { |
656 | return session_idx; | 655 | r = session_idx; |
656 | goto out; | ||
657 | } | ||
657 | size = &p->adev->vce.img_size[session_idx]; | 658 | size = &p->adev->vce.img_size[session_idx]; |
658 | break; | 659 | break; |
659 | 660 | ||
660 | case 0x00000002: // task info | 661 | case 0x00000002: /* task info */ |
661 | fb_idx = amdgpu_get_ib_value(p, ib_idx, idx + 6); | 662 | fb_idx = amdgpu_get_ib_value(p, ib_idx, idx + 6); |
662 | bs_idx = amdgpu_get_ib_value(p, ib_idx, idx + 7); | 663 | bs_idx = amdgpu_get_ib_value(p, ib_idx, idx + 7); |
663 | break; | 664 | break; |
664 | 665 | ||
665 | case 0x01000001: // create | 666 | case 0x01000001: /* create */ |
666 | created = true; | 667 | created |= 1 << session_idx; |
667 | if (!allocated) { | 668 | if (destroyed & (1 << session_idx)) { |
669 | destroyed &= ~(1 << session_idx); | ||
670 | allocated |= 1 << session_idx; | ||
671 | |||
672 | } else if (!(allocated & (1 << session_idx))) { | ||
668 | DRM_ERROR("Handle already in use!\n"); | 673 | DRM_ERROR("Handle already in use!\n"); |
669 | r = -EINVAL; | 674 | r = -EINVAL; |
670 | goto out; | 675 | goto out; |
@@ -675,16 +680,16 @@ int amdgpu_vce_ring_parse_cs(struct amdgpu_cs_parser *p, uint32_t ib_idx) | |||
675 | 8 * 3 / 2; | 680 | 8 * 3 / 2; |
676 | break; | 681 | break; |
677 | 682 | ||
678 | case 0x04000001: // config extension | 683 | case 0x04000001: /* config extension */ |
679 | case 0x04000002: // pic control | 684 | case 0x04000002: /* pic control */ |
680 | case 0x04000005: // rate control | 685 | case 0x04000005: /* rate control */ |
681 | case 0x04000007: // motion estimation | 686 | case 0x04000007: /* motion estimation */ |
682 | case 0x04000008: // rdo | 687 | case 0x04000008: /* rdo */ |
683 | case 0x04000009: // vui | 688 | case 0x04000009: /* vui */ |
684 | case 0x05000002: // auxiliary buffer | 689 | case 0x05000002: /* auxiliary buffer */ |
685 | break; | 690 | break; |
686 | 691 | ||
687 | case 0x03000001: // encode | 692 | case 0x03000001: /* encode */ |
688 | r = amdgpu_vce_cs_reloc(p, ib_idx, idx + 10, idx + 9, | 693 | r = amdgpu_vce_cs_reloc(p, ib_idx, idx + 10, idx + 9, |
689 | *size, 0); | 694 | *size, 0); |
690 | if (r) | 695 | if (r) |
@@ -696,18 +701,18 @@ int amdgpu_vce_ring_parse_cs(struct amdgpu_cs_parser *p, uint32_t ib_idx) | |||
696 | goto out; | 701 | goto out; |
697 | break; | 702 | break; |
698 | 703 | ||
699 | case 0x02000001: // destroy | 704 | case 0x02000001: /* destroy */ |
700 | destroyed = true; | 705 | destroyed |= 1 << session_idx; |
701 | break; | 706 | break; |
702 | 707 | ||
703 | case 0x05000001: // context buffer | 708 | case 0x05000001: /* context buffer */ |
704 | r = amdgpu_vce_cs_reloc(p, ib_idx, idx + 3, idx + 2, | 709 | r = amdgpu_vce_cs_reloc(p, ib_idx, idx + 3, idx + 2, |
705 | *size * 2, 0); | 710 | *size * 2, 0); |
706 | if (r) | 711 | if (r) |
707 | goto out; | 712 | goto out; |
708 | break; | 713 | break; |
709 | 714 | ||
710 | case 0x05000004: // video bitstream buffer | 715 | case 0x05000004: /* video bitstream buffer */ |
711 | tmp = amdgpu_get_ib_value(p, ib_idx, idx + 4); | 716 | tmp = amdgpu_get_ib_value(p, ib_idx, idx + 4); |
712 | r = amdgpu_vce_cs_reloc(p, ib_idx, idx + 3, idx + 2, | 717 | r = amdgpu_vce_cs_reloc(p, ib_idx, idx + 3, idx + 2, |
713 | tmp, bs_idx); | 718 | tmp, bs_idx); |
@@ -715,7 +720,7 @@ int amdgpu_vce_ring_parse_cs(struct amdgpu_cs_parser *p, uint32_t ib_idx) | |||
715 | goto out; | 720 | goto out; |
716 | break; | 721 | break; |
717 | 722 | ||
718 | case 0x05000005: // feedback buffer | 723 | case 0x05000005: /* feedback buffer */ |
719 | r = amdgpu_vce_cs_reloc(p, ib_idx, idx + 3, idx + 2, | 724 | r = amdgpu_vce_cs_reloc(p, ib_idx, idx + 3, idx + 2, |
720 | 4096, fb_idx); | 725 | 4096, fb_idx); |
721 | if (r) | 726 | if (r) |
@@ -737,21 +742,24 @@ int amdgpu_vce_ring_parse_cs(struct amdgpu_cs_parser *p, uint32_t ib_idx) | |||
737 | idx += len / 4; | 742 | idx += len / 4; |
738 | } | 743 | } |
739 | 744 | ||
740 | if (allocated && !created) { | 745 | if (allocated & ~created) { |
741 | DRM_ERROR("New session without create command!\n"); | 746 | DRM_ERROR("New session without create command!\n"); |
742 | r = -ENOENT; | 747 | r = -ENOENT; |
743 | } | 748 | } |
744 | 749 | ||
745 | out: | 750 | out: |
746 | if ((!r && destroyed) || (r && allocated)) { | 751 | if (!r) { |
747 | /* | 752 | /* No error, free all destroyed handle slots */ |
748 | * IB contains a destroy msg or we have allocated an | 753 | tmp = destroyed; |
749 | * handle and got an error, anyway free the handle | 754 | } else { |
750 | */ | 755 | /* Error during parsing, free all allocated handle slots */ |
751 | for (i = 0; i < AMDGPU_MAX_VCE_HANDLES; ++i) | 756 | tmp = allocated; |
752 | atomic_cmpxchg(&p->adev->vce.handles[i], handle, 0); | ||
753 | } | 757 | } |
754 | 758 | ||
759 | for (i = 0; i < AMDGPU_MAX_VCE_HANDLES; ++i) | ||
760 | if (tmp & (1 << i)) | ||
761 | atomic_set(&p->adev->vce.handles[i], 0); | ||
762 | |||
755 | return r; | 763 | return r; |
756 | } | 764 | } |
757 | 765 | ||
@@ -837,10 +845,10 @@ int amdgpu_vce_ring_test_ring(struct amdgpu_ring *ring) | |||
837 | * @ring: the engine to test on | 845 | * @ring: the engine to test on |
838 | * | 846 | * |
839 | */ | 847 | */ |
840 | int amdgpu_vce_ring_test_ib(struct amdgpu_ring *ring) | 848 | int amdgpu_vce_ring_test_ib(struct amdgpu_ring *ring, long timeout) |
841 | { | 849 | { |
842 | struct fence *fence = NULL; | 850 | struct fence *fence = NULL; |
843 | int r; | 851 | long r; |
844 | 852 | ||
845 | /* skip vce ring1 ib test for now, since it's not reliable */ | 853 | /* skip vce ring1 ib test for now, since it's not reliable */ |
846 | if (ring == &ring->adev->vce.ring[1]) | 854 | if (ring == &ring->adev->vce.ring[1]) |
@@ -848,21 +856,25 @@ int amdgpu_vce_ring_test_ib(struct amdgpu_ring *ring) | |||
848 | 856 | ||
849 | r = amdgpu_vce_get_create_msg(ring, 1, NULL); | 857 | r = amdgpu_vce_get_create_msg(ring, 1, NULL); |
850 | if (r) { | 858 | if (r) { |
851 | DRM_ERROR("amdgpu: failed to get create msg (%d).\n", r); | 859 | DRM_ERROR("amdgpu: failed to get create msg (%ld).\n", r); |
852 | goto error; | 860 | goto error; |
853 | } | 861 | } |
854 | 862 | ||
855 | r = amdgpu_vce_get_destroy_msg(ring, 1, true, &fence); | 863 | r = amdgpu_vce_get_destroy_msg(ring, 1, true, &fence); |
856 | if (r) { | 864 | if (r) { |
857 | DRM_ERROR("amdgpu: failed to get destroy ib (%d).\n", r); | 865 | DRM_ERROR("amdgpu: failed to get destroy ib (%ld).\n", r); |
858 | goto error; | 866 | goto error; |
859 | } | 867 | } |
860 | 868 | ||
861 | r = fence_wait(fence, false); | 869 | r = fence_wait_timeout(fence, false, timeout); |
862 | if (r) { | 870 | if (r == 0) { |
863 | DRM_ERROR("amdgpu: fence wait failed (%d).\n", r); | 871 | DRM_ERROR("amdgpu: IB test timed out.\n"); |
872 | r = -ETIMEDOUT; | ||
873 | } else if (r < 0) { | ||
874 | DRM_ERROR("amdgpu: fence wait failed (%ld).\n", r); | ||
864 | } else { | 875 | } else { |
865 | DRM_INFO("ib test on ring %d succeeded\n", ring->idx); | 876 | DRM_INFO("ib test on ring %d succeeded\n", ring->idx); |
877 | r = 0; | ||
866 | } | 878 | } |
867 | error: | 879 | error: |
868 | fence_put(fence); | 880 | fence_put(fence); |