From 16c255335b0ec39b4e5e976f4b260978aeed5a68 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Wed, 12 Jun 2013 17:27:25 -0300 Subject: [PATCH] drm/i915: propagate errors from intel_dp_init_connector In case we detect a "ghost eDP", intel_edp_init_connector frees both the connector and encoder and then returns. On Haswell, intel_ddi_init then tries to use the freed encoder on the HDMI initialization path since the following commit: commit 21a8e6a4853b2ed39fa4c5188a710f2cf1b92026 Author: Daniel Vetter Date: Wed Apr 10 23:28:35 2013 +0200 drm/i915: don't setup hdmi for port D edp in ddi_init So now on intel_ddi_init we check for the "ghost eDP" case and return without trying to initialize HDMI. This way we won't try to read the freed "intel_encoder" struct in the next "if" statement. Signed-off-by: Paulo Zanoni Reviewed-by: Zoltan Nyul Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ddi.c | 3 ++- drivers/gpu/drm/i915/intel_dp.c | 6 ++++-- drivers/gpu/drm/i915/intel_drv.h | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 224ce25..0f835d1 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1356,7 +1356,8 @@ void intel_ddi_init(struct drm_device *dev, enum port port) intel_encoder->cloneable = false; intel_encoder->hot_plug = intel_ddi_hot_plug; - intel_dp_init_connector(intel_dig_port, dp_connector); + if (!intel_dp_init_connector(intel_dig_port, dp_connector)) + return; if (intel_encoder->type != INTEL_OUTPUT_EDP) { hdmi_connector = kzalloc(sizeof(struct intel_connector), diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 30514e5..1a429cf 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -3035,7 +3035,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, return true; } -void +bool intel_dp_init_connector(struct intel_digital_port *intel_dig_port, struct intel_connector *intel_connector) { @@ -3147,7 +3147,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, intel_dp_i2c_init(intel_dp, intel_connector, name); if (!intel_edp_init_connector(intel_dp, intel_connector)) - return; + return false; intel_dp_add_properties(intel_dp, connector); @@ -3159,6 +3159,8 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, u32 temp = I915_READ(PEG_BAND_GAP_DATA); I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd); } + + return true; } void diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index ffe9d35..9ddbe3b 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -586,7 +586,7 @@ extern void intel_lvds_init(struct drm_device *dev); extern bool intel_is_dual_link_lvds(struct drm_device *dev); extern void intel_dp_init(struct drm_device *dev, int output_reg, enum port port); -extern void intel_dp_init_connector(struct intel_digital_port *intel_dig_port, +extern bool intel_dp_init_connector(struct intel_digital_port *intel_dig_port, struct intel_connector *intel_connector); extern void intel_dp_init_link_config(struct intel_dp *intel_dp); extern void intel_dp_start_link_train(struct intel_dp *intel_dp); -- 2.7.4