diff options
author | Paulo Zanoni <paulo.r.zanoni@intel.com> | 2013-06-12 16:27:27 -0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2013-06-28 08:14:19 -0400 |
commit | 15b1d171d87e86366266255462e6b11d21b61c1c (patch) | |
tree | aafd88ac91164f176ed365ec7ff8cd82c8112dde | |
parent | b2f246a8998ccf9e00477c8829a62139804e9857 (diff) |
drm/i915: fix the "ghost eDP" encoder unwind path
Because calling intel_dp_encoder_destroy inside
intel_edp_init_connector is just wrong. This is the initialization
path, so we should properly unwind all the initialization through the
whole caller stack.
On the intel_dp_encoder_destroy function we do the following:
1 - Call i2c_del_adapter
2 - Call drm_encoder_cleanup
3 - If edp:
3.1 - Cancel panel_vdd_work
3.2 - Call ironlake_panel_vdd_of_sync
4 - Free the encoder
And here is how we unwind each specific step:
1 - We have intel_dp_init_connector -> intel_dp_i2c_init ->
i2c_dp_aux_add_bus -> i2c_add_adapter, so we call
i2c_del_dapter at intel_dp_init_connector
2 - Call it in the same function that called drm_encoder_init
3 - Call it in the same function that called INIT_DELAYED_WORK
4 - Free it in the same function that allocated it
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Reviewed-by: Zoltan Nyul <zoltan.nyul@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r-- | drivers/gpu/drm/i915/intel_ddi.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_dp.c | 13 |
2 files changed, 13 insertions, 2 deletions
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index aed363cabe07..324211ac9c55 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c | |||
@@ -1357,6 +1357,8 @@ void intel_ddi_init(struct drm_device *dev, enum port port) | |||
1357 | intel_encoder->hot_plug = intel_ddi_hot_plug; | 1357 | intel_encoder->hot_plug = intel_ddi_hot_plug; |
1358 | 1358 | ||
1359 | if (!intel_dp_init_connector(intel_dig_port, dp_connector)) { | 1359 | if (!intel_dp_init_connector(intel_dig_port, dp_connector)) { |
1360 | drm_encoder_cleanup(encoder); | ||
1361 | kfree(intel_dig_port); | ||
1360 | kfree(dp_connector); | 1362 | kfree(dp_connector); |
1361 | return; | 1363 | return; |
1362 | } | 1364 | } |
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 5ba0a612d463..ed1d34680125 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
@@ -2986,7 +2986,6 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, | |||
2986 | } else { | 2986 | } else { |
2987 | /* if this fails, presume the device is a ghost */ | 2987 | /* if this fails, presume the device is a ghost */ |
2988 | DRM_INFO("failed to retrieve link info, disabling eDP\n"); | 2988 | DRM_INFO("failed to retrieve link info, disabling eDP\n"); |
2989 | intel_dp_encoder_destroy(&intel_dig_port->base.base); | ||
2990 | return false; | 2989 | return false; |
2991 | } | 2990 | } |
2992 | 2991 | ||
@@ -3146,6 +3145,13 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, | |||
3146 | intel_dp_i2c_init(intel_dp, intel_connector, name); | 3145 | intel_dp_i2c_init(intel_dp, intel_connector, name); |
3147 | 3146 | ||
3148 | if (!intel_edp_init_connector(intel_dp, intel_connector)) { | 3147 | if (!intel_edp_init_connector(intel_dp, intel_connector)) { |
3148 | i2c_del_adapter(&intel_dp->adapter); | ||
3149 | if (is_edp(intel_dp)) { | ||
3150 | cancel_delayed_work_sync(&intel_dp->panel_vdd_work); | ||
3151 | mutex_lock(&dev->mode_config.mutex); | ||
3152 | ironlake_panel_vdd_off_sync(intel_dp); | ||
3153 | mutex_unlock(&dev->mode_config.mutex); | ||
3154 | } | ||
3149 | drm_sysfs_connector_remove(connector); | 3155 | drm_sysfs_connector_remove(connector); |
3150 | drm_connector_cleanup(connector); | 3156 | drm_connector_cleanup(connector); |
3151 | return false; | 3157 | return false; |
@@ -3208,6 +3214,9 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port) | |||
3208 | intel_encoder->cloneable = false; | 3214 | intel_encoder->cloneable = false; |
3209 | intel_encoder->hot_plug = intel_dp_hot_plug; | 3215 | intel_encoder->hot_plug = intel_dp_hot_plug; |
3210 | 3216 | ||
3211 | if (!intel_dp_init_connector(intel_dig_port, intel_connector)) | 3217 | if (!intel_dp_init_connector(intel_dig_port, intel_connector)) { |
3218 | drm_encoder_cleanup(encoder); | ||
3219 | kfree(intel_dig_port); | ||
3212 | kfree(intel_connector); | 3220 | kfree(intel_connector); |
3221 | } | ||
3213 | } | 3222 | } |