123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081 |
- From cc502edf8c0515a8b3c410d4bfda002a4db88e4f Mon Sep 17 00:00:00 2001
- From: Eric Anholt <eric@anholt.net>
- Date: Mon, 8 Feb 2016 11:19:14 -0800
- Subject: [PATCH 286/381] 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>
- (cherry picked from commit c4ce60dc30912df09b2438f1e5594eae1ef64d1e)
- ---
- drivers/gpu/drm/vc4/vc4_drv.h | 6 +++++-
- drivers/gpu/drm/vc4/vc4_gem.c | 19 ++++++++++++++-----
- 2 files changed, 19 insertions(+), 6 deletions(-)
- --- a/drivers/gpu/drm/vc4/vc4_drv.h
- +++ b/drivers/gpu/drm/vc4/vc4_drv.h
- @@ -93,7 +93,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;
- @@ -203,6 +202,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;
-
- --- a/drivers/gpu/drm/vc4/vc4_gem.c
- +++ b/drivers/gpu/drm/vc4/vc4_gem.c
- @@ -271,10 +271,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));
- @@ -282,14 +289,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.
|