From: Peter Wang <peter.wang@xxxxxxxxxxxx> Both ufshcd_shtdown and ufshcd_wl_shutdown could run concurrently. And it have race condition when ufshcd_wl_shutdown on-going and clock/power turn off by ufshcd_shutdown. The normal case: ufshcd_wl_shutdown -> ufshcd_shtdown ufshcd_shtdown should turn off clock/power. The abnormal case: ufshcd_shtdown -> ufshcd_wl_shutdown Wait ufshcd_wl_shutdown set device to power off and turn off clock/power. If timeout happen, means device still in active mode, cannot turn off clock/power directly. Skip and keep clock/power on in this case. Also remove pm_runtime_get_sync because shutdown is focus on turn off clock/power. We don't need turn on(resume) and turn off. The second reason is ufshcd_wl_shutdown call ufshcd_rpm_get_sync already, if ufshcd_shtdown wait ufshcd_wl_shutdown finish, hba->dev is already resume and no need pm_runtime_get_sync. Signed-off-by: Peter Wang <peter.wang@xxxxxxxxxxxx> --- drivers/ufs/core/ufshcd.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c index c7b337480e3e..533563a2a6b7 100644 --- a/drivers/ufs/core/ufshcd.c +++ b/drivers/ufs/core/ufshcd.c @@ -58,6 +58,9 @@ /* Task management command timeout */ #define TM_CMD_TIMEOUT 100 /* msecs */ +/* Shutdown wait devcie into power off timeout */ +#define UFS_SHUTDWON_TIMEOUT 500 /* msecs */ + /* maximum number of retries for a general UIC command */ #define UFS_UIC_COMMAND_RETRIES 3 @@ -9461,10 +9464,15 @@ EXPORT_SYMBOL(ufshcd_runtime_resume); */ int ufshcd_shutdown(struct ufs_hba *hba) { - if (ufshcd_is_ufs_dev_poweroff(hba) && ufshcd_is_link_off(hba)) - goto out; + unsigned long timeout; - pm_runtime_get_sync(hba->dev); + /* Wait ufshcd_wl_shutdown clear ufs state */ + timeout = jiffies + msecs_to_jiffies(UFS_SHUTDWON_TIMEOUT); + while (!ufshcd_is_ufs_dev_poweroff(hba) || !ufshcd_is_link_off(hba)) { + if (time_after(jiffies, timeout)) + goto out; + msleep(1); + } ufshcd_suspend(hba); out: -- 2.18.0