AMD General
> -----Original Message-----
> From: amd-gfx <[email protected]> On Behalf Of Prike
> Liang
> Sent: Thursday, October 29, 2026 10:48 PM
> 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);
> +
With early_fini(), hw_fini(), suspend() and sw_fini() now all potentially
calling the cancel for the different fini paths, the cancel now happens
multiple times without
explicit conditions to make clear when each call is actually needed.
For example, on the normal unload/teardown path, early_fini() cancels
synchronously, then hw_fini() cancels again (no-op), then sw_fini()
cancels again (no-op). It would be cleaner to add an explicit condition at
each call.
Thanks,
Leo
> + 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