1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
From patchwork Fri Jul 8 15:37:35 2016
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: drm/amdgpu: Disable RPM helpers while reprobing connectors on resume
From: cpaul@redhat.com
X-Patchwork-Id: 97837
Message-Id: <1467992256-23832-1-git-send-email-cpaul@redhat.com>
To: amd-gfx@lists.freedesktop.org
Cc: Tom St Denis <tom.stdenis@amd.com>, Jammy Zhou <Jammy.Zhou@amd.com>,
open list <linux-kernel@vger.kernel.org>, stable@vger.kernel.org,
"open list:RADEON and AMDGPU DRM DRIVERS"
<dri-devel@lists.freedesktop.org>,
Alex Deucher <alexander.deucher@amd.com>, Lyude <cpaul@redhat.com>,
Flora Cui <Flora.Cui@amd.com>,
=?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com>,
Monk Liu <Monk.Liu@amd.com>
Date: Fri, 8 Jul 2016 11:37:35 -0400
Just about all of amdgpu's connector probing functions try to acquire
runtime PM refs. If we try to do this in the context of
amdgpu_resume_kms by calling drm_helper_hpd_irq_event(), we end up
deadlocking the system.
Since we're guaranteed to be holding the spinlock for RPM in
amdgpu_resume_kms, and we already know the GPU is in working order, we
need to prevent the RPM helpers from trying to run during the initial
connector reprobe on resume.
There's a couple of solutions I've explored for fixing this, but this
one by far seems to be the simplest and most reliable (plus I'm pretty
sure that's what disable_depth is there for anyway).
Reproduction recipe:
- Get any laptop dual GPUs using PRIME
- Make sure runtime PM is enabled for amdgpu
- Boot the machine
- If the machine managed to boot without hanging, switch out of X to
another VT. This should definitely cause X to hang infinitely.
Cc: stable@vger.kernel.org
Signed-off-by: Lyude <cpaul@redhat.com>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index 6e92008..46c1fee 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -1841,7 +1841,19 @@ int amdgpu_resume_kms(struct drm_device *dev, bool resume, bool fbcon)
}
drm_kms_helper_poll_enable(dev);
+
+ /*
+ * Most of the connector probing functions try to acquire runtime pm
+ * refs to ensure that the GPU is powered on when connector polling is
+ * performed. Since we're calling this from a runtime PM callback,
+ * trying to acquire rpm refs will cause us to deadlock.
+ *
+ * Since we're guaranteed to be holding the rpm lock, it's safe to
+ * temporarily disable the rpm helpers so this doesn't deadlock us.
+ */
+ dev->dev->power.disable_depth++;
drm_helper_hpd_irq_event(dev);
+ dev->dev->power.disable_depth--;
if (fbcon) {
amdgpu_fbdev_set_suspend(adev, 0);
|