blob: c127a2e10e6459eaec6a62074500ec8919a7ef9a [file] [log] [blame]
From b76b6f1d0b67532fdd33934addae3c3e30e8f8c1 Mon Sep 17 00:00:00 2001
From: Paulo Zanoni <paulo.r.zanoni@intel.com>
Date: Wed, 12 Jun 2013 17:27:27 -0300
Subject: 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>
(cherry picked from commit 15b1d171d87e86366266255462e6b11d21b61c1c)
Signed-off-by: Darren Hart <dvhart@linux.intel.com>
---
drivers/gpu/drm/i915/intel_ddi.c | 2 ++
drivers/gpu/drm/i915/intel_dp.c | 13 +++++++++++--
2 files changed, 13 insertions(+), 2 deletions(-)
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -1367,6 +1367,8 @@ void intel_ddi_init(struct drm_device *d
intel_encoder->hot_plug = intel_ddi_hot_plug;
if (!intel_dp_init_connector(intel_dig_port, dp_connector)) {
+ drm_encoder_cleanup(encoder);
+ kfree(intel_dig_port);
kfree(dp_connector);
return;
}
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -3013,7 +3013,6 @@ static bool intel_edp_init_connector(str
} else {
/* if this fails, presume the device is a ghost */
DRM_INFO("failed to retrieve link info, disabling eDP\n");
- intel_dp_encoder_destroy(&intel_dig_port->base.base);
return false;
}
@@ -3173,6 +3172,13 @@ intel_dp_init_connector(struct intel_dig
intel_dp_i2c_init(intel_dp, intel_connector, name);
if (!intel_edp_init_connector(intel_dp, intel_connector)) {
+ i2c_del_adapter(&intel_dp->adapter);
+ if (is_edp(intel_dp)) {
+ cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
+ mutex_lock(&dev->mode_config.mutex);
+ ironlake_panel_vdd_off_sync(intel_dp);
+ mutex_unlock(&dev->mode_config.mutex);
+ }
drm_sysfs_connector_remove(connector);
drm_connector_cleanup(connector);
return false;
@@ -3235,6 +3241,9 @@ intel_dp_init(struct drm_device *dev, in
intel_encoder->cloneable = false;
intel_encoder->hot_plug = intel_dp_hot_plug;
- if (!intel_dp_init_connector(intel_dig_port, intel_connector))
+ if (!intel_dp_init_connector(intel_dig_port, intel_connector)) {
+ drm_encoder_cleanup(encoder);
+ kfree(intel_dig_port);
kfree(intel_connector);
+ }
}