]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/3.16.3/drm-nouveau-dis-enable-vblank-irqs-during-suspend-resume.patch
4.9-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 3.16.3 / drm-nouveau-dis-enable-vblank-irqs-during-suspend-resume.patch
1 From 9cba5efab5a8145ae6c52ea273553f069c294482 Mon Sep 17 00:00:00 2001
2 From: Mario Kleiner <mario.kleiner.de@gmail.com>
3 Date: Tue, 29 Jul 2014 02:36:44 +0200
4 Subject: drm/nouveau: Dis/Enable vblank irqs during suspend/resume.
5
6 From: Mario Kleiner <mario.kleiner.de@gmail.com>
7
8 commit 9cba5efab5a8145ae6c52ea273553f069c294482 upstream.
9
10 Vblank irqs don't get disabled during suspend or driver
11 unload, which causes irq delivery after "suspend" or
12 driver unload, at least until the gpu is powered off.
13 This could race with drm_vblank_cleanup() in the case
14 of nouveau and cause a use-after-free bug if the driver
15 is unloaded.
16
17 More annoyingly during everyday use, at least on nv50
18 display engine (likely also others), vblank irqs are
19 off after a resume from suspend, but the drm doesn't
20 know this, so all vblank related functionality is dead
21 after a resume. E.g., all windowed OpenGL clients will
22 hang at swapbuffers time, as well as many fullscreen
23 clients in many cases. This makes suspend/resume useless
24 if one wants to use any OpenGL apps after the resume.
25
26 In Linux 3.16, drm_vblank_on() was added, complementing
27 the older drm_vblank_off() to solve these problems
28 elegantly, so use those calls in nouveaus suspend/resume
29 code.
30
31 For kernels 3.8 - 3.15, we need to cherry-pick the
32 drm_vblank_on() patch to support this patch.
33
34 Signed-off-by: Mario Kleiner <mario.kleiner.de@gmail.com>
35 Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
36 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
37
38 ---
39 drivers/gpu/drm/nouveau/nouveau_display.c | 11 +++++++++++
40 1 file changed, 11 insertions(+)
41
42 --- a/drivers/gpu/drm/nouveau/nouveau_display.c
43 +++ b/drivers/gpu/drm/nouveau/nouveau_display.c
44 @@ -404,6 +404,11 @@ nouveau_display_fini(struct drm_device *
45 {
46 struct nouveau_display *disp = nouveau_display(dev);
47 struct drm_connector *connector;
48 + int head;
49 +
50 + /* Make sure that drm and hw vblank irqs get properly disabled. */
51 + for (head = 0; head < dev->mode_config.num_crtc; head++)
52 + drm_vblank_off(dev, head);
53
54 /* disable hotplug interrupts */
55 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
56 @@ -620,6 +625,8 @@ void
57 nouveau_display_resume(struct drm_device *dev)
58 {
59 struct drm_crtc *crtc;
60 + int head;
61 +
62 nouveau_display_init(dev);
63
64 /* Force CLUT to get re-loaded during modeset */
65 @@ -629,6 +636,10 @@ nouveau_display_resume(struct drm_device
66 nv_crtc->lut.depth = 0;
67 }
68
69 + /* Make sure that drm and hw vblank irqs get resumed if needed. */
70 + for (head = 0; head < dev->mode_config.num_crtc; head++)
71 + drm_vblank_on(dev, head);
72 +
73 drm_helper_resume_force_mode(dev);
74
75 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {