AMD-GFX Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 1/5] drm/amdgpu/vcn4.0.3: rework reset handling
@ 2026-01-19  5:34 Jesse.Zhang
  2026-01-19  5:34 ` [PATCH v2 2/5] drm/amdgpu/vcn4.0.3: ensure JPEG is powered on during VCN reset for VCN 4.0.3 Jesse.Zhang
                   ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: Jesse.Zhang @ 2026-01-19  5:34 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alexander.Deucher, Christian Koenig, Alex Deucher

From: "Alex Deucher" <alexander.deucher@amd.com>

Resetting VCN resets the entire tile, including jpeg.
When we reset VCN, we also need to handle the jpeg queues.
Add a helper to handle recovering the jpeg queues when
VCN is reset.

v2: split the jpeg helper in two, in the top helper we can stop the sched workqueues and attempt to wait for any outstanding fences.
Then in the bottom helper, we can force completion, re-init the rings, and restart the sched workqueues

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c | 11 +++-
 drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c  | 70 +++++++++++++++++++++++-
 2 files changed, 77 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c
index aae7328973d1..1a32dadf8c5d 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c
@@ -1145,13 +1145,20 @@ static int jpeg_v4_0_3_ring_reset(struct amdgpu_ring *ring,
 				  unsigned int vmid,
 				  struct amdgpu_fence *timedout_fence)
 {
+	struct amdgpu_device *adev = ring->adev;
+	struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[ring->me];
+	int r;
+
 	if (amdgpu_sriov_vf(ring->adev))
 		return -EOPNOTSUPP;
-
+	/* take the vcn reset mutex here because resetting VCN will reset jpeg as well */
+	mutex_lock(&vinst->engine_reset_mutex);
 	amdgpu_ring_reset_helper_begin(ring, timedout_fence);
 	jpeg_v4_0_3_core_stall_reset(ring);
 	jpeg_v4_0_3_start_jrbc(ring);
-	return amdgpu_ring_reset_helper_end(ring, timedout_fence);
+	r = amdgpu_ring_reset_helper_end(ring, timedout_fence);
+	mutex_unlock(&vinst->engine_reset_mutex);
+	return r;
 }
 
 static const struct amd_ip_funcs jpeg_v4_0_3_ip_funcs = {
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
index cb7123ec1a5d..c7f94976ce6a 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
@@ -1596,6 +1596,60 @@ static void vcn_v4_0_3_unified_ring_set_wptr(struct amdgpu_ring *ring)
 	}
 }
 
+static int vcn_v4_0_3_reset_jpeg_pre_helper(struct amdgpu_device *adev, int inst)
+{
+	struct amdgpu_ring *ring;
+	uint32_t wait_seq = 0;
+	int i;
+
+	for (i = 0; i < adev->jpeg.num_jpeg_rings; ++i) {
+		ring = &adev->jpeg.inst[inst].ring_dec[i];
+
+		drm_sched_wqueue_stop(&ring->sched);
+		/* Get the last emitted fence sequence */
+		wait_seq = atomic_read(&ring->fence_drv.last_seq);
+		if (wait_seq)
+			continue;
+
+		/* if Jobs are still pending after timeout,
+		 * We'll handle them in the bottom helper
+		 */
+		amdgpu_fence_wait_polling(ring, wait_seq, adev->video_timeout);
+       }
+
+	return 0;
+}
+
+static int vcn_v4_0_3_reset_jpeg_post_helper(struct amdgpu_device *adev, int inst)
+{
+	struct amdgpu_ring *ring;
+	int i, r = 0;
+
+	for (i = 0; i < adev->jpeg.num_jpeg_rings; ++i) {
+		ring = &adev->jpeg.inst[inst].ring_dec[i];
+		/* Force completion of any remaining jobs */
+		amdgpu_fence_driver_force_completion(ring);
+
+		if (ring->use_doorbell)
+			WREG32_SOC15_OFFSET(
+				VCN, GET_INST(VCN, inst),
+				regVCN_JPEG_DB_CTRL,
+				(ring->pipe ? (ring->pipe - 0x15) : 0),
+				ring->doorbell_index << VCN_JPEG_DB_CTRL__OFFSET__SHIFT |
+				VCN_JPEG_DB_CTRL__EN_MASK);
+
+		r = amdgpu_ring_test_helper(ring);
+		if (r)
+			return r;
+
+		drm_sched_wqueue_start(&ring->sched);
+
+		DRM_DEV_DEBUG(adev->dev, "JPEG ring %d (inst %d) restored and sched restarted\n",
+		      i, inst);
+	}
+	return 0;
+}
+
 static int vcn_v4_0_3_ring_reset(struct amdgpu_ring *ring,
 				 unsigned int vmid,
 				 struct amdgpu_fence *timedout_fence)
@@ -1605,6 +1659,9 @@ static int vcn_v4_0_3_ring_reset(struct amdgpu_ring *ring,
 	struct amdgpu_device *adev = ring->adev;
 	struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[ring->me];
 
+	/* take the vcn reset mutex here because resetting VCN will reset jpeg as well */
+	mutex_lock(&vinst->engine_reset_mutex);
+	vcn_v4_0_3_reset_jpeg_pre_helper(adev, ring->me);
 	amdgpu_ring_reset_helper_begin(ring, timedout_fence);
 
 	vcn_inst = GET_INST(VCN, ring->me);
@@ -1612,7 +1669,7 @@ static int vcn_v4_0_3_ring_reset(struct amdgpu_ring *ring,
 
 	if (r) {
 		DRM_DEV_ERROR(adev->dev, "VCN reset fail : %d\n", r);
-		return r;
+		goto unlock;
 	}
 
 	/* This flag is not set for VF, assumed to be disabled always */
@@ -1621,7 +1678,16 @@ static int vcn_v4_0_3_ring_reset(struct amdgpu_ring *ring,
 	vcn_v4_0_3_hw_init_inst(vinst);
 	vcn_v4_0_3_start_dpg_mode(vinst, adev->vcn.inst[ring->me].indirect_sram);
 
-	return amdgpu_ring_reset_helper_end(ring, timedout_fence);
+	r = amdgpu_ring_reset_helper_end(ring, timedout_fence);
+	if (r)
+		goto unlock;
+
+	r = vcn_v4_0_3_reset_jpeg_post_helper(adev, ring->me);
+
+unlock:
+	mutex_unlock(&vinst->engine_reset_mutex);
+
+	return r;
 }
 
 static const struct amdgpu_ring_funcs vcn_v4_0_3_unified_ring_vm_funcs = {
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v2 2/5] drm/amdgpu/vcn4.0.3: ensure JPEG is powered on during VCN reset for VCN 4.0.3
  2026-01-19  5:34 [PATCH v2 1/5] drm/amdgpu/vcn4.0.3: rework reset handling Jesse.Zhang
@ 2026-01-19  5:34 ` Jesse.Zhang
  2026-01-19  5:34 ` [PATCH v2 3/5] drm/amdgpu/vcn4.0.3: implement DPG pause mode handling " Jesse.Zhang
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 6+ messages in thread
From: Jesse.Zhang @ 2026-01-19  5:34 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alexander.Deucher, Christian Koenig, Jesse.Zhang, Jesse Zhang

Resetting VCN resets the entire tile, including JPEG hardware.
When we reset VCN, we need to ensure the JPEG block is accessible
for proper reset handling and queue recovery.

Signed-off-by: Jesse Zhang <jesse.zhang@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c | 25 ++++++++++++++++++++++++-
 1 file changed, 24 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
index c7f94976ce6a..78c13724a7ba 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
@@ -1658,9 +1658,18 @@ static int vcn_v4_0_3_ring_reset(struct amdgpu_ring *ring,
 	int vcn_inst;
 	struct amdgpu_device *adev = ring->adev;
 	struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[ring->me];
+	bool pg_state = false;
 
 	/* take the vcn reset mutex here because resetting VCN will reset jpeg as well */
 	mutex_lock(&vinst->engine_reset_mutex);
+	mutex_lock(&adev->jpeg.jpeg_pg_lock);
+	/* Ensure JPEG is powered on during reset if currently gated */
+	if (adev->jpeg.cur_state == AMD_PG_STATE_GATE) {
+		amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_JPEG,
+						       AMD_PG_STATE_UNGATE);
+		pg_state = true;
+	}
+
 	vcn_v4_0_3_reset_jpeg_pre_helper(adev, ring->me);
 	amdgpu_ring_reset_helper_begin(ring, timedout_fence);
 
@@ -1669,6 +1678,11 @@ static int vcn_v4_0_3_ring_reset(struct amdgpu_ring *ring,
 
 	if (r) {
 		DRM_DEV_ERROR(adev->dev, "VCN reset fail : %d\n", r);
+		/* Restore JPEG power gating state if it was originally gated */
+		if (pg_state)
+			amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_JPEG,
+							       AMD_PG_STATE_GATE);
+		mutex_unlock(&adev->jpeg.jpeg_pg_lock);
 		goto unlock;
 	}
 
@@ -1679,10 +1693,19 @@ static int vcn_v4_0_3_ring_reset(struct amdgpu_ring *ring,
 	vcn_v4_0_3_start_dpg_mode(vinst, adev->vcn.inst[ring->me].indirect_sram);
 
 	r = amdgpu_ring_reset_helper_end(ring, timedout_fence);
-	if (r)
+	if (r) {
+		if (pg_state)
+			amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_JPEG,
+							       AMD_PG_STATE_GATE);
+		mutex_unlock(&adev->jpeg.jpeg_pg_lock);
 		goto unlock;
+	}
 
 	r = vcn_v4_0_3_reset_jpeg_post_helper(adev, ring->me);
+	if (pg_state)
+		amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_JPEG,
+						       AMD_PG_STATE_GATE);
+	mutex_unlock(&adev->jpeg.jpeg_pg_lock);
 
 unlock:
 	mutex_unlock(&vinst->engine_reset_mutex);
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v2 3/5] drm/amdgpu/vcn4.0.3: implement DPG pause mode handling for VCN 4.0.3
  2026-01-19  5:34 [PATCH v2 1/5] drm/amdgpu/vcn4.0.3: rework reset handling Jesse.Zhang
  2026-01-19  5:34 ` [PATCH v2 2/5] drm/amdgpu/vcn4.0.3: ensure JPEG is powered on during VCN reset for VCN 4.0.3 Jesse.Zhang
@ 2026-01-19  5:34 ` Jesse.Zhang
  2026-01-19 16:19   ` Alex Deucher
  2026-01-19  5:34 ` [PATCH v2 4/5] drm/amdgpu/vcn5.0.1: rework reset handling Jesse.Zhang
  2026-01-19  5:34 ` [PATCH v2 5/5] drm/amdgpu/vcn5.0.1: ensure JPEG is powered on during VCN reset for VCN 5.0.1 Jesse.Zhang
  3 siblings, 1 reply; 6+ messages in thread
From: Jesse.Zhang @ 2026-01-19  5:34 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alexander.Deucher, Christian Koenig, Jesse.Zhang, Jesse Zhang

For MI projects, when Dynamic Power Gating (DPG) is enabled,
VCN reset operations should be performed with DPG in pause mode.
Otherwise, the hardware may perform undesirable reset operations

Signed-off-by: Jesse Zhang <jesse.zhang@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c | 41 +++++++++++++++++++++++++
 1 file changed, 41 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
index 78c13724a7ba..dd247abce1ab 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
@@ -847,6 +847,7 @@ static int vcn_v4_0_3_start_dpg_mode(struct amdgpu_vcn_inst *vinst,
 	int inst_idx = vinst->inst;
 	struct amdgpu_vcn4_fw_shared *fw_shared =
 						adev->vcn.inst[inst_idx].fw_shared.cpu_addr;
+	struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__PAUSE};
 	struct amdgpu_ring *ring;
 	int vcn_inst, ret;
 	uint32_t tmp;
@@ -951,6 +952,9 @@ static int vcn_v4_0_3_start_dpg_mode(struct amdgpu_vcn_inst *vinst,
 
 	ring = &adev->vcn.inst[inst_idx].ring_enc[0];
 
+	/* Pause dpg */
+	vcn_v4_0_3_pause_dpg_mode(vinst, &state);
+
 	/* program the RB_BASE for ring buffer */
 	WREG32_SOC15(VCN, vcn_inst, regUVD_RB_BASE_LO,
 		     lower_32_bits(ring->gpu_addr));
@@ -1360,9 +1364,13 @@ static int vcn_v4_0_3_stop_dpg_mode(struct amdgpu_vcn_inst *vinst)
 	int inst_idx = vinst->inst;
 	uint32_t tmp;
 	int vcn_inst;
+	struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__UNPAUSE};
 
 	vcn_inst = GET_INST(VCN, inst_idx);
 
+	/* Unpause dpg */
+	vcn_v4_0_3_pause_dpg_mode(vinst, &state);
+
 	/* Wait for power status to be 1 */
 	SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_POWER_STATUS, 1,
 			   UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
@@ -1486,6 +1494,39 @@ static int vcn_v4_0_3_stop(struct amdgpu_vcn_inst *vinst)
 static int vcn_v4_0_3_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
 				     struct dpg_pause_state *new_state)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst_idx = vinst->inst;
+	uint32_t reg_data = 0;
+	int ret_code;
+
+	/* pause/unpause if state is changed */
+	if (adev->vcn.inst[inst_idx].pause_state.fw_based != new_state->fw_based) {
+		DRM_DEV_DEBUG(adev->dev, "dpg pause state changed %d -> %d",
+			adev->vcn.inst[inst_idx].pause_state.fw_based,	new_state->fw_based);
+		reg_data = RREG32_SOC15(VCN, inst_idx, regUVD_DPG_PAUSE) &
+			(~UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK);
+
+		if (new_state->fw_based == VCN_DPG_STATE__PAUSE) {
+			ret_code = SOC15_WAIT_ON_RREG(VCN, inst_idx, regUVD_POWER_STATUS, 0x1,
+				UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
+
+			if (!ret_code) {
+				/* pause DPG */
+				reg_data |= UVD_DPG_PAUSE__NJ_PAUSE_DPG_REQ_MASK;
+				WREG32_SOC15(VCN, inst_idx, regUVD_DPG_PAUSE, reg_data);
+
+				/* wait for ACK */
+				SOC15_WAIT_ON_RREG(VCN, inst_idx, regUVD_DPG_PAUSE,
+					UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK,
+					UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK);
+			}
+		} else {
+			/* unpause dpg, no need to wait */
+			reg_data &= ~UVD_DPG_PAUSE__NJ_PAUSE_DPG_REQ_MASK;
+			WREG32_SOC15(VCN, inst_idx, regUVD_DPG_PAUSE, reg_data);
+		}
+		adev->vcn.inst[inst_idx].pause_state.fw_based = new_state->fw_based;
+	}
 
 	return 0;
 }
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v2 4/5] drm/amdgpu/vcn5.0.1: rework reset handling
  2026-01-19  5:34 [PATCH v2 1/5] drm/amdgpu/vcn4.0.3: rework reset handling Jesse.Zhang
  2026-01-19  5:34 ` [PATCH v2 2/5] drm/amdgpu/vcn4.0.3: ensure JPEG is powered on during VCN reset for VCN 4.0.3 Jesse.Zhang
  2026-01-19  5:34 ` [PATCH v2 3/5] drm/amdgpu/vcn4.0.3: implement DPG pause mode handling " Jesse.Zhang
@ 2026-01-19  5:34 ` Jesse.Zhang
  2026-01-19  5:34 ` [PATCH v2 5/5] drm/amdgpu/vcn5.0.1: ensure JPEG is powered on during VCN reset for VCN 5.0.1 Jesse.Zhang
  3 siblings, 0 replies; 6+ messages in thread
From: Jesse.Zhang @ 2026-01-19  5:34 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alexander.Deucher, Christian Koenig, Alex Deucher

From: "Alex Deucher" <alexander.deucher@amd.com>

Resetting VCN resets the entire tile, including jpeg.
When we reset VCN, we also need to handle the jpeg queues.
Add a helper to handle recovering the jpeg queues when
VCN is reset.

v2: split the jpeg helper in two, in the top helper we can stop the sched workqueues and attempt to wait for any outstanding fences.
    Then in the bottom helper, we can force completion, re-init the rings, and restart the sched workqueues

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c | 11 +++-
 drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c  | 69 +++++++++++++++++++++++-
 2 files changed, 77 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c
index ab0bf880d3d8..edecbfe66c79 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c
@@ -844,10 +844,19 @@ static int jpeg_v5_0_1_ring_reset(struct amdgpu_ring *ring,
 				  unsigned int vmid,
 				  struct amdgpu_fence *timedout_fence)
 {
+	struct amdgpu_device *adev = ring->adev;
+	struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[ring->me];
+	int r;
+
+	/* take the vcn reset mutex here because resetting VCN will reset jpeg as well */
+	mutex_lock(&vinst->engine_reset_mutex);
+
 	amdgpu_ring_reset_helper_begin(ring, timedout_fence);
 	jpeg_v5_0_1_core_stall_reset(ring);
 	jpeg_v5_0_1_init_jrbc(ring);
-	return amdgpu_ring_reset_helper_end(ring, timedout_fence);
+	r = amdgpu_ring_reset_helper_end(ring, timedout_fence);
+	mutex_unlock(&vinst->engine_reset_mutex);
+	return r;
 }
 
 static const struct amd_ip_funcs jpeg_v5_0_1_ip_funcs = {
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
index 8bd457dea4cf..db2c8efb112c 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
@@ -1301,6 +1301,59 @@ static void vcn_v5_0_1_unified_ring_set_wptr(struct amdgpu_ring *ring)
 	}
 }
 
+static int vcn_v5_0_1_reset_jpeg_pre_helper(struct amdgpu_device *adev, int inst)
+{
+	struct amdgpu_ring *ring;
+	uint32_t wait_seq = 0;
+	int i;
+
+	for (i = 0; i < adev->jpeg.num_jpeg_rings; ++i) {
+		ring = &adev->jpeg.inst[inst].ring_dec[i];
+
+		drm_sched_wqueue_stop(&ring->sched);
+		wait_seq = atomic_read(&ring->fence_drv.last_seq);
+		if (wait_seq)
+			continue;
+
+		/* if Jobs are still pending after timeout,
+		 * We'll handle them in the bottom helper
+		 */
+		amdgpu_fence_wait_polling(ring, wait_seq, adev->video_timeout);
+       }
+
+	return 0;
+}
+
+static int vcn_v5_0_1_reset_jpeg_post_helper(struct amdgpu_device *adev, int inst)
+{
+	struct amdgpu_ring *ring;
+	int i, r = 0;
+
+	for (i = 0; i < adev->jpeg.num_jpeg_rings; ++i) {
+		ring = &adev->jpeg.inst[inst].ring_dec[i];
+		/* Force completion of any remaining jobs */
+		amdgpu_fence_driver_force_completion(ring);
+
+		if (ring->use_doorbell)
+			WREG32_SOC15_OFFSET(
+				VCN, GET_INST(VCN, inst),
+				regVCN_JPEG_DB_CTRL,
+				(ring->pipe ? (ring->pipe - 0x15) : 0),
+				ring->doorbell_index << VCN_JPEG_DB_CTRL__OFFSET__SHIFT |
+				VCN_JPEG_DB_CTRL__EN_MASK);
+
+		r = amdgpu_ring_test_helper(ring);
+		if (r)
+			return r;
+
+		drm_sched_wqueue_start(&ring->sched);
+
+		DRM_DEV_DEBUG(adev->dev, "JPEG ring %d (inst %d) restored and sched restarted\n",
+		      i, inst);
+	}
+	return 0;
+}
+
 static int vcn_v5_0_1_ring_reset(struct amdgpu_ring *ring,
 				 unsigned int vmid,
 				 struct amdgpu_fence *timedout_fence)
@@ -1310,6 +1363,9 @@ static int vcn_v5_0_1_ring_reset(struct amdgpu_ring *ring,
 	struct amdgpu_device *adev = ring->adev;
 	struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[ring->me];
 
+	/* take the vcn reset mutex here because resetting VCN will reset jpeg as well */
+	mutex_lock(&vinst->engine_reset_mutex);
+	vcn_v5_0_1_reset_jpeg_pre_helper(adev, ring->me);
 	amdgpu_ring_reset_helper_begin(ring, timedout_fence);
 
 	vcn_inst = GET_INST(VCN, ring->me);
@@ -1317,13 +1373,22 @@ static int vcn_v5_0_1_ring_reset(struct amdgpu_ring *ring,
 
 	if (r) {
 		DRM_DEV_ERROR(adev->dev, "VCN reset fail : %d\n", r);
-		return r;
+		goto unlock;
 	}
 
 	vcn_v5_0_1_hw_init_inst(adev, ring->me);
 	vcn_v5_0_1_start_dpg_mode(vinst, vinst->indirect_sram);
 
-	return amdgpu_ring_reset_helper_end(ring, timedout_fence);
+	r = amdgpu_ring_reset_helper_end(ring, timedout_fence);
+	if (r)
+		goto unlock;
+
+	r = vcn_v5_0_1_reset_jpeg_post_helper(adev, ring->me);
+
+unlock:
+	mutex_unlock(&vinst->engine_reset_mutex);
+
+	return r;
 }
 
 static const struct amdgpu_ring_funcs vcn_v5_0_1_unified_ring_vm_funcs = {
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v2 5/5] drm/amdgpu/vcn5.0.1: ensure JPEG is powered on during VCN reset for VCN 5.0.1
  2026-01-19  5:34 [PATCH v2 1/5] drm/amdgpu/vcn4.0.3: rework reset handling Jesse.Zhang
                   ` (2 preceding siblings ...)
  2026-01-19  5:34 ` [PATCH v2 4/5] drm/amdgpu/vcn5.0.1: rework reset handling Jesse.Zhang
@ 2026-01-19  5:34 ` Jesse.Zhang
  3 siblings, 0 replies; 6+ messages in thread
From: Jesse.Zhang @ 2026-01-19  5:34 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alexander.Deucher, Christian Koenig, Jesse.Zhang, Jesse Zhang

Resetting VCN resets the entire tile, including JPEG hardware.
When we reset VCN, we need to ensure the JPEG block is accessible
for proper reset handling and queue recovery.

Signed-off-by: Jesse Zhang <jesse.zhang@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c | 26 ++++++++++++++++++++++++-
 1 file changed, 25 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
index db2c8efb112c..c28c6aff17aa 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
@@ -1362,10 +1362,19 @@ static int vcn_v5_0_1_ring_reset(struct amdgpu_ring *ring,
 	int vcn_inst;
 	struct amdgpu_device *adev = ring->adev;
 	struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[ring->me];
+	bool pg_state = false;
 
 	/* take the vcn reset mutex here because resetting VCN will reset jpeg as well */
 	mutex_lock(&vinst->engine_reset_mutex);
 	vcn_v5_0_1_reset_jpeg_pre_helper(adev, ring->me);
+	mutex_lock(&adev->jpeg.jpeg_pg_lock);
+	/* Ensure JPEG is powered on during reset if currently gated */
+	if (adev->jpeg.cur_state == AMD_PG_STATE_GATE) {
+		amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_JPEG,
+					       AMD_PG_STATE_UNGATE);
+		pg_state = true;
+	}
+
 	amdgpu_ring_reset_helper_begin(ring, timedout_fence);
 
 	vcn_inst = GET_INST(VCN, ring->me);
@@ -1373,6 +1382,11 @@ static int vcn_v5_0_1_ring_reset(struct amdgpu_ring *ring,
 
 	if (r) {
 		DRM_DEV_ERROR(adev->dev, "VCN reset fail : %d\n", r);
+		/* Restore JPEG power gating state if it was originally gated */
+		if (pg_state)
+			amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_JPEG,
+							       AMD_PG_STATE_GATE);
+		mutex_unlock(&adev->jpeg.jpeg_pg_lock);
 		goto unlock;
 	}
 
@@ -1380,8 +1394,18 @@ static int vcn_v5_0_1_ring_reset(struct amdgpu_ring *ring,
 	vcn_v5_0_1_start_dpg_mode(vinst, vinst->indirect_sram);
 
 	r = amdgpu_ring_reset_helper_end(ring, timedout_fence);
-	if (r)
+	if (r) {
+		if (pg_state)
+			amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_JPEG,
+							       AMD_PG_STATE_GATE);
+		mutex_unlock(&adev->jpeg.jpeg_pg_lock);
 		goto unlock;
+	}
+
+	if (pg_state)
+		amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_JPEG,
+						       AMD_PG_STATE_GATE);
+	mutex_unlock(&adev->jpeg.jpeg_pg_lock);
 
 	r = vcn_v5_0_1_reset_jpeg_post_helper(adev, ring->me);
 
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH v2 3/5] drm/amdgpu/vcn4.0.3: implement DPG pause mode handling for VCN 4.0.3
  2026-01-19  5:34 ` [PATCH v2 3/5] drm/amdgpu/vcn4.0.3: implement DPG pause mode handling " Jesse.Zhang
@ 2026-01-19 16:19   ` Alex Deucher
  0 siblings, 0 replies; 6+ messages in thread
From: Alex Deucher @ 2026-01-19 16:19 UTC (permalink / raw)
  To: Jesse.Zhang; +Cc: amd-gfx, Alexander.Deucher, Christian Koenig

On Mon, Jan 19, 2026 at 12:52 AM Jesse.Zhang <Jesse.Zhang@amd.com> wrote:
>
> For MI projects, when Dynamic Power Gating (DPG) is enabled,
> VCN reset operations should be performed with DPG in pause mode.
> Otherwise, the hardware may perform undesirable reset operations
>
> Signed-off-by: Jesse Zhang <jesse.zhang@amd.com>

This patch should probably come first in the series.  You could also
merge patches 1 and 2 into one patch.  Same with 4 and 5.  Either way,
the series is:
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>


> ---
>  drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c | 41 +++++++++++++++++++++++++
>  1 file changed, 41 insertions(+)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
> index 78c13724a7ba..dd247abce1ab 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
> @@ -847,6 +847,7 @@ static int vcn_v4_0_3_start_dpg_mode(struct amdgpu_vcn_inst *vinst,
>         int inst_idx = vinst->inst;
>         struct amdgpu_vcn4_fw_shared *fw_shared =
>                                                 adev->vcn.inst[inst_idx].fw_shared.cpu_addr;
> +       struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__PAUSE};
>         struct amdgpu_ring *ring;
>         int vcn_inst, ret;
>         uint32_t tmp;
> @@ -951,6 +952,9 @@ static int vcn_v4_0_3_start_dpg_mode(struct amdgpu_vcn_inst *vinst,
>
>         ring = &adev->vcn.inst[inst_idx].ring_enc[0];
>
> +       /* Pause dpg */
> +       vcn_v4_0_3_pause_dpg_mode(vinst, &state);
> +
>         /* program the RB_BASE for ring buffer */
>         WREG32_SOC15(VCN, vcn_inst, regUVD_RB_BASE_LO,
>                      lower_32_bits(ring->gpu_addr));
> @@ -1360,9 +1364,13 @@ static int vcn_v4_0_3_stop_dpg_mode(struct amdgpu_vcn_inst *vinst)
>         int inst_idx = vinst->inst;
>         uint32_t tmp;
>         int vcn_inst;
> +       struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__UNPAUSE};
>
>         vcn_inst = GET_INST(VCN, inst_idx);
>
> +       /* Unpause dpg */
> +       vcn_v4_0_3_pause_dpg_mode(vinst, &state);
> +
>         /* Wait for power status to be 1 */
>         SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_POWER_STATUS, 1,
>                            UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
> @@ -1486,6 +1494,39 @@ static int vcn_v4_0_3_stop(struct amdgpu_vcn_inst *vinst)
>  static int vcn_v4_0_3_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
>                                      struct dpg_pause_state *new_state)
>  {
> +       struct amdgpu_device *adev = vinst->adev;
> +       int inst_idx = vinst->inst;
> +       uint32_t reg_data = 0;
> +       int ret_code;
> +
> +       /* pause/unpause if state is changed */
> +       if (adev->vcn.inst[inst_idx].pause_state.fw_based != new_state->fw_based) {
> +               DRM_DEV_DEBUG(adev->dev, "dpg pause state changed %d -> %d",
> +                       adev->vcn.inst[inst_idx].pause_state.fw_based,  new_state->fw_based);
> +               reg_data = RREG32_SOC15(VCN, inst_idx, regUVD_DPG_PAUSE) &
> +                       (~UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK);
> +
> +               if (new_state->fw_based == VCN_DPG_STATE__PAUSE) {
> +                       ret_code = SOC15_WAIT_ON_RREG(VCN, inst_idx, regUVD_POWER_STATUS, 0x1,
> +                               UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
> +
> +                       if (!ret_code) {
> +                               /* pause DPG */
> +                               reg_data |= UVD_DPG_PAUSE__NJ_PAUSE_DPG_REQ_MASK;
> +                               WREG32_SOC15(VCN, inst_idx, regUVD_DPG_PAUSE, reg_data);
> +
> +                               /* wait for ACK */
> +                               SOC15_WAIT_ON_RREG(VCN, inst_idx, regUVD_DPG_PAUSE,
> +                                       UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK,
> +                                       UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK);
> +                       }
> +               } else {
> +                       /* unpause dpg, no need to wait */
> +                       reg_data &= ~UVD_DPG_PAUSE__NJ_PAUSE_DPG_REQ_MASK;
> +                       WREG32_SOC15(VCN, inst_idx, regUVD_DPG_PAUSE, reg_data);
> +               }
> +               adev->vcn.inst[inst_idx].pause_state.fw_based = new_state->fw_based;
> +       }
>
>         return 0;
>  }
> --
> 2.49.0
>

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-01-19 16:19 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-19  5:34 [PATCH v2 1/5] drm/amdgpu/vcn4.0.3: rework reset handling Jesse.Zhang
2026-01-19  5:34 ` [PATCH v2 2/5] drm/amdgpu/vcn4.0.3: ensure JPEG is powered on during VCN reset for VCN 4.0.3 Jesse.Zhang
2026-01-19  5:34 ` [PATCH v2 3/5] drm/amdgpu/vcn4.0.3: implement DPG pause mode handling " Jesse.Zhang
2026-01-19 16:19   ` Alex Deucher
2026-01-19  5:34 ` [PATCH v2 4/5] drm/amdgpu/vcn5.0.1: rework reset handling Jesse.Zhang
2026-01-19  5:34 ` [PATCH v2 5/5] drm/amdgpu/vcn5.0.1: ensure JPEG is powered on during VCN reset for VCN 5.0.1 Jesse.Zhang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox