[PATCH v2 1/2] ufs: core: Fix a race condition triggered by ufshcd_eh_timed_out()
Bart Van Assche <[email protected]>
| Newsgroups | org.kernel.vger.linux-scsi |
|---|---|
| Message-ID | <fd054bab859b55a9a8182e54a8e5c901c474c421.1786569828.git.bvanassche@acm.org> |
If a START STOP UNIT command times out, the ufshcd_link_recovery() call
in ufshcd_eh_timed_out() may call scsi_done() for that command via the
force-completion mechanism. This may cause ufshcd_set_dev_pwr_mode() to
return before link recovery has finished. Fix this race condition by
moving the ufshcd_link_recovery() call into ufshcd_set_dev_pwr_mode().
Fixes: 7029e2151a7c ("scsi: ufs: Fix a deadlock between PM and the SCSI error handler")
Signed-off-by: Bart Van Assche <[email protected]>
---
drivers/ufs/core/ufshcd.c | 13 +------------
1 file changed, 1 insertion(+), 12 deletions(-)
diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
index a51e071916cf..d719100bfe38 100644
--- a/drivers/ufs/core/ufshcd.c
+++ b/drivers/ufs/core/ufshcd.c
@@ -9582,18 +9582,6 @@ static enum scsi_timeout_action ufshcd_eh_timed_out(struct scsi_cmnd *scmd)
return SCSI_EH_NOT_HANDLED;
}
- /*
- * Handle the timeout directly to prevent a deadlock between
- * ufshcd_set_dev_pwr_mode() and ufshcd_err_handler().
- */
- ufshcd_link_recovery(hba);
- dev_info(hba->dev, "%s() finished; outstanding_tasks = %#lx.\n",
- __func__, hba->outstanding_tasks);
-
- /*
- * ufshcd_link_recovery() may already have completed @scmd, e.g. via
- * the existing MCQ force-completion path.
- */
if (!test_bit(SCMD_STATE_COMPLETE, &scmd->state)) {
if (!hba->mcq_enabled) {
unsigned long flags;
@@ -10130,6 +10118,7 @@ static int ufshcd_set_dev_pwr_mode(struct ufs_hba *hba,
if (ret > 0) {
if (scsi_sense_valid(&sshdr))
scsi_print_sense_hdr(sdp, NULL, &sshdr);
+ ufshcd_link_recovery(hba);
ret = -EIO;
}
} else {