forked from mirrors/linux
		
	drm/msm: Handle fence rollover
Add some helpers for fence comparision, which handle rollover properly, and stop open coding fence seqno comparisions. Signed-off-by: Rob Clark <robdclark@chromium.org> Reviewed-by: Akhil P Oommen <akhilpo@codeaurora.org> Link: https://lore.kernel.org/r/20211109181117.591148-5-robdclark@gmail.com Signed-off-by: Rob Clark <robdclark@chromium.org>
This commit is contained in:
		
							parent
							
								
									c28e2f2b41
								
							
						
					
					
						commit
						5f3aee4ceb
					
				
					 4 changed files with 17 additions and 5 deletions
				
			
		| 
						 | 
				
			
			@ -967,7 +967,7 @@ static int wait_fence(struct msm_gpu_submitqueue *queue, uint32_t fence_id,
 | 
			
		|||
	struct dma_fence *fence;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	if (fence_id > queue->last_fence) {
 | 
			
		||||
	if (fence_after(fence_id, queue->last_fence)) {
 | 
			
		||||
		DRM_ERROR_RATELIMITED("waiting on invalid fence: %u (of %u)\n",
 | 
			
		||||
				      fence_id, queue->last_fence);
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -60,4 +60,16 @@ void msm_update_fence(struct msm_fence_context *fctx, uint32_t fence);
 | 
			
		|||
 | 
			
		||||
struct dma_fence * msm_fence_alloc(struct msm_fence_context *fctx);
 | 
			
		||||
 | 
			
		||||
static inline bool
 | 
			
		||||
fence_before(uint32_t a, uint32_t b)
 | 
			
		||||
{
 | 
			
		||||
   return (int32_t)(a - b) < 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline bool
 | 
			
		||||
fence_after(uint32_t a, uint32_t b)
 | 
			
		||||
{
 | 
			
		||||
   return (int32_t)(a - b) > 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -172,7 +172,7 @@ static void update_fences(struct msm_gpu *gpu, struct msm_ringbuffer *ring,
 | 
			
		|||
 | 
			
		||||
	spin_lock_irqsave(&ring->submit_lock, flags);
 | 
			
		||||
	list_for_each_entry(submit, &ring->submits, node) {
 | 
			
		||||
		if (submit->seqno > fence)
 | 
			
		||||
		if (fence_after(submit->seqno, fence))
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		msm_update_fence(submit->ring->fctx,
 | 
			
		||||
| 
						 | 
				
			
			@ -509,7 +509,7 @@ static void hangcheck_handler(struct timer_list *t)
 | 
			
		|||
	if (fence != ring->hangcheck_fence) {
 | 
			
		||||
		/* some progress has been made.. ya! */
 | 
			
		||||
		ring->hangcheck_fence = fence;
 | 
			
		||||
	} else if (fence < ring->seqno) {
 | 
			
		||||
	} else if (fence_before(fence, ring->seqno)) {
 | 
			
		||||
		/* no progress and not done.. hung! */
 | 
			
		||||
		ring->hangcheck_fence = fence;
 | 
			
		||||
		DRM_DEV_ERROR(dev->dev, "%s: hangcheck detected gpu lockup rb %d!\n",
 | 
			
		||||
| 
						 | 
				
			
			@ -523,7 +523,7 @@ static void hangcheck_handler(struct timer_list *t)
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	/* if still more pending work, reset the hangcheck timer: */
 | 
			
		||||
	if (ring->seqno > ring->hangcheck_fence)
 | 
			
		||||
	if (fence_after(ring->seqno, ring->hangcheck_fence))
 | 
			
		||||
		hangcheck_timer_reset(gpu);
 | 
			
		||||
 | 
			
		||||
	/* workaround for missing irq: */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -262,7 +262,7 @@ static inline bool msm_gpu_active(struct msm_gpu *gpu)
 | 
			
		|||
	for (i = 0; i < gpu->nr_rings; i++) {
 | 
			
		||||
		struct msm_ringbuffer *ring = gpu->rb[i];
 | 
			
		||||
 | 
			
		||||
		if (ring->seqno > ring->memptrs->fence)
 | 
			
		||||
		if (fence_after(ring->seqno, ring->memptrs->fence))
 | 
			
		||||
			return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue