diff options
Diffstat (limited to 'drivers/gpu/drm/lima/lima_sched.c')
| -rw-r--r-- | drivers/gpu/drm/lima/lima_sched.c | 38 | 
1 files changed, 31 insertions, 7 deletions
diff --git a/drivers/gpu/drm/lima/lima_sched.c b/drivers/gpu/drm/lima/lima_sched.c index c3bf8cda8498..00b19adfc888 100644 --- a/drivers/gpu/drm/lima/lima_sched.c +++ b/drivers/gpu/drm/lima/lima_sched.c @@ -1,6 +1,7 @@  // SPDX-License-Identifier: GPL-2.0 OR MIT  /* Copyright 2017-2019 Qiang Yu <yuq825@gmail.com> */ +#include <linux/hardirq.h>  #include <linux/iosys-map.h>  #include <linux/kthread.h>  #include <linux/slab.h> @@ -153,13 +154,12 @@ void lima_sched_task_fini(struct lima_sched_task *task)  }  int lima_sched_context_init(struct lima_sched_pipe *pipe, -			    struct lima_sched_context *context, -			    atomic_t *guilty) +			    struct lima_sched_context *context)  {  	struct drm_gpu_scheduler *sched = &pipe->base;  	return drm_sched_entity_init(&context->base, DRM_SCHED_PRIORITY_NORMAL, -				     &sched, 1, guilty); +				     &sched, 1, NULL);  }  void lima_sched_context_fini(struct lima_sched_pipe *pipe, @@ -401,9 +401,35 @@ static enum drm_gpu_sched_stat lima_sched_timedout_job(struct drm_sched_job *job  	struct lima_sched_pipe *pipe = to_lima_pipe(job->sched);  	struct lima_sched_task *task = to_lima_task(job);  	struct lima_device *ldev = pipe->ldev; +	struct lima_ip *ip = pipe->processor[0]; +	int i; + +	/* +	 * If the GPU managed to complete this jobs fence, the timeout is +	 * spurious. Bail out. +	 */ +	if (dma_fence_is_signaled(task->fence)) { +		DRM_WARN("%s spurious timeout\n", lima_ip_name(ip)); +		return DRM_GPU_SCHED_STAT_NOMINAL; +	} + +	/* +	 * Lima IRQ handler may take a long time to process an interrupt +	 * if there is another IRQ handler hogging the processing. +	 * In order to catch such cases and not report spurious Lima job +	 * timeouts, synchronize the IRQ handler and re-check the fence +	 * status. +	 */ +	for (i = 0; i < pipe->num_processor; i++) +		synchronize_irq(pipe->processor[i]->irq); + +	if (dma_fence_is_signaled(task->fence)) { +		DRM_WARN("%s unexpectedly high interrupt latency\n", lima_ip_name(ip)); +		return DRM_GPU_SCHED_STAT_NOMINAL; +	}  	if (!pipe->error) -		DRM_ERROR("lima job timeout\n"); +		DRM_ERROR("%s job timeout\n", lima_ip_name(ip));  	drm_sched_stop(&pipe->base, &task->base); @@ -417,8 +443,6 @@ static enum drm_gpu_sched_stat lima_sched_timedout_job(struct drm_sched_job *job  	if (pipe->bcast_mmu)  		lima_mmu_page_fault_resume(pipe->bcast_mmu);  	else { -		int i; -  		for (i = 0; i < pipe->num_mmu; i++)  			lima_mmu_page_fault_resume(pipe->mmu[i]);  	} @@ -481,7 +505,7 @@ static void lima_sched_recover_work(struct work_struct *work)  int lima_sched_pipe_init(struct lima_sched_pipe *pipe, const char *name)  {  	unsigned int timeout = lima_sched_timeout_ms > 0 ? -			       lima_sched_timeout_ms : 500; +			       lima_sched_timeout_ms : 10000;  	pipe->fence_context = dma_fence_context_alloc(1);  	spin_lock_init(&pipe->fence_lock);  | 
