diff options
author | Kiwoong Kim <kwmad.kim@samsung.com> | 2020-08-10 13:02:27 +0300 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2020-08-21 04:53:42 +0300 |
commit | 29707fab584540ce4e85526b0dde49b976bc1bdf (patch) | |
tree | b8c7e98dbfc86ba8d480b9c154109deea9fbfcaf /drivers/scsi | |
parent | b0008625795b6f8de2fc785041dd1dc8468f0367 (diff) | |
download | linux-29707fab584540ce4e85526b0dde49b976bc1bdf.tar.xz |
scsi: ufs: Change fDeviceInit busy wait
Currently, the UFS driver busy waits for fDeviceInit to be cleared. Provide
an upper bound and sleep between attempts instead of busy waiting.
Link: https://lore.kernel.org/r/1597053747-75171-1-git-send-email-kwmad.kim@samsung.com
Tested-by: Kiwoong Kim <kwmad.kim@samsung.com>
Reviewed-by: Avri Altman <avri.altman@wdc.com>
Signed-off-by: Kiwoong Kim <kwmad.kim@samsung.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/ufs/ufshcd.c | 33 |
1 files changed, 21 insertions, 12 deletions
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 2b55c2e9f026..66e837c9af8c 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -74,6 +74,9 @@ /* Default value of wait time before gating device ref clock */ #define UFSHCD_REF_CLK_GATING_WAIT_US 0xFF /* microsecs */ +/* Polling time to wait for fDeviceInit */ +#define FDEVICEINIT_COMPL_TIMEOUT 1500 /* millisecs */ + #define ufshcd_toggle_vreg(_dev, _vreg, _on) \ ({ \ int _ret; \ @@ -4175,9 +4178,9 @@ EXPORT_SYMBOL_GPL(ufshcd_config_pwr_mode); */ static int ufshcd_complete_dev_init(struct ufs_hba *hba) { - int i; int err; bool flag_res = true; + ktime_t timeout; err = ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_SET_FLAG, QUERY_FLAG_IDN_FDEVICEINIT, 0, NULL); @@ -4188,20 +4191,26 @@ static int ufshcd_complete_dev_init(struct ufs_hba *hba) goto out; } - /* poll for max. 1000 iterations for fDeviceInit flag to clear */ - for (i = 0; i < 1000 && !err && flag_res; i++) - err = ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_READ_FLAG, - QUERY_FLAG_IDN_FDEVICEINIT, 0, &flag_res); + /* Poll fDeviceInit flag to be cleared */ + timeout = ktime_add_ms(ktime_get(), FDEVICEINIT_COMPL_TIMEOUT); + do { + err = ufshcd_query_flag(hba, UPIU_QUERY_OPCODE_READ_FLAG, + QUERY_FLAG_IDN_FDEVICEINIT, 0, &flag_res); + if (!flag_res) + break; + usleep_range(5000, 10000); + } while (ktime_before(ktime_get(), timeout)); - if (err) + if (err) { dev_err(hba->dev, - "%s reading fDeviceInit flag failed with error %d\n", - __func__, err); - else if (flag_res) + "%s reading fDeviceInit flag failed with error %d\n", + __func__, err); + } else if (flag_res) { dev_err(hba->dev, - "%s fDeviceInit was not cleared by the device\n", - __func__); - + "%s fDeviceInit was not cleared by the device\n", + __func__); + err = -EBUSY; + } out: return err; } |