summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2011-11-28 21:10:05 +0000
committerEugeni Dodonov <eugeni.dodonov@intel.com>2012-02-10 18:01:18 -0200
commit5b4714e45c6f3c3761c09851e9878763043aa24c (patch)
treec23e1b0abb4b10763a9a8baa4ad5247f9c11d592
parent94a99359b289fcac8cd4254de16e34f5fcf78d63 (diff)
drm: Fix lack of CRTC disable for drm_crtc_helper_set_config(.fb=NULL)
Disabling the CRTC by setting its framebuffer to NULL, as used by drm_framebuffer_cleanup(), was failing to pass the current framebuffer to the crtc_func->disable callback. This is because of the dance within drm_crtc_helper_set_config to pass the new_fb (NULL in this case) to the drm_crtc_helper_set_mode with the currently attached fb as a parameter. drm_crtc_helper_set_mode treats this as a no-op and the encoder is still enabled. And so the current fb is forgotten before the call to drm_helper_disable_unused_functions. This patch treats disabling the CRTC as a simple special case rather than adding further complexity into the configuration logic. This fixes a pin-leak of the fb bo on Xserver close. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Signed-off-by: Dave Airlie <airlied@redhat.com> Signed-off-by: Eugeni Dodonov <eugeni.dodonov@intel.com>
-rw-r--r--drivers/gpu/drm/drm_crtc_helper.c27
1 files changed, 25 insertions, 2 deletions
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index 92369655dca..6491d217154 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -451,6 +451,30 @@ done:
EXPORT_SYMBOL(drm_crtc_helper_set_mode);
+static int
+drm_crtc_helper_disable(struct drm_crtc *crtc)
+{
+ struct drm_device *dev = crtc->dev;
+ struct drm_connector *connector;
+ struct drm_encoder *encoder;
+
+ /* Decouple all encoders and their attached connectors from this crtc */
+ list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+ if (encoder->crtc != crtc)
+ continue;
+
+ list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+ if (connector->encoder != encoder)
+ continue;
+
+ connector->encoder = NULL;
+ }
+ }
+
+ drm_helper_disable_unused_functions(dev);
+ return 0;
+}
+
/**
* drm_crtc_helper_set_config - set a new config from userspace
* @crtc: CRTC to setup
@@ -504,8 +528,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
(int)set->num_connectors, set->x, set->y);
} else {
DRM_DEBUG_KMS("[CRTC:%d] [NOFB]\n", set->crtc->base.id);
- set->mode = NULL;
- set->num_connectors = 0;
+ return drm_crtc_helper_disable(set->crtc);
}
dev = set->crtc->dev;