scsi: ufs: handle LINERESET during hibern8
If LINERESET was detected during Hibern8 operation, link moves to default PWM-G1 mode hence full reinit is required to move link to HS speeds. Change-Id: I4cdcbd31b5fa5ceac0eea7c743ea9286f231b80b Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
This commit is contained in:
parent
1ff56658f3
commit
badf0ba0b4
3 changed files with 32 additions and 5 deletions
|
@ -4132,7 +4132,13 @@ static int __ufshcd_uic_hibern8_enter(struct ufs_hba *hba)
|
||||||
trace_ufshcd_profile_hibern8(dev_name(hba->dev), "enter",
|
trace_ufshcd_profile_hibern8(dev_name(hba->dev), "enter",
|
||||||
ktime_to_us(ktime_sub(ktime_get(), start)), ret);
|
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);
|
ufshcd_update_error_stats(hba, UFS_ERR_HIBERN8_ENTER);
|
||||||
dev_err(hba->dev, "%s: hibern8 enter failed. ret = %d",
|
dev_err(hba->dev, "%s: hibern8 enter failed. ret = %d",
|
||||||
__func__, ret);
|
__func__, ret);
|
||||||
|
@ -4175,8 +4181,13 @@ int ufshcd_uic_hibern8_exit(struct ufs_hba *hba)
|
||||||
ret = ufshcd_uic_pwr_ctrl(hba, &uic_cmd);
|
ret = ufshcd_uic_pwr_ctrl(hba, &uic_cmd);
|
||||||
trace_ufshcd_profile_hibern8(dev_name(hba->dev), "exit",
|
trace_ufshcd_profile_hibern8(dev_name(hba->dev), "exit",
|
||||||
ktime_to_us(ktime_sub(ktime_get(), start)), ret);
|
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);
|
ufshcd_update_error_stats(hba, UFS_ERR_HIBERN8_EXIT);
|
||||||
dev_err(hba->dev, "%s: hibern8 exit failed. ret = %d",
|
dev_err(hba->dev, "%s: hibern8 exit failed. ret = %d",
|
||||||
__func__, ret);
|
__func__, ret);
|
||||||
|
@ -5827,9 +5838,8 @@ static void ufshcd_update_uic_error(struct ufs_hba *hba)
|
||||||
|
|
||||||
/* PHY layer lane error */
|
/* PHY layer lane error */
|
||||||
reg = ufshcd_readl(hba, REG_UIC_ERROR_CODE_PHY_ADAPTER_LAYER);
|
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) &&
|
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
|
* To know whether this error is fatal or not, DB timeout
|
||||||
* must be checked but this error is handled separately.
|
* must be checked but this error is handled separately.
|
||||||
|
@ -5837,6 +5847,20 @@ static void ufshcd_update_uic_error(struct ufs_hba *hba)
|
||||||
dev_dbg(hba->dev, "%s: UIC Lane error reported, reg 0x%x\n",
|
dev_dbg(hba->dev, "%s: UIC Lane error reported, reg 0x%x\n",
|
||||||
__func__, reg);
|
__func__, reg);
|
||||||
ufshcd_update_uic_reg_hist(&hba->ufs_stats.pa_err, 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 */
|
/* PA_INIT_ERROR is fatal and needs UIC reset */
|
||||||
|
|
|
@ -902,6 +902,8 @@ struct ufs_hba {
|
||||||
bool no_ref_clk_gating;
|
bool no_ref_clk_gating;
|
||||||
|
|
||||||
int scsi_block_reqs_cnt;
|
int scsi_block_reqs_cnt;
|
||||||
|
|
||||||
|
bool full_init_linereset;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Returns true if clocks can be gated. Otherwise false */
|
/* Returns true if clocks can be gated. Otherwise false */
|
||||||
|
|
|
@ -190,6 +190,7 @@ enum {
|
||||||
|
|
||||||
/* UECPA - Host UIC Error Code PHY Adapter Layer 38h */
|
/* UECPA - Host UIC Error Code PHY Adapter Layer 38h */
|
||||||
#define UIC_PHY_ADAPTER_LAYER_ERROR UFS_BIT(31)
|
#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_ERROR_CODE_MASK 0x1F
|
||||||
#define UIC_PHY_ADAPTER_LAYER_LANE_ERR_MASK 0xF
|
#define UIC_PHY_ADAPTER_LAYER_LANE_ERR_MASK 0xF
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue