Three minor fixes w.r.t suspend/resume
cover Three minor fixes w.r.t suspend/resume
1st change can fix a possible OCP issue.
2nd and 3rd change can fix race conditions btw suspend/resume and other contexts.
Can Guo (3):
scsi: ufs: Do not put UFS power into LPM if link is broken
scsi: ufs: Cancel rpm_dev_flush_recheck_work during system suspend
scsi: ufs: Narrow down fast pass in system suspend path
drivers/scsi/ufs/ufshcd.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-)
Signature · 1 line
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project.
PATCH 1/3 scsi: ufs: Do not put UFS power into LPM if link is broken
During resume, if link is broken due to AH8 failure, make sure ufshcd_resume() do not put UFS power back into LPM.
--- drivers/scsi/ufs/ufshcd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/scsi/ufs/ufshcd.c +2 -2
@@ -8666,7 +8666,7 @@ static void ufshcd_vreg_set_lpm(struct ufs_hba *hba) }else if (!ufshcd_is_ufs_dev_active (hba)) {ufshcd_toggle_vreg (hba->dev, hba->vreg_info.vcc, false); vcc_off = true; -if (!ufshcd_is_link_active (hba)) { +if (ufshcd_is_link_hibern8 (hba) ||ufshcd_is_link_off (hba)) {ufshcd_config_vreg_lpm (hba, hba->vreg_info.vccq);ufshcd_config_vreg_lpm (hba, hba->vreg_info.vccq2); }
@@ -8688,7 +8688,7 @@ static int ufshcd_vreg_set_hpm(struct ufs_hba *hba) !hba->dev_info.is_lu_power_on_wp) { ret =ufshcd_setup_vreg (hba, true); } else if (!ufshcd_is_ufs_dev_active(hba)) { -if (!ret && !ufshcd_is_link_active (hba)) { +if (!ufshcd_is_link_active (hba)) { ret =ufshcd_config_vreg_hpm (hba, hba->vreg_info.vccq);if (ret) goto vcc_disable;
Signature · 1 line
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project.
PATCH 2/3 scsi: ufs: Cancel rpm_dev_flush_recheck_work during system suspend
In reply to Can GuoDuring ufs system suspend, leaving rpm_dev_flush_recheck_work running or pending is risky, because concurrency may happen btw system suspend/resume and runtime resume routine. Fix it by cancelling rpm_dev_flush_recheck_work synchronously during system suspend.
--- drivers/scsi/ufs/ufshcd.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/scsi/ufs/ufshcd.c +3 -2
@@ -9058,11 +9058,12 @@ int ufshcd_system_suspend(struct ufs_hba *hba)if (!hba->is_powered)return 0 ; +cancel_delayed_work_sync (&hba->rpm_dev_flush_recheck_work); +if ((ufs_get_pm_lvl_to_dev_pwr_mode (hba->spm_lvl) == hba->curr_dev_pwr_mode) && (ufs_get_pm_lvl_to_link_pwr_state (hba->spm_lvl) == - hba->uic_link_state) && - !hba->dev_info.b_rpm_dev_flush_capable) + hba->uic_link_state)) goto out;if (pm_runtime_suspended (hba->dev)) {
Signature · 1 line
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project.
RE: [PATCH v1 2/3] scsi: ufs: Cancel rpm_dev_flush_recheck_work during system suspend
Hi Can Guo,
Quoted 5 lines
drivers/scsi/ufs/ufshcd.c +0
-0
drivers/scsi/ufs/ufshcd.c int ufshcd_system_suspend(struct ufs_hba *hba) · line 9065
Quoted 10 lines
drivers/scsi/ufs/ufshcd.c +2
-2@@ -9058,11 +9058,12 @@ int ufshcd_system_suspend(struct ufs_hba *hba)if (!hba->is_powered)return 0 ; +cancel_delayed_work_sync (&hba->rpm_dev_flush_recheck_work); + if ((ufs_get_pm_lvl_to_dev_pwr_mode(hba->spm_lvl) == hba->curr_dev_pwr_mode) && (ufs_get_pm_lvl_to_link_pwr_state(hba->spm_lvl) == - hba->uic_link_state) && - !hba->dev_info.b_rpm_dev_flush_capable)
I think it should not be removed.
It prevents power drain when runtime suspend and system suspend have same power mode.
Thanks,
Daejun
Re: [PATCH v1 2/3] scsi: ufs: Cancel rpm_dev_flush_recheck_work during system suspend
Quoted 10 lines · Daejun Park
Hi Can Guo,
Quoted 8 lines
drivers/scsi/ufs/ufshcd.c +0
-0@@ -9058,11 +9058,12 @@ int ufshcd_system_suspend(struct ufs_hba *hba)if (!hba->is_powered)return 0 ;
Quoted 11 lines
drivers/scsi/ufs/ufshcd.c int ufshcd_system_suspend(struct ufs_hba *hba) · line 9065
Quoted 7 lines
drivers/scsi/ufs/ufshcd.c +2
-2+cancel_delayed_work_sync (&hba->rpm_dev_flush_recheck_work); + if ((ufs_get_pm_lvl_to_dev_pwr_mode(hba->spm_lvl) == hba->curr_dev_pwr_mode) && (ufs_get_pm_lvl_to_link_pwr_state(hba->spm_lvl) == - hba->uic_link_state) && - !hba->dev_info.b_rpm_dev_flush_capable)I think it should not be removed.
It prevents power drain when runtime suspend and system suspend have same power mode.
I will add it back in next ver.
Thanks,
Can Guo
Quoted 2 lines
Thanks,
Daejun
PATCH 3/3 scsi: ufs: Narrow down fast pass in system suspend path
In reply to Can GuoIf spm_lvl is set to 0 or 1, when system suspend kicks start and hba is runtime active, system suspend may just bail without doing anything (the fast pass), leaving other contexts still running, e.g., clock gating and clock scaling. When system resume kicks start, concurrency can happen btw ufshcd_resume() and these contexts, leading to various stability issues. Fix it by adding a check against hba's runtime status and allowing fast pass only if hba is runtime suspended, otherwise let system suspend go ahead call ufshcd_suspend(). This can guarantee that these contexts are stopped by either runtime suspend or system suspend.
--- drivers/scsi/ufs/ufshcd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/scsi/ufs/ufshcd.c +2 -1
@@ -9060,7 +9060,8 @@ int ufshcd_system_suspend(struct ufs_hba *hba)cancel_delayed_work_sync (&hba->rpm_dev_flush_recheck_work); -if ((ufs_get_pm_lvl_to_dev_pwr_mode (hba->spm_lvl) == +if (pm_runtime_suspended (hba->dev) && + (ufs_get_pm_lvl_to_dev_pwr_mode (hba->spm_lvl) == hba->curr_dev_pwr_mode) && (ufs_get_pm_lvl_to_link_pwr_state (hba->spm_lvl) == hba->uic_link_state))
Signature · 1 line
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project.