Patchwork [3.11.y.z,extended,stable] Patch "drm/i915: Break encoder->crtc link separately in intel_sanitize_crtc()" has been added to staging queue

mail settings
Submitter Luis Henriques
Date May 14, 2014, 2:57 p.m.
Message ID <>
Download mbox | patch
Permalink /patch/348819/
State New
Headers show


Luis Henriques - May 14, 2014, 2:57 p.m.
This is a note to let you know that I have just added a patch titled

    drm/i915: Break encoder->crtc link separately in intel_sanitize_crtc()

to the linux-3.11.y-queue branch of the 3.11.y.z extended stable tree 
which can be found at:;a=shortlog;h=refs/heads/linux-3.11.y-queue

If you, or anyone else, feels it should not be added to this tree, please 
reply to this email.

For more information about the 3.11.y.z tree, see



From 05d8dc27a946882f184fa7c84ece8cf00e08d85f Mon Sep 17 00:00:00 2001
From: Egbert Eich <>
Date: Fri, 25 Apr 2014 10:56:22 +0200
Subject: drm/i915: Break encoder->crtc link separately in

commit 7f1950fbb989e8fc5463b307e062b4529d51c862 upstream.

Depending on the SDVO output_flags SDVO may have multiple connectors
linking to the same encoder (in intel_connector->encoder->base).
Only one of those connectors should be active (ie link to the encoder
thru drm_connector->encoder).
If intel_connector_break_all_links() is called from intel_sanitize_crtc()
we may break the crtc connection of an encoder thru an inactive connector
in which case intel_connector_break_all_links() will not be called again
for the active connector if this happens to come later in the list due to:
    if (connector->encoder->base.crtc != &crtc->base)
in intel_sanitize_crtc().
This will however leave the drm_connector->encoder linkage for this
active connector in place. Subsequently this will cause multiple
warnings in intel_connector_check_state() to trigger and the driver
will eventually die in drm_encoder_crtc_ok() (because of crtc == NULL).

To avoid this remove intel_connector_break_all_links() and move its
code to its two calling functions: intel_sanitize_crtc() and
This allows to implement the link breaking more flexibly matching
the surrounding code: ie. in intel_sanitize_crtc() we can break the
crtc link separatly after the links to the encoders have been
broken which avoids above problem.

This regression has been introduced in:

commit 24929352481f085c5f85d4d4cbc919ddf106d381
Author: Daniel Vetter <>
Date:   Mon Jul 2 20:28:59 2012 +0200

    drm/i915: read out the modeset hw state at load and resume time

so goes back to the very beginning of the modeset rework.

v2: This patch takes care of the concernes voiced by Chris Wilson
and Daniel Vetter that only breaking links if the drm_connector
is linked to an encoder may miss some links.
v3: move all encoder handling to encoder loop as suggested by
Daniel Vetter.

Signed-off-by: Egbert Eich <>
Reviewed-by: Daniel Vetter <>
Cc: Jani Nikula <>
Signed-off-by: Jani Nikula <>
Signed-off-by: Luis Henriques <>
 drivers/gpu/drm/i915/intel_display.c | 26 ++++++++++++++------------
 1 file changed, 14 insertions(+), 12 deletions(-)



diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 91cbf6f..d6bce47 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -9682,15 +9682,6 @@  void intel_modeset_init(struct drm_device *dev)

-static void
-intel_connector_break_all_links(struct intel_connector *connector)
-	connector->base.dpms = DRM_MODE_DPMS_OFF;
-	connector->base.encoder = NULL;
-	connector->encoder->connectors_active = false;
-	connector->encoder->base.crtc = NULL;
 static void intel_enable_pipe_a(struct drm_device *dev)
 	struct intel_connector *connector;
@@ -9772,8 +9763,17 @@  static void intel_sanitize_crtc(struct intel_crtc *crtc)
 			if (connector->encoder->base.crtc != &crtc->base)

-			intel_connector_break_all_links(connector);
+			connector->base.dpms = DRM_MODE_DPMS_OFF;
+			connector->base.encoder = NULL;
+		/* multiple connectors may have the same encoder:
+		 *  handle them and break crtc link separately */
+		list_for_each_entry(connector, &dev->mode_config.connector_list,
+				    base.head)
+			if (connector->encoder->base.crtc == &crtc->base) {
+				connector->encoder->base.crtc = NULL;
+				connector->encoder->connectors_active = false;
+			}

 		crtc->base.enabled = false;
@@ -9844,6 +9844,8 @@  static void intel_sanitize_encoder(struct intel_encoder *encoder)
+		encoder->base.crtc = NULL;
+		encoder->connectors_active = false;

 		/* Inconsistent output/port/pipe state happens presumably due to
 		 * a bug in one of the get_hw_state functions. Or someplace else
@@ -9854,8 +9856,8 @@  static void intel_sanitize_encoder(struct intel_encoder *encoder)
 				    base.head) {
 			if (connector->encoder != encoder)
-			intel_connector_break_all_links(connector);
+			connector->base.dpms = DRM_MODE_DPMS_OFF;
+			connector->base.encoder = NULL;
 	/* Enabled encoders without active connectors will be fixed in