FROMLIST: scsi: ufs: fix livelock of ufshcd_clear_ua_wluns
When gate_work/ungate_work gets an error during hibern8_enter or exit,
ufshcd_err_handler()
ufshcd_scsi_block_requests()
ufshcd_reset_and_restore()
ufshcd_clear_ua_wluns() -> stuck
ufshcd_scsi_unblock_requests()
In order to avoid it, ufshcd_clear_ua_wluns() can be called per recovery flows
such as suspend/resume, link_recovery, and error_handler.
Bug: 175391270
Link: https://lore.kernel.org/linux-scsi/20201218033131.2624065-1-jaegeuk@kernel.org/T/#u
Fixes: fc6762d925
("FROMLIST: scsi: ufs: Clear UAC for RPMB after ufshcd resets")
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@google.com>
Change-Id: Ia53b70ce24c191985de3f8678c854e2df626de11
This commit is contained in:

committed by
Alistair Delva

parent
de594973f8
commit
b56c9e4cdf
@@ -3973,6 +3973,8 @@ int ufshcd_link_recovery(struct ufs_hba *hba)
|
||||
if (ret)
|
||||
dev_err(hba->dev, "%s: link recovery failed, err %d",
|
||||
__func__, ret);
|
||||
else
|
||||
ufshcd_clear_ua_wluns(hba);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -5969,6 +5971,9 @@ skip_err_handling:
|
||||
ufshcd_scsi_unblock_requests(hba);
|
||||
ufshcd_err_handling_unprepare(hba);
|
||||
up(&hba->eh_sem);
|
||||
|
||||
if (!err && needs_reset)
|
||||
ufshcd_clear_ua_wluns(hba);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -6906,14 +6911,11 @@ static int ufshcd_host_reset_and_restore(struct ufs_hba *hba)
|
||||
ufshcd_set_clk_freq(hba, true);
|
||||
|
||||
err = ufshcd_hba_enable(hba);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
/* Establish the link again and restore the device */
|
||||
err = ufshcd_probe_hba(hba, false);
|
||||
if (!err)
|
||||
ufshcd_clear_ua_wluns(hba);
|
||||
out:
|
||||
err = ufshcd_probe_hba(hba, false);
|
||||
|
||||
if (err)
|
||||
dev_err(hba->dev, "%s: Host init failed %d\n", __func__, err);
|
||||
ufshcd_update_reg_hist(&hba->ufs_stats.host_reset, (u32)err);
|
||||
@@ -8734,6 +8736,7 @@ enable_gating:
|
||||
ufshcd_resume_clkscaling(hba);
|
||||
hba->clk_gating.is_suspended = false;
|
||||
hba->dev_info.b_rpm_dev_flush_capable = false;
|
||||
ufshcd_clear_ua_wluns(hba);
|
||||
ufshcd_release(hba);
|
||||
out:
|
||||
if (hba->dev_info.b_rpm_dev_flush_capable) {
|
||||
@@ -8839,6 +8842,8 @@ static int ufshcd_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
|
||||
cancel_delayed_work(&hba->rpm_dev_flush_recheck_work);
|
||||
}
|
||||
|
||||
ufshcd_clear_ua_wluns(hba);
|
||||
|
||||
/* Schedule clock gating in case of no access to UFS device yet */
|
||||
ufshcd_release(hba);
|
||||
|
||||
|
Reference in New Issue
Block a user