]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/4.15.10/drm-amdgpu-fix-deadlock-on-runtime-suspend.patch
Fix up backported ptrace patch
[thirdparty/kernel/stable-queue.git] / releases / 4.15.10 / drm-amdgpu-fix-deadlock-on-runtime-suspend.patch
CommitLineData
bbecac5b
GKH
1From aa0aad57909eb321746325951d66af88a83bc956 Mon Sep 17 00:00:00 2001
2From: Lukas Wunner <lukas@wunner.de>
3Date: Sun, 11 Feb 2018 10:38:28 +0100
4Subject: drm/amdgpu: Fix deadlock on runtime suspend
5
6From: Lukas Wunner <lukas@wunner.de>
7
8commit aa0aad57909eb321746325951d66af88a83bc956 upstream.
9
10amdgpu's ->runtime_suspend hook calls drm_kms_helper_poll_disable(),
11which waits for the output poll worker to finish if it's running.
12
13The output poll worker meanwhile calls pm_runtime_get_sync() in
14amdgpu's ->detect hooks, which waits for the ongoing suspend to finish,
15causing a deadlock.
16
17Fix by not acquiring a runtime PM ref if the ->detect hooks are called
18in the output poll worker's context. This is safe because the poll
19worker is only enabled while runtime active and we know that
20->runtime_suspend waits for it to finish.
21
22Fixes: d38ceaf99ed0 ("drm/amdgpu: add core driver (v4)")
23Cc: stable@vger.kernel.org # v4.2+: 27d4ee03078a: workqueue: Allow retrieval of current task's work struct
24Cc: stable@vger.kernel.org # v4.2+: 25c058ccaf2e: drm: Allow determining if current task is output poll worker
25Cc: Alex Deucher <alexander.deucher@amd.com>
26Tested-by: Mike Lothian <mike@fireburn.co.uk>
27Reviewed-by: Lyude Paul <lyude@redhat.com>
28Signed-off-by: Lukas Wunner <lukas@wunner.de>
29Link: https://patchwork.freedesktop.org/patch/msgid/4c9bf72aacae1eef062bd134cd112e0770a7f121.1518338789.git.lukas@wunner.de
30Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
31
32---
33 drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c | 58 ++++++++++++++++---------
34 1 file changed, 38 insertions(+), 20 deletions(-)
35
36--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
37+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
38@@ -737,9 +737,11 @@ amdgpu_connector_lvds_detect(struct drm_
39 enum drm_connector_status ret = connector_status_disconnected;
40 int r;
41
42- r = pm_runtime_get_sync(connector->dev->dev);
43- if (r < 0)
44- return connector_status_disconnected;
45+ if (!drm_kms_helper_is_poll_worker()) {
46+ r = pm_runtime_get_sync(connector->dev->dev);
47+ if (r < 0)
48+ return connector_status_disconnected;
49+ }
50
51 if (encoder) {
52 struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder);
53@@ -758,8 +760,12 @@ amdgpu_connector_lvds_detect(struct drm_
54 /* check acpi lid status ??? */
55
56 amdgpu_connector_update_scratch_regs(connector, ret);
57- pm_runtime_mark_last_busy(connector->dev->dev);
58- pm_runtime_put_autosuspend(connector->dev->dev);
59+
60+ if (!drm_kms_helper_is_poll_worker()) {
61+ pm_runtime_mark_last_busy(connector->dev->dev);
62+ pm_runtime_put_autosuspend(connector->dev->dev);
63+ }
64+
65 return ret;
66 }
67
68@@ -869,9 +875,11 @@ amdgpu_connector_vga_detect(struct drm_c
69 enum drm_connector_status ret = connector_status_disconnected;
70 int r;
71
72- r = pm_runtime_get_sync(connector->dev->dev);
73- if (r < 0)
74- return connector_status_disconnected;
75+ if (!drm_kms_helper_is_poll_worker()) {
76+ r = pm_runtime_get_sync(connector->dev->dev);
77+ if (r < 0)
78+ return connector_status_disconnected;
79+ }
80
81 encoder = amdgpu_connector_best_single_encoder(connector);
82 if (!encoder)
83@@ -925,8 +933,10 @@ amdgpu_connector_vga_detect(struct drm_c
84 amdgpu_connector_update_scratch_regs(connector, ret);
85
86 out:
87- pm_runtime_mark_last_busy(connector->dev->dev);
88- pm_runtime_put_autosuspend(connector->dev->dev);
89+ if (!drm_kms_helper_is_poll_worker()) {
90+ pm_runtime_mark_last_busy(connector->dev->dev);
91+ pm_runtime_put_autosuspend(connector->dev->dev);
92+ }
93
94 return ret;
95 }
96@@ -989,9 +999,11 @@ amdgpu_connector_dvi_detect(struct drm_c
97 enum drm_connector_status ret = connector_status_disconnected;
98 bool dret = false, broken_edid = false;
99
100- r = pm_runtime_get_sync(connector->dev->dev);
101- if (r < 0)
102- return connector_status_disconnected;
103+ if (!drm_kms_helper_is_poll_worker()) {
104+ r = pm_runtime_get_sync(connector->dev->dev);
105+ if (r < 0)
106+ return connector_status_disconnected;
107+ }
108
109 if (!force && amdgpu_connector_check_hpd_status_unchanged(connector)) {
110 ret = connector->status;
111@@ -1116,8 +1128,10 @@ out:
112 amdgpu_connector_update_scratch_regs(connector, ret);
113
114 exit:
115- pm_runtime_mark_last_busy(connector->dev->dev);
116- pm_runtime_put_autosuspend(connector->dev->dev);
117+ if (!drm_kms_helper_is_poll_worker()) {
118+ pm_runtime_mark_last_busy(connector->dev->dev);
119+ pm_runtime_put_autosuspend(connector->dev->dev);
120+ }
121
122 return ret;
123 }
124@@ -1360,9 +1374,11 @@ amdgpu_connector_dp_detect(struct drm_co
125 struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector);
126 int r;
127
128- r = pm_runtime_get_sync(connector->dev->dev);
129- if (r < 0)
130- return connector_status_disconnected;
131+ if (!drm_kms_helper_is_poll_worker()) {
132+ r = pm_runtime_get_sync(connector->dev->dev);
133+ if (r < 0)
134+ return connector_status_disconnected;
135+ }
136
137 if (!force && amdgpu_connector_check_hpd_status_unchanged(connector)) {
138 ret = connector->status;
139@@ -1430,8 +1446,10 @@ amdgpu_connector_dp_detect(struct drm_co
140
141 amdgpu_connector_update_scratch_regs(connector, ret);
142 out:
143- pm_runtime_mark_last_busy(connector->dev->dev);
144- pm_runtime_put_autosuspend(connector->dev->dev);
145+ if (!drm_kms_helper_is_poll_worker()) {
146+ pm_runtime_mark_last_busy(connector->dev->dev);
147+ pm_runtime_put_autosuspend(connector->dev->dev);
148+ }
149
150 return ret;
151 }