brcm2708: update linux 4.4 patches to latest version
[librecmc/librecmc.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.