diff options
author | Eric Anholt <eric@anholt.net> | 2016-02-08 11:19:14 -0800 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2016-02-16 12:21:00 -0800 |
commit | c4ce60dc30912df09b2438f1e5594eae1ef64d1e (patch) | |
tree | 6d248da2d9bd32a4d8f5cc9e0405a512e863932e /drivers/gpu/drm/vc4/vc4_gem.c | |
parent | 2ee94657e2bbd13b358060edc91b2b2fdef9038f (diff) | |
download | linux-c4ce60dc30912df09b2438f1e5594eae1ef64d1e.tar.gz linux-c4ce60dc30912df09b2438f1e5594eae1ef64d1e.tar.bz2 linux-c4ce60dc30912df09b2438f1e5594eae1ef64d1e.zip |
drm/vc4: Fix spurious GPU resets due to BO reuse.
We were tracking the "where are the head pointers pointing" globally,
so if another job reused the same BOs and execution was at the same
point as last time we checked, we'd stop and trigger a reset even
though the GPU had made progress.
Signed-off-by: Eric Anholt <eric@anholt.net>
Diffstat (limited to 'drivers/gpu/drm/vc4/vc4_gem.c')
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_gem.c | 19 |
1 files changed, 14 insertions, 5 deletions
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) 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. |