Commit dc8f9f0f authored by David Rosca's avatar David Rosca Committed by Alex Deucher
Browse files

drm/amdgpu/vcn4: Fix IB parsing with multiple engine info packages



There can be multiple engine info packages in one IB and the first one
may be common engine, not decode/encode.
We need to parse the entire IB instead of stopping after finding first
engine info.

Signed-off-by: default avatarDavid Rosca <david.rosca@amd.com>
Reviewed-by: default avatarLeo Liu <leo.liu@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent d426a5b6
Loading
Loading
Loading
Loading
+21 −31
Original line number Diff line number Diff line
@@ -1903,22 +1903,16 @@ static int vcn_v4_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job,

#define RADEON_VCN_ENGINE_TYPE_ENCODE			(0x00000002)
#define RADEON_VCN_ENGINE_TYPE_DECODE			(0x00000003)

#define RADEON_VCN_ENGINE_INFO				(0x30000001)
#define RADEON_VCN_ENGINE_INFO_MAX_OFFSET		16

#define RENCODE_ENCODE_STANDARD_AV1			2
#define RENCODE_IB_PARAM_SESSION_INIT			0x00000003
#define RENCODE_IB_PARAM_SESSION_INIT_MAX_OFFSET	64

/* return the offset in ib if id is found, -1 otherwise
 * to speed up the searching we only search upto max_offset
 */
static int vcn_v4_0_enc_find_ib_param(struct amdgpu_ib *ib, uint32_t id, int max_offset)
/* return the offset in ib if id is found, -1 otherwise */
static int vcn_v4_0_enc_find_ib_param(struct amdgpu_ib *ib, uint32_t id, int start)
{
	int i;

	for (i = 0; i < ib->length_dw && i < max_offset && ib->ptr[i] >= 8; i += ib->ptr[i]/4) {
	for (i = start; i < ib->length_dw && ib->ptr[i] >= 8; i += ib->ptr[i] / 4) {
		if (ib->ptr[i + 1] == id)
			return i;
	}
@@ -1933,18 +1927,13 @@ static int vcn_v4_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
	struct amdgpu_vcn_decode_buffer *decode_buffer;
	uint64_t addr;
	uint32_t val;
	int idx;
	int idx = 0, sidx;

	/* The first instance can decode anything */
	if (!ring->me)
		return 0;

	/* RADEON_VCN_ENGINE_INFO is at the top of ib block */
	idx = vcn_v4_0_enc_find_ib_param(ib, RADEON_VCN_ENGINE_INFO,
			RADEON_VCN_ENGINE_INFO_MAX_OFFSET);
	if (idx < 0) /* engine info is missing */
		return 0;

	while ((idx = vcn_v4_0_enc_find_ib_param(ib, RADEON_VCN_ENGINE_INFO, idx)) >= 0) {
		val = amdgpu_ib_get_value(ib, idx + 2); /* RADEON_VCN_ENGINE_TYPE */
		if (val == RADEON_VCN_ENGINE_TYPE_DECODE) {
			decode_buffer = (struct amdgpu_vcn_decode_buffer *)&ib->ptr[idx + 6];
@@ -1956,11 +1945,12 @@ static int vcn_v4_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
				decode_buffer->msg_buffer_address_lo;
			return vcn_v4_0_dec_msg(p, job, addr);
		} else if (val == RADEON_VCN_ENGINE_TYPE_ENCODE) {
		idx = vcn_v4_0_enc_find_ib_param(ib, RENCODE_IB_PARAM_SESSION_INIT,
			RENCODE_IB_PARAM_SESSION_INIT_MAX_OFFSET);
		if (idx >= 0 && ib->ptr[idx + 2] == RENCODE_ENCODE_STANDARD_AV1)
			sidx = vcn_v4_0_enc_find_ib_param(ib, RENCODE_IB_PARAM_SESSION_INIT, idx);
			if (sidx >= 0 && ib->ptr[sidx + 2] == RENCODE_ENCODE_STANDARD_AV1)
				return vcn_v4_0_limit_sched(p, job);
		}
		idx += ib->ptr[idx] / 4;
	}
	return 0;
}