Commit 187561dd authored by Veerabadhran G's avatar Veerabadhran G Committed by Alex Deucher
Browse files

drm/amdgpu: vcn and jpeg ring synchronization



Synchronize the ring usage for vcn1 and jpeg1 to workaround a hardware bug.

Signed-off-by: default avatarVeerabadhran Gopalakrishnan <veerabadhran.gopalakrishnan@amd.com>
Acked-by: default avatarChristian König <christian.koenig@amd.com>
Reviewed-by: default avatarChristian König <christian.koenig@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org
parent 83da6eea
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -68,6 +68,7 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)

	INIT_DELAYED_WORK(&adev->vcn.idle_work, amdgpu_vcn_idle_work_handler);
	mutex_init(&adev->vcn.vcn_pg_lock);
	mutex_init(&adev->vcn.vcn1_jpeg1_workaround);
	atomic_set(&adev->vcn.total_submission_cnt, 0);
	for (i = 0; i < adev->vcn.num_vcn_inst; i++)
		atomic_set(&adev->vcn.inst[i].dpg_enc_submission_cnt, 0);
@@ -237,6 +238,7 @@ int amdgpu_vcn_sw_fini(struct amdgpu_device *adev)
	}

	release_firmware(adev->vcn.fw);
	mutex_destroy(&adev->vcn.vcn1_jpeg1_workaround);
	mutex_destroy(&adev->vcn.vcn_pg_lock);

	return 0;
+1 −0
Original line number Diff line number Diff line
@@ -220,6 +220,7 @@ struct amdgpu_vcn {
	struct amdgpu_vcn_inst	 inst[AMDGPU_MAX_VCN_INSTANCES];
	struct amdgpu_vcn_reg	 internal;
	struct mutex		 vcn_pg_lock;
	struct mutex		vcn1_jpeg1_workaround;
	atomic_t		 total_submission_cnt;

	unsigned	harvest_config;
+22 −2
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@

static void jpeg_v1_0_set_dec_ring_funcs(struct amdgpu_device *adev);
static void jpeg_v1_0_set_irq_funcs(struct amdgpu_device *adev);
static void jpeg_v1_0_ring_begin_use(struct amdgpu_ring *ring);

static void jpeg_v1_0_decode_ring_patch_wreg(struct amdgpu_ring *ring, uint32_t *ptr, uint32_t reg_offset, uint32_t val)
{
@@ -564,8 +565,8 @@ static const struct amdgpu_ring_funcs jpeg_v1_0_decode_ring_vm_funcs = {
	.insert_start = jpeg_v1_0_decode_ring_insert_start,
	.insert_end = jpeg_v1_0_decode_ring_insert_end,
	.pad_ib = amdgpu_ring_generic_pad_ib,
	.begin_use = vcn_v1_0_ring_begin_use,
	.end_use = amdgpu_vcn_ring_end_use,
	.begin_use = jpeg_v1_0_ring_begin_use,
	.end_use = vcn_v1_0_ring_end_use,
	.emit_wreg = jpeg_v1_0_decode_ring_emit_wreg,
	.emit_reg_wait = jpeg_v1_0_decode_ring_emit_reg_wait,
	.emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
@@ -586,3 +587,22 @@ static void jpeg_v1_0_set_irq_funcs(struct amdgpu_device *adev)
{
	adev->jpeg.inst->irq.funcs = &jpeg_v1_0_irq_funcs;
}

static void jpeg_v1_0_ring_begin_use(struct amdgpu_ring *ring)
{
	struct	amdgpu_device *adev = ring->adev;
	bool	set_clocks = !cancel_delayed_work_sync(&adev->vcn.idle_work);
	int		cnt = 0;

	mutex_lock(&adev->vcn.vcn1_jpeg1_workaround);

	if (amdgpu_fence_wait_empty(&adev->vcn.inst->ring_dec))
		DRM_ERROR("JPEG dec: vcn dec ring may not be empty\n");

	for (cnt = 0; cnt < adev->vcn.num_enc_rings; cnt++) {
		if (amdgpu_fence_wait_empty(&adev->vcn.inst->ring_enc[cnt]))
			DRM_ERROR("JPEG dec: vcn enc ring[%d] may not be empty\n", cnt);
	}

	vcn_v1_0_set_pg_for_begin_use(ring, set_clocks);
}
+24 −4
Original line number Diff line number Diff line
@@ -54,6 +54,7 @@ static int vcn_v1_0_pause_dpg_mode(struct amdgpu_device *adev,
				int inst_idx, struct dpg_pause_state *new_state);

static void vcn_v1_0_idle_work_handler(struct work_struct *work);
static void vcn_v1_0_ring_begin_use(struct amdgpu_ring *ring);

/**
 * vcn_v1_0_early_init - set function pointers
@@ -1804,11 +1805,24 @@ static void vcn_v1_0_idle_work_handler(struct work_struct *work)
	}
}

void vcn_v1_0_ring_begin_use(struct amdgpu_ring *ring)
static void vcn_v1_0_ring_begin_use(struct amdgpu_ring *ring)
{
	struct	amdgpu_device *adev = ring->adev;
	bool set_clocks = !cancel_delayed_work_sync(&adev->vcn.idle_work);

	mutex_lock(&adev->vcn.vcn1_jpeg1_workaround);

	if (amdgpu_fence_wait_empty(&ring->adev->jpeg.inst->ring_dec))
		DRM_ERROR("VCN dec: jpeg dec ring may not be empty\n");

	vcn_v1_0_set_pg_for_begin_use(ring, set_clocks);

}

void vcn_v1_0_set_pg_for_begin_use(struct amdgpu_ring *ring, bool set_clocks)
{
	struct amdgpu_device *adev = ring->adev;

	if (set_clocks) {
		amdgpu_gfx_off_ctrl(adev, false);
		if (adev->pm.dpm_enabled)
@@ -1844,6 +1858,12 @@ void vcn_v1_0_ring_begin_use(struct amdgpu_ring *ring)
	}
}

void vcn_v1_0_ring_end_use(struct amdgpu_ring *ring)
{
	schedule_delayed_work(&ring->adev->vcn.idle_work, VCN_IDLE_TIMEOUT);
	mutex_unlock(&ring->adev->vcn.vcn1_jpeg1_workaround);
}

static const struct amd_ip_funcs vcn_v1_0_ip_funcs = {
	.name = "vcn_v1_0",
	.early_init = vcn_v1_0_early_init,
@@ -1891,7 +1911,7 @@ static const struct amdgpu_ring_funcs vcn_v1_0_dec_ring_vm_funcs = {
	.insert_end = vcn_v1_0_dec_ring_insert_end,
	.pad_ib = amdgpu_ring_generic_pad_ib,
	.begin_use = vcn_v1_0_ring_begin_use,
	.end_use = amdgpu_vcn_ring_end_use,
	.end_use = vcn_v1_0_ring_end_use,
	.emit_wreg = vcn_v1_0_dec_ring_emit_wreg,
	.emit_reg_wait = vcn_v1_0_dec_ring_emit_reg_wait,
	.emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
@@ -1923,7 +1943,7 @@ static const struct amdgpu_ring_funcs vcn_v1_0_enc_ring_vm_funcs = {
	.insert_end = vcn_v1_0_enc_ring_insert_end,
	.pad_ib = amdgpu_ring_generic_pad_ib,
	.begin_use = vcn_v1_0_ring_begin_use,
	.end_use = amdgpu_vcn_ring_end_use,
	.end_use = vcn_v1_0_ring_end_use,
	.emit_wreg = vcn_v1_0_enc_ring_emit_wreg,
	.emit_reg_wait = vcn_v1_0_enc_ring_emit_reg_wait,
	.emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
+2 −1
Original line number Diff line number Diff line
@@ -24,7 +24,8 @@
#ifndef __VCN_V1_0_H__
#define __VCN_V1_0_H__

void vcn_v1_0_ring_begin_use(struct amdgpu_ring *ring);
void vcn_v1_0_ring_end_use(struct amdgpu_ring *ring);
void vcn_v1_0_set_pg_for_begin_use(struct amdgpu_ring *ring, bool set_clocks);

extern const struct amdgpu_ip_block_version vcn_v1_0_ip_block;