diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_ih.c')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_ih.c | 55 | 
1 files changed, 25 insertions, 30 deletions
| diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.c index 0c7963dfacad..3df146579ad9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.c @@ -164,52 +164,32 @@ void amdgpu_ih_ring_write(struct amdgpu_ih_ring *ih, const uint32_t *iv,  	}  } -/* Waiter helper that checks current rptr matches or passes checkpoint wptr */ -static bool amdgpu_ih_has_checkpoint_processed(struct amdgpu_device *adev, -					struct amdgpu_ih_ring *ih, -					uint32_t checkpoint_wptr, -					uint32_t *prev_rptr) -{ -	uint32_t cur_rptr = ih->rptr | (*prev_rptr & ~ih->ptr_mask); - -	/* rptr has wrapped. */ -	if (cur_rptr < *prev_rptr) -		cur_rptr += ih->ptr_mask + 1; -	*prev_rptr = cur_rptr; - -	/* check ring is empty to workaround missing wptr overflow flag */ -	return cur_rptr >= checkpoint_wptr || -	       (cur_rptr & ih->ptr_mask) == amdgpu_ih_get_wptr(adev, ih); -} -  /** - * amdgpu_ih_wait_on_checkpoint_process - wait to process IVs up to checkpoint + * amdgpu_ih_wait_on_checkpoint_process_ts - wait to process IVs up to checkpoint   *   * @adev: amdgpu_device pointer   * @ih: ih ring to process   *   * Used to ensure ring has processed IVs up to the checkpoint write pointer.   */ -int amdgpu_ih_wait_on_checkpoint_process(struct amdgpu_device *adev, +int amdgpu_ih_wait_on_checkpoint_process_ts(struct amdgpu_device *adev,  					struct amdgpu_ih_ring *ih)  { -	uint32_t checkpoint_wptr, rptr; +	uint32_t checkpoint_wptr; +	uint64_t checkpoint_ts; +	long timeout = HZ;  	if (!ih->enabled || adev->shutdown)  		return -ENODEV;  	checkpoint_wptr = amdgpu_ih_get_wptr(adev, ih); -	/* Order wptr with rptr. */ +	/* Order wptr with ring data. */  	rmb(); -	rptr = READ_ONCE(ih->rptr); - -	/* wptr has wrapped. */ -	if (rptr > checkpoint_wptr) -		checkpoint_wptr += ih->ptr_mask + 1; +	checkpoint_ts = amdgpu_ih_decode_iv_ts(adev, ih, checkpoint_wptr, -1); -	return wait_event_interruptible(ih->wait_process, -				amdgpu_ih_has_checkpoint_processed(adev, ih, -						checkpoint_wptr, &rptr)); +	return wait_event_interruptible_timeout(ih->wait_process, +		    amdgpu_ih_ts_after(checkpoint_ts, ih->processed_timestamp) || +		    ih->rptr == amdgpu_ih_get_wptr(adev, ih), timeout);  }  /** @@ -299,3 +279,18 @@ void amdgpu_ih_decode_iv_helper(struct amdgpu_device *adev,  	/* wptr/rptr are in bytes! */  	ih->rptr += 32;  } + +uint64_t amdgpu_ih_decode_iv_ts_helper(struct amdgpu_ih_ring *ih, u32 rptr, +				       signed int offset) +{ +	uint32_t iv_size = 32; +	uint32_t ring_index; +	uint32_t dw1, dw2; + +	rptr += iv_size * offset; +	ring_index = (rptr & ih->ptr_mask) >> 2; + +	dw1 = le32_to_cpu(ih->ring[ring_index + 1]); +	dw2 = le32_to_cpu(ih->ring[ring_index + 2]); +	return dw1 | ((u64)(dw2 & 0xffff) << 32); +} |