aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLucas Stach <l.stach@pengutronix.de>2018-06-27 09:58:13 -0400
committerLucas Stach <l.stach@pengutronix.de>2018-07-05 08:16:20 -0400
commit2c83a726d6fbb5d130d8f2edd82a258adb675ac3 (patch)
tree13bdac98cf9037a544e3e7650f2578edcfddd244
parentbf6ba3aeb2962e5ee4a78e7535af579ecba630bb (diff)
drm/etnaviv: bring back progress check in job timeout handler
When the hangcheck handler was replaced by the DRM scheduler timeout handling we dropped the forward progress check, as this might allow clients to hog the GPU for a long time with a big job. It turns out that even reasonably well behaved clients like the Armada Xorg driver occasionally trip over the 500ms timeout. Bring back the forward progress check to get rid of the userspace regression. We would still like to fix userspace to submit smaller batches if possible, but that is for another day. Cc: <stable@vger.kernel.org> Fixes: 6d7a20c07760 (drm/etnaviv: replace hangcheck with scheduler timeout) Reported-by: Russell King <linux@armlinux.org.uk> Signed-off-by: Lucas Stach <l.stach@pengutronix.de> Reviewed-by: Eric Anholt <eric@anholt.net>
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_gpu.h3
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_sched.c24
2 files changed, 27 insertions, 0 deletions
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h
index dd430f0f8ff5..90f17ff7888e 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h
@@ -131,6 +131,9 @@ struct etnaviv_gpu {
131 struct work_struct sync_point_work; 131 struct work_struct sync_point_work;
132 int sync_point_event; 132 int sync_point_event;
133 133
134 /* hang detection */
135 u32 hangcheck_dma_addr;
136
134 void __iomem *mmio; 137 void __iomem *mmio;
135 int irq; 138 int irq;
136 139
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_sched.c b/drivers/gpu/drm/etnaviv/etnaviv_sched.c
index a74eb57af15b..50d6b88cb7aa 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_sched.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_sched.c
@@ -10,6 +10,7 @@
10#include "etnaviv_gem.h" 10#include "etnaviv_gem.h"
11#include "etnaviv_gpu.h" 11#include "etnaviv_gpu.h"
12#include "etnaviv_sched.h" 12#include "etnaviv_sched.h"
13#include "state.xml.h"
13 14
14static int etnaviv_job_hang_limit = 0; 15static int etnaviv_job_hang_limit = 0;
15module_param_named(job_hang_limit, etnaviv_job_hang_limit, int , 0444); 16module_param_named(job_hang_limit, etnaviv_job_hang_limit, int , 0444);
@@ -85,6 +86,29 @@ static void etnaviv_sched_timedout_job(struct drm_sched_job *sched_job)
85{ 86{
86 struct etnaviv_gem_submit *submit = to_etnaviv_submit(sched_job); 87 struct etnaviv_gem_submit *submit = to_etnaviv_submit(sched_job);
87 struct etnaviv_gpu *gpu = submit->gpu; 88 struct etnaviv_gpu *gpu = submit->gpu;
89 u32 dma_addr;
90 int change;
91
92 /*
93 * If the GPU managed to complete this jobs fence, the timout is
94 * spurious. Bail out.
95 */
96 if (fence_completed(gpu, submit->out_fence->seqno))
97 return;
98
99 /*
100 * If the GPU is still making forward progress on the front-end (which
101 * should never loop) we shift out the timeout to give it a chance to
102 * finish the job.
103 */
104 dma_addr = gpu_read(gpu, VIVS_FE_DMA_ADDRESS);
105 change = dma_addr - gpu->hangcheck_dma_addr;
106 if (change < 0 || change > 16) {
107 gpu->hangcheck_dma_addr = dma_addr;
108 schedule_delayed_work(&sched_job->work_tdr,
109 sched_job->sched->timeout);
110 return;
111 }
88 112
89 /* block scheduler */ 113 /* block scheduler */
90 kthread_park(gpu->sched.thread); 114 kthread_park(gpu->sched.thread);