diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c | 101 |
1 files changed, 99 insertions, 2 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c index 92477e67087c..a91abfb32746 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c | |||
@@ -544,6 +544,54 @@ err: | |||
544 | } | 544 | } |
545 | 545 | ||
546 | /** | 546 | /** |
547 | * amdgpu_vce_cs_validate_bo - make sure not to cross 4GB boundary | ||
548 | * | ||
549 | * @p: parser context | ||
550 | * @lo: address of lower dword | ||
551 | * @hi: address of higher dword | ||
552 | * @size: minimum size | ||
553 | * @index: bs/fb index | ||
554 | * | ||
555 | * Make sure that no BO cross a 4GB boundary. | ||
556 | */ | ||
557 | static int amdgpu_vce_validate_bo(struct amdgpu_cs_parser *p, uint32_t ib_idx, | ||
558 | int lo, int hi, unsigned size, int32_t index) | ||
559 | { | ||
560 | int64_t offset = ((uint64_t)size) * ((int64_t)index); | ||
561 | struct amdgpu_bo_va_mapping *mapping; | ||
562 | unsigned i, fpfn, lpfn; | ||
563 | struct amdgpu_bo *bo; | ||
564 | uint64_t addr; | ||
565 | int r; | ||
566 | |||
567 | addr = ((uint64_t)amdgpu_get_ib_value(p, ib_idx, lo)) | | ||
568 | ((uint64_t)amdgpu_get_ib_value(p, ib_idx, hi)) << 32; | ||
569 | if (index >= 0) { | ||
570 | addr += offset; | ||
571 | fpfn = PAGE_ALIGN(offset) >> PAGE_SHIFT; | ||
572 | lpfn = 0x100000000ULL >> PAGE_SHIFT; | ||
573 | } else { | ||
574 | fpfn = 0; | ||
575 | lpfn = (0x100000000ULL - PAGE_ALIGN(offset)) >> PAGE_SHIFT; | ||
576 | } | ||
577 | |||
578 | r = amdgpu_cs_find_mapping(p, addr, &bo, &mapping); | ||
579 | if (r) { | ||
580 | DRM_ERROR("Can't find BO for addr 0x%010Lx %d %d %d %d\n", | ||
581 | addr, lo, hi, size, index); | ||
582 | return r; | ||
583 | } | ||
584 | |||
585 | for (i = 0; i < bo->placement.num_placement; ++i) { | ||
586 | bo->placements[i].fpfn = max(bo->placements[i].fpfn, fpfn); | ||
587 | bo->placements[i].lpfn = bo->placements[i].fpfn ? | ||
588 | min(bo->placements[i].fpfn, lpfn) : lpfn; | ||
589 | } | ||
590 | return ttm_bo_validate(&bo->tbo, &bo->placement, false, false); | ||
591 | } | ||
592 | |||
593 | |||
594 | /** | ||
547 | * amdgpu_vce_cs_reloc - command submission relocation | 595 | * amdgpu_vce_cs_reloc - command submission relocation |
548 | * | 596 | * |
549 | * @p: parser context | 597 | * @p: parser context |
@@ -648,12 +696,13 @@ int amdgpu_vce_ring_parse_cs(struct amdgpu_cs_parser *p, uint32_t ib_idx) | |||
648 | uint32_t allocated = 0; | 696 | uint32_t allocated = 0; |
649 | uint32_t tmp, handle = 0; | 697 | uint32_t tmp, handle = 0; |
650 | uint32_t *size = &tmp; | 698 | uint32_t *size = &tmp; |
651 | int i, r = 0, idx = 0; | 699 | unsigned idx; |
700 | int i, r = 0; | ||
652 | 701 | ||
653 | p->job->vm = NULL; | 702 | p->job->vm = NULL; |
654 | ib->gpu_addr = amdgpu_sa_bo_gpu_addr(ib->sa_bo); | 703 | ib->gpu_addr = amdgpu_sa_bo_gpu_addr(ib->sa_bo); |
655 | 704 | ||
656 | while (idx < ib->length_dw) { | 705 | for (idx = 0; idx < ib->length_dw;) { |
657 | uint32_t len = amdgpu_get_ib_value(p, ib_idx, idx); | 706 | uint32_t len = amdgpu_get_ib_value(p, ib_idx, idx); |
658 | uint32_t cmd = amdgpu_get_ib_value(p, ib_idx, idx + 1); | 707 | uint32_t cmd = amdgpu_get_ib_value(p, ib_idx, idx + 1); |
659 | 708 | ||
@@ -664,6 +713,54 @@ int amdgpu_vce_ring_parse_cs(struct amdgpu_cs_parser *p, uint32_t ib_idx) | |||
664 | } | 713 | } |
665 | 714 | ||
666 | switch (cmd) { | 715 | switch (cmd) { |
716 | case 0x00000002: /* task info */ | ||
717 | fb_idx = amdgpu_get_ib_value(p, ib_idx, idx + 6); | ||
718 | bs_idx = amdgpu_get_ib_value(p, ib_idx, idx + 7); | ||
719 | break; | ||
720 | |||
721 | case 0x03000001: /* encode */ | ||
722 | r = amdgpu_vce_validate_bo(p, ib_idx, idx + 10, | ||
723 | idx + 9, 0, 0); | ||
724 | if (r) | ||
725 | goto out; | ||
726 | |||
727 | r = amdgpu_vce_validate_bo(p, ib_idx, idx + 12, | ||
728 | idx + 11, 0, 0); | ||
729 | if (r) | ||
730 | goto out; | ||
731 | break; | ||
732 | |||
733 | case 0x05000001: /* context buffer */ | ||
734 | r = amdgpu_vce_validate_bo(p, ib_idx, idx + 3, | ||
735 | idx + 2, 0, 0); | ||
736 | if (r) | ||
737 | goto out; | ||
738 | break; | ||
739 | |||
740 | case 0x05000004: /* video bitstream buffer */ | ||
741 | tmp = amdgpu_get_ib_value(p, ib_idx, idx + 4); | ||
742 | r = amdgpu_vce_validate_bo(p, ib_idx, idx + 3, idx + 2, | ||
743 | tmp, bs_idx); | ||
744 | if (r) | ||
745 | goto out; | ||
746 | break; | ||
747 | |||
748 | case 0x05000005: /* feedback buffer */ | ||
749 | r = amdgpu_vce_validate_bo(p, ib_idx, idx + 3, idx + 2, | ||
750 | 4096, fb_idx); | ||
751 | if (r) | ||
752 | goto out; | ||
753 | break; | ||
754 | } | ||
755 | |||
756 | idx += len / 4; | ||
757 | } | ||
758 | |||
759 | for (idx = 0; idx < ib->length_dw;) { | ||
760 | uint32_t len = amdgpu_get_ib_value(p, ib_idx, idx); | ||
761 | uint32_t cmd = amdgpu_get_ib_value(p, ib_idx, idx + 1); | ||
762 | |||
763 | switch (cmd) { | ||
667 | case 0x00000001: /* session */ | 764 | case 0x00000001: /* session */ |
668 | handle = amdgpu_get_ib_value(p, ib_idx, idx + 2); | 765 | handle = amdgpu_get_ib_value(p, ib_idx, idx + 2); |
669 | session_idx = amdgpu_vce_validate_handle(p, handle, | 766 | session_idx = amdgpu_vce_validate_handle(p, handle, |