Protect media idle workers with a reset-domain read trylock. On contention, requeue the idle timeout and return without hardware access. Keep the ordinary end-use scheduling event, including from reset-time ring tests, so otherwise idle engines eventually power down and VCN drops its profile.
A blocking read acquisition would deadlock with reset-time synchronous cancellation of these workers, so the workers must only try the lock. Signed-off-by: Prike Liang <[email protected]> --- drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c | 7 +++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c index 9887a4f99aed..7b10260ad0d4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c @@ -114,6 +114,12 @@ static void amdgpu_jpeg_idle_work_handler(struct work_struct *work) unsigned int fences = 0; unsigned int i, j; + /* Reset may cancel this worker synchronously while holding the writer. */ + if (!down_read_trylock(&adev->reset_domain->sem)) { + schedule_delayed_work(&adev->jpeg.idle_work, JPEG_IDLE_TIMEOUT); + return; + } + for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) { if (adev->jpeg.harvest_config & (1U << i)) continue; @@ -129,6 +135,7 @@ 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) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c index 17db7264269e..f851a6ecea1b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c @@ -470,6 +470,12 @@ static void amdgpu_vcn_idle_work_handler(struct work_struct *work) if (adev->vcn.harvest_config & (1 << i)) return; + /* Reset may cancel this worker synchronously while holding the writer. */ + if (!down_read_trylock(&adev->reset_domain->sem)) { + schedule_delayed_work(&vcn_inst->idle_work, VCN_IDLE_TIMEOUT); + return; + } + 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 +505,7 @@ 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) -- 2.34.1
