scsi: ufs: retry failed query flag requests
UFS flag query requests may fail sometimes due to timeouts etc. Add a wrapper function to retry up to 10 times in case of such failure, similar to retries being made for attribute queries. Change-Id: Ie3ea4b3c516481e9ec176ab9db884a8a75cd33f9 Signed-off-by: Gilad Broner <gbroner@codeaurora.org> [subhashj@codeaurora.org: resolved trivial merge conflicts] Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
This commit is contained in:
parent
dc20c1b847
commit
c5c33e40b8
1 changed files with 37 additions and 26 deletions
|
@ -2912,6 +2912,29 @@ static inline void ufshcd_init_query(struct ufs_hba *hba,
|
||||||
(*request)->upiu_req.selector = selector;
|
(*request)->upiu_req.selector = selector;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ufshcd_query_flag_retry(struct ufs_hba *hba,
|
||||||
|
enum query_opcode opcode, enum flag_idn idn, bool *flag_res)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
int retries;
|
||||||
|
|
||||||
|
for (retries = 0; retries < QUERY_REQ_RETRIES; retries++) {
|
||||||
|
ret = ufshcd_query_flag(hba, opcode, idn, flag_res);
|
||||||
|
if (ret)
|
||||||
|
dev_dbg(hba->dev,
|
||||||
|
"%s: failed with error %d, retries %d\n",
|
||||||
|
__func__, ret, retries);
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
dev_err(hba->dev,
|
||||||
|
"%s: query attribute, opcode %d, idn %d, failed with error %d after %d retires\n",
|
||||||
|
__func__, opcode, idn, ret, retries);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ufshcd_query_flag() - API function for sending flag query requests
|
* ufshcd_query_flag() - API function for sending flag query requests
|
||||||
* hba: per-adapter instance
|
* hba: per-adapter instance
|
||||||
|
@ -4156,17 +4179,12 @@ static int ufshcd_config_pwr_mode(struct ufs_hba *hba,
|
||||||
*/
|
*/
|
||||||
static int ufshcd_complete_dev_init(struct ufs_hba *hba)
|
static int ufshcd_complete_dev_init(struct ufs_hba *hba)
|
||||||
{
|
{
|
||||||
int i, retries, err = 0;
|
int i;
|
||||||
|
int err;
|
||||||
bool flag_res = 1;
|
bool flag_res = 1;
|
||||||
|
|
||||||
for (retries = QUERY_REQ_RETRIES; retries > 0; retries--) {
|
err = ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_SET_FLAG,
|
||||||
/* Set the fDeviceInit flag */
|
|
||||||
err = ufshcd_query_flag(hba, UPIU_QUERY_OPCODE_SET_FLAG,
|
|
||||||
QUERY_FLAG_IDN_FDEVICEINIT, NULL);
|
QUERY_FLAG_IDN_FDEVICEINIT, NULL);
|
||||||
if (!err || err == -ETIMEDOUT)
|
|
||||||
break;
|
|
||||||
dev_dbg(hba->dev, "%s: error %d retrying\n", __func__, err);
|
|
||||||
}
|
|
||||||
if (err) {
|
if (err) {
|
||||||
dev_err(hba->dev,
|
dev_err(hba->dev,
|
||||||
"%s setting fDeviceInit flag failed with error %d\n",
|
"%s setting fDeviceInit flag failed with error %d\n",
|
||||||
|
@ -4175,17 +4193,10 @@ static int ufshcd_complete_dev_init(struct ufs_hba *hba)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* poll for max. 1000 iterations for fDeviceInit flag to clear */
|
/* poll for max. 1000 iterations for fDeviceInit flag to clear */
|
||||||
for (i = 0; i < 1000 && !err && flag_res; i++) {
|
for (i = 0; i < 1000 && !err && flag_res; i++)
|
||||||
for (retries = QUERY_REQ_RETRIES; retries > 0; retries--) {
|
err = ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_READ_FLAG,
|
||||||
err = ufshcd_query_flag(hba,
|
|
||||||
UPIU_QUERY_OPCODE_READ_FLAG,
|
|
||||||
QUERY_FLAG_IDN_FDEVICEINIT, &flag_res);
|
QUERY_FLAG_IDN_FDEVICEINIT, &flag_res);
|
||||||
if (!err || err == -ETIMEDOUT)
|
|
||||||
break;
|
|
||||||
dev_dbg(hba->dev, "%s: error %d retrying\n", __func__,
|
|
||||||
err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (err)
|
if (err)
|
||||||
dev_err(hba->dev,
|
dev_err(hba->dev,
|
||||||
"%s reading fDeviceInit flag failed with error %d\n",
|
"%s reading fDeviceInit flag failed with error %d\n",
|
||||||
|
@ -5057,7 +5068,7 @@ static int ufshcd_enable_auto_bkops(struct ufs_hba *hba)
|
||||||
if (hba->auto_bkops_enabled)
|
if (hba->auto_bkops_enabled)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
err = ufshcd_query_flag(hba, UPIU_QUERY_OPCODE_SET_FLAG,
|
err = ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_SET_FLAG,
|
||||||
QUERY_FLAG_IDN_BKOPS_EN, NULL);
|
QUERY_FLAG_IDN_BKOPS_EN, NULL);
|
||||||
if (err) {
|
if (err) {
|
||||||
dev_err(hba->dev, "%s: failed to enable bkops %d\n",
|
dev_err(hba->dev, "%s: failed to enable bkops %d\n",
|
||||||
|
@ -5107,7 +5118,7 @@ static int ufshcd_disable_auto_bkops(struct ufs_hba *hba)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = ufshcd_query_flag(hba, UPIU_QUERY_OPCODE_CLEAR_FLAG,
|
err = ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_CLEAR_FLAG,
|
||||||
QUERY_FLAG_IDN_BKOPS_EN, NULL);
|
QUERY_FLAG_IDN_BKOPS_EN, NULL);
|
||||||
if (err) {
|
if (err) {
|
||||||
dev_err(hba->dev, "%s: failed to disable bkops %d\n",
|
dev_err(hba->dev, "%s: failed to disable bkops %d\n",
|
||||||
|
@ -6612,7 +6623,7 @@ static int ufshcd_probe_hba(struct ufs_hba *hba)
|
||||||
|
|
||||||
/* clear any previous UFS device information */
|
/* clear any previous UFS device information */
|
||||||
memset(&hba->dev_info, 0, sizeof(hba->dev_info));
|
memset(&hba->dev_info, 0, sizeof(hba->dev_info));
|
||||||
if (!ufshcd_query_flag(hba, UPIU_QUERY_OPCODE_READ_FLAG,
|
if (!ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_READ_FLAG,
|
||||||
QUERY_FLAG_IDN_PWR_ON_WPE, &flag))
|
QUERY_FLAG_IDN_PWR_ON_WPE, &flag))
|
||||||
hba->dev_info.f_power_on_wp_en = flag;
|
hba->dev_info.f_power_on_wp_en = flag;
|
||||||
|
|
||||||
|
@ -6791,8 +6802,8 @@ static int ufshcd_query_ioctl(struct ufs_hba *hba, u8 lun, void __user *buffer)
|
||||||
default:
|
default:
|
||||||
goto out_einval;
|
goto out_einval;
|
||||||
}
|
}
|
||||||
err = ufshcd_query_flag(hba, ioctl_data->opcode, ioctl_data->idn,
|
err = ufshcd_query_flag_retry(hba, ioctl_data->opcode,
|
||||||
&flag);
|
ioctl_data->idn, &flag);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
goto out_einval;
|
goto out_einval;
|
||||||
|
|
Loading…
Add table
Reference in a new issue