On Wed, Apr 16, 2014 at 11:16:45AM +0200, Egbert Eich wrote:
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)
continue;
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
intel_sanitize_encoder().
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.
Signed-off-by: Egbert Eich e...@suse.de
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.
---
drivers/gpu/drm/i915/intel_display.c | 25 +
1 file changed, 13 insertions(+), 12 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_display.c
b/drivers/gpu/drm/i915/intel_display.c
index 1390ab5..c276733 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -11386,15 +11386,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;
@@ -11476,8 +11467,16 @@ static void intel_sanitize_crtc(struct intel_crtc
*crtc)
if (connector-encoder-base.crtc != crtc-base)
continue;
- intel_connector_break_all_links(connector);
+ connector-base.dpms = DRM_MODE_DPMS_OFF;
+ connector-encoder-connectors_active = false;
I'd move the encoder-connectors_active = false down into the encoder
loop, but doesn't really matter. Jani can frob this when applying for
3.15-fixes.
This regression has been introduced in
commit 24929352481f085c5f85d4d4cbc919ddf106d381
Author: Daniel Vetter daniel.vet...@ffwll.ch
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.
Reviewed-by: Daniel Vetter daniel.vet...@ffwll.ch
Cc: sta...@vger.kernel.org
Thanks, Daniel
+ connector-base.encoder = NULL;
}
+ /* multiple connectors may have the same encoder:
+ * 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;
WARN_ON(crtc-active);
crtc-base.enabled = false;
@@ -11559,6 +11558,8 @@ static void intel_sanitize_encoder(struct
intel_encoder *encoder)
drm_get_encoder_name(encoder-base));
encoder-disable(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
@@ -11569,8 +11570,8 @@ static void intel_sanitize_encoder(struct
intel_encoder *encoder)
base.head) {
if (connector-encoder != encoder)