Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/amdgpu: add VCE VM session tracking

Fix the problems with killing VCE sessions in VM mode.

Signed-off-by: Christian König <christian.koenig@amd.com>
Reviewed-and-Tested by: Leo Liu <leo.liu@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Christian König and committed by
Alex Deucher
98614701 45088efc

+92
+90
drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
··· 792 792 } 793 793 794 794 /** 795 + * amdgpu_vce_cs_parse_vm - parse the command stream in VM mode 796 + * 797 + * @p: parser context 798 + * 799 + */ 800 + int amdgpu_vce_ring_parse_cs_vm(struct amdgpu_cs_parser *p, uint32_t ib_idx) 801 + { 802 + struct amdgpu_ib *ib = &p->job->ibs[ib_idx]; 803 + int session_idx = -1; 804 + uint32_t destroyed = 0; 805 + uint32_t created = 0; 806 + uint32_t allocated = 0; 807 + uint32_t tmp, handle = 0; 808 + int i, r = 0, idx = 0; 809 + 810 + while (idx < ib->length_dw) { 811 + uint32_t len = amdgpu_get_ib_value(p, ib_idx, idx); 812 + uint32_t cmd = amdgpu_get_ib_value(p, ib_idx, idx + 1); 813 + 814 + if ((len < 8) || (len & 3)) { 815 + DRM_ERROR("invalid VCE command length (%d)!\n", len); 816 + r = -EINVAL; 817 + goto out; 818 + } 819 + 820 + switch (cmd) { 821 + case 0x00000001: /* session */ 822 + handle = amdgpu_get_ib_value(p, ib_idx, idx + 2); 823 + session_idx = amdgpu_vce_validate_handle(p, handle, 824 + &allocated); 825 + if (session_idx < 0) { 826 + r = session_idx; 827 + goto out; 828 + } 829 + break; 830 + 831 + case 0x01000001: /* create */ 832 + created |= 1 << session_idx; 833 + if (destroyed & (1 << session_idx)) { 834 + destroyed &= ~(1 << session_idx); 835 + allocated |= 1 << session_idx; 836 + 837 + } else if (!(allocated & (1 << session_idx))) { 838 + DRM_ERROR("Handle already in use!\n"); 839 + r = -EINVAL; 840 + goto out; 841 + } 842 + 843 + break; 844 + 845 + case 0x02000001: /* destroy */ 846 + destroyed |= 1 << session_idx; 847 + break; 848 + 849 + default: 850 + break; 851 + } 852 + 853 + if (session_idx == -1) { 854 + DRM_ERROR("no session command at start of IB\n"); 855 + r = -EINVAL; 856 + goto out; 857 + } 858 + 859 + idx += len / 4; 860 + } 861 + 862 + if (allocated & ~created) { 863 + DRM_ERROR("New session without create command!\n"); 864 + r = -ENOENT; 865 + } 866 + 867 + out: 868 + if (!r) { 869 + /* No error, free all destroyed handle slots */ 870 + tmp = destroyed; 871 + amdgpu_ib_free(p->adev, ib, NULL); 872 + } else { 873 + /* Error during parsing, free all allocated handle slots */ 874 + tmp = allocated; 875 + } 876 + 877 + for (i = 0; i < AMDGPU_MAX_VCE_HANDLES; ++i) 878 + if (tmp & (1 << i)) 879 + atomic_set(&p->adev->vce.handles[i], 0); 880 + 881 + return r; 882 + } 883 + 884 + /** 795 885 * amdgpu_vce_ring_emit_ib - execute indirect buffer 796 886 * 797 887 * @ring: engine to use
+1
drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h
··· 34 34 bool direct, struct fence **fence); 35 35 void amdgpu_vce_free_handles(struct amdgpu_device *adev, struct drm_file *filp); 36 36 int amdgpu_vce_ring_parse_cs(struct amdgpu_cs_parser *p, uint32_t ib_idx); 37 + int amdgpu_vce_ring_parse_cs_vm(struct amdgpu_cs_parser *p, uint32_t ib_idx); 37 38 void amdgpu_vce_ring_emit_ib(struct amdgpu_ring *ring, struct amdgpu_ib *ib, 38 39 unsigned vm_id, bool ctx_switch); 39 40 void amdgpu_vce_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq,
+1
drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
··· 856 856 .get_rptr = vce_v3_0_ring_get_rptr, 857 857 .get_wptr = vce_v3_0_ring_get_wptr, 858 858 .set_wptr = vce_v3_0_ring_set_wptr, 859 + .parse_cs = amdgpu_vce_ring_parse_cs_vm, 859 860 .emit_frame_size = 860 861 6 + /* vce_v3_0_emit_vm_flush */ 861 862 4 + /* vce_v3_0_emit_pipeline_sync */