summaryrefslogtreecommitdiffstats
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 080865e..b6ccf81 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -92,7 +92,6 @@ struct vc4_dev {
struct work_struct overflow_mem_work;
struct {
- uint32_t last_ct0ca, last_ct1ca;
struct timer_list timer;
struct work_struct reset_work;
} hangcheck;
@@ -192,6 +191,11 @@ struct vc4_exec_info {
/* Sequence number for this bin/render job. */
uint64_t seqno;
+ /* Last current addresses the hardware was processing when the
+ * hangcheck timer checked on us.
+ */
+ uint32_t last_ct0ca, last_ct1ca;
+
/* Kernel-space copy of the ioctl arguments */
struct drm_vc4_submit_cl *args;
diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c
index a9d020e..1a819dd 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)
struct drm_device *dev = (struct drm_device *)data;
struct vc4_dev *vc4 = to_vc4_dev(dev);
uint32_t ct0ca, ct1ca;
+ unsigned long irqflags;
+ struct vc4_exec_info *exec;
+
+ spin_lock_irqsave(&vc4->job_lock, irqflags);
+ exec = vc4_first_job(vc4);
/* If idle, we can stop watching for hangs. */
- if (list_empty(&vc4->job_list))
+ if (!exec) {
+ spin_unlock_irqrestore(&vc4->job_lock, irqflags);
return;
+ }
ct0ca = V3D_READ(V3D_CTNCA(0));
ct1ca = V3D_READ(V3D_CTNCA(1));
@@ -268,14 +275,16 @@ vc4_hangcheck_elapsed(unsigned long data)
/* If we've made any progress in execution, rearm the timer
* and wait.
*/
- if (ct0ca != vc4->hangcheck.last_ct0ca ||
- ct1ca != vc4->hangcheck.last_ct1ca) {
- vc4->hangcheck.last_ct0ca = ct0ca;
- vc4->hangcheck.last_ct1ca = ct1ca;
+ if (ct0ca != exec->last_ct0ca || ct1ca != exec->last_ct1ca) {
+ exec->last_ct0ca = ct0ca;
+ exec->last_ct1ca = ct1ca;
+ spin_unlock_irqrestore(&vc4->job_lock, irqflags);
vc4_queue_hangcheck(dev);
return;
}
+ spin_unlock_irqrestore(&vc4->job_lock, irqflags);
+
/* We've gone too long with no progress, reset. This has to
* be done from a work struct, since resetting can sleep and
* this timer hook isn't allowed to.
OpenPOWER on IntegriCloud