diff options
Diffstat (limited to 'target/linux/brcm2708/patches-4.4/0286-drm-vc4-Fix-spurious-GPU-resets-due-to-BO-reuse.patch')
-rw-r--r-- | target/linux/brcm2708/patches-4.4/0286-drm-vc4-Fix-spurious-GPU-resets-due-to-BO-reuse.patch | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/target/linux/brcm2708/patches-4.4/0286-drm-vc4-Fix-spurious-GPU-resets-due-to-BO-reuse.patch b/target/linux/brcm2708/patches-4.4/0286-drm-vc4-Fix-spurious-GPU-resets-due-to-BO-reuse.patch new file mode 100644 index 0000000000..367bb562d0 --- /dev/null +++ b/target/linux/brcm2708/patches-4.4/0286-drm-vc4-Fix-spurious-GPU-resets-due-to-BO-reuse.patch @@ -0,0 +1,81 @@ +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. |