diff options
author | Lukas Wunner <lukas@wunner.de> | 2016-06-08 18:47:27 +0200 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2016-06-24 08:49:34 +0200 |
commit | 523872f6b0724ee93d4dad898219306c45c78553 (patch) | |
tree | 1d318958561a1e4521c08bc9218094e832973943 | |
parent | 6a0d95285035c43361c72776b4c618f60c0f4ab4 (diff) | |
download | linux-523872f6b0724ee93d4dad898219306c45c78553.tar.bz2 |
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
-rw-r--r-- | drivers/gpu/drm/nouveau/dispnv04/disp.c | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_display.c | 1 |
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 aea81a547e85..34c0f2f67548 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 6072fe292db8..bd8d5bb2c885 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) |