aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLyude Paul <lyude@redhat.com>2018-06-04 15:35:03 -0400
committerAlex Deucher <alexander.deucher@amd.com>2018-06-13 14:45:22 -0400
commit97028037a38ae40c0e06789b71038d3a6045a413 (patch)
treea3999376f5ce3ca4b50c58ac3eccd8c5732f0744
parent7584498c1c67bba4d1f5a0f7bf48c9a50c3ff5c8 (diff)
drm/amdgpu: Grab/put runtime PM references in atomic_commit_tail()
So, unfortunately I recently made the discovery that in the upstream kernel, the only reason that amdgpu is not currently suffering from issues with runtime PM putting the GPU into suspend while it's driving displays is due to the fact that on most prime systems, we have sound devices associated with the GPU that hold their own runtime PM ref for the GPU. What this means however, is that in the event that there isn't any kind of sound device active (which can easily be reproduced by building a kernel with sound drivers disabled), the GPU will fall asleep even when there's displays active. This appears to be in part due to the fact that amdgpu has not actually ever relied on it's rpm_idle() function to be the only thing keeping it running, and normally grabs it's own power references whenever there are displays active (as can be seen with the original pre-DC codepath in amdgpu_display_crtc_set_config() in amdgpu_display.c). This means it's very likely that this bug was introduced during the switch over the DC. So to fix this, we start grabbing runtime PM references every time we enable a previously disabled CRTC in atomic_commit_tail(). This appears to be the correct solution, as it matches up with what i915 does in i915/intel_runtime_pm.c. The one sideaffect of this is that we ignore the variable that the pre-DC code used to use for tracking when it needed runtime PM refs, adev->have_disp_power_ref. This is mainly because there's no way for a driver to tell whether or not all of it's CRTCs are enabled or disabled when we've begun committing an atomic state, as there may be CRTC commits happening in parallel that aren't contained within the atomic state being committed. So, it's safer to just get/put a reference for each CRTC being enabled or disabled in the new atomic state. Signed-off-by: Lyude Paul <lyude@redhat.com> Acked-by: Christian König <christian.koenig@amd.com>. Reviewed-by: Harry Wentland <harry.wentland@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> Cc: stable@vger.kernel.org
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c13
1 files changed, 13 insertions, 0 deletions
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 0a06941204d7..5e9e6772f754 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -46,6 +46,7 @@
46#include <linux/moduleparam.h> 46#include <linux/moduleparam.h>
47#include <linux/version.h> 47#include <linux/version.h>
48#include <linux/types.h> 48#include <linux/types.h>
49#include <linux/pm_runtime.h>
49 50
50#include <drm/drmP.h> 51#include <drm/drmP.h>
51#include <drm/drm_atomic.h> 52#include <drm/drm_atomic.h>
@@ -4278,6 +4279,8 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
4278 if (dm_old_crtc_state->stream) 4279 if (dm_old_crtc_state->stream)
4279 remove_stream(adev, acrtc, dm_old_crtc_state->stream); 4280 remove_stream(adev, acrtc, dm_old_crtc_state->stream);
4280 4281
4282 pm_runtime_get_noresume(dev->dev);
4283
4281 acrtc->enabled = true; 4284 acrtc->enabled = true;
4282 acrtc->hw_mode = new_crtc_state->mode; 4285 acrtc->hw_mode = new_crtc_state->mode;
4283 crtc->hwmode = new_crtc_state->mode; 4286 crtc->hwmode = new_crtc_state->mode;
@@ -4466,6 +4469,16 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
4466 drm_atomic_helper_wait_for_flip_done(dev, state); 4469 drm_atomic_helper_wait_for_flip_done(dev, state);
4467 4470
4468 drm_atomic_helper_cleanup_planes(dev, state); 4471 drm_atomic_helper_cleanup_planes(dev, state);
4472
4473 /* Finally, drop a runtime PM reference for each newly disabled CRTC,
4474 * so we can put the GPU into runtime suspend if we're not driving any
4475 * displays anymore
4476 */
4477 pm_runtime_mark_last_busy(dev->dev);
4478 for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
4479 if (old_crtc_state->active && !new_crtc_state->active)
4480 pm_runtime_put_autosuspend(dev->dev);
4481 }
4469} 4482}
4470 4483
4471 4484