From: Paulo Zanoni <[email protected]>

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 <[email protected]>
---
 drivers/gpu/drm/i915/intel_ddi.c |  2 ++
 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 aed363c..324211a 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)
        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;
        }
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index da7460c..b311eaf 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,
        } 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;
        }
 
@@ -3146,6 +3145,13 @@ 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)) {
+               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;
@@ -3208,6 +3214,9 @@ intel_dp_init(struct drm_device *dev, int output_reg, 
enum port port)
        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);
+       }
 }
-- 
1.8.1.2

_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to