scsi: ufs: detect data link error and recovery
authorhgchu <hg.chu@samsung.com>
Fri, 12 Jan 2018 02:07:49 +0000 (11:07 +0900)
committerJaeHun Jung <jh0801.jung@samsung.com>
Tue, 8 May 2018 08:20:17 +0000 (17:20 +0900)
Change-Id: I7418d2c071e737b1a4de5248e97bb0735af65975
Signed-off-by: hgchu <hg.chu@samsung.com>
drivers/scsi/ufs/ufshcd.c
drivers/scsi/ufs/ufshcd.h

index 5d0b203856ec19f9c6229a35c3cf4369864c229c..9686aa31ffaae40df48b6e94c4b2516949a4ed80 100644 (file)
@@ -136,6 +136,7 @@ enum {
        UFSHCD_UIC_NL_ERROR = (1 << 3), /* Network layer error */
        UFSHCD_UIC_TL_ERROR = (1 << 4), /* Transport Layer error */
        UFSHCD_UIC_DME_ERROR = (1 << 5), /* DME error */
+       UFSHCD_UIC_DL_ERROR = (1 << 6), /* Data link layer error */
 };
 
 #define ufshcd_set_eh_in_progress(h) \
@@ -3873,6 +3874,9 @@ static int ufshcd_link_hibern8_ctrl(struct ufs_hba *hba, bool en)
        if (hba->vops && hba->vops->hibern8_notify)
                hba->vops->hibern8_notify(hba, en, POST_CHANGE);
 out:
+       hba->tcx_replay_timer_expired_cnt = 0;
+       hba->fcx_protection_timer_expired_cnt = 0;
+
        return ret;
 }
 
@@ -5370,6 +5374,16 @@ static void ufshcd_update_uic_error(struct ufs_hba *hba)
                        hba->uic_error |= UFSHCD_UIC_DL_TCx_REPLAY_ERROR;
        }
 
+       if (reg & UIC_DATA_LINK_LAYER_ERROR_TCX_REP_TIMER_EXP)
+               hba->tcx_replay_timer_expired_cnt++;
+
+       if (reg & UIC_DATA_LINK_LAYER_ERROR_FCX_PRO_TIMER_EXP)
+               hba->fcx_protection_timer_expired_cnt++;
+
+       if (hba->tcx_replay_timer_expired_cnt >= 2 ||
+           hba->fcx_protection_timer_expired_cnt >= 2)
+               hba->uic_error |= UFSHCD_UIC_DL_ERROR;
+
        /* UIC NL/TL/DME errors needs software retry */
        reg = ufshcd_readl(hba, REG_UIC_ERROR_CODE_NETWORK_LAYER);
        if (reg) {
index d824d679694798e30aa270e5dbc1ae234baaad9e..b2669823fa0c602722cb437bcaef336ec217739d 100644 (file)
@@ -634,6 +634,9 @@ struct ufs_hba {
        u32 saved_uic_err;
        struct ufs_stats ufs_stats;
 
+       u32 tcx_replay_timer_expired_cnt;
+       u32 fcx_protection_timer_expired_cnt;
+
        /* Device management request data */
        struct ufs_dev_cmd dev_cmd;
        ktime_t last_dme_cmd_tstamp;