From mboxrd@z Thu Jan 1 00:00:00 1970 From: Paulo Zanoni Subject: [PATCH 5/8] drm/i915: fix the "ghost eDP" encoder unwind path Date: Wed, 12 Jun 2013 17:27:27 -0300 Message-ID: <1371068850-3531-6-git-send-email-przanoni@gmail.com> References: <1371068850-3531-1-git-send-email-przanoni@gmail.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: Received: from mail-yh0-f46.google.com (mail-yh0-f46.google.com [209.85.213.46]) by gabe.freedesktop.org (Postfix) with ESMTP id B2A4DE60A1 for ; Wed, 12 Jun 2013 13:28:06 -0700 (PDT) Received: by mail-yh0-f46.google.com with SMTP id i57so2233370yha.19 for ; Wed, 12 Jun 2013 13:28:06 -0700 (PDT) In-Reply-To: <1371068850-3531-1-git-send-email-przanoni@gmail.com> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: intel-gfx-bounces+gcfxdi-intel-gfx=m.gmane.org@lists.freedesktop.org Errors-To: intel-gfx-bounces+gcfxdi-intel-gfx=m.gmane.org@lists.freedesktop.org To: intel-gfx@lists.freedesktop.org Cc: Paulo Zanoni List-Id: intel-gfx@lists.freedesktop.org From: Paulo Zanoni 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 --- 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