brcm2708-gpu-fw: update to latest version
[openwrt/openwrt.git] / target / linux / brcm2708 / patches-4.4 / 0287-drm-vc4-Fix-spurious-GPU-resets-due-to-BO-reuse.patch
1 From 6fde872f91f4ff8dcf1b2c2017c04e4f1dee07f7 Mon Sep 17 00:00:00 2001
2 From: Eric Anholt <eric@anholt.net>
3 Date: Mon, 8 Feb 2016 11:19:14 -0800
4 Subject: [PATCH 287/304] drm/vc4: Fix spurious GPU resets due to BO reuse.
5
6 We were tracking the "where are the head pointers pointing" globally,
7 so if another job reused the same BOs and execution was at the same
8 point as last time we checked, we'd stop and trigger a reset even
9 though the GPU had made progress.
10
11 Signed-off-by: Eric Anholt <eric@anholt.net>
12 (cherry picked from commit c4ce60dc30912df09b2438f1e5594eae1ef64d1e)
13 ---
14 drivers/gpu/drm/vc4/vc4_drv.h | 6 +++++-
15 drivers/gpu/drm/vc4/vc4_gem.c | 19 ++++++++++++++-----
16 2 files changed, 19 insertions(+), 6 deletions(-)
17
18 --- a/drivers/gpu/drm/vc4/vc4_drv.h
19 +++ b/drivers/gpu/drm/vc4/vc4_drv.h
20 @@ -93,7 +93,6 @@ struct vc4_dev {
21 struct work_struct overflow_mem_work;
22
23 struct {
24 - uint32_t last_ct0ca, last_ct1ca;
25 struct timer_list timer;
26 struct work_struct reset_work;
27 } hangcheck;
28 @@ -203,6 +202,11 @@ struct vc4_exec_info {
29 /* Sequence number for this bin/render job. */
30 uint64_t seqno;
31
32 + /* Last current addresses the hardware was processing when the
33 + * hangcheck timer checked on us.
34 + */
35 + uint32_t last_ct0ca, last_ct1ca;
36 +
37 /* Kernel-space copy of the ioctl arguments */
38 struct drm_vc4_submit_cl *args;
39
40 --- a/drivers/gpu/drm/vc4/vc4_gem.c
41 +++ b/drivers/gpu/drm/vc4/vc4_gem.c
42 @@ -271,10 +271,17 @@ vc4_hangcheck_elapsed(unsigned long data
43 struct drm_device *dev = (struct drm_device *)data;
44 struct vc4_dev *vc4 = to_vc4_dev(dev);
45 uint32_t ct0ca, ct1ca;
46 + unsigned long irqflags;
47 + struct vc4_exec_info *exec;
48 +
49 + spin_lock_irqsave(&vc4->job_lock, irqflags);
50 + exec = vc4_first_job(vc4);
51
52 /* If idle, we can stop watching for hangs. */
53 - if (list_empty(&vc4->job_list))
54 + if (!exec) {
55 + spin_unlock_irqrestore(&vc4->job_lock, irqflags);
56 return;
57 + }
58
59 ct0ca = V3D_READ(V3D_CTNCA(0));
60 ct1ca = V3D_READ(V3D_CTNCA(1));
61 @@ -282,14 +289,16 @@ vc4_hangcheck_elapsed(unsigned long data
62 /* If we've made any progress in execution, rearm the timer
63 * and wait.
64 */
65 - if (ct0ca != vc4->hangcheck.last_ct0ca ||
66 - ct1ca != vc4->hangcheck.last_ct1ca) {
67 - vc4->hangcheck.last_ct0ca = ct0ca;
68 - vc4->hangcheck.last_ct1ca = ct1ca;
69 + if (ct0ca != exec->last_ct0ca || ct1ca != exec->last_ct1ca) {
70 + exec->last_ct0ca = ct0ca;
71 + exec->last_ct1ca = ct1ca;
72 + spin_unlock_irqrestore(&vc4->job_lock, irqflags);
73 vc4_queue_hangcheck(dev);
74 return;
75 }
76
77 + spin_unlock_irqrestore(&vc4->job_lock, irqflags);
78 +
79 /* We've gone too long with no progress, reset. This has to
80 * be done from a work struct, since resetting can sleep and
81 * this timer hook isn't allowed to.