dp_write_aux(catalog, REG_DP_DP_HPD_CTRL, DP_DP_HPD_CTRL_HPD_EN);
 }
 
-u32 dp_catalog_hpd_get_state_status(struct dp_catalog *dp_catalog)
+u32 dp_catalog_link_is_connected(struct dp_catalog *dp_catalog)
 {
        struct dp_catalog_private *catalog = container_of(dp_catalog,
                                struct dp_catalog_private, dp_catalog);
 
 void dp_catalog_hpd_config_intr(struct dp_catalog *dp_catalog,
                        u32 intr_mask, bool en);
 void dp_catalog_ctrl_hpd_config(struct dp_catalog *dp_catalog);
-u32 dp_catalog_hpd_get_state_status(struct dp_catalog *dp_catalog);
+u32 dp_catalog_link_is_connected(struct dp_catalog *dp_catalog);
 u32 dp_catalog_hpd_get_intr_status(struct dp_catalog *dp_catalog);
 void dp_catalog_ctrl_phy_reset(struct dp_catalog *dp_catalog);
 int dp_catalog_ctrl_update_vx_px(struct dp_catalog *dp_catalog, u8 v_level,
 
        return ret;
 }
 
+static int dp_ctrl_deinitialize_mainlink(struct dp_ctrl_private *ctrl)
+{
+       struct dp_io *dp_io;
+       struct phy *phy;
+       int ret;
+
+       dp_io = &ctrl->parser->io;
+       phy = dp_io->phy;
+
+       dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, false);
+
+       dp_catalog_ctrl_reset(ctrl->catalog);
+
+       ret = dp_power_clk_enable(ctrl->power, DP_CTRL_PM, false);
+       if (ret) {
+               DRM_ERROR("Failed to disable link clocks. ret=%d\n", ret);
+       }
+
+       phy_power_off(phy);
+       phy_exit(phy);
+
+       return 0;
+}
+
 static int dp_ctrl_link_maintenance(struct dp_ctrl_private *ctrl)
 {
        int ret = 0;
        if (rc)
                return rc;
 
-       while (--link_train_max_retries &&
-               !atomic_read(&ctrl->dp_ctrl.aborted)) {
+       while (--link_train_max_retries) {
                rc = dp_ctrl_reinitialize_mainlink(ctrl);
                if (rc) {
                        DRM_ERROR("Failed to reinitialize mainlink. rc=%d\n",
                        break;
                } else if (training_step == DP_TRAINING_1) {
                        /* link train_1 failed */
+                       if (!dp_catalog_link_is_connected(ctrl->catalog)) {
+                               break;
+                       }
+
                        rc = dp_ctrl_link_rate_down_shift(ctrl);
                        if (rc < 0) { /* already in RBR = 1.6G */
                                if (cr.lane_0_1 & DP_LANE0_1_CR_DONE) {
                        }
                } else if (training_step == DP_TRAINING_2) {
                        /* link train_2 failed, lower lane rate */
+                       if (!dp_catalog_link_is_connected(ctrl->catalog)) {
+                               break;
+                       }
+
                        rc = dp_ctrl_link_lane_down_shift(ctrl);
                        if (rc < 0) {
                                /* end with failure */
         */
        if (rc == 0)  /* link train successfully */
                dp_ctrl_push_idle(dp_ctrl);
+       else  {
+               /* link training failed */
+               dp_ctrl_deinitialize_mainlink(ctrl);
+               rc = -ECONNRESET;
+       }
 
        return rc;
 }
 
        if (ret) {      /* link train failed */
                hpd->hpd_high = 0;
                dp->hpd_state = ST_DISCONNECTED;
+
+               if (ret == -ECONNRESET) { /* cable unplugged */
+                       dp->core_initialized = false;
+               }
+
        } else {
                /* start sentinel checking in case of missing uevent */
                dp_add_event(dp, EV_CONNECT_PENDING_TIMEOUT, 0, tout);
 
        dp_display = g_dp_display;
 
+       if (dp_display->power_on) {
+               DRM_DEBUG_DP("Link already setup, return\n");
+               return 0;
+       }
+
        rc = dp_ctrl_on_stream(dp->ctrl);
        if (!rc)
                dp_display->power_on = true;
 
        dp_display = g_dp_display;
 
+       if (!dp_display->power_on)
+               return 0;
+
        /* wait only if audio was enabled */
        if (dp_display->audio_enabled) {
                if (!wait_for_completion_timeout(&dp->audio_comp,
 
        dp_catalog_ctrl_hpd_config(dp->catalog);
 
-       status = dp_catalog_hpd_get_state_status(dp->catalog);
+       status = dp_catalog_link_is_connected(dp->catalog);
 
        if (status)
                dp->dp_display.is_connected = true;
 
        if (!dp_panel->edid) {
                DRM_ERROR("panel edid read failed\n");
                /* check edid read fail is due to unplug */
-               if (!dp_catalog_hpd_get_state_status(panel->catalog)) {
+               if (!dp_catalog_link_is_connected(panel->catalog)) {
                        rc = -ETIMEDOUT;
                        goto end;
                }