summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/i915/intel_display.c
diff options
context:
space:
mode:
authorVille Syrjälä <ville.syrjala@linux.intel.com>2014-01-10 11:28:09 +0200
committerDaniel Vetter <daniel.vetter@ffwll.ch>2014-01-24 17:22:42 +0100
commit7d00a1f574842270515270ff27b86acde4e3d3c1 (patch)
treed12c47fc9247f2508836bdc485aa3750df4991a7 /drivers/gpu/drm/i915/intel_display.c
parent2f2d7aa15499aaa8fb43c88f150e00923b0e0fee (diff)
downloadlwn-7d00a1f574842270515270ff27b86acde4e3d3c1.tar.gz
lwn-7d00a1f574842270515270ff27b86acde4e3d3c1.zip
drm/i915: Don't oops if the initial modeset fails
If the first modeset operation fails, we will attempt to restore the previous configuration that we read out from the hardware. But as we don't yet reconstruct the framebuffer information, we end up calling the modeset code with an enabled crtc but with fb==NULL. This will lead to an oops within the modeset code. Check for NULL fb when restoring the configuration, and instead of oopsing simply disable the pipe. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Imre Deak <imre.deak@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r--drivers/gpu/drm/i915/intel_display.c32
1 files changed, 32 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index ce790d891473..3d6ce9774995 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -10024,6 +10024,29 @@ intel_modeset_stage_output_state(struct drm_device *dev,
return 0;
}
+static void disable_crtc_nofb(struct intel_crtc *crtc)
+{
+ struct drm_device *dev = crtc->base.dev;
+ struct intel_encoder *encoder;
+ struct intel_connector *connector;
+
+ DRM_DEBUG_KMS("Trying to restore without FB -> disabling pipe %c\n",
+ pipe_name(crtc->pipe));
+
+ list_for_each_entry(connector, &dev->mode_config.connector_list, base.head) {
+ if (connector->new_encoder &&
+ connector->new_encoder->new_crtc == crtc)
+ connector->new_encoder = NULL;
+ }
+
+ list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
+ if (encoder->new_crtc == crtc)
+ encoder->new_crtc = NULL;
+ }
+
+ crtc->new_enabled = false;
+}
+
static int intel_crtc_set_config(struct drm_mode_set *set)
{
struct drm_device *dev;
@@ -10100,6 +10123,15 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
fail:
intel_set_config_restore_state(dev, config);
+ /*
+ * HACK: if the pipe was on, but we didn't have a framebuffer,
+ * force the pipe off to avoid oopsing in the modeset code
+ * due to fb==NULL. This should only happen during boot since
+ * we don't yet reconstruct the FB from the hardware state.
+ */
+ if (to_intel_crtc(save_set.crtc)->new_enabled && !save_set.fb)
+ disable_crtc_nofb(to_intel_crtc(save_set.crtc));
+
/* Try to restore the config */
if (config->mode_changed &&
intel_set_mode(save_set.crtc, save_set.mode,