brcm2708: update linux 4.4 patches to latest version
[openwrt/openwrt.git] / target / linux / brcm2708 / patches-4.4 / 0467-drm-vc4-Use-runtime-PM-to-power-cycle-the-device-whe.patch
1 From a933cf6cc414d067087f311598e4acd42bc4f6d2 Mon Sep 17 00:00:00 2001
2 From: Eric Anholt <eric@anholt.net>
3 Date: Mon, 8 Feb 2016 12:59:02 -0800
4 Subject: [PATCH] drm/vc4: Use runtime PM to power cycle the device when the
5 GPU hangs.
6
7 This gets us functional GPU reset again, like we had until a refactor
8 at merge time. Tested with a little patch to stuff in a broken binner
9 job every 100 frames.
10
11 Signed-off-by: Eric Anholt <eric@anholt.net>
12 (cherry picked from commit 36cb6253f9383fd9a59ee7b8458c6232ef48577c)
13 ---
14 drivers/gpu/drm/vc4/vc4_drv.h | 6 +++++-
15 drivers/gpu/drm/vc4/vc4_gem.c | 26 +++++++++++++++++++++-----
16 2 files changed, 26 insertions(+), 6 deletions(-)
17
18 --- a/drivers/gpu/drm/vc4/vc4_drv.h
19 +++ b/drivers/gpu/drm/vc4/vc4_drv.h
20 @@ -104,6 +104,11 @@ struct vc4_dev {
21 struct vc4_bo *overflow_mem;
22 struct work_struct overflow_mem_work;
23
24 + int power_refcount;
25 +
26 + /* Mutex controlling the power refcount. */
27 + struct mutex power_lock;
28 +
29 struct {
30 struct timer_list timer;
31 struct work_struct reset_work;
32 @@ -495,7 +500,6 @@ void vc4_plane_async_set_fb(struct drm_p
33 extern struct platform_driver vc4_v3d_driver;
34 int vc4_v3d_debugfs_ident(struct seq_file *m, void *unused);
35 int vc4_v3d_debugfs_regs(struct seq_file *m, void *unused);
36 -int vc4_v3d_set_power(struct vc4_dev *vc4, bool on);
37
38 /* vc4_validate.c */
39 int
40 --- a/drivers/gpu/drm/vc4/vc4_gem.c
41 +++ b/drivers/gpu/drm/vc4/vc4_gem.c
42 @@ -261,8 +261,16 @@ vc4_reset(struct drm_device *dev)
43 struct vc4_dev *vc4 = to_vc4_dev(dev);
44
45 DRM_INFO("Resetting GPU.\n");
46 - vc4_v3d_set_power(vc4, false);
47 - vc4_v3d_set_power(vc4, true);
48 +
49 + mutex_lock(&vc4->power_lock);
50 + if (vc4->power_refcount) {
51 + /* Power the device off and back on the by dropping the
52 + * reference on runtime PM.
53 + */
54 + pm_runtime_put_sync_suspend(&vc4->v3d->pdev->dev);
55 + pm_runtime_get_sync(&vc4->v3d->pdev->dev);
56 + }
57 + mutex_unlock(&vc4->power_lock);
58
59 vc4_irq_reset(dev);
60
61 @@ -709,7 +717,10 @@ vc4_complete_exec(struct drm_device *dev
62 }
63 mutex_unlock(&dev->struct_mutex);
64
65 - pm_runtime_put(&vc4->v3d->pdev->dev);
66 + mutex_lock(&vc4->power_lock);
67 + if (--vc4->power_refcount == 0)
68 + pm_runtime_put(&vc4->v3d->pdev->dev);
69 + mutex_unlock(&vc4->power_lock);
70
71 kfree(exec);
72 }
73 @@ -851,7 +862,7 @@ vc4_submit_cl_ioctl(struct drm_device *d
74 struct vc4_dev *vc4 = to_vc4_dev(dev);
75 struct drm_vc4_submit_cl *args = data;
76 struct vc4_exec_info *exec;
77 - int ret;
78 + int ret = 0;
79
80 if ((args->flags & ~VC4_SUBMIT_CL_USE_CLEAR_COLOR) != 0) {
81 DRM_ERROR("Unknown flags: 0x%02x\n", args->flags);
82 @@ -864,7 +875,10 @@ vc4_submit_cl_ioctl(struct drm_device *d
83 return -ENOMEM;
84 }
85
86 - ret = pm_runtime_get_sync(&vc4->v3d->pdev->dev);
87 + mutex_lock(&vc4->power_lock);
88 + if (vc4->power_refcount++ == 0)
89 + ret = pm_runtime_get_sync(&vc4->v3d->pdev->dev);
90 + mutex_unlock(&vc4->power_lock);
91 if (ret < 0) {
92 kfree(exec);
93 return ret;
94 @@ -925,6 +939,8 @@ vc4_gem_init(struct drm_device *dev)
95 (unsigned long)dev);
96
97 INIT_WORK(&vc4->job_done_work, vc4_job_done_work);
98 +
99 + mutex_init(&vc4->power_lock);
100 }
101
102 void