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

Reply via email to