summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2016-11-17 10:08:44 -0800
committerGerrit - the friendly Code Review server <code-review@localhost>2016-11-17 10:08:43 -0800
commit5b00a91adb403b89a28e4aa45260f0ee9b5027a0 (patch)
tree92cccb1eaaa17a308c175d0d1fdf5704cddff296 /drivers
parenta1008bfb7692e78771caa8f0d56cc1bdbc948274 (diff)
parentbadf0ba0b466a9c7ee4f6cac7f0279a136508ff7 (diff)
Merge "scsi: ufs: handle LINERESET during hibern8"
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/ufs/ufshcd.c34
-rw-r--r--drivers/scsi/ufs/ufshcd.h2
-rw-r--r--drivers/scsi/ufs/ufshci.h1
3 files changed, 32 insertions, 5 deletions
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 19a8aacf98d0..259abcdf612e 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -4205,7 +4205,13 @@ static int __ufshcd_uic_hibern8_enter(struct ufs_hba *hba)
trace_ufshcd_profile_hibern8(dev_name(hba->dev), "enter",
ktime_to_us(ktime_sub(ktime_get(), start)), ret);
- if (ret) {
+ /*
+ * Do full reinit if enter failed or if LINERESET was detected during
+ * Hibern8 operation. After LINERESET, link moves to default PWM-G1
+ * mode hence full reinit is required to move link to HS speeds.
+ */
+ if (ret || hba->full_init_linereset) {
+ hba->full_init_linereset = false;
ufshcd_update_error_stats(hba, UFS_ERR_HIBERN8_ENTER);
dev_err(hba->dev, "%s: hibern8 enter failed. ret = %d",
__func__, ret);
@@ -4248,8 +4254,13 @@ int ufshcd_uic_hibern8_exit(struct ufs_hba *hba)
ret = ufshcd_uic_pwr_ctrl(hba, &uic_cmd);
trace_ufshcd_profile_hibern8(dev_name(hba->dev), "exit",
ktime_to_us(ktime_sub(ktime_get(), start)), ret);
-
- if (ret) {
+ /*
+ * Do full reinit if exit failed or if LINERESET was detected during
+ * Hibern8 operation. After LINERESET, link moves to default PWM-G1
+ * mode hence full reinit is required to move link to HS speeds.
+ */
+ if (ret || hba->full_init_linereset) {
+ hba->full_init_linereset = false;
ufshcd_update_error_stats(hba, UFS_ERR_HIBERN8_EXIT);
dev_err(hba->dev, "%s: hibern8 exit failed. ret = %d",
__func__, ret);
@@ -5900,9 +5911,8 @@ static void ufshcd_update_uic_error(struct ufs_hba *hba)
/* PHY layer lane error */
reg = ufshcd_readl(hba, REG_UIC_ERROR_CODE_PHY_ADAPTER_LAYER);
- /* Ignore LINERESET indication, as this is not an error */
if ((reg & UIC_PHY_ADAPTER_LAYER_ERROR) &&
- (reg & UIC_PHY_ADAPTER_LAYER_LANE_ERR_MASK)) {
+ (reg & UIC_PHY_ADAPTER_LAYER_ERROR_CODE_MASK)) {
/*
* To know whether this error is fatal or not, DB timeout
* must be checked but this error is handled separately.
@@ -5910,6 +5920,20 @@ static void ufshcd_update_uic_error(struct ufs_hba *hba)
dev_dbg(hba->dev, "%s: UIC Lane error reported, reg 0x%x\n",
__func__, reg);
ufshcd_update_uic_reg_hist(&hba->ufs_stats.pa_err, reg);
+
+ /* Don't ignore LINERESET indication during hibern8 operation */
+ if (reg & UIC_PHY_ADAPTER_LAYER_GENERIC_ERROR) {
+ struct uic_command *cmd = hba->active_uic_cmd;
+
+ if (cmd) {
+ if ((cmd->command == UIC_CMD_DME_HIBER_ENTER)
+ || (cmd->command == UIC_CMD_DME_HIBER_EXIT)) {
+ dev_err(hba->dev, "%s: LINERESET during hibern8, reg 0x%x\n",
+ __func__, reg);
+ hba->full_init_linereset = true;
+ }
+ }
+ }
}
/* PA_INIT_ERROR is fatal and needs UIC reset */
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 74fe46cf34fe..9f2b04c8ff82 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -905,6 +905,8 @@ struct ufs_hba {
bool no_ref_clk_gating;
int scsi_block_reqs_cnt;
+
+ bool full_init_linereset;
};
static inline void ufshcd_mark_shutdown_ongoing(struct ufs_hba *hba)
diff --git a/drivers/scsi/ufs/ufshci.h b/drivers/scsi/ufs/ufshci.h
index d65dad03bdd2..c0e4650a75ad 100644
--- a/drivers/scsi/ufs/ufshci.h
+++ b/drivers/scsi/ufs/ufshci.h
@@ -190,6 +190,7 @@ enum {
/* UECPA - Host UIC Error Code PHY Adapter Layer 38h */
#define UIC_PHY_ADAPTER_LAYER_ERROR UFS_BIT(31)
+#define UIC_PHY_ADAPTER_LAYER_GENERIC_ERROR UFS_BIT(4)
#define UIC_PHY_ADAPTER_LAYER_ERROR_CODE_MASK 0x1F
#define UIC_PHY_ADAPTER_LAYER_LANE_ERR_MASK 0xF