[v2,10/15] drm/nouveau: Turn off CRTCs on driver unload
diff mbox

Message ID 66daa161322444bbde05d83cb0210b90a66988a4.1465392124.git.lukas@wunner.de
State New
Headers show

Commit Message

Lukas Wunner June 8, 2016, 4:47 p.m. UTC
nouveau leaks a runtime pm ref if at least one CRTC is enabled on
unload. The ref is taken by nouveau_crtc_set_config() and held as long
as a CRTC is in use.

nv04_display_destroy() should solve this by turning off all CRTCs, but

(1) nv50_display_destroy() doesn't do the same and

(2) it's broken since commit d6bf2f370703 ("drm/nouveau: run mode_config
    destructor before destroying internal display state") because the
    crtc structs are torn down by drm_mode_config_cleanup() before being
    turned off. Also, there's no locking.

Move the code to turn off all CRTCs from nv04_display_destroy() to
nouveau_display_destroy() so that it's called for both nv04 and nv50
and before drm_mode_config_cleanup(). Use drm_crtc_force_disable_all()
helper to save on code and have proper locking.

Cc: Ben Skeggs <bskeggs@redhat.com>
Signed-off-by: Lukas Wunner <lukas@wunner.de>
---
 drivers/gpu/drm/nouveau/dispnv04/disp.c   | 10 ----------
 drivers/gpu/drm/nouveau/nouveau_display.c |  1 +
 2 files changed, 1 insertion(+), 10 deletions(-)

Patch
diff mbox

diff --git a/drivers/gpu/drm/nouveau/dispnv04/disp.c b/drivers/gpu/drm/nouveau/dispnv04/disp.c
index aea81a5..34c0f2f6 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/disp.c
@@ -125,18 +125,8 @@  nv04_display_destroy(struct drm_device *dev)
 	struct nv04_display *disp = nv04_display(dev);
 	struct nouveau_drm *drm = nouveau_drm(dev);
 	struct nouveau_encoder *encoder;
-	struct drm_crtc *crtc;
 	struct nouveau_crtc *nv_crtc;
 
-	/* Turn every CRTC off. */
-	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-		struct drm_mode_set modeset = {
-			.crtc = crtc,
-		};
-
-		drm_mode_set_config_internal(&modeset);
-	}
-
 	/* Restore state */
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.base.head)
 		encoder->enc_restore(&encoder->base.base);
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index 7c77f96..cbdb3d4 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -554,6 +554,7 @@  nouveau_display_destroy(struct drm_device *dev)
 	nouveau_display_vblank_fini(dev);
 
 	drm_kms_helper_poll_fini(dev);
+	drm_crtc_force_disable_all(dev);
 	drm_mode_config_cleanup(dev);
 
 	if (disp->dtor)