summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorLukas Wunner <lukas@wunner.de>2016-06-08 16:47:27 (GMT)
committerDaniel Vetter <daniel.vetter@ffwll.ch>2016-06-24 06:49:34 (GMT)
commit523872f6b0724ee93d4dad898219306c45c78553 (patch)
tree1d318958561a1e4521c08bc9218094e832973943 /drivers
parent6a0d95285035c43361c72776b4c618f60c0f4ab4 (diff)
downloadlinux-523872f6b0724ee93d4dad898219306c45c78553.tar.xz
drm/nouveau: Turn off CRTCs on driver unload
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> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: http://patchwork.freedesktop.org/patch/msgid/66daa161322444bbde05d83cb0210b90a66988a4.1465392124.git.lukas@wunner.de
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/disp.c10
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.c1
2 files changed, 1 insertions, 10 deletions
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 6072fe2..bd8d5bb 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)