AMD General
Hi @Liu, Leo
Could you please take a look at patches 2 and 3 when you get a chance?
Regards,
Prike
> -----Original Message-----
> From: Liang, Prike <[email protected]>
> Sent: Friday, October 30, 2026 10:48 AM
> To: [email protected]
> Cc: Deucher, Alexander <[email protected]>; Koenig, Christian
> <[email protected]>; Lazar, Lijo <[email protected]>; Prosyak, Vitaly
> <[email protected]>; Liang, Prike <[email protected]>; Lazar, Lijo
> <[email protected]>
> Subject: [PATCH 3/3] drm/amdgpu: stop GPU recovery wait for the JPEG/VCN idle
> work
>
> The common JPEG and VCN idle workers program power gating and DPG pause,
> so they must not run while a GPU reset is in progress. Recovery must not wait
> for
> them either, since everything the workers depend on then becomes a dependency
> of
> GPU recovery.
>
> Make the workers take reset_domain->sem for read, so they wait for a running
> reset
> instead of touching the hardware. hw_fini/suspend, the hw_init error paths and
> begin_use, the latter for the IB tests, run from GPU recovery as well, so
> only skip
> waiting for the idle work when the reset itself calls them. The reset holds
> the
> semaphore for write and would otherwise deadlock on a worker blocked on it.
> Outside a reset the cancel stays synchronous as before.
>
> A device can also be torn down while a peer in its XGMI reset domain is being
> reset.
> hw_fini then doesn't wait for the worker either, and is skipped entirely if
> the peer's
> reset has already suspended the device.
> Cancel the idle work synchronously in early_fini, which only runs on teardown
> and
> before any hw_fini, so the worker is done before the hardware it touches is
> torn
> down.
>
> Update versions:
> v1: https://lists.freedesktop.org/archives/amd-gfx/2026-October/155441.html
> v2: https://lists.freedesktop.org/archives/amd-gfx/2026-October/156119.html
>
> Signed-off-by: Prike Liang <[email protected]> Cc; Leo Liu
> <[email protected]>
> Reviewed-by: Lijo Lazar <[email protected]>
> ---
> drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c | 30 ++++++++++++++++++--
> drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.h | 1 +
> drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 36 +++++++++++++++++++++++-
> drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h | 2 ++
> drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c | 5 ++--
> drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c | 6 ++--
> drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c | 5 ++--
> drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c | 5 ++--
> drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c | 5 ++--
> drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_5.c | 5 ++--
> drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c | 5 ++--
> drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c | 5 ++--
> drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_2.c | 5 ++--
> drivers/gpu/drm/amd/amdgpu/jpeg_v5_3_0.c | 5 ++--
> drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c | 4 +--
> drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c | 5 ++--
> drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c | 4 +--
> drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c | 5 ++--
> drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c | 5 ++--
> drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c | 5 ++--
> drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c | 5 ++--
> drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c | 5 ++--
> drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c | 5 ++--
> drivers/gpu/drm/amd/amdgpu/vcn_v5_0_2.c | 5 ++--
> 24 files changed, 125 insertions(+), 43 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c
> index 2b0e658b63b6..87f0ba6a79d6 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c
> @@ -95,9 +95,30 @@ int amdgpu_jpeg_sw_fini(struct amdgpu_device *adev)
> return 0;
> }
>
> +int amdgpu_jpeg_early_fini(struct amdgpu_ip_block *ip_block) {
> + /* Called on teardown even if sw_init never ran */
> + if (!ip_block->status.sw)
> + return 0;
> +
> + /* hw_fini may not wait while a peer in the reset domain resets */
> + cancel_delayed_work_sync(&ip_block->adev->jpeg.idle_work);
> +
> + return 0;
> +}
> +
> +static void amdgpu_jpeg_cancel_idle_work(struct amdgpu_device *adev) {
> + /* The reset mustn't wait for the idle work, which waits for the reset
> */
> + if (amdgpu_in_reset(adev))
> + cancel_delayed_work(&adev->jpeg.idle_work);
> + else
> + cancel_delayed_work_sync(&adev->jpeg.idle_work);
> +}
> +
> int amdgpu_jpeg_suspend(struct amdgpu_device *adev) {
> - cancel_delayed_work_sync(&adev->jpeg.idle_work);
> + amdgpu_jpeg_cancel_idle_work(adev);
>
> return 0;
> }
> @@ -114,6 +135,9 @@ static void amdgpu_jpeg_idle_work_handler(struct
> work_struct *work)
> unsigned int fences = 0;
> unsigned int i, j;
>
> + /* Nothing holding the reset semaphore waits for this work */
> + down_read(&adev->reset_domain->sem);
> +
> for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
> if (adev->jpeg.harvest_config & (1U << i))
> continue;
> @@ -129,6 +153,8 @@ static void amdgpu_jpeg_idle_work_handler(struct
> work_struct *work)
> mutex_unlock(&adev->jpeg.jpeg_pg_lock);
> } else
> schedule_delayed_work(&adev->jpeg.idle_work,
> JPEG_IDLE_TIMEOUT);
> +
> + up_read(&adev->reset_domain->sem);
> }
>
> void amdgpu_jpeg_ring_begin_use(struct amdgpu_ring *ring) @@ -136,7 +162,7
> @@ void amdgpu_jpeg_ring_begin_use(struct amdgpu_ring *ring)
> struct amdgpu_device *adev = ring->adev;
>
> if (!atomic_fetch_inc(&adev->jpeg.total_submission_cnt))
> - cancel_delayed_work_sync(&adev->jpeg.idle_work);
> + amdgpu_jpeg_cancel_idle_work(adev);
>
> mutex_lock(&adev->jpeg.jpeg_pg_lock);
> amdgpu_device_ip_set_powergating_state(adev,
> AMD_IP_BLOCK_TYPE_JPEG, diff --git
> a/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.h
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.h
> index 05d58e6bbfab..a473becb5def 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.h
> @@ -156,6 +156,7 @@ struct amdgpu_jpeg {
>
> int amdgpu_jpeg_sw_init(struct amdgpu_device *adev); int
> amdgpu_jpeg_sw_fini(struct amdgpu_device *adev);
> +int amdgpu_jpeg_early_fini(struct amdgpu_ip_block *ip_block);
> int amdgpu_jpeg_suspend(struct amdgpu_device *adev); int
> amdgpu_jpeg_resume(struct amdgpu_device *adev);
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
> index 34e1242d66ea..6c12d8aa3c76 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
> @@ -299,6 +299,26 @@ void amdgpu_vcn_sw_fini(struct amdgpu_device *adev,
> int i)
> mutex_destroy(&adev->vcn.inst[i].vcn1_jpeg1_workaround);
> }
>
> +int amdgpu_vcn_early_fini(struct amdgpu_ip_block *ip_block) {
> + struct amdgpu_device *adev = ip_block->adev;
> + int i;
> +
> + /* Called on teardown even if sw_init never ran */
> + if (!ip_block->status.sw)
> + return 0;
> +
> + /* hw_fini may not wait while a peer in the reset domain resets */
> + for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> + if (adev->vcn.harvest_config & (1 << i))
> + continue;
> +
> + cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work);
> + }
> +
> + return 0;
> +}
> +
> bool amdgpu_vcn_is_disabled_vcn(struct amdgpu_device *adev, enum
> vcn_ring_type type, uint32_t vcn_instance) {
> bool ret = false;
> @@ -459,6 +479,15 @@ void amdgpu_vcn_put_profile(struct amdgpu_device
> *adev)
> mutex_unlock(&adev->vcn.workload_profile_mutex);
> }
>
> +void amdgpu_vcn_cancel_idle_work(struct amdgpu_vcn_inst *vcn_inst) {
> + /* The reset mustn't wait for the idle work, which waits for the reset
> */
> + if (amdgpu_in_reset(vcn_inst->adev))
> + cancel_delayed_work(&vcn_inst->idle_work);
> + else
> + cancel_delayed_work_sync(&vcn_inst->idle_work);
> +}
> +
> static void amdgpu_vcn_idle_work_handler(struct work_struct *work) {
> struct amdgpu_vcn_inst *vcn_inst =
> @@ -470,6 +499,9 @@ static void amdgpu_vcn_idle_work_handler(struct
> work_struct *work)
> if (adev->vcn.harvest_config & (1 << i))
> return;
>
> + /* Nothing holding the reset semaphore waits for this work */
> + down_read(&adev->reset_domain->sem);
> +
> for (j = 0; j < adev->vcn.inst[i].num_enc_rings; ++j)
> fence[i] += amdgpu_fence_count_emitted(&vcn_inst->ring_enc[j]);
>
> @@ -499,6 +531,8 @@ static void amdgpu_vcn_idle_work_handler(struct
> work_struct *work)
> } else {
> schedule_delayed_work(&vcn_inst->idle_work,
> VCN_IDLE_TIMEOUT);
> }
> +
> + up_read(&adev->reset_domain->sem);
> }
>
> void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring) @@ -507,7 +541,7
> @@ void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring)
> struct amdgpu_vcn_inst *vcn_inst = &adev->vcn.inst[ring->me];
>
> if (!atomic_fetch_inc(&vcn_inst->total_submission_cnt))
> - cancel_delayed_work_sync(&vcn_inst->idle_work);
> + amdgpu_vcn_cancel_idle_work(vcn_inst);
>
> mutex_lock(&vcn_inst->vcn_pg_lock);
> vcn_inst->set_pg_state(vcn_inst, AMD_PG_STATE_UNGATE); diff --git
> a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
> index bea95307fd42..509c83799a8a 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
> @@ -522,10 +522,12 @@ enum vcn_ring_type { int amdgpu_vcn_early_init(struct
> amdgpu_device *adev, int i); int amdgpu_vcn_sw_init(struct amdgpu_device
> *adev,
> int i); void amdgpu_vcn_sw_fini(struct amdgpu_device *adev, int i);
> +int amdgpu_vcn_early_fini(struct amdgpu_ip_block *ip_block);
> int amdgpu_vcn_suspend(struct amdgpu_device *adev, int i); int
> amdgpu_vcn_resume(struct amdgpu_device *adev, int i); void
> amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring); void
> amdgpu_vcn_ring_end_use(struct amdgpu_ring *ring);
> +void amdgpu_vcn_cancel_idle_work(struct amdgpu_vcn_inst *vcn_inst);
>
> bool amdgpu_vcn_is_disabled_vcn(struct amdgpu_device *adev,
> enum vcn_ring_type type, uint32_t
> vcn_instance); diff -
> -git a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c
> b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c
> index f03c1a37c8dd..1b498190954d 100644
> --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c
> @@ -166,7 +166,7 @@ static int jpeg_v2_0_hw_init(struct amdgpu_ip_block
> *ip_block)
>
> r = amdgpu_ring_test_helper(ring);
> if (r)
> - cancel_delayed_work_sync(&adev->jpeg.idle_work);
> + amdgpu_jpeg_suspend(adev);
> return r;
> }
>
> @@ -181,7 +181,7 @@ static int jpeg_v2_0_hw_fini(struct amdgpu_ip_block
> *ip_block) {
> struct amdgpu_device *adev = ip_block->adev;
>
> - cancel_delayed_work_sync(&adev->jpeg.idle_work);
> + amdgpu_jpeg_suspend(adev);
>
> if (adev->jpeg.cur_state != AMD_PG_STATE_GATE &&
> RREG32_SOC15(JPEG, 0, mmUVD_JRBC_STATUS)) @@ -792,6
> +792,7 @@ static const struct amd_ip_funcs jpeg_v2_0_ip_funcs = {
> .early_init = jpeg_v2_0_early_init,
> .sw_init = jpeg_v2_0_sw_init,
> .sw_fini = jpeg_v2_0_sw_fini,
> + .early_fini = amdgpu_jpeg_early_fini,
> .hw_init = jpeg_v2_0_hw_init,
> .hw_fini = jpeg_v2_0_hw_fini,
> .suspend = jpeg_v2_0_suspend,
> diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c
> b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c
> index 46293664fd28..80c79aeeb410 100644
> --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c
> +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c
> @@ -227,7 +227,7 @@ static int jpeg_v2_5_hw_init(struct amdgpu_ip_block
> *ip_block)
> return 0;
>
> error:
> - cancel_delayed_work_sync(&adev->jpeg.idle_work);
> + amdgpu_jpeg_suspend(adev);
> return r;
> }
>
> @@ -243,7 +243,7 @@ static int jpeg_v2_5_hw_fini(struct amdgpu_ip_block
> *ip_block)
> struct amdgpu_device *adev = ip_block->adev;
> int i;
>
> - cancel_delayed_work_sync(&adev->jpeg.idle_work);
> + amdgpu_jpeg_suspend(adev);
>
> for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
> if (adev->jpeg.harvest_config & (1 << i)) @@ -665,6 +665,7 @@
> static const struct amd_ip_funcs jpeg_v2_5_ip_funcs = {
> .early_init = jpeg_v2_5_early_init,
> .sw_init = jpeg_v2_5_sw_init,
> .sw_fini = jpeg_v2_5_sw_fini,
> + .early_fini = amdgpu_jpeg_early_fini,
> .hw_init = jpeg_v2_5_hw_init,
> .hw_fini = jpeg_v2_5_hw_fini,
> .suspend = jpeg_v2_5_suspend,
> @@ -681,6 +682,7 @@ static const struct amd_ip_funcs jpeg_v2_6_ip_funcs = {
> .early_init = jpeg_v2_5_early_init,
> .sw_init = jpeg_v2_5_sw_init,
> .sw_fini = jpeg_v2_5_sw_fini,
> + .early_fini = amdgpu_jpeg_early_fini,
> .hw_init = jpeg_v2_5_hw_init,
> .hw_fini = jpeg_v2_5_hw_fini,
> .suspend = jpeg_v2_5_suspend,
> diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c
> b/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c
> index 361d0f4b4bc7..3411a32d00ee 100644
> --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c
> @@ -181,7 +181,7 @@ static int jpeg_v3_0_hw_init(struct amdgpu_ip_block
> *ip_block)
>
> r = amdgpu_ring_test_helper(ring);
> if (r)
> - cancel_delayed_work_sync(&adev->jpeg.idle_work);
> + amdgpu_jpeg_suspend(adev);
> return r;
> }
>
> @@ -196,7 +196,7 @@ static int jpeg_v3_0_hw_fini(struct amdgpu_ip_block
> *ip_block) {
> struct amdgpu_device *adev = ip_block->adev;
>
> - cancel_delayed_work_sync(&adev->jpeg.idle_work);
> + amdgpu_jpeg_suspend(adev);
>
> if (adev->jpeg.cur_state != AMD_PG_STATE_GATE &&
> RREG32_SOC15(JPEG, 0, mmUVD_JRBC_STATUS)) @@ -564,6
> +564,7 @@ static const struct amd_ip_funcs jpeg_v3_0_ip_funcs = {
> .early_init = jpeg_v3_0_early_init,
> .sw_init = jpeg_v3_0_sw_init,
> .sw_fini = jpeg_v3_0_sw_fini,
> + .early_fini = amdgpu_jpeg_early_fini,
> .hw_init = jpeg_v3_0_hw_init,
> .hw_fini = jpeg_v3_0_hw_fini,
> .suspend = jpeg_v3_0_suspend,
> diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c
> b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c
> index 4e8eed2b62db..4a916cc2bd01 100644
> --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c
> @@ -210,7 +210,7 @@ static int jpeg_v4_0_hw_init(struct amdgpu_ip_block
> *ip_block)
> return 0;
>
> error:
> - cancel_delayed_work_sync(&adev->jpeg.idle_work);
> + amdgpu_jpeg_suspend(adev);
> return r;
> }
>
> @@ -225,7 +225,7 @@ static int jpeg_v4_0_hw_fini(struct amdgpu_ip_block
> *ip_block) {
> struct amdgpu_device *adev = ip_block->adev;
>
> - cancel_delayed_work_sync(&adev->jpeg.idle_work);
> + amdgpu_jpeg_suspend(adev);
> if (!amdgpu_sriov_vf(adev)) {
> if (adev->jpeg.cur_state != AMD_PG_STATE_GATE &&
> RREG32_SOC15(JPEG, 0, regUVD_JRBC_STATUS)) @@ -
> 748,6 +748,7 @@ static const struct amd_ip_funcs jpeg_v4_0_ip_funcs = {
> .early_init = jpeg_v4_0_early_init,
> .sw_init = jpeg_v4_0_sw_init,
> .sw_fini = jpeg_v4_0_sw_fini,
> + .early_fini = amdgpu_jpeg_early_fini,
> .hw_init = jpeg_v4_0_hw_init,
> .hw_fini = jpeg_v4_0_hw_fini,
> .suspend = jpeg_v4_0_suspend,
> 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 9f298c4ea8ff..6b62731495ab 100644
> --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c
> +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c
> @@ -443,7 +443,7 @@ static int jpeg_v4_0_3_hw_init(struct amdgpu_ip_block
> *ip_block)
> return 0;
>
> error:
> - cancel_delayed_work_sync(&adev->jpeg.idle_work);
> + amdgpu_jpeg_suspend(adev);
> return r;
> }
>
> @@ -459,7 +459,7 @@ static int jpeg_v4_0_3_hw_fini(struct amdgpu_ip_block
> *ip_block)
> struct amdgpu_device *adev = ip_block->adev;
> int ret = 0;
>
> - cancel_delayed_work_sync(&adev->jpeg.idle_work);
> + amdgpu_jpeg_suspend(adev);
>
> if (!amdgpu_sriov_vf(adev)) {
> if (adev->jpeg.cur_state != AMD_PG_STATE_GATE) @@ -1227,6
> +1227,7 @@ static const struct amd_ip_funcs jpeg_v4_0_3_ip_funcs = {
> .early_init = jpeg_v4_0_3_early_init,
> .sw_init = jpeg_v4_0_3_sw_init,
> .sw_fini = jpeg_v4_0_3_sw_fini,
> + .early_fini = amdgpu_jpeg_early_fini,
> .hw_init = jpeg_v4_0_3_hw_init,
> .hw_fini = jpeg_v4_0_3_hw_fini,
> .suspend = jpeg_v4_0_3_suspend,
> diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_5.c
> b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_5.c
> index a1496412810c..109237055eba 100644
> --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_5.c
> +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_5.c
> @@ -238,7 +238,7 @@ static int jpeg_v4_0_5_hw_init(struct amdgpu_ip_block
> *ip_block)
> return 0;
>
> error:
> - cancel_delayed_work_sync(&adev->jpeg.idle_work);
> + amdgpu_jpeg_suspend(adev);
> return r;
> }
>
> @@ -254,7 +254,7 @@ static int jpeg_v4_0_5_hw_fini(struct amdgpu_ip_block
> *ip_block)
> struct amdgpu_device *adev = ip_block->adev;
> int i;
>
> - cancel_delayed_work_sync(&adev->jpeg.idle_work);
> + amdgpu_jpeg_suspend(adev);
>
> for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
> if (adev->jpeg.harvest_config & (1 << i)) @@ -807,6 +807,7 @@
> static const struct amd_ip_funcs jpeg_v4_0_5_ip_funcs = {
> .early_init = jpeg_v4_0_5_early_init,
> .sw_init = jpeg_v4_0_5_sw_init,
> .sw_fini = jpeg_v4_0_5_sw_fini,
> + .early_fini = amdgpu_jpeg_early_fini,
> .hw_init = jpeg_v4_0_5_hw_init,
> .hw_fini = jpeg_v4_0_5_hw_fini,
> .suspend = jpeg_v4_0_5_suspend,
> diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c
> b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c
> index 1a4594d5d952..c0bacaafdf7f 100644
> --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c
> @@ -178,7 +178,7 @@ static int jpeg_v5_0_0_hw_init(struct amdgpu_ip_block
> *ip_block)
> return 0;
>
> error:
> - cancel_delayed_work_sync(&adev->jpeg.idle_work);
> + amdgpu_jpeg_suspend(adev);
> return r;
> }
>
> @@ -193,7 +193,7 @@ static int jpeg_v5_0_0_hw_fini(struct amdgpu_ip_block
> *ip_block) {
> struct amdgpu_device *adev = ip_block->adev;
>
> - cancel_delayed_work_sync(&adev->jpeg.idle_work);
> + amdgpu_jpeg_suspend(adev);
>
> if (adev->jpeg.cur_state != AMD_PG_STATE_GATE &&
> RREG32_SOC15(JPEG, 0, regUVD_JRBC_STATUS)) @@ -683,6
> +683,7 @@ static const struct amd_ip_funcs jpeg_v5_0_0_ip_funcs = {
> .early_init = jpeg_v5_0_0_early_init,
> .sw_init = jpeg_v5_0_0_sw_init,
> .sw_fini = jpeg_v5_0_0_sw_fini,
> + .early_fini = amdgpu_jpeg_early_fini,
> .hw_init = jpeg_v5_0_0_hw_init,
> .hw_fini = jpeg_v5_0_0_hw_fini,
> .suspend = jpeg_v5_0_0_suspend,
> 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 efdc537ec81e..9ae23235d16c 100644
> --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c
> +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c
> @@ -314,7 +314,7 @@ static int jpeg_v5_0_1_hw_init(struct amdgpu_ip_block
> *ip_block)
> return 0;
>
> error:
> - cancel_delayed_work_sync(&adev->jpeg.idle_work);
> + amdgpu_jpeg_suspend(adev);
> return r;
> }
>
> @@ -330,7 +330,7 @@ static int jpeg_v5_0_1_hw_fini(struct amdgpu_ip_block
> *ip_block)
> struct amdgpu_device *adev = ip_block->adev;
> int ret = 0;
>
> - cancel_delayed_work_sync(&adev->jpeg.idle_work);
> + amdgpu_jpeg_suspend(adev);
>
> if (!amdgpu_sriov_vf(adev)) {
> if (adev->jpeg.cur_state != AMD_PG_STATE_GATE) @@ -887,6
> +887,7 @@ static const struct amd_ip_funcs jpeg_v5_0_1_ip_funcs = {
> .late_init = NULL,
> .sw_init = jpeg_v5_0_1_sw_init,
> .sw_fini = jpeg_v5_0_1_sw_fini,
> + .early_fini = amdgpu_jpeg_early_fini,
> .hw_init = jpeg_v5_0_1_hw_init,
> .hw_fini = jpeg_v5_0_1_hw_fini,
> .suspend = jpeg_v5_0_1_suspend,
> diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_2.c
> b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_2.c
> index eb3dc9558e0d..0fc58d25abe1 100644
> --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_2.c
> +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_2.c
> @@ -287,7 +287,7 @@ static int jpeg_v5_0_2_hw_init(struct amdgpu_ip_block
> *ip_block)
> return 0;
>
> error:
> - cancel_delayed_work_sync(&adev->jpeg.idle_work);
> + amdgpu_jpeg_suspend(adev);
> return r;
> }
>
> @@ -303,7 +303,7 @@ static int jpeg_v5_0_2_hw_fini(struct amdgpu_ip_block
> *ip_block)
> struct amdgpu_device *adev = ip_block->adev;
> int ret = 0;
>
> - cancel_delayed_work_sync(&adev->jpeg.idle_work);
> + amdgpu_jpeg_suspend(adev);
>
> if (!amdgpu_sriov_vf(adev)) {
> if (adev->jpeg.cur_state != AMD_PG_STATE_GATE) @@ -871,6
> +871,7 @@ static const struct amd_ip_funcs jpeg_v5_0_2_ip_funcs = {
> .late_init = NULL,
> .sw_init = jpeg_v5_0_2_sw_init,
> .sw_fini = jpeg_v5_0_2_sw_fini,
> + .early_fini = amdgpu_jpeg_early_fini,
> .hw_init = jpeg_v5_0_2_hw_init,
> .hw_fini = jpeg_v5_0_2_hw_fini,
> .suspend = jpeg_v5_0_2_suspend,
> diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_3_0.c
> b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_3_0.c
> index 0cbb2b8a7e78..d5bc6820ad8d 100644
> --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_3_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_3_0.c
> @@ -161,7 +161,7 @@ static int jpeg_v5_3_0_hw_init(struct amdgpu_ip_block
> *ip_block)
> return 0;
>
> error:
> - cancel_delayed_work_sync(&adev->jpeg.idle_work);
> + amdgpu_jpeg_suspend(adev);
> return r;
> }
>
> @@ -176,7 +176,7 @@ static int jpeg_v5_3_0_hw_fini(struct amdgpu_ip_block
> *ip_block) {
> struct amdgpu_device *adev = ip_block->adev;
>
> - cancel_delayed_work_sync(&adev->jpeg.idle_work);
> + amdgpu_jpeg_suspend(adev);
>
> if (adev->jpeg.cur_state != AMD_PG_STATE_GATE &&
> RREG32_SOC15(JPEG, 0, regUVD_JRBC0_UVD_JRBC_STATUS))
> @@ -671,6 +671,7 @@ static const struct amd_ip_funcs jpeg_v5_3_0_ip_funcs = {
> .early_init = jpeg_v5_3_0_early_init,
> .sw_init = jpeg_v5_3_0_sw_init,
> .sw_fini = jpeg_v5_3_0_sw_fini,
> + .early_fini = amdgpu_jpeg_early_fini,
> .hw_init = jpeg_v5_3_0_hw_init,
> .hw_fini = jpeg_v5_3_0_hw_fini,
> .suspend = jpeg_v5_3_0_suspend,
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
> b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
> index b3e63d6e79a8..897310d04f83 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
> @@ -150,8 +150,8 @@ static int vcn_v1_0_sw_init(struct amdgpu_ip_block
> *ip_block)
> if (r)
> return r;
>
> - /* Override the work func */
> - adev->vcn.inst[0].idle_work.work.func = vcn_v1_0_idle_work_handler;
> + /* Own lockdep class, this work is still cancelled synchronously */
> + INIT_DELAYED_WORK(&adev->vcn.inst[0].idle_work,
> +vcn_v1_0_idle_work_handler);
>
> amdgpu_vcn_setup_ucode(adev, 0);
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
> b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
> index 12ac20484396..706089744803 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
> @@ -310,7 +310,7 @@ static int vcn_v2_0_hw_init(struct amdgpu_ip_block
> *ip_block)
> return 0;
>
> error:
> - cancel_delayed_work_sync(&adev->vcn.inst->idle_work);
> + amdgpu_vcn_cancel_idle_work(adev->vcn.inst);
> return r;
> }
>
> @@ -326,7 +326,7 @@ static int vcn_v2_0_hw_fini(struct amdgpu_ip_block
> *ip_block)
> struct amdgpu_device *adev = ip_block->adev;
> struct amdgpu_vcn_inst *vinst = adev->vcn.inst;
>
> - cancel_delayed_work_sync(&vinst->idle_work);
> + amdgpu_vcn_cancel_idle_work(vinst);
>
> if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
> (vinst->cur_state != AMD_PG_STATE_GATE && @@ -2103,6 +2103,7
> @@ static const struct amd_ip_funcs vcn_v2_0_ip_funcs = {
> .early_init = vcn_v2_0_early_init,
> .sw_init = vcn_v2_0_sw_init,
> .sw_fini = vcn_v2_0_sw_fini,
> + .early_fini = amdgpu_vcn_early_fini,
> .hw_init = vcn_v2_0_hw_init,
> .hw_fini = vcn_v2_0_hw_fini,
> .suspend = vcn_v2_0_suspend,
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
> b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
> index 2b2abe689508..c3f2265f50fc 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
> @@ -304,8 +304,8 @@ static int vcn_v2_5_sw_init(struct amdgpu_ip_block
> *ip_block)
> if (r)
> return r;
>
> - /* Override the work func */
> - adev->vcn.inst[j].idle_work.work.func =
> vcn_v2_5_idle_work_handler;
> + /* Own lockdep class, this work is still cancelled
> synchronously */
> + INIT_DELAYED_WORK(&adev->vcn.inst[j].idle_work,
> +vcn_v2_5_idle_work_handler);
>
> amdgpu_vcn_setup_ucode(adev, j);
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
> b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
> index 6543f21daa1e..8f256d962ce5 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
> @@ -433,7 +433,7 @@ static int vcn_v3_0_hw_init(struct amdgpu_ip_block
> *ip_block)
> error:
> while (i >= 0) {
> if (!(adev->vcn.harvest_config & (1 << i)))
> - cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work);
> + amdgpu_vcn_cancel_idle_work(&adev->vcn.inst[i]);
> i--;
> }
> return r;
> @@ -457,7 +457,7 @@ static int vcn_v3_0_hw_fini(struct amdgpu_ip_block
> *ip_block)
> if (adev->vcn.harvest_config & (1 << i))
> continue;
>
> - cancel_delayed_work_sync(&vinst->idle_work);
> + amdgpu_vcn_cancel_idle_work(vinst);
>
> if (!amdgpu_sriov_vf(adev)) {
> if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
> @@ -2366,6 +2366,7 @@ static const struct amd_ip_funcs vcn_v3_0_ip_funcs = {
> .early_init = vcn_v3_0_early_init,
> .sw_init = vcn_v3_0_sw_init,
> .sw_fini = vcn_v3_0_sw_fini,
> + .early_fini = amdgpu_vcn_early_fini,
> .hw_init = vcn_v3_0_hw_init,
> .hw_fini = vcn_v3_0_hw_fini,
> .suspend = vcn_v3_0_suspend,
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
> b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
> index 8b5646297c2e..b68746b37a15 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
> @@ -358,7 +358,7 @@ static int vcn_v4_0_hw_init(struct amdgpu_ip_block
> *ip_block)
> error:
> while (i >= 0) {
> if (!(adev->vcn.harvest_config & (1 << i)))
> - cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work);
> + amdgpu_vcn_cancel_idle_work(&adev->vcn.inst[i]);
> i--;
> }
> return r;
> @@ -382,7 +382,7 @@ static int vcn_v4_0_hw_fini(struct amdgpu_ip_block
> *ip_block)
> if (adev->vcn.harvest_config & (1 << i))
> continue;
>
> - cancel_delayed_work_sync(&vinst->idle_work);
> + amdgpu_vcn_cancel_idle_work(vinst);
>
> if (!amdgpu_sriov_vf(adev)) {
> if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
> @@ -2287,6 +2287,7 @@ static const struct amd_ip_funcs vcn_v4_0_ip_funcs = {
> .early_init = vcn_v4_0_early_init,
> .sw_init = vcn_v4_0_sw_init,
> .sw_fini = vcn_v4_0_sw_fini,
> + .early_fini = amdgpu_vcn_early_fini,
> .hw_init = vcn_v4_0_hw_init,
> .hw_fini = vcn_v4_0_hw_fini,
> .suspend = vcn_v4_0_suspend,
> 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 0c58ca25d7b5..a1bfcece38fb 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
> @@ -404,7 +404,7 @@ static int vcn_v4_0_3_hw_init(struct amdgpu_ip_block
> *ip_block)
> error:
> while (i >= 0) {
> if (!(adev->vcn.harvest_config & (1 << i)))
> - cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work);
> + amdgpu_vcn_cancel_idle_work(&adev->vcn.inst[i]);
> i--;
> }
> return r;
> @@ -425,7 +425,7 @@ static int vcn_v4_0_3_hw_fini(struct amdgpu_ip_block
> *ip_block)
> for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
>
> - cancel_delayed_work_sync(&vinst->idle_work);
> + amdgpu_vcn_cancel_idle_work(vinst);
>
> if (vinst->cur_state != AMD_PG_STATE_GATE)
> vinst->set_pg_state(vinst, AMD_PG_STATE_GATE); @@ -
> 2035,6 +2035,7 @@ static const struct amd_ip_funcs vcn_v4_0_3_ip_funcs = {
> .late_init = vcn_v4_0_3_late_init,
> .sw_init = vcn_v4_0_3_sw_init,
> .sw_fini = vcn_v4_0_3_sw_fini,
> + .early_fini = amdgpu_vcn_early_fini,
> .hw_init = vcn_v4_0_3_hw_init,
> .hw_fini = vcn_v4_0_3_hw_fini,
> .suspend = vcn_v4_0_3_suspend,
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
> b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
> index a6eaa57ec2ee..fb5336f46ac9 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
> @@ -311,7 +311,7 @@ static int vcn_v4_0_5_hw_init(struct amdgpu_ip_block
> *ip_block)
> error:
> while (i >= 0) {
> if (!(adev->vcn.harvest_config & (1 << i)))
> - cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work);
> + amdgpu_vcn_cancel_idle_work(&adev->vcn.inst[i]);
> i--;
> }
> return r;
> @@ -335,7 +335,7 @@ static int vcn_v4_0_5_hw_fini(struct amdgpu_ip_block
> *ip_block)
> if (adev->vcn.harvest_config & (1 << i))
> continue;
>
> - cancel_delayed_work_sync(&vinst->idle_work);
> + amdgpu_vcn_cancel_idle_work(vinst);
>
> if (!amdgpu_sriov_vf(adev)) {
> if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
> @@ -1690,6 +1690,7 @@ static const struct amd_ip_funcs vcn_v4_0_5_ip_funcs =
> {
> .early_init = vcn_v4_0_5_early_init,
> .sw_init = vcn_v4_0_5_sw_init,
> .sw_fini = vcn_v4_0_5_sw_fini,
> + .early_fini = amdgpu_vcn_early_fini,
> .hw_init = vcn_v4_0_5_hw_init,
> .hw_fini = vcn_v4_0_5_hw_fini,
> .suspend = vcn_v4_0_5_suspend,
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
> b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
> index 055729a42094..b18c61e6d099 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
> @@ -275,7 +275,7 @@ static int vcn_v5_0_0_hw_init(struct amdgpu_ip_block
> *ip_block)
> error:
> while (i >= 0) {
> if (!(adev->vcn.harvest_config & (1 << i)))
> - cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work);
> + amdgpu_vcn_cancel_idle_work(&adev->vcn.inst[i]);
> i--;
> }
> return r;
> @@ -299,7 +299,7 @@ static int vcn_v5_0_0_hw_fini(struct amdgpu_ip_block
> *ip_block)
> if (adev->vcn.harvest_config & (1 << i))
> continue;
>
> - cancel_delayed_work_sync(&vinst->idle_work);
> + amdgpu_vcn_cancel_idle_work(vinst);
>
> if (!amdgpu_sriov_vf(adev)) {
> if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
> @@ -1476,6 +1476,7 @@ static const struct amd_ip_funcs vcn_v5_0_0_ip_funcs =
> {
> .early_init = vcn_v5_0_0_early_init,
> .sw_init = vcn_v5_0_0_sw_init,
> .sw_fini = vcn_v5_0_0_sw_fini,
> + .early_fini = amdgpu_vcn_early_fini,
> .hw_init = vcn_v5_0_0_hw_init,
> .hw_fini = vcn_v5_0_0_hw_fini,
> .suspend = vcn_v5_0_0_suspend,
> 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 55a4b2f9463f..a5d3ee06fced 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
> @@ -351,7 +351,7 @@ static int vcn_v5_0_1_hw_init(struct amdgpu_ip_block
> *ip_block)
> error:
> while (i >= 0) {
> if (!(adev->vcn.harvest_config & (1 << i)))
> - cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work);
> + amdgpu_vcn_cancel_idle_work(&adev->vcn.inst[i]);
> i--;
> }
> return r;
> @@ -372,7 +372,7 @@ static int vcn_v5_0_1_hw_fini(struct amdgpu_ip_block
> *ip_block)
> for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
>
> - cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work);
> + amdgpu_vcn_cancel_idle_work(&adev->vcn.inst[i]);
> if (vinst->cur_state != AMD_PG_STATE_GATE)
> vinst->set_pg_state(vinst, AMD_PG_STATE_GATE);
> }
> @@ -1660,6 +1660,7 @@ static const struct amd_ip_funcs vcn_v5_0_1_ip_funcs =
> {
> .late_init = vcn_v5_0_1_late_init,
> .sw_init = vcn_v5_0_1_sw_init,
> .sw_fini = vcn_v5_0_1_sw_fini,
> + .early_fini = amdgpu_vcn_early_fini,
> .hw_init = vcn_v5_0_1_hw_init,
> .hw_fini = vcn_v5_0_1_hw_fini,
> .suspend = vcn_v5_0_1_suspend,
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_2.c
> b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_2.c
> index ea6cdbcb6352..1b7897bb9953 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_2.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_2.c
> @@ -266,7 +266,7 @@ static int vcn_v5_0_2_hw_init(struct amdgpu_ip_block
> *ip_block)
> error:
> while (i >= 0) {
> if (!(adev->vcn.harvest_config & (1 << i)))
> - cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work);
> + amdgpu_vcn_cancel_idle_work(&adev->vcn.inst[i]);
> i--;
> }
> return r;
> @@ -287,7 +287,7 @@ static int vcn_v5_0_2_hw_fini(struct amdgpu_ip_block
> *ip_block)
> for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
>
> - cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work);
> + amdgpu_vcn_cancel_idle_work(&adev->vcn.inst[i]);
> if (vinst->cur_state != AMD_PG_STATE_GATE)
> vinst->set_pg_state(vinst, AMD_PG_STATE_GATE);
> }
> @@ -1451,6 +1451,7 @@ static const struct amd_ip_funcs vcn_v5_0_2_ip_funcs =
> {
> .late_init = NULL,
> .sw_init = vcn_v5_0_2_sw_init,
> .sw_fini = vcn_v5_0_2_sw_fini,
> + .early_fini = amdgpu_vcn_early_fini,
> .hw_init = vcn_v5_0_2_hw_init,
> .hw_fini = vcn_v5_0_2_hw_fini,
> .suspend = vcn_v5_0_2_suspend,
> --
> 2.34.1