linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] drm/amdgpu: Grab/put runtime PM references in atomic_commit_tail()
@ 2018-06-04 19:35 Lyude Paul
  2018-06-05  6:16 ` Christian König
  2018-06-05 19:04 ` Harry Wentland
  0 siblings, 2 replies; 3+ messages in thread
From: Lyude Paul @ 2018-06-04 19:35 UTC (permalink / raw)
  To: amd-gfx
  Cc: Alex Deucher, Christian König, David (ChunMing) Zhou,
	David Airlie, Harry Wentland, Andrey Grodzovsky, Tony Cheng,
	Leo (Sunpeng) Li, Shirish S, dri-devel, linux-kernel

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>
---
As a note, I'm not entirely happy with this fix and I wouldn't be
surprised if I missed something while looking through amdgpu. So, please
don't hesistate to suggest a better fix :).

 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

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 1dd1142246c2..361b81ef6997 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 @@
 #include <linux/moduleparam.h>
 #include <linux/version.h>
 #include <linux/types.h>
+#include <linux/pm_runtime.h>
 
 #include <drm/drmP.h>
 #include <drm/drm_atomic.h>
@@ -4211,6 +4212,8 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
 			if (dm_old_crtc_state->stream)
 				remove_stream(adev, acrtc, dm_old_crtc_state->stream);
 
+			pm_runtime_get_noresume(dev->dev);
+
 			acrtc->enabled = true;
 			acrtc->hw_mode = new_crtc_state->mode;
 			crtc->hwmode = new_crtc_state->mode;
@@ -4396,6 +4399,16 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
 		drm_atomic_helper_wait_for_flip_done(dev, state);
 
 	drm_atomic_helper_cleanup_planes(dev, state);
+
+	/* Finally, drop a runtime PM reference for each newly disabled CRTC,
+	 * so we can put the GPU into runtime suspend if we're not driving any
+	 * displays anymore
+	 */
+	pm_runtime_mark_last_busy(dev->dev);
+	for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
+		if (old_crtc_state->active && !new_crtc_state->active)
+			pm_runtime_put_autosuspend(dev->dev);
+	}
 }
 
 
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] drm/amdgpu: Grab/put runtime PM references in atomic_commit_tail()
  2018-06-04 19:35 [PATCH] drm/amdgpu: Grab/put runtime PM references in atomic_commit_tail() Lyude Paul
@ 2018-06-05  6:16 ` Christian König
  2018-06-05 19:04 ` Harry Wentland
  1 sibling, 0 replies; 3+ messages in thread
From: Christian König @ 2018-06-05  6:16 UTC (permalink / raw)
  To: Lyude Paul, amd-gfx
  Cc: Alex Deucher, David (ChunMing) Zhou, David Airlie,
	Harry Wentland, Andrey Grodzovsky, Tony Cheng, Leo (Sunpeng) Li,
	Shirish S, dri-devel, linux-kernel

Am 04.06.2018 um 21:35 schrieb Lyude Paul:
> 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>

The final decision is with Harray, but at least the explanation makes 
perfect sense to me.

Acked-by: Christian König <christian.koenig@amd.com>.

Harry do you want to pick that up and push it into our internal branch 
while Alex is on vacation or should I do that?

Regards,
Christian.

> ---
> As a note, I'm not entirely happy with this fix and I wouldn't be
> surprised if I missed something while looking through amdgpu. So, please
> don't hesistate to suggest a better fix :).
>
>   drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 13 +++++++++++++
>   1 file changed, 13 insertions(+)
>
> 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 1dd1142246c2..361b81ef6997 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 @@
>   #include <linux/moduleparam.h>
>   #include <linux/version.h>
>   #include <linux/types.h>
> +#include <linux/pm_runtime.h>
>   
>   #include <drm/drmP.h>
>   #include <drm/drm_atomic.h>
> @@ -4211,6 +4212,8 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
>   			if (dm_old_crtc_state->stream)
>   				remove_stream(adev, acrtc, dm_old_crtc_state->stream);
>   
> +			pm_runtime_get_noresume(dev->dev);
> +
>   			acrtc->enabled = true;
>   			acrtc->hw_mode = new_crtc_state->mode;
>   			crtc->hwmode = new_crtc_state->mode;
> @@ -4396,6 +4399,16 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
>   		drm_atomic_helper_wait_for_flip_done(dev, state);
>   
>   	drm_atomic_helper_cleanup_planes(dev, state);
> +
> +	/* Finally, drop a runtime PM reference for each newly disabled CRTC,
> +	 * so we can put the GPU into runtime suspend if we're not driving any
> +	 * displays anymore
> +	 */
> +	pm_runtime_mark_last_busy(dev->dev);
> +	for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
> +		if (old_crtc_state->active && !new_crtc_state->active)
> +			pm_runtime_put_autosuspend(dev->dev);
> +	}
>   }
>   
>   

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] drm/amdgpu: Grab/put runtime PM references in atomic_commit_tail()
  2018-06-04 19:35 [PATCH] drm/amdgpu: Grab/put runtime PM references in atomic_commit_tail() Lyude Paul
  2018-06-05  6:16 ` Christian König
@ 2018-06-05 19:04 ` Harry Wentland
  1 sibling, 0 replies; 3+ messages in thread
From: Harry Wentland @ 2018-06-05 19:04 UTC (permalink / raw)
  To: Lyude Paul, amd-gfx
  Cc: Alex Deucher, Christian König, David (ChunMing) Zhou,
	David Airlie, Andrey Grodzovsky, Tony Cheng, Leo (Sunpeng) Li,
	Shirish S, dri-devel, linux-kernel

On 2018-06-04 03:35 PM, Lyude Paul wrote:
> 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>


I'm not familiar with the runtime_pm stuff, as is painfully obvious from the fact that we missed that with the DC driver. That said, from a cursory look at runtime_pm.txt, this looks right. 

Reviewed-by: Harry Wentland <harry.wentland@amd.com>

I'll pull this in through the amd-stg tree.

> ---
> As a note, I'm not entirely happy with this fix and I wouldn't be
> surprised if I missed something while looking through amdgpu. So, please
> don't hesistate to suggest a better fix :).

I still don't really like amdgpu_dm_atomic_commit_tail and related functions. We have plans to rework these and make them more straight-forward.

Harry

> 
>  drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 13 +++++++++++++
>  1 file changed, 13 insertions(+)
> 
> 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 1dd1142246c2..361b81ef6997 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 @@
>  #include <linux/moduleparam.h>
>  #include <linux/version.h>
>  #include <linux/types.h>
> +#include <linux/pm_runtime.h>
>  
>  #include <drm/drmP.h>
>  #include <drm/drm_atomic.h>
> @@ -4211,6 +4212,8 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
>  			if (dm_old_crtc_state->stream)
>  				remove_stream(adev, acrtc, dm_old_crtc_state->stream);
>  
> +			pm_runtime_get_noresume(dev->dev);
> +
>  			acrtc->enabled = true;
>  			acrtc->hw_mode = new_crtc_state->mode;
>  			crtc->hwmode = new_crtc_state->mode;
> @@ -4396,6 +4399,16 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
>  		drm_atomic_helper_wait_for_flip_done(dev, state);
>  
>  	drm_atomic_helper_cleanup_planes(dev, state);
> +
> +	/* Finally, drop a runtime PM reference for each newly disabled CRTC,
> +	 * so we can put the GPU into runtime suspend if we're not driving any
> +	 * displays anymore
> +	 */
> +	pm_runtime_mark_last_busy(dev->dev);
> +	for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
> +		if (old_crtc_state->active && !new_crtc_state->active)
> +			pm_runtime_put_autosuspend(dev->dev);
> +	}
>  }
>  
>  
> 

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2018-06-05 19:05 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-06-04 19:35 [PATCH] drm/amdgpu: Grab/put runtime PM references in atomic_commit_tail() Lyude Paul
2018-06-05  6:16 ` Christian König
2018-06-05 19:04 ` Harry Wentland

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).