aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/vc4/vc4_drv.h6
-rw-r--r--drivers/gpu/drm/vc4/vc4_gem.c19
2 files changed, 19 insertions, 6 deletions
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index 080865ec2bae..b6ccf8181643 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -92,7 +92,6 @@ struct vc4_dev {
92 struct work_struct overflow_mem_work; 92 struct work_struct overflow_mem_work;
93 93
94 struct { 94 struct {
95 uint32_t last_ct0ca, last_ct1ca;
96 struct timer_list timer; 95 struct timer_list timer;
97 struct work_struct reset_work; 96 struct work_struct reset_work;
98 } hangcheck; 97 } hangcheck;
@@ -192,6 +191,11 @@ struct vc4_exec_info {
192 /* Sequence number for this bin/render job. */ 191 /* Sequence number for this bin/render job. */
193 uint64_t seqno; 192 uint64_t seqno;
194 193
194 /* Last current addresses the hardware was processing when the
195 * hangcheck timer checked on us.
196 */
197 uint32_t last_ct0ca, last_ct1ca;
198
195 /* Kernel-space copy of the ioctl arguments */ 199 /* Kernel-space copy of the ioctl arguments */
196 struct drm_vc4_submit_cl *args; 200 struct drm_vc4_submit_cl *args;
197 201
diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c
index a9d020e7e891..1a819dd826f8 100644
--- a/drivers/gpu/drm/vc4/vc4_gem.c
+++ b/drivers/gpu/drm/vc4/vc4_gem.c
@@ -257,10 +257,17 @@ vc4_hangcheck_elapsed(unsigned long data)
257 struct drm_device *dev = (struct drm_device *)data; 257 struct drm_device *dev = (struct drm_device *)data;
258 struct vc4_dev *vc4 = to_vc4_dev(dev); 258 struct vc4_dev *vc4 = to_vc4_dev(dev);
259 uint32_t ct0ca, ct1ca; 259 uint32_t ct0ca, ct1ca;
260 unsigned long irqflags;
261 struct vc4_exec_info *exec;
262
263 spin_lock_irqsave(&vc4->job_lock, irqflags);
264 exec = vc4_first_job(vc4);
260 265
261 /* If idle, we can stop watching for hangs. */ 266 /* If idle, we can stop watching for hangs. */
262 if (list_empty(&vc4->job_list)) 267 if (!exec) {
268 spin_unlock_irqrestore(&vc4->job_lock, irqflags);
263 return; 269 return;
270 }
264 271
265 ct0ca = V3D_READ(V3D_CTNCA(0)); 272 ct0ca = V3D_READ(V3D_CTNCA(0));
266 ct1ca = V3D_READ(V3D_CTNCA(1)); 273 ct1ca = V3D_READ(V3D_CTNCA(1));
@@ -268,14 +275,16 @@ vc4_hangcheck_elapsed(unsigned long data)
268 /* If we've made any progress in execution, rearm the timer 275 /* If we've made any progress in execution, rearm the timer
269 * and wait. 276 * and wait.
270 */ 277 */
271 if (ct0ca != vc4->hangcheck.last_ct0ca || 278 if (ct0ca != exec->last_ct0ca || ct1ca != exec->last_ct1ca) {
272 ct1ca != vc4->hangcheck.last_ct1ca) { 279 exec->last_ct0ca = ct0ca;
273 vc4->hangcheck.last_ct0ca = ct0ca; 280 exec->last_ct1ca = ct1ca;
274 vc4->hangcheck.last_ct1ca = ct1ca; 281 spin_unlock_irqrestore(&vc4->job_lock, irqflags);
275 vc4_queue_hangcheck(dev); 282 vc4_queue_hangcheck(dev);
276 return; 283 return;
277 } 284 }
278 285
286 spin_unlock_irqrestore(&vc4->job_lock, irqflags);
287
279 /* We've gone too long with no progress, reset. This has to 288 /* We've gone too long with no progress, reset. This has to
280 * be done from a work struct, since resetting can sleep and 289 * be done from a work struct, since resetting can sleep and
281 * this timer hook isn't allowed to. 290 * this timer hook isn't allowed to.