mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 04:34:03 +02:00
drm/amdgpu/vcn: handle pipe reset more gracefully
Save any unprocessed work in the queues using the new ring helper. Reviewed-by: Jesse Zhang <jesse.zhang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
714d354479
commit
659fe71521
|
|
@ -1485,6 +1485,37 @@ int vcn_set_powergating_state(struct amdgpu_ip_block *ip_block,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static struct amdgpu_fence *
|
||||
amdgpu_vcn_ring_reset_begin_helper(struct amdgpu_ring *ring,
|
||||
struct amdgpu_ring *guilty_ring,
|
||||
struct amdgpu_fence *timedout_fence)
|
||||
{
|
||||
struct amdgpu_fence *fence;
|
||||
|
||||
drm_sched_wqueue_stop(&ring->sched);
|
||||
if (ring == guilty_ring)
|
||||
fence = timedout_fence;
|
||||
else
|
||||
fence = amdgpu_ring_find_guilty_fence(ring);
|
||||
amdgpu_ring_reset_helper_begin(ring, fence);
|
||||
|
||||
return fence;
|
||||
}
|
||||
|
||||
static int
|
||||
amdgpu_vcn_ring_reset_end_helper(struct amdgpu_ring *ring,
|
||||
struct amdgpu_fence *fence)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = amdgpu_ring_reset_helper_end(ring, fence);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
drm_sched_wqueue_start(&ring->sched);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_vcn_ring_reset - Reset a VCN ring
|
||||
* @ring: ring to reset
|
||||
|
|
@ -1502,48 +1533,33 @@ int amdgpu_vcn_ring_reset(struct amdgpu_ring *ring,
|
|||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[ring->me];
|
||||
struct amdgpu_fence *dec_fence;
|
||||
struct amdgpu_fence *enc_fence[AMDGPU_VCN_MAX_ENC_RINGS];
|
||||
int r, i;
|
||||
|
||||
if (adev->vcn.inst[ring->me].using_unified_queue)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&vinst->engine_reset_mutex);
|
||||
/* Stop the scheduler's work queue for the dec and enc rings if they are running.
|
||||
* This ensures that no new tasks are submitted to the queues while
|
||||
* the reset is in progress.
|
||||
*/
|
||||
drm_sched_wqueue_stop(&vinst->ring_dec.sched);
|
||||
dec_fence = amdgpu_vcn_ring_reset_begin_helper(&vinst->ring_dec, ring,
|
||||
timedout_fence);
|
||||
for (i = 0; i < vinst->num_enc_rings; i++)
|
||||
drm_sched_wqueue_stop(&vinst->ring_enc[i].sched);
|
||||
enc_fence[i] = amdgpu_vcn_ring_reset_begin_helper(&vinst->ring_enc[i], ring,
|
||||
timedout_fence);
|
||||
|
||||
/* Perform the VCN reset for the specified instance */
|
||||
r = vinst->reset(vinst);
|
||||
if (r)
|
||||
goto unlock;
|
||||
r = amdgpu_ring_test_ring(&vinst->ring_dec);
|
||||
|
||||
r = amdgpu_vcn_ring_reset_end_helper(&vinst->ring_dec, dec_fence);
|
||||
if (r)
|
||||
goto unlock;
|
||||
for (i = 0; i < vinst->num_enc_rings; i++) {
|
||||
r = amdgpu_ring_test_ring(&vinst->ring_enc[i]);
|
||||
r = amdgpu_vcn_ring_reset_end_helper(&vinst->ring_enc[i], enc_fence[i]);
|
||||
if (r)
|
||||
goto unlock;
|
||||
}
|
||||
amdgpu_fence_driver_force_completion(&vinst->ring_dec,
|
||||
(&vinst->ring_dec == ring) ?
|
||||
&timedout_fence->base : NULL);
|
||||
for (i = 0; i < vinst->num_enc_rings; i++)
|
||||
amdgpu_fence_driver_force_completion(&vinst->ring_enc[i],
|
||||
(&vinst->ring_enc[i] == ring) ?
|
||||
&timedout_fence->base : NULL);
|
||||
|
||||
/* Restart the scheduler's work queue for the dec and enc rings
|
||||
* if they were stopped by this function. This allows new tasks
|
||||
* to be submitted to the queues after the reset is complete.
|
||||
*/
|
||||
drm_sched_wqueue_start(&vinst->ring_dec.sched);
|
||||
for (i = 0; i < vinst->num_enc_rings; i++)
|
||||
drm_sched_wqueue_start(&vinst->ring_enc[i].sched);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&vinst->engine_reset_mutex);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user