diff mbox

[v2,2/3] drm/nouveau: Fix runtime PM leak in nv50_disp_atomic_commit()

Message ID 20180712170256.13018-3-lyude@redhat.com (mailing list archive)
State New, archived
Headers show

Commit Message

Lyude Paul July 12, 2018, 5:02 p.m. UTC
A CRTC being enabled doesn't mean it's on! It doesn't even necessarily
mean it's being used. This fixes runtime PM leaks on the P50 I've got
next to me.

Signed-off-by: Lyude Paul <lyude@redhat.com>
Cc: stable@vger.kernel.org
---
 drivers/gpu/drm/nouveau/dispnv50/disp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Comments

Lukas Wunner July 17, 2018, 7:33 a.m. UTC | #1
On Thu, Jul 12, 2018 at 01:02:53PM -0400, Lyude Paul wrote:
> --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
> +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> @@ -1878,7 +1878,7 @@ nv50_disp_atomic_commit(struct drm_device *dev,
>  		nv50_disp_atomic_commit_tail(state);
>  
>  	drm_for_each_crtc(crtc, dev) {
> -		if (crtc->state->enable) {
> +		if (crtc->state->active) {
>  			if (!drm->have_disp_power_ref) {
>  				drm->have_disp_power_ref = true;
>  				return 0;

Somewhat tangential comment on this older patch, since you
continue to dig around in the runtime PM area:

Whenever a crtc is activated or deactivated in nouveau, we iterate
over all crtcs and acquire a runtime PM if a crtc is active and
previously there was no active one, or we drop a ref if none is
active and previously there was an active one.

For a while now I've been thinking that it would be more straightforward
to acquire a ref whenever a crtc is activated and drop one when a crtc
is deactivated, i.e. hold one ref for every active crtc.  That way the
have_disp_power_ref variable as well as the iteration logic could be
removed, leading to a simplification.  Just a suggestion anyway.

Thanks,

Lukas
Ville Syrjälä July 17, 2018, 10:31 a.m. UTC | #2
On Tue, Jul 17, 2018 at 09:33:52AM +0200, Lukas Wunner wrote:
> On Thu, Jul 12, 2018 at 01:02:53PM -0400, Lyude Paul wrote:
> > --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > @@ -1878,7 +1878,7 @@ nv50_disp_atomic_commit(struct drm_device *dev,
> >  		nv50_disp_atomic_commit_tail(state);
> >  
> >  	drm_for_each_crtc(crtc, dev) {
> > -		if (crtc->state->enable) {
> > +		if (crtc->state->active) {
> >  			if (!drm->have_disp_power_ref) {
> >  				drm->have_disp_power_ref = true;
> >  				return 0;
> 
> Somewhat tangential comment on this older patch, since you
> continue to dig around in the runtime PM area:
> 
> Whenever a crtc is activated or deactivated in nouveau, we iterate
> over all crtcs and acquire a runtime PM if a crtc is active and
> previously there was no active one, or we drop a ref if none is
> active and previously there was an active one.
> 
> For a while now I've been thinking that it would be more straightforward
> to acquire a ref whenever a crtc is activated and drop one when a crtc
> is deactivated, i.e. hold one ref for every active crtc.  That way the
> have_disp_power_ref variable as well as the iteration logic could be
> removed, leading to a simplification.  Just a suggestion anyway.

The current code looks somewhat busted anyway. First problem is that
it's accessing crtc->state without the appropriate locks held (unless
something always pulls in all crtcs to every commit?). Second issue
is that the rpm_put() is called without waiting for nonblocking commits
to have finished so it looks like you can currentlly remove the power
before the hardware has been properly shut down.
diff mbox

Patch

diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index d9da69c83ae7..9bae4db84cfb 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -1878,7 +1878,7 @@  nv50_disp_atomic_commit(struct drm_device *dev,
 		nv50_disp_atomic_commit_tail(state);
 
 	drm_for_each_crtc(crtc, dev) {
-		if (crtc->state->enable) {
+		if (crtc->state->active) {
 			if (!drm->have_disp_power_ref) {
 				drm->have_disp_power_ref = true;
 				return 0;