Commit 2df74b69 authored by Can Guo's avatar Can Guo Committed by Martin K. Petersen

scsi: ufs: Complete pending requests in host reset and restore path

In UFS host reset and restore path, before probe, we stop and start the
host controller once. After host controller is stopped, the pending
requests, if any, are cleared from the doorbell, but no completion IRQ
would be raised due to the hba is stopped.  These pending requests shall be
completed along with the first NOP_OUT command (as it is the first command
which can raise a transfer completion IRQ) sent during probe.  Since the
OCSs of these pending requests are not SUCCESS (because they are not yet
literally finished), their UPIUs shall be dumped. When there are multiple
pending requests, the UPIU dump can be overwhelming and may lead to
stability issues because it is in atomic context.  Therefore, before probe,
complete these pending requests right after host controller is stopped and
silence the UPIU dump from them.

Link: https://lore.kernel.org/r/1574751214-8321-5-git-send-email-cang@qti.qualcomm.comReviewed-by: default avatarAlim Akhtar <alim.akhtar@samsung.com>
Reviewed-by: default avatarBean Huo <beanhuo@micron.com>
Tested-by: default avatarBean Huo <beanhuo@micron.com>
Signed-off-by: default avatarCan Guo <cang@codeaurora.org>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 74a527a2
...@@ -4736,7 +4736,7 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) ...@@ -4736,7 +4736,7 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
break; break;
} /* end of switch */ } /* end of switch */
if (host_byte(result) != DID_OK) if ((host_byte(result) != DID_OK) && !hba->silence_err_logs)
ufshcd_print_trs(hba, 1 << lrbp->task_tag, true); ufshcd_print_trs(hba, 1 << lrbp->task_tag, true);
return result; return result;
} }
...@@ -5284,8 +5284,8 @@ static void ufshcd_err_handler(struct work_struct *work) ...@@ -5284,8 +5284,8 @@ static void ufshcd_err_handler(struct work_struct *work)
/* /*
* if host reset is required then skip clearing the pending * if host reset is required then skip clearing the pending
* transfers forcefully because they will automatically get * transfers forcefully because they will get cleared during
* cleared after link startup. * host reset and restore
*/ */
if (needs_reset) if (needs_reset)
goto skip_pending_xfer_clear; goto skip_pending_xfer_clear;
...@@ -6244,9 +6244,15 @@ static int ufshcd_host_reset_and_restore(struct ufs_hba *hba) ...@@ -6244,9 +6244,15 @@ static int ufshcd_host_reset_and_restore(struct ufs_hba *hba)
int err; int err;
unsigned long flags; unsigned long flags;
/* Reset the host controller */ /*
* Stop the host controller and complete the requests
* cleared by h/w
*/
spin_lock_irqsave(hba->host->host_lock, flags); spin_lock_irqsave(hba->host->host_lock, flags);
ufshcd_hba_stop(hba, false); ufshcd_hba_stop(hba, false);
hba->silence_err_logs = true;
ufshcd_complete_requests(hba);
hba->silence_err_logs = false;
spin_unlock_irqrestore(hba->host->host_lock, flags); spin_unlock_irqrestore(hba->host->host_lock, flags);
/* scale up clocks to max frequency before full reinitialization */ /* scale up clocks to max frequency before full reinitialization */
...@@ -6280,7 +6286,6 @@ static int ufshcd_host_reset_and_restore(struct ufs_hba *hba) ...@@ -6280,7 +6286,6 @@ static int ufshcd_host_reset_and_restore(struct ufs_hba *hba)
static int ufshcd_reset_and_restore(struct ufs_hba *hba) static int ufshcd_reset_and_restore(struct ufs_hba *hba)
{ {
int err = 0; int err = 0;
unsigned long flags;
int retries = MAX_HOST_RESET_RETRIES; int retries = MAX_HOST_RESET_RETRIES;
do { do {
...@@ -6290,15 +6295,6 @@ static int ufshcd_reset_and_restore(struct ufs_hba *hba) ...@@ -6290,15 +6295,6 @@ static int ufshcd_reset_and_restore(struct ufs_hba *hba)
err = ufshcd_host_reset_and_restore(hba); err = ufshcd_host_reset_and_restore(hba);
} while (err && --retries); } while (err && --retries);
/*
* After reset the door-bell might be cleared, complete
* outstanding requests in s/w here.
*/
spin_lock_irqsave(hba->host->host_lock, flags);
ufshcd_transfer_req_compl(hba);
ufshcd_tmc_handler(hba);
spin_unlock_irqrestore(hba->host->host_lock, flags);
return err; return err;
} }
......
...@@ -509,6 +509,7 @@ struct ufs_stats { ...@@ -509,6 +509,7 @@ struct ufs_stats {
* @uic_error: UFS interconnect layer error status * @uic_error: UFS interconnect layer error status
* @saved_err: sticky error mask * @saved_err: sticky error mask
* @saved_uic_err: sticky UIC error mask * @saved_uic_err: sticky UIC error mask
* @silence_err_logs: flag to silence error logs
* @dev_cmd: ufs device management command information * @dev_cmd: ufs device management command information
* @last_dme_cmd_tstamp: time stamp of the last completed DME command * @last_dme_cmd_tstamp: time stamp of the last completed DME command
* @auto_bkops_enabled: to track whether bkops is enabled in device * @auto_bkops_enabled: to track whether bkops is enabled in device
...@@ -664,6 +665,7 @@ struct ufs_hba { ...@@ -664,6 +665,7 @@ struct ufs_hba {
u32 saved_err; u32 saved_err;
u32 saved_uic_err; u32 saved_uic_err;
struct ufs_stats ufs_stats; struct ufs_stats ufs_stats;
bool silence_err_logs;
/* Device management request data */ /* Device management request data */
struct ufs_dev_cmd dev_cmd; struct ufs_dev_cmd dev_cmd;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment